diff options
470 files changed, 15655 insertions, 5760 deletions
@@ -121,7 +121,8 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \ telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl \ telephony/java/com/android/internal/telephony/gsm/ISms.aidl \ - wifi/java/android/net/wifi/IWifiManager.aidl + wifi/java/android/net/wifi/IWifiManager.aidl \ + telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl # FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) @@ -125608,7 +125608,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -125652,7 +125652,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -125665,7 +125665,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > diff --git a/api/current.xml b/api/current.xml index 9deab57..a6414b5 100644 --- a/api/current.xml +++ b/api/current.xml @@ -628,17 +628,6 @@ visibility="public" > </field> -<field name="PACKAGE_USAGE_STATS" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.permission.PACKAGE_USAGE_STATS"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="PERSISTENT_ACTIVITY" type="java.lang.String" transient="false" @@ -3771,6 +3760,39 @@ visibility="public" > </field> +<field name="imeExtractEnterAnimation" + type="int" + transient="false" + volatile="false" + value="16843368" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="imeExtractExitAnimation" + type="int" + transient="false" + volatile="false" + value="16843369" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="imeFullscreenBackground" + type="int" + transient="false" + volatile="false" + value="16843308" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="imeOptions" type="int" transient="false" @@ -6631,17 +6653,6 @@ visibility="public" > </field> -<field name="starStyleButtonless" - type="int" - transient="false" - volatile="false" - value="16843308" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="startColor" type="int" transient="false" @@ -8782,7 +8793,7 @@ type="int" transient="false" volatile="false" - value="17301686" + value="17301669" static="true" final="true" deprecated="not deprecated" @@ -8899,193 +8910,6 @@ visibility="public" > </field> -<field name="emo_im_angel" - type="int" - transient="false" - volatile="false" - value="17301668" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_cool" - type="int" - transient="false" - volatile="false" - value="17301669" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_crying" - type="int" - transient="false" - volatile="false" - value="17301670" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_embarrassed" - type="int" - transient="false" - volatile="false" - value="17301671" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_foot_in_mouth" - type="int" - transient="false" - volatile="false" - value="17301672" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_happy" - type="int" - transient="false" - volatile="false" - value="17301673" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_kissing" - type="int" - transient="false" - volatile="false" - value="17301674" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_laughing" - type="int" - transient="false" - volatile="false" - value="17301675" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_lips_are_sealed" - type="int" - transient="false" - volatile="false" - value="17301676" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_money_mouth" - type="int" - transient="false" - volatile="false" - value="17301677" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_sad" - type="int" - transient="false" - volatile="false" - value="17301678" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_surprised" - type="int" - transient="false" - volatile="false" - value="17301679" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_tongue_sticking_out" - type="int" - transient="false" - volatile="false" - value="17301680" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_undecided" - type="int" - transient="false" - volatile="false" - value="17301681" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_winking" - type="int" - transient="false" - volatile="false" - value="17301682" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_wtf" - type="int" - transient="false" - volatile="false" - value="17301683" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="emo_im_yelling" - type="int" - transient="false" - volatile="false" - value="17301684" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="gallery_thumb" type="int" transient="false" @@ -9101,7 +8925,7 @@ type="int" transient="false" volatile="false" - value="17301685" + value="17301668" static="true" final="true" deprecated="not deprecated" @@ -10498,7 +10322,7 @@ type="int" transient="false" volatile="false" - value="17301687" + value="17301670" static="true" final="true" deprecated="not deprecated" @@ -10599,33 +10423,33 @@ visibility="public" > </field> -<field name="button_close" +<field name="candidatesArea" type="int" transient="false" volatile="false" - value="16908327" + value="16908317" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> -<field name="candidatesArea" +<field name="checkbox" type="int" transient="false" volatile="false" - value="16908317" + value="16908289" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> -<field name="checkbox" +<field name="closeButton" type="int" transient="false" volatile="false" - value="16908289" + value="16908327" static="true" final="true" deprecated="not deprecated" @@ -12087,6 +11911,17 @@ visibility="public" > </field> +<field name="Theme_Light_Panel" + type="int" + transient="false" + volatile="false" + value="16973914" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="Theme_NoDisplay" type="int" transient="false" @@ -12120,6 +11955,17 @@ visibility="public" > </field> +<field name="Theme_Panel" + type="int" + transient="false" + volatile="false" + value="16973913" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="Theme_Translucent" type="int" transient="false" @@ -18918,6 +18764,16 @@ visibility="public" > </field> +<field name="extras" + type="android.os.Bundle" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="icon" type="android.graphics.drawable.Drawable" transient="false" @@ -21482,6 +21338,28 @@ visibility="public" > </field> +<field name="EXTRA_CUSTOM_EXTRAS" + type="java.lang.String" + transient="false" + volatile="false" + value=""customExtras"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="EXTRA_CUSTOM_INFO" + type="java.lang.String" + transient="false" + volatile="false" + value=""customInfo"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="INVALID_APPWIDGET_ID" type="int" transient="false" @@ -28325,6 +28203,17 @@ visibility="public" > </field> +<field name="ACTION_PACKAGE_REPLACED" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.intent.action.PACKAGE_REPLACED"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="ACTION_PACKAGE_RESTARTED" type="java.lang.String" transient="false" @@ -28501,6 +28390,17 @@ visibility="public" > </field> +<field name="ACTION_SYSTEM_TUTORIAL" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.intent.action.SYSTEM_TUTORIAL"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="ACTION_TIMEZONE_CHANGED" type="java.lang.String" transient="false" @@ -33653,6 +33553,17 @@ visibility="public" > </field> +<field name="INSTALL_FAILED_CONFLICTING_PROVIDER" + type="int" + transient="false" + volatile="false" + value="-13" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="INSTALL_FAILED_DEXOPT" type="int" transient="false" @@ -58793,6 +58704,17 @@ visibility="public" > </method> +<method name="isExtractViewShown" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="isFullscreenMode" return="boolean" abstract="false" @@ -58882,17 +58804,6 @@ <parameter name="isCandidatesOnly" type="boolean"> </parameter> </method> -<method name="onCreateBackgroundDrawable" - return="android.graphics.drawable.Drawable" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> <method name="onCreateCandidatesView" return="android.view.View" abstract="false" @@ -59244,7 +59155,20 @@ <parameter name="text" type="android.view.inputmethod.ExtractedText"> </parameter> </method> -<method name="onUpdateExtractingAccessories" +<method name="onUpdateExtractingViews" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="ei" type="android.view.inputmethod.EditorInfo"> +</parameter> +</method> +<method name="onUpdateExtractingVisibility" return="void" abstract="false" native="false" @@ -59393,6 +59317,19 @@ <parameter name="view" type="android.view.View"> </parameter> </method> +<method name="setExtractViewShown" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="shown" type="boolean"> +</parameter> +</method> <method name="setInputView" return="void" abstract="false" @@ -60716,6 +60653,25 @@ <parameter name="heightMeasureSpec" type="int"> </parameter> </method> +<method name="onSizeChanged" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="w" type="int"> +</parameter> +<parameter name="h" type="int"> +</parameter> +<parameter name="oldw" type="int"> +</parameter> +<parameter name="oldh" type="int"> +</parameter> +</method> <method name="setKeyboard" return="void" abstract="false" @@ -63575,6 +63531,21 @@ <parameter name="effectType" type="int"> </parameter> </method> +<method name="playSoundEffect" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="effectType" type="int"> +</parameter> +<parameter name="volume" type="float"> +</parameter> +</method> <method name="setBluetoothA2dpOn" return="void" abstract="false" @@ -63932,6 +63903,50 @@ visibility="public" > </field> +<field name="FX_KEYPRESS_DELETE" + type="int" + transient="false" + volatile="false" + value="7" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FX_KEYPRESS_RETURN" + type="int" + transient="false" + volatile="false" + value="8" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FX_KEYPRESS_SPACEBAR" + type="int" + transient="false" + volatile="false" + value="6" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FX_KEYPRESS_STANDARD" + type="int" + transient="false" + volatile="false" + value="5" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="FX_KEY_CLICK" type="int" transient="false" @@ -64346,6 +64361,23 @@ visibility="public" > </method> +<method name="getMinBufferSize" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="sampleRateInHz" type="int"> +</parameter> +<parameter name="channelConfig" type="int"> +</parameter> +<parameter name="audioFormat" type="int"> +</parameter> +</method> <method name="getNotificationMarkerPosition" return="int" abstract="false" @@ -64461,8 +64493,8 @@ visibility="public" > </method> -<method name="setMarkerReachedListener" - return="void" +<method name="setNotificationMarkerPosition" + return="int" abstract="false" native="false" synchronized="false" @@ -64471,10 +64503,10 @@ deprecated="not deprecated" visibility="public" > -<parameter name="listener" type="android.media.AudioRecord.OnMarkerReachedListener"> +<parameter name="markerInFrames" type="int"> </parameter> </method> -<method name="setNotificationMarkerPosition" +<method name="setPositionNotificationPeriod" return="int" abstract="false" native="false" @@ -64484,10 +64516,10 @@ deprecated="not deprecated" visibility="public" > -<parameter name="markerInFrames" type="int"> +<parameter name="periodInFrames" type="int"> </parameter> </method> -<method name="setPeriodicNotificationListener" +<method name="setRecordPositionUpdateListener" return="void" abstract="false" native="false" @@ -64497,11 +64529,11 @@ deprecated="not deprecated" visibility="public" > -<parameter name="listener" type="android.media.AudioRecord.OnPeriodicNotificationListener"> +<parameter name="listener" type="android.media.AudioRecord.OnRecordPositionUpdateListener"> </parameter> </method> -<method name="setPositionNotificationPeriod" - return="int" +<method name="setRecordPositionUpdateListener" + return="void" abstract="false" native="false" synchronized="false" @@ -64510,7 +64542,9 @@ deprecated="not deprecated" visibility="public" > -<parameter name="periodInFrames" type="int"> +<parameter name="listener" type="android.media.AudioRecord.OnRecordPositionUpdateListener"> +</parameter> +<parameter name="handler" type="android.os.Handler"> </parameter> </method> <method name="startRecording" @@ -64628,7 +64662,7 @@ > </field> </class> -<interface name="AudioRecord.OnMarkerReachedListener" +<interface name="AudioRecord.OnRecordPositionUpdateListener" abstract="true" static="true" final="false" @@ -64648,14 +64682,6 @@ <parameter name="recorder" type="android.media.AudioRecord"> </parameter> </method> -</interface> -<interface name="AudioRecord.OnPeriodicNotificationListener" - abstract="true" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> <method name="onPeriodicNotification" return="void" abstract="true" @@ -64755,6 +64781,23 @@ visibility="public" > </method> +<method name="getMinBufferSize" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="sampleRateInHz" type="int"> +</parameter> +<parameter name="channelConfig" type="int"> +</parameter> +<parameter name="audioFormat" type="int"> +</parameter> +</method> <method name="getMinVolume" return="float" abstract="false" @@ -64823,6 +64866,17 @@ visibility="public" > </method> +<method name="getPlaybackRate" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getPositionNotificationPeriod" return="int" abstract="false" @@ -65573,11 +65627,11 @@ deprecated="not deprecated" visibility="public" > -<parameter name="listener" type="android.media.JetPlayer.JetEventListener"> +<parameter name="listener" type="android.media.JetPlayer.OnJetEventListener"> </parameter> </method> -<method name="setMuteArray" - return="boolean" +<method name="setEventListener" + return="void" abstract="false" native="false" synchronized="false" @@ -65586,12 +65640,12 @@ deprecated="not deprecated" visibility="public" > -<parameter name="muteArray" type="boolean[]"> +<parameter name="listener" type="android.media.JetPlayer.OnJetEventListener"> </parameter> -<parameter name="sync" type="boolean"> +<parameter name="handler" type="android.os.Handler"> </parameter> </method> -<method name="setMuteFlag" +<method name="setMuteArray" return="boolean" abstract="false" native="false" @@ -65601,14 +65655,12 @@ deprecated="not deprecated" visibility="public" > -<parameter name="trackId" type="int"> -</parameter> -<parameter name="muteFlag" type="boolean"> +<parameter name="muteArray" type="boolean[]"> </parameter> <parameter name="sync" type="boolean"> </parameter> </method> -<method name="setMuteFlags" +<method name="setMuteFlag" return="boolean" abstract="false" native="false" @@ -65618,13 +65670,15 @@ deprecated="not deprecated" visibility="public" > -<parameter name="muteFlags" type="int"> +<parameter name="trackId" type="int"> +</parameter> +<parameter name="muteFlag" type="boolean"> </parameter> <parameter name="sync" type="boolean"> </parameter> </method> -<method name="setStatusUpdateListener" - return="void" +<method name="setMuteFlags" + return="boolean" abstract="false" native="false" synchronized="false" @@ -65633,7 +65687,9 @@ deprecated="not deprecated" visibility="public" > -<parameter name="listener" type="android.media.JetPlayer.JetStatusUpdateListener"> +<parameter name="muteFlags" type="int"> +</parameter> +<parameter name="sync" type="boolean"> </parameter> </method> <method name="triggerClip" @@ -65650,7 +65706,7 @@ </parameter> </method> </class> -<interface name="JetPlayer.JetEventListener" +<interface name="JetPlayer.OnJetEventListener" abstract="true" static="true" final="false" @@ -65680,14 +65736,6 @@ <parameter name="value" type="byte"> </parameter> </method> -</interface> -<interface name="JetPlayer.JetStatusUpdateListener" - abstract="true" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> <method name="onJetNumQueuedSegmentUpdate" return="void" abstract="true" @@ -66076,7 +66124,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="l" type="android.media.MediaPlayer.OnBufferingUpdateListener"> +<parameter name="listener" type="android.media.MediaPlayer.OnBufferingUpdateListener"> </parameter> </method> <method name="setOnCompletionListener" @@ -66089,7 +66137,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="l" type="android.media.MediaPlayer.OnCompletionListener"> +<parameter name="listener" type="android.media.MediaPlayer.OnCompletionListener"> </parameter> </method> <method name="setOnErrorListener" @@ -66105,6 +66153,19 @@ <parameter name="listener" type="android.media.MediaPlayer.OnErrorListener"> </parameter> </method> +<method name="setOnInfoListener" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.media.MediaPlayer.OnInfoListener"> +</parameter> +</method> <method name="setOnPreparedListener" return="void" abstract="false" @@ -66115,7 +66176,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="l" type="android.media.MediaPlayer.OnPreparedListener"> +<parameter name="listener" type="android.media.MediaPlayer.OnPreparedListener"> </parameter> </method> <method name="setOnSeekCompleteListener" @@ -66128,7 +66189,20 @@ deprecated="not deprecated" visibility="public" > -<parameter name="l" type="android.media.MediaPlayer.OnSeekCompleteListener"> +<parameter name="listener" type="android.media.MediaPlayer.OnSeekCompleteListener"> +</parameter> +</method> +<method name="setOnVideoSizeChangedListener" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.media.MediaPlayer.OnVideoSizeChangedListener"> </parameter> </method> <method name="setScreenOnWhilePlaying" @@ -66200,6 +66274,17 @@ <exception name="IllegalStateException" type="java.lang.IllegalStateException"> </exception> </method> +<field name="MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK" + type="int" + transient="false" + volatile="false" + value="200" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="MEDIA_ERROR_SERVER_DIED" type="int" transient="false" @@ -66222,6 +66307,50 @@ visibility="public" > </field> +<field name="MEDIA_INFO_BAD_INTERLEAVING" + type="int" + transient="false" + volatile="false" + value="800" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MEDIA_INFO_NOT_SEEKABLE" + type="int" + transient="false" + volatile="false" + value="801" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MEDIA_INFO_UNKNOWN" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MEDIA_INFO_VIDEO_TRACK_LAGGING" + type="int" + transient="false" + volatile="false" + value="700" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> </class> <interface name="MediaPlayer.OnBufferingUpdateListener" abstract="true" @@ -66292,6 +66421,31 @@ </parameter> </method> </interface> +<interface name="MediaPlayer.OnInfoListener" + abstract="true" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="onInfo" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="mp" type="android.media.MediaPlayer"> +</parameter> +<parameter name="what" type="int"> +</parameter> +<parameter name="extra" type="int"> +</parameter> +</method> +</interface> <interface name="MediaPlayer.OnPreparedListener" abstract="true" static="true" @@ -66334,6 +66488,31 @@ </parameter> </method> </interface> +<interface name="MediaPlayer.OnVideoSizeChangedListener" + abstract="true" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="onVideoSizeChanged" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="mp" type="android.media.MediaPlayer"> +</parameter> +<parameter name="width" type="int"> +</parameter> +<parameter name="height" type="int"> +</parameter> +</method> +</interface> <class name="MediaRecorder" extends="java.lang.Object" abstract="false" @@ -66458,6 +66637,21 @@ <exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> </exception> </method> +<method name="setMaxFileSize" + return="void" + abstract="false" + native="true" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="max_filesize_bytes" type="long"> +</parameter> +<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> +</exception> +</method> <method name="setOnErrorListener" return="void" abstract="false" @@ -66652,6 +66846,17 @@ visibility="public" > </field> +<field name="MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED" + type="int" + transient="false" + volatile="false" + value="801" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="MEDIA_RECORDER_INFO_UNKNOWN" type="int" transient="false" @@ -72965,6 +73170,55 @@ <parameter name="debugFlags" type="int"> </parameter> </method> +<method name="setEGLConfigChooser" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="configChooser" type="android.opengl.GLSurfaceView.EGLConfigChooser"> +</parameter> +</method> +<method name="setEGLConfigChooser" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="needDepth" type="boolean"> +</parameter> +</method> +<method name="setEGLConfigChooser" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="redSize" type="int"> +</parameter> +<parameter name="greenSize" type="int"> +</parameter> +<parameter name="blueSize" type="int"> +</parameter> +<parameter name="alphaSize" type="int"> +</parameter> +<parameter name="depthSize" type="int"> +</parameter> +<parameter name="stencilSize" type="int"> +</parameter> +</method> <method name="setGLWrapper" return="void" abstract="false" @@ -73094,15 +73348,15 @@ > </field> </class> -<interface name="GLSurfaceView.GLWrapper" +<interface name="GLSurfaceView.EGLConfigChooser" abstract="true" static="true" final="false" deprecated="not deprecated" visibility="public" > -<method name="wrap" - return="javax.microedition.khronos.opengles.GL" +<method name="chooseConfig" + return="javax.microedition.khronos.egl.EGLConfig" abstract="true" native="false" synchronized="false" @@ -73111,19 +73365,21 @@ deprecated="not deprecated" visibility="public" > -<parameter name="gl" type="javax.microedition.khronos.opengles.GL"> +<parameter name="egl" type="javax.microedition.khronos.egl.EGL10"> +</parameter> +<parameter name="display" type="javax.microedition.khronos.egl.EGLDisplay"> </parameter> </method> </interface> -<interface name="GLSurfaceView.Renderer" +<interface name="GLSurfaceView.GLWrapper" abstract="true" static="true" final="false" deprecated="not deprecated" visibility="public" > -<method name="getConfigSpec" - return="int[]" +<method name="wrap" + return="javax.microedition.khronos.opengles.GL" abstract="true" native="false" synchronized="false" @@ -73132,7 +73388,17 @@ deprecated="not deprecated" visibility="public" > +<parameter name="gl" type="javax.microedition.khronos.opengles.GL"> +</parameter> </method> +</interface> +<interface name="GLSurfaceView.Renderer" + abstract="true" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> <method name="onDrawFrame" return="void" abstract="true" @@ -86064,6 +86330,17 @@ visibility="public" > </field> +<field name="EXTRA_CREATE_DESCRIPTION" + type="java.lang.String" + transient="false" + volatile="false" + value=""com.android.contacts.action.CREATE_DESCRIPTION"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="EXTRA_FORCE_CREATE" type="java.lang.String" transient="false" @@ -101410,6 +101687,19 @@ <parameter name="view" type="android.view.View"> </parameter> </method> +<method name="getSize" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="view" type="android.view.View"> +</parameter> +</method> </class> <class name="BoringLayout" extends="android.text.Layout" @@ -110398,6 +110688,36 @@ deprecated="not deprecated" visibility="public" > +<method name="getInitialScrollX" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="widget" type="android.widget.TextView"> +</parameter> +<parameter name="buffer" type="android.text.Spannable"> +</parameter> +</method> +<method name="getInitialScrollY" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="widget" type="android.widget.TextView"> +</parameter> +<parameter name="buffer" type="android.text.Spannable"> +</parameter> +</method> <method name="onTouchEvent" return="boolean" abstract="false" @@ -118584,10 +118904,6 @@ > <parameter name="origEvent" type="android.view.KeyEvent"> </parameter> -<parameter name="eventTime" type="long"> -</parameter> -<parameter name="newRepeat" type="int"> -</parameter> </constructor> <constructor name="KeyEvent" type="android.view.KeyEvent" @@ -118598,9 +118914,58 @@ > <parameter name="origEvent" type="android.view.KeyEvent"> </parameter> -<parameter name="action" type="int"> +<parameter name="eventTime" type="long"> +</parameter> +<parameter name="newRepeat" type="int"> </parameter> </constructor> +<method name="changeAction" + return="android.view.KeyEvent" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="event" type="android.view.KeyEvent"> +</parameter> +<parameter name="action" type="int"> +</parameter> +</method> +<method name="changeFlags" + return="android.view.KeyEvent" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="event" type="android.view.KeyEvent"> +</parameter> +<parameter name="flags" type="int"> +</parameter> +</method> +<method name="changeTimeRepeat" + return="android.view.KeyEvent" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="event" type="android.view.KeyEvent"> +</parameter> +<parameter name="eventTime" type="long"> +</parameter> +<parameter name="newRepeat" type="int"> +</parameter> +</method> <method name="describeContents" return="int" abstract="false" @@ -118974,6 +119339,28 @@ visibility="public" > </field> +<field name="FLAG_EDITOR_ACTION" + type="int" + transient="false" + volatile="false" + value="16" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FLAG_FROM_SYSTEM" + type="int" + transient="false" + volatile="false" + value="8" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="FLAG_KEEP_TOUCH_MODE" type="int" transient="false" @@ -134912,7 +135299,7 @@ > <parameter name="targetView" type="android.view.View"> </parameter> -<parameter name="dummyMode" type="boolean"> +<parameter name="fullEditor" type="boolean"> </parameter> </constructor> <method name="beginBatchEdit" @@ -135492,6 +135879,17 @@ visibility="public" > </field> +<field name="IME_FLAG_NO_ACCESSORY_ACTION" + type="int" + transient="false" + volatile="false" + value="536870912" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="IME_FLAG_NO_ENTER_ACTION" type="int" transient="false" @@ -135503,6 +135901,17 @@ visibility="public" > </field> +<field name="IME_FLAG_NO_EXTRACT_UI" + type="int" + transient="false" + volatile="false" + value="268435456" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="IME_MASK_ACTION" type="int" transient="false" @@ -136320,6 +136729,8 @@ > <parameter name="target" type="android.view.inputmethod.InputConnection"> </parameter> +<parameter name="mutable" type="boolean"> +</parameter> </constructor> <method name="beginBatchEdit" return="boolean" @@ -136565,6 +136976,19 @@ <parameter name="end" type="int"> </parameter> </method> +<method name="setTarget" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="target" type="android.view.inputmethod.InputConnection"> +</parameter> +</method> </class> <interface name="InputMethod" abstract="true" @@ -139954,6 +140378,17 @@ visibility="public" > </method> +<method name="getBuiltInZoomControls" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getCacheMode" return="int" abstract="false" @@ -140277,6 +140712,19 @@ <parameter name="flag" type="boolean"> </parameter> </method> +<method name="setBuiltInZoomControls" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="enabled" type="boolean"> +</parameter> +</method> <method name="setCacheMode" return="void" abstract="false" @@ -141408,7 +141856,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -146094,7 +146542,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -146138,7 +146586,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -146151,7 +146599,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -157030,6 +157478,17 @@ visibility="public" > </method> +<method name="moveCursorToVisibleOffset" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="onBeginBatchEdit" return="void" abstract="false" diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk index 2dfe659..96cc512 100644 --- a/camera/libcameraservice/Android.mk +++ b/camera/libcameraservice/Android.mk @@ -42,7 +42,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES:= \ libui \ libutils \ - libcutils + libcutils \ + libmedia LOCAL_MODULE:= libcameraservice diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index 15e3b21..cb8ab58 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -28,8 +28,12 @@ #include <utils/MemoryHeapBase.h> #include <ui/ICameraService.h> +#include <media/mediaplayer.h> +#include <media/AudioSystem.h> #include "CameraService.h" +#include <cutils/properties.h> + namespace android { extern "C" { @@ -151,6 +155,25 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) } } +static sp<MediaPlayer> newMediaPlayer(const char *file) +{ + sp<MediaPlayer> mp = new MediaPlayer(); + if (mp->setDataSource(file) == NO_ERROR) { + char value[PROPERTY_VALUE_MAX]; + property_get("ro.camera.sound.forced", value, "0"); + if (atoi(value)) { + mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE); + } else { + mp->setAudioStreamType(AudioSystem::SYSTEM); + } + mp->prepare(); + } else { + mp.clear(); + LOGE("Failed to load CameraService sounds."); + } + return mp; +} + CameraService::Client::Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, pid_t clientPid) { @@ -161,6 +184,9 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, mHardware = openCameraHardware(); mUseOverlay = mHardware->useOverlay(); + mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg"); + mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg"); + // Callback is disabled by default mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; LOGD("Client X constructor"); @@ -265,6 +291,15 @@ CameraService::Client::~Client() #endif } + if (mMediaPlayerBeep.get() != NULL) { + mMediaPlayerBeep->disconnect(); + mMediaPlayerBeep.clear(); + } + if (mMediaPlayerClick.get() != NULL) { + mMediaPlayerClick->disconnect(); + mMediaPlayerClick.clear(); + } + // make sure we tear down the hardware mClientPid = IPCThreadState::self()->getCallingPid(); disconnect(); @@ -464,6 +499,10 @@ status_t CameraService::Client::startPreview() status_t CameraService::Client::startRecording() { + if (mMediaPlayerBeep.get() != NULL) { + mMediaPlayerBeep->seekTo(0); + mMediaPlayerBeep->start(); + } return startCameraMode(CAMERA_RECORDING_MODE); } @@ -502,6 +541,10 @@ void CameraService::Client::stopRecording() return; } + if (mMediaPlayerBeep.get() != NULL) { + mMediaPlayerBeep->seekTo(0); + mMediaPlayerBeep->start(); + } mHardware->stopRecording(); LOGV("stopRecording(), hardware stopped OK"); mPreviewBuffer.clear(); @@ -698,6 +741,12 @@ void CameraService::Client::shutterCallback(void *user) return; } + // Play shutter sound. + if (client->mMediaPlayerClick.get() != NULL) { + client->mMediaPlayerClick->seekTo(0); + client->mMediaPlayerClick->start(); + } + // Screen goes black after the buffer is unregistered. if (client->mSurface != 0 && !client->mUseOverlay) { client->mSurface->unregisterBuffers(); diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index d9b7927..6752f26 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -27,6 +27,8 @@ class android::MemoryHeapBase; namespace android { +class MediaPlayer; + // ---------------------------------------------------------------------------- #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) @@ -178,6 +180,9 @@ private: sp<MemoryHeapBase> mPreviewBuffer; int mPreviewCallbackFlag; + sp<MediaPlayer> mMediaPlayerClick; + sp<MediaPlayer> mMediaPlayerBeep; + // these are immutable once the object is created, // they don't need to be protected by a lock sp<ICameraClient> mCameraClient; diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index c2d8da5..161bb46 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -528,8 +528,14 @@ public final class Pm { case PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY: s = "INSTALL_FAILED_MISSING_SHARED_LIBRARY"; break; - case PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE: - s = "INSTALL_FAILED_REPLACE_COULDNT_DELETE"; + case PackageManager.INSTALL_FAILED_DEXOPT: + s = "INSTALL_FAILED_DEXOPT"; + break; + case PackageManager.INSTALL_FAILED_OLDER_SDK: + s = "INSTALL_FAILED_OLDER_SDK"; + break; + case PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER: + s = "INSTALL_FAILED_CONFLICTING_PROVIDER"; break; case PackageManager.INSTALL_PARSE_FAILED_NOT_APK: s = "INSTALL_PARSE_FAILED_NOT_APK"; @@ -561,9 +567,6 @@ public final class Pm { case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY: s = "INSTALL_PARSE_FAILED_MANIFEST_EMPTY"; break; - case PackageManager.INSTALL_FAILED_OLDER_SDK: - s = "INSTALL_FAILED_OLDER_SDK"; - break; default: s = Integer.toString(result); break; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f49005e..d816193 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -114,6 +114,7 @@ public final class ActivityThread { private static final boolean DEBUG = false; private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; private static final boolean DEBUG_BROADCAST = false; + private static final boolean DEBUG_RESULTS = false; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; @@ -2118,6 +2119,8 @@ public final class ActivityThread { public final void sendActivityResult( IBinder token, String id, int requestCode, int resultCode, Intent data) { + if (DEBUG_RESULTS) Log.v(TAG, "sendActivityResult: id=" + id + + " req=" + requestCode + " res=" + resultCode + " data=" + data); ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); list.add(new ResultInfo(id, requestCode, resultCode, data)); mAppThread.scheduleSendResult(token, list); @@ -2993,6 +2996,8 @@ public final class ActivityThread { if (ri.mData != null) { ri.mData.setExtrasClassLoader(r.activity.getClassLoader()); } + if (DEBUG_RESULTS) Log.v(TAG, + "Delivering result to activity " + r + " : " + ri); r.activity.dispatchActivityResult(ri.mResultWho, ri.mRequestCode, ri.mResultCode, ri.mData); } catch (Exception e) { @@ -3008,7 +3013,7 @@ public final class ActivityThread { private final void handleSendResult(ResultData res) { ActivityRecord r = mActivities.get(res.token); - if (localLOGV) Log.v(TAG, "Handling send result to " + r); + if (DEBUG_RESULTS) Log.v(TAG, "Handling send result to " + r); if (r != null) { final boolean resumed = !r.paused; if (!r.activity.mFinished && r.activity.mDecor != null @@ -3250,8 +3255,21 @@ public final class ActivityThread { r.window = null; r.hideForNow = false; r.nextIdle = null; - r.pendingResults = tmp.pendingResults; - r.pendingIntents = tmp.pendingIntents; + // Merge any pending results and pending intents; don't just replace them + if (tmp.pendingResults != null) { + if (r.pendingResults == null) { + r.pendingResults = tmp.pendingResults; + } else { + r.pendingResults.addAll(tmp.pendingResults); + } + } + if (tmp.pendingIntents != null) { + if (r.pendingIntents == null) { + r.pendingIntents = tmp.pendingIntents; + } else { + r.pendingIntents.addAll(tmp.pendingIntents); + } + } r.startsNotResumed = tmp.startsNotResumed; if (savedState != null) { r.state = savedState; @@ -3469,9 +3487,11 @@ public final class ActivityThread { callbacks.get(i).onLowMemory(); } - // Ask SQLite to free up as much memory as it can, mostly from it's page caches - int sqliteReleased = SQLiteDatabase.releaseMemory(); - EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); + // Ask SQLite to free up as much memory as it can, mostly from its page caches. + if (Process.myUid() != Process.SYSTEM_UID) { + int sqliteReleased = SQLiteDatabase.releaseMemory(); + EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); + } BinderInternal.forceGc("mem"); } diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java index f2b89c3..021dc2e 100644 --- a/core/java/android/app/AlertDialog.java +++ b/core/java/android/app/AlertDialog.java @@ -763,7 +763,16 @@ public class AlertDialog extends Dialog implements DialogInterface { P.mForceInverseBackground = useInverseBackground; return this; } - + + /** + * @hide + */ + public Builder setRecycleOnMeasureEnabled(boolean enabled) { + P.mRecycleOnMeasure = enabled; + return this; + } + + /** * Creates a {@link AlertDialog} with the arguments supplied to this builder. It does not * {@link Dialog#show()} the dialog. This allows the user to do any extra processing diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 3b5ad86..55fce49 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -103,6 +103,9 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.WeakHashMap; +import java.util.Set; +import java.util.HashSet; import java.util.Map.Entry; import org.xmlpull.v1.XmlPullParserException; @@ -2476,7 +2479,8 @@ class ApplicationContext extends Context { private final FileStatus mFileStatus = new FileStatus(); private long mTimestamp; - private List<OnSharedPreferenceChangeListener> mListeners; + private static final Object mContent = new Object(); + private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners; SharedPreferencesImpl( File file, int mode, Map initialContents) { @@ -2487,7 +2491,7 @@ class ApplicationContext extends Context { if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) { mTimestamp = mFileStatus.mtime; } - mListeners = new ArrayList<OnSharedPreferenceChangeListener>(); + mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>(); } public boolean hasFileChanged() { @@ -2509,9 +2513,7 @@ class ApplicationContext extends Context { public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { synchronized(this) { - if (!mListeners.contains(listener)) { - mListeners.add(listener); - } + mListeners.put(listener, mContent); } } @@ -2620,13 +2622,14 @@ class ApplicationContext extends Context { boolean hasListeners; List<String> keysModified = null; - List<OnSharedPreferenceChangeListener> listeners = null; + Set<OnSharedPreferenceChangeListener> listeners = null; synchronized (SharedPreferencesImpl.this) { hasListeners = mListeners.size() > 0; if (hasListeners) { keysModified = new ArrayList<String>(); - listeners = new ArrayList<OnSharedPreferenceChangeListener>(mListeners); + listeners = + new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet()); } synchronized (this) { @@ -2635,9 +2638,7 @@ class ApplicationContext extends Context { mClear = false; } - Iterator<Entry<String, Object>> it = mModified.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<String, Object> e = it.next(); + for (Entry<String, Object> e : mModified.entrySet()) { String k = e.getKey(); Object v = e.getValue(); if (v == this) { @@ -2660,10 +2661,10 @@ class ApplicationContext extends Context { if (hasListeners) { for (int i = keysModified.size() - 1; i >= 0; i--) { final String key = keysModified.get(i); - // Call in the order they were registered - final int listenersSize = listeners.size(); - for (int j = 0; j < listenersSize; j++) { - listeners.get(j).onSharedPreferenceChanged(SharedPreferencesImpl.this, key); + for (OnSharedPreferenceChangeListener listener : listeners) { + if (listener != null) { + listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key); + } } } } @@ -2722,10 +2723,8 @@ class ApplicationContext extends Context { mTimestamp = mFileStatus.mtime; } - // Writing was successful, delete the backup file - if (!mBackupFile.delete()) { - Log.e(TAG, "Couldn't delete new backup file " + mBackupFile); - } + // Writing was successful, delete the backup file if there is one. + mBackupFile.delete(); return true; } catch (XmlPullParserException e) { Log.w(TAG, "writeFileLocked: Got exception:", e); diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java index ee5e0d5..863cbcc 100644 --- a/core/java/android/app/DatePickerDialog.java +++ b/core/java/android/app/DatePickerDialog.java @@ -47,6 +47,7 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener, private final OnDateSetListener mCallBack; private final Calendar mCalendar; private final java.text.DateFormat mDateFormat; + private final java.text.DateFormat mTitleDateFormat; private final String[] mWeekDays; private int mInitialYear; @@ -108,6 +109,8 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener, mWeekDays = symbols.getShortWeekdays(); mDateFormat = DateFormat.getMediumDateFormat(context); + mTitleDateFormat = java.text.DateFormat. + getDateInstance(java.text.DateFormat.FULL); mCalendar = Calendar.getInstance(); updateTitle(mInitialYear, mInitialMonth, mInitialDay); @@ -126,7 +129,7 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener, @Override public void show() { super.show(); - + /* Sometimes the full month is displayed causing the title * to be very long, in those cases ensure it doesn't wrap to * 2 lines (as that looks jumpy) and ensure we ellipsize the end. @@ -160,8 +163,7 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener, mCalendar.set(Calendar.YEAR, year); mCalendar.set(Calendar.MONTH, month); mCalendar.set(Calendar.DAY_OF_MONTH, day); - String weekday = mWeekDays[mCalendar.get(Calendar.DAY_OF_WEEK)]; - setTitle(weekday + ", " + mDateFormat.format(mCalendar.getTime())); + setTitle(mTitleDateFormat.format(mCalendar.getTime())); } @Override diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java index d6fcbb1..8d249da 100644 --- a/core/java/android/app/LauncherActivity.java +++ b/core/java/android/app/LauncherActivity.java @@ -65,6 +65,7 @@ public abstract class LauncherActivity extends ListActivity { public Drawable icon; public String packageName; public String className; + public Bundle extras; ListItem(PackageManager pm, ResolveInfo resolveInfo, IconResizer resizer) { label = resolveInfo.loadLabel(pm); @@ -115,6 +116,9 @@ public abstract class LauncherActivity extends ListActivity { Intent intent = new Intent(mIntent); ListItem item = mActivitiesList.get(position); intent.setClassName(item.packageName, item.className); + if (item.extras != null) { + intent.putExtras(item.extras); + } return intent; } diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 64288d2..a0cdb63 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -49,6 +49,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AutoCompleteTextView; import android.widget.Button; @@ -922,6 +923,20 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } }; + @Override + public void cancel() { + // We made sure the IME was displayed, so also make sure it is closed + // when we go away. + InputMethodManager imm = (InputMethodManager)getContext() + .getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.hideSoftInputFromWindow( + getWindow().getDecorView().getWindowToken(), 0); + } + + super.cancel(); + } + /** * Various ways to launch searches */ diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index a6a436f..d2fb605 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -278,11 +278,11 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac } /** - * Stop the service, if the most recent time it was started was + * Stop the service if the most recent time it was started was * <var>startId</var>. This is the same as calling {@link * android.content.Context#stopService} for this particular service but allows you to * safely avoid stopping if there is a start request from a client that you - * haven't yet see in {@link #onStart}. + * haven't yet seen in {@link #onStart}. * * @param startId The most recent start identifier received in {@link * #onStart}. diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 3b10ed2..eca04b3 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -109,6 +109,23 @@ public class AppWidgetManager { public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds"; /** + * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of + * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are + * installed. (This is how the launcher shows the search widget). + */ + public static final String EXTRA_CUSTOM_INFO = "customInfo"; + + /** + * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of + * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are + * installed. It will be added to the extras object on the {@link android.content.Intent} + * that is returned from the picker activity. + * + * {@more} + */ + public static final String EXTRA_CUSTOM_EXTRAS = "customExtras"; + + /** * A sentiel value that the AppWidget manager will never return as a appWidgetId. */ public static final int INVALID_APPWIDGET_ID = 0; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 1ba1c1e..abf08cb 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -31,6 +31,12 @@ import java.io.UnsupportedEncodingException; * @hide */ public class BluetoothDevice { + + public static final int BLUETOOTH_STATE_OFF = 0; + public static final int BLUETOOTH_STATE_TURNING_ON = 1; + public static final int BLUETOOTH_STATE_ON = 2; + public static final int BLUETOOTH_STATE_TURNING_OFF = 3; + /** Inquiry scan and page scan are both off. * Device is neither discoverable nor connectable */ public static final int SCAN_MODE_NONE = 0; @@ -83,7 +89,7 @@ public class BluetoothDevice { } /** - * Get the current status of Bluetooth hardware. + * Is Bluetooth currently turned on. * * @return true if Bluetooth enabled, false otherwise. */ @@ -95,37 +101,30 @@ public class BluetoothDevice { } /** + * Get the current state of Bluetooth. + * + * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR. + */ + public int getBluetoothState() { + try { + return mService.getBluetoothState(); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return BluetoothError.ERROR; + } + + /** * Enable the Bluetooth device. * Turn on the underlying hardware. - * This is an asynchronous call, BluetoothIntent.ENABLED_ACTION will be - * sent if and when the device is successfully enabled. + * This is an asynchronous call, + * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if + * and when the device is sucessfully enabled. * @return false if we cannot enable the Bluetooth device. True does not * imply the device was enabled, it only implies that so far there were no * problems. */ public boolean enable() { - return enable(null); - } - - /** - * Enable the Bluetooth device. - * Turns on the underlying hardware. - * This is an asynchronous call. onEnableResult() of your callback will be - * called when the call is complete, with either RESULT_SUCCESS or - * RESULT_FAILURE. - * - * Your callback will be called from a binder thread, not the main thread. - * - * In addition to the callback, BluetoothIntent.ENABLED_ACTION will be - * broadcast if the device is successfully enabled. - * - * @param callback Your callback, null is ok. - * @return true if your callback was successfully registered, or false if - * there was an error, implying your callback will never be called. - */ - public boolean enable(IBluetoothDeviceCallback callback) { try { - return mService.enable(callback); + return mService.enable(); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -138,7 +137,7 @@ public class BluetoothDevice { */ public boolean disable() { try { - return mService.disable(); + return mService.disable(true); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -551,7 +550,6 @@ public class BluetoothDevice { } return pinBytes; } - private static final int ADDRESS_LENGTH = 17; /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */ diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 1dbe0cc..e198435 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -82,6 +82,12 @@ public class BluetoothHeadset { /** Default priority for headsets that should not be auto-connected */ public static final int PRIORITY_OFF = 0; + /** The voice dialer 'works' but the user experience is poor. The voice + * recognizer has trouble dealing with the 8kHz SCO signal, and it still + * requires visual confirmation. Disable for cupcake. + */ + public static final boolean DISABLE_BT_VOICE_DIALING = true; + /** * An interface for notifying BluetoothHeadset IPC clients when they have * been connected to the BluetoothHeadset service. diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java index 9273d0d..344601b 100644 --- a/core/java/android/bluetooth/BluetoothIntent.java +++ b/core/java/android/bluetooth/BluetoothIntent.java @@ -41,6 +41,10 @@ public interface BluetoothIntent { "android.bluetooth.intent.RSSI"; public static final String CLASS = "android.bluetooth.intent.CLASS"; + public static final String BLUETOOTH_STATE = + "android.bluetooth.intent.BLUETOOTH_STATE"; + public static final String BLUETOOTH_PREVIOUS_STATE = + "android.bluetooth.intent.BLUETOOTH_PREVIOUS_STATE"; public static final String HEADSET_STATE = "android.bluetooth.intent.HEADSET_STATE"; public static final String HEADSET_PREVIOUS_STATE = @@ -54,12 +58,12 @@ public interface BluetoothIntent { public static final String REASON = "android.bluetooth.intent.REASON"; + /** Broadcast when the local Bluetooth device state changes, for example + * when Bluetooth is enabled. Will contain int extra's BLUETOOTH_STATE and + * BLUETOOTH_PREVIOUS_STATE. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ENABLED_ACTION = - "android.bluetooth.intent.action.ENABLED"; - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String DISABLED_ACTION = - "android.bluetooth.intent.action.DISABLED"; + public static final String BLUETOOTH_STATE_CHANGED_ACTION = + "android.bluetooth.intent.action.BLUETOOTH_STATE_CHANGED"; @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String NAME_CHANGED_ACTION = diff --git a/core/java/android/bluetooth/HeadsetBase.java b/core/java/android/bluetooth/HeadsetBase.java index fd2d2ab..f31e7a2 100644 --- a/core/java/android/bluetooth/HeadsetBase.java +++ b/core/java/android/bluetooth/HeadsetBase.java @@ -105,7 +105,7 @@ public class HeadsetBase { /* Process an incoming AT command line */ - protected synchronized void handleInput(String input) { + protected void handleInput(String input) { acquireWakeLock(); long timestamp; @@ -267,13 +267,13 @@ public class HeadsetBase { } private native boolean sendURCNative(String urc); - private void acquireWakeLock() { + private synchronized void acquireWakeLock() { if (!mWakeLock.isHeld()) { mWakeLock.acquire(); } } - private void releaseWakeLock() { + private synchronized void releaseWakeLock() { if (mWakeLock.isHeld()) { mWakeLock.release(); } diff --git a/core/java/android/bluetooth/IBluetoothDevice.aidl b/core/java/android/bluetooth/IBluetoothDevice.aidl index 4351d2e..6cd792e 100644 --- a/core/java/android/bluetooth/IBluetoothDevice.aidl +++ b/core/java/android/bluetooth/IBluetoothDevice.aidl @@ -26,8 +26,9 @@ import android.bluetooth.IBluetoothDeviceCallback; interface IBluetoothDevice { boolean isEnabled(); - boolean enable(in IBluetoothDeviceCallback callback); // async - boolean disable(); + int getBluetoothState(); + boolean enable(); + boolean disable(boolean persistSetting); String getAddress(); String getName(); diff --git a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl index d25bd56..d057093 100644 --- a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl @@ -22,6 +22,4 @@ package android.bluetooth; oneway interface IBluetoothDeviceCallback { void onGetRemoteServiceChannelResult(in String address, int channel); - - void onEnableResult(int result); } diff --git a/core/java/android/bluetooth/ScoSocket.java b/core/java/android/bluetooth/ScoSocket.java index a43a08b..1bf786f 100644 --- a/core/java/android/bluetooth/ScoSocket.java +++ b/core/java/android/bluetooth/ScoSocket.java @@ -76,7 +76,7 @@ public class ScoSocket { try { if (VDBG) log(this + " SCO OBJECT DTOR"); destroyNative(); - releaseWakeLock(); + releaseWakeLockNow(); } finally { super.finalize(); } @@ -98,7 +98,7 @@ public class ScoSocket { return true; } else { mState = STATE_CLOSED; - releaseWakeLock(); + releaseWakeLockNow(); return false; } } @@ -148,7 +148,7 @@ public class ScoSocket { mState = STATE_CLOSED; } mHandler.obtainMessage(mConnectedCode, mState, -1, this).sendToTarget(); - releaseWakeLock(); + releaseWakeLockNow(); } private synchronized void onAccepted(int result) { @@ -183,7 +183,19 @@ public class ScoSocket { private void releaseWakeLock() { if (mWakeLock.isHeld()) { - if (VDBG) log("mWakeLock.release() " + this); + // Keep apps processor awake for a further 2 seconds. + // This is a hack to resolve issue http://b/1616263 - in which + // we are left in a 80 mA power state when remotely terminating a + // call while connected to BT headset "HTC BH S100 " with A2DP and + // HFP profiles. + if (VDBG) log("mWakeLock.release() in 2 sec" + this); + mWakeLock.acquire(2000); + } + } + + private void releaseWakeLockNow() { + if (mWakeLock.isHeld()) { + if (VDBG) log("mWakeLock.release() now" + this); mWakeLock.release(); } } diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java index 08f6191..a41627a 100644 --- a/core/java/android/content/BroadcastReceiver.java +++ b/core/java/android/content/BroadcastReceiver.java @@ -68,7 +68,7 @@ import android.util.Log; * these broadcasts, the Intent broadcast mechanism here is completely separate * from Intents that are used to start Activities with * {@link Context#startActivity Context.startActivity()}. - * There is no way for an BroadcastReceiver + * There is no way for a BroadcastReceiver * to see or capture Intents used with startActivity(); likewise, when * you broadcast an Intent, you will never find or start an Activity. * These two operations are semantically very different: starting an @@ -103,7 +103,7 @@ import android.util.Log; * its process before the asynchronous operation completes. * * <p>In particular, you may <i>not</i> show a dialog or bind to a service from - * within an BroadcastReceiver. For the former, you should instead use the + * within a BroadcastReceiver. For the former, you should instead use the * {@link android.app.NotificationManager} API. For the latter, you can * use {@link android.content.Context#startService Context.startService()} to * send a command to the service. @@ -141,7 +141,7 @@ import android.util.Log; * <a name="ProcessLifecycle"></a> * <h3>Process Lifecycle</h3> * - * <p>A process that is currently executing an BroadcastReceiver (that is, + * <p>A process that is currently executing a BroadcastReceiver (that is, * currently running the code in its {@link #onReceive} method) is * considered to be a foreground process and will be kept running by the * system except under cases of extreme memory pressure. @@ -156,7 +156,7 @@ import android.util.Log; * more important processes. * * <p>This means that for longer-running operations you will often use - * a {@link android.app.Service} in conjunction with an BroadcastReceiver to keep + * an {@link android.app.Service} in conjunction with a BroadcastReceiver to keep * the containing process active for the entire time of your operation. */ public abstract class BroadcastReceiver { diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 25544de..5cc5730 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -172,7 +172,8 @@ public abstract class ContentProvider implements ComponentCallbacks { public ISyncAdapter getSyncAdapter() { checkWritePermission(null); - return ContentProvider.this.getSyncAdapter().getISyncAdapter(); + SyncAdapter sa = ContentProvider.this.getSyncAdapter(); + return sa != null ? sa.getISyncAdapter() : null; } private void checkReadPermission(Uri uri) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index c47b72f..d320c4b 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -969,6 +969,15 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SEARCH = "android.intent.action.SEARCH"; /** + * Activity Action: Start the platform-defined tutorial + * <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)} + * is the text to search for. If empty, simply + * enter your search results Activity with the search UI activated. + * <p>Output: nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL"; + /** * Activity Action: Perform a web search. * <p> * Input: {@link android.app.SearchManager#QUERY @@ -1037,7 +1046,7 @@ public class Intent implements Parcelable { */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS"; - + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent broadcast actions (see action variable). @@ -1054,7 +1063,7 @@ public class Intent implements Parcelable { public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON"; /** - * Broadcast Action: Sent when the user is present after device wakes up (e.g when the + * Broadcast Action: Sent when the user is present after device wakes up (e.g when the * keyguard is gone). */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @@ -1127,7 +1136,8 @@ public class Intent implements Parcelable { public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL"; /** * Broadcast Action: A new application package has been installed on the - * device. The data contains the name of the package. + * device. The data contains the name of the package. Note that the + * newly installed package does <em>not</em> receive this broadcast. * <p>My include the following extras: * <ul> * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package. @@ -1138,6 +1148,17 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED"; /** + * Broadcast Action: A new version of an application package has been + * installed, replacing an existing version that was previously installed. + * The data contains the name of the package. + * <p>My include the following extras: + * <ul> + * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package. + * </ul> + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED"; + /** * Broadcast Action: An existing application package has been removed from * the device. The data contains the name of the package. The package * that is being installed does <em>not</em> receive this Intent. @@ -1165,7 +1186,9 @@ public class Intent implements Parcelable { * Broadcast Action: The user has restarted a package, and all of its * processes have been killed. All runtime state * associated with it (processes, alarms, notifications, etc) should - * be removed. The data contains the name of the package. + * be removed. Note that the restarted package does <em>not</em> + * receive this broadcast. + * The data contains the name of the package. * <ul> * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. * </ul> @@ -1175,8 +1198,9 @@ public class Intent implements Parcelable { /** * Broadcast Action: The user has cleared the data of a package. This should * be preceded by {@link #ACTION_PACKAGE_RESTARTED}, after which all of - * its persistent data is erased and this broadcast sent. The data contains - * the name of the package. + * its persistent data is erased and this broadcast sent. + * Note that the cleared package does <em>not</em> + * receive this broadcast. The data contains the name of the package. * <ul> * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. * </ul> @@ -1212,7 +1236,7 @@ public class Intent implements Parcelable { /** * Broadcast Action: The charging state, or charge level of the battery has * changed. - * + * * <p class="note"> * You can <em>not</em> receive this through components declared * in manifests, only by exlicitly registering for it with @@ -1401,7 +1425,7 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_GTALK_SERVICE_DISCONNECTED = "android.intent.action.GTALK_DISCONNECTED"; - + /** * Broadcast Action: An input method has been changed. * {@hide pending API Council approval} @@ -1471,12 +1495,12 @@ public class Intent implements Parcelable { * * <p>The Intent will have the following extra value: * <ul> - * <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> - + * <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> - * the phone number originally intended to be dialed.</li> * </ul> * <p>Once the broadcast is finished, the resultData is used as the actual * number to call. If <code>null</code>, no call will be placed.</p> - * <p>It is perfectly acceptable for multiple receivers to process the + * <p>It is perfectly acceptable for multiple receivers to process the * outgoing call in turn: for example, a parental control application * might verify that the user is authorized to place the call at that * time, then a number-rewriting application might add an area code if @@ -1484,7 +1508,7 @@ public class Intent implements Parcelable { * <p>For consistency, any receiver whose purpose is to prohibit phone * calls should have a priority of 0, to ensure it will see the final * phone number to be dialed. - * Any receiver whose purpose is to rewrite phone numbers to be called + * Any receiver whose purpose is to rewrite phone numbers to be called * should have a positive priority. * Negative priorities are reserved for the system for this broadcast; * using them may cause problems.</p> @@ -1493,7 +1517,7 @@ public class Intent implements Parcelable { * <p>Emergency calls cannot be intercepted using this mechanism, and * other calls cannot be modified to call emergency numbers using this * mechanism. - * <p>You must hold the + * <p>You must hold the * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS} * permission to receive this Intent.</p> */ @@ -1730,7 +1754,7 @@ public class Intent implements Parcelable { * implying that this is an update). */ public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED"; - + /** * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} * intents to indicate that this is a replacement of the package, so this @@ -1738,7 +1762,7 @@ public class Intent implements Parcelable { * different version of the same package. */ public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING"; - + /** * Used as an int extra field in {@link android.app.AlarmManager} intents * to tell the application being invoked how many pending alarms are being @@ -1749,15 +1773,6 @@ public class Intent implements Parcelable { */ public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT"; - /** - * Used as an int extra field in {@link android.content.Intent#ACTION_VOICE_COMMAND} - * intents to request which audio route the voice command should prefer. - * The value should be a route from {@link android.media.AudioManager}, for - * example ROUTE_BLUETOOTH_SCO. Providing this value is optional. - * {@hide pending API Council approval} - */ - public static final String EXTRA_AUDIO_ROUTE = "android.intent.extra.AUDIO_ROUTE"; - // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). @@ -1802,7 +1817,7 @@ public class Intent implements Parcelable { * next task activity) defines an atomic group of activities that the * user can move to. Tasks can be moved to the foreground and background; * all of the activities inside of a particular task always remain in - * the same order. See + * the same order. See * <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals: * Activities and Tasks</a> for more details on tasks. * @@ -1833,7 +1848,7 @@ public class Intent implements Parcelable { * <p><strong>Because the default system does not include graphical task management, * you should not use this flag unless you provide some way for a user to * return back to the tasks you have launched.</strong> - * + * * <p>This flag is ignored if * {@link #FLAG_ACTIVITY_NEW_TASK} is not set. * @@ -1922,7 +1937,7 @@ public class Intent implements Parcelable { * the user re-launching it from home), this activity and all on top of * it will be finished so that the user does not return to them, but * instead returns to whatever activity preceeded it. - * + * * <p>This is useful for cases where you have a logical break in your * application. For example, an e-mail application may have a command * to view an attachment, which launches an image view activity to @@ -1940,31 +1955,31 @@ public class Intent implements Parcelable { * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint} * callback from occurring on the current frontmost activity before it is * paused as the newly-started activity is brought to the front. - * + * * <p>Typically, an activity can rely on that callback to indicate that an * explicit user action has caused their activity to be moved out of the * foreground. The callback marks an appropriate point in the activity's * lifecycle for it to dismiss any notifications that it intends to display * "until the user has seen them," such as a blinking LED. - * + * * <p>If an activity is ever started via any non-user-driven events such as * phone-call receipt or an alarm handler, this flag should be passed to {@link * Context#startActivity Context.startActivity}, ensuring that the pausing - * activity does not think the user has acknowledged its notification. + * activity does not think the user has acknowledged its notification. */ public static final int FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000; /** * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, * this flag will cause the launched activity to be brought to the front of its * task's history stack if it is already running. - * + * * <p>For example, consider a task consisting of four activities: A, B, C, D. * If D calls startActivity() with an Intent that resolves to the component * of activity B, then B will be brought to the front of the history stack, * with this resulting order: A, C, D, B. - * + * * This flag will be ignored if {@link #FLAG_ACTIVITY_CLEAR_TOP} is also - * specified. + * specified. */ public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 0X00020000; /** @@ -1978,11 +1993,11 @@ public class Intent implements Parcelable { * will be launched. Sticky intent state will be recorded properly even * if no receivers wind up being called. If {@link #FLAG_RECEIVER_REGISTERED_ONLY} * is specified in the broadcast intent, this flag is unnecessary. - * + * * <p>This flag is only for use by system sevices as a convenience to * avoid having to implement a more complex mechanism around detection * of boot completion. - * + * * @hide */ public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000; @@ -2142,7 +2157,7 @@ public class Intent implements Parcelable { // old format Intent URI if (!uri.startsWith("#Intent;", i)) return getIntentOld(uri); - + // new format Intent intent = new Intent(ACTION_VIEW); @@ -2151,7 +2166,7 @@ public class Intent implements Parcelable { intent.mData = Uri.parse(uri.substring(0, i)); } i += "#Intent;".length(); - + // loop over contents of Intent, all name=value; while (!uri.startsWith("end", i)) { int eq = uri.indexOf('=', i); @@ -2182,7 +2197,7 @@ public class Intent implements Parcelable { else if (uri.startsWith("component=", i)) { intent.mComponent = ComponentName.unflattenFromString(value); } - + // extra else { String key = Uri.decode(uri.substring(i + 2, eq)); @@ -2202,18 +2217,18 @@ public class Intent implements Parcelable { else if (uri.startsWith("s.", i)) b.putShort(key, Short.parseShort(value)); else throw new URISyntaxException(uri, "unknown EXTRA type", i); } - + // move to the next item i = semi + 1; } return intent; - + } catch (IndexOutOfBoundsException e) { throw new URISyntaxException(uri, "illegal Intent URI format", i); } } - + public static Intent getIntentOld(String uri) throws URISyntaxException { Intent intent; @@ -2278,7 +2293,7 @@ public class Intent implements Parcelable { if (uri.regionMatches(i, "extras(", 0, 7)) { i += 7; - + final int closeParen = uri.indexOf(')', i); if (closeParen == -1) throw new URISyntaxException(uri, "EXTRA missing trailing ')'", i); @@ -2293,7 +2308,7 @@ public class Intent implements Parcelable { i++; String key = uri.substring(i, j); i = j + 1; - + // get type-value j = uri.indexOf('!', i); if (j == -1 || j >= closeParen) j = closeParen; @@ -2303,7 +2318,7 @@ public class Intent implements Parcelable { // create Bundle if it doesn't already exist if (intent.mExtras == null) intent.mExtras = new Bundle(); - + // add item to bundle try { switch (type) { @@ -2340,7 +2355,7 @@ public class Intent implements Parcelable { } catch (NumberFormatException e) { throw new URISyntaxException(uri, "EXTRA value can't be parsed", i); } - + char ch = uri.charAt(i); if (ch == ')') break; if (ch != '!') throw new URISyntaxException(uri, "EXTRA missing '!'", i); @@ -2543,7 +2558,7 @@ public class Intent implements Parcelable { public boolean hasFileDescriptors() { return mExtras != null && mExtras.hasFileDescriptors(); } - + /** * Retrieve extended data from the intent. * @@ -3910,7 +3925,7 @@ public class Intent implements Parcelable { /** * Completely replace the extras in the Intent with the extras in the * given Intent. - * + * * @param src The exact extras contained in this Intent are copied * into the target intent, replacing any that were previously there. */ @@ -3918,11 +3933,11 @@ public class Intent implements Parcelable { mExtras = src.mExtras != null ? new Bundle(src.mExtras) : null; return this; } - + /** * Completely replace the extras in the Intent with the given Bundle of * extras. - * + * * @param extras The new set of extras in the Intent, or null to erase * all extras. */ @@ -3930,7 +3945,7 @@ public class Intent implements Parcelable { mExtras = extras != null ? new Bundle(extras) : null; return this; } - + /** * Remove extended data from the intent. * @@ -4418,12 +4433,12 @@ public class Intent implements Parcelable { } } } - + uri.append("end"); return uri.toString(); } - + public int describeContents() { return (mExtras != null) ? mExtras.describeContents() : 0; } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 7287d9c..3e94734 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -341,6 +341,14 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_OLDER_SDK = -12; /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package failed because it contains a content provider with the + * same authority as a provider already installed in the system. + */ + public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13; + + /** * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser was given a path that is not a file, or does not end with the expected diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java index 389bd07..e0b12ae 100644 --- a/core/java/android/emoji/EmojiFactory.java +++ b/core/java/android/emoji/EmojiFactory.java @@ -253,6 +253,22 @@ public final class EmojiFactory { * is returned. */ public static native EmojiFactory newAvailableInstance(); + + /** + * Returns the lowest code point corresponding to an Android + * emoji character. + */ + public int getMinimumAndroidPua() { + return nativeGetMinimumAndroidPua(mNativeEmojiFactory); + } + + /** + * Returns the highest code point corresponding to an Android + * emoji character. + */ + public int getMaximumAndroidPua() { + return nativeGetMaximumAndroidPua(mNativeEmojiFactory); + } // native methods diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index e232c2c..7fbb3a7 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -304,6 +304,9 @@ public class SensorManager extends IRotationWatcher.Stub if (mSensorDataFd == null) { Log.e(TAG, "mSensorDataFd == NULL, exiting"); + synchronized (sListeners) { + mThread = null; + } return; } // this thread is guaranteed to be unique @@ -321,17 +324,16 @@ public class SensorManager extends IRotationWatcher.Stub // wait for an event final int sensor = sensors_data_poll(values, status, timestamp); - if (sensor == -1) { - // we lost the connection to the event stream. this happens - // when the last listener is removed. - Log.d(TAG, "_sensors_data_poll() failed, we bail out."); - break; - } - int accuracy = status[0]; synchronized (sListeners) { - if (sListeners.isEmpty()) { - // we have no more listeners, terminate the thread + if (sensor == -1 || sListeners.isEmpty()) { + if (sensor == -1) { + // we lost the connection to the event stream. this happens + // when the last listener is removed. + Log.d(TAG, "_sensors_data_poll() failed, we bail out."); + } + + // we have no more listeners or polling failed, terminate the thread sensors_data_close(); mThread = null; break; diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 32270c4..6ee92ce 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -22,8 +22,8 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.app.Dialog; import android.content.Context; import android.content.res.Configuration; +import android.content.res.TypedArray; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.IBinder; import android.os.ResultReceiver; @@ -44,6 +44,7 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; +import android.view.animation.AnimationUtils; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -54,6 +55,8 @@ import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.FrameLayout; +import android.widget.LinearLayout; + import java.io.FileDescriptor; import java.io.PrintWriter; @@ -204,6 +207,10 @@ import java.io.PrintWriter; * You can use these to reset and initialize your input state for the current * target. For example, you will often want to clear any input state, and * update a soft keyboard to be appropriate for the new inputType.</p> + * + * @attr ref android.R.styleable#InputMethodService_imeFullscreenBackground + * @attr ref android.R.styleable#InputMethodService_imeExtractEnterAnimation + * @attr ref android.R.styleable#InputMethodService_imeExtractExitAnimation */ public class InputMethodService extends AbstractInputMethodService { static final String TAG = "InputMethodService"; @@ -211,13 +218,19 @@ public class InputMethodService extends AbstractInputMethodService { InputMethodManager mImm; + int mTheme = android.R.style.Theme_InputMethod; + LayoutInflater mInflater; + TypedArray mThemeAttrs; View mRootView; SoftInputWindow mWindow; boolean mInitialized; boolean mWindowCreated; boolean mWindowAdded; boolean mWindowVisible; + boolean mWindowWasVisible; + boolean mInShowWindow; + ViewGroup mFullscreenArea; FrameLayout mExtractFrame; FrameLayout mCandidatesFrame; FrameLayout mInputFrame; @@ -243,6 +256,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean mFullscreenApplied; boolean mIsFullscreen; View mExtractView; + boolean mExtractViewHidden; ExtractEditText mExtractEditText; ViewGroup mExtractAccessories; Button mExtractAction; @@ -260,8 +274,8 @@ public class InputMethodService extends AbstractInputMethodService { final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = new ViewTreeObserver.OnComputeInternalInsetsListener() { public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { - if (isFullscreenMode()) { - // In fullscreen mode, we just say the window isn't covering + if (isExtractViewShown()) { + // In true fullscreen mode, we just say the window isn't covering // any content so we don't impact whatever is behind. View decor = getWindow().getWindow().getDecorView(); info.contentInsets.top = info.visibleInsets.top @@ -519,12 +533,28 @@ public class InputMethodService extends AbstractInputMethodService { public int touchableInsets; } + /** + * You can call this to customize the theme used by your IME's window. + * This theme should typically be one that derives from + * {@link android.R.style#Theme_InputMethod}, which is the default theme + * you will get. This must be set before {@link #onCreate}, so you + * will typically call it in your constructor with the resource ID + * of your custom theme. + */ + public void setTheme(int theme) { + if (mWindow != null) { + throw new IllegalStateException("Must be called before onCreate()"); + } + mTheme = theme; + } + @Override public void onCreate() { + super.setTheme(mTheme); super.onCreate(); mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); mInflater = (LayoutInflater)getSystemService( Context.LAYOUT_INFLATER_SERVICE); - mWindow = new SoftInputWindow(this); + mWindow = new SoftInputWindow(this, mTheme); initViews(); mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT); } @@ -551,6 +581,7 @@ public class InputMethodService extends AbstractInputMethodService { mShowInputRequested = false; mShowInputForced = false; + mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService); mRootView = mInflater.inflate( com.android.internal.R.layout.input_method, null); mWindow.setContentView(mRootView); @@ -560,6 +591,8 @@ public class InputMethodService extends AbstractInputMethodService { mWindow.getWindow().setWindowAnimations( com.android.internal.R.style.Animation_InputMethodFancy); } + mFullscreenArea = (ViewGroup)mRootView.findViewById(com.android.internal.R.id.fullscreenArea); + mExtractViewHidden = false; mExtractFrame = (FrameLayout)mRootView.findViewById(android.R.id.extractArea); mExtractView = null; mExtractEditText = null; @@ -731,14 +764,20 @@ public class InputMethodService extends AbstractInputMethodService { if (ic != null) ic.reportFullscreenMode(isFullscreen); mFullscreenApplied = true; initialize(); - Drawable bg = onCreateBackgroundDrawable(); - if (bg == null) { - // We need to give the window a real drawable, so that it - // correctly sets its mode. - bg = getResources().getDrawable(android.R.color.transparent); + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) + mFullscreenArea.getLayoutParams(); + if (isFullscreen) { + mFullscreenArea.setBackgroundDrawable(mThemeAttrs.getDrawable( + com.android.internal.R.styleable.InputMethodService_imeFullscreenBackground)); + lp.height = 0; + lp.weight = 1; + } else { + mFullscreenArea.setBackgroundDrawable(null); + lp.height = LinearLayout.LayoutParams.WRAP_CONTENT; + lp.weight = 0; } - mWindow.getWindow().setBackgroundDrawable(bg); - mExtractFrame.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); + ((ViewGroup)mFullscreenArea.getParent()).updateViewLayout( + mFullscreenArea, lp); if (isFullscreen) { if (mExtractView == null) { View v = onCreateExtractTextView(); @@ -748,6 +787,7 @@ public class InputMethodService extends AbstractInputMethodService { } startExtractingText(false); } + updateExtractFrameVisibility(); } if (changed) { @@ -805,12 +845,66 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * Controls the visibility of the extracted text area. This only applies + * when the input method is in fullscreen mode, and thus showing extracted + * text. When false, the extracted text will not be shown, allowing some + * of the application to be seen behind. This is normally set for you + * by {@link #onUpdateExtractingVisibility}. This controls the visibility + * of both the extracted text and candidate view; the latter since it is + * not useful if there is no text to see. + */ + public void setExtractViewShown(boolean shown) { + if (mExtractViewHidden == shown) { + mExtractViewHidden = !shown; + updateExtractFrameVisibility(); + } + } + + /** + * Return whether the fullscreen extract view is shown. This will only + * return true if {@link #isFullscreenMode()} returns true, and in that + * case its value depends on the last call to + * {@link #setExtractViewShown(boolean)}. This effectively lets you + * determine if the application window is entirely covered (when this + * returns true) or if some part of it may be shown (if this returns + * false, though if {@link #isFullscreenMode()} returns true in that case + * then it is probably only a sliver of the application). + */ + public boolean isExtractViewShown() { + return mIsFullscreen && !mExtractViewHidden; + } + + void updateExtractFrameVisibility() { + int vis; + if (isFullscreenMode()) { + vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE; + mExtractFrame.setVisibility(View.VISIBLE); + } else { + vis = View.VISIBLE; + mExtractFrame.setVisibility(View.GONE); + } + updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE); + if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) { + int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE + ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation + : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation, + 0); + if (animRes != 0) { + mFullscreenArea.startAnimation(AnimationUtils.loadAnimation( + this, animRes)); + } + } + mFullscreenArea.setVisibility(vis); + } + + /** * Compute the interesting insets into your UI. The default implementation * uses the top of the candidates frame for the visible insets, and the * top of the input frame for the content insets. The default touchable * insets are {@link Insets#TOUCHABLE_INSETS_VISIBLE}. * - * <p>Note that this method is not called when in fullscreen mode, since + * <p>Note that this method is not called when + * {@link #isExtractViewShown} returns true, since * in that case the application is left as-is behind the input method and * not impacted by anything in its UI. * @@ -821,9 +915,16 @@ public class InputMethodService extends AbstractInputMethodService { if (mInputFrame.getVisibility() == View.VISIBLE) { mInputFrame.getLocationInWindow(loc); } else { - loc[1] = 0; + View decor = getWindow().getWindow().getDecorView(); + loc[1] = decor.getHeight(); + } + if (isFullscreenMode()) { + // In fullscreen mode, we never resize the underlying window. + View decor = getWindow().getWindow().getDecorView(); + outInsets.contentTopInsets = decor.getHeight(); + } else { + outInsets.contentTopInsets = loc[1]; } - outInsets.contentTopInsets = loc[1]; if (mCandidatesFrame.getVisibility() == View.VISIBLE) { mCandidatesFrame.getLocationInWindow(loc); } @@ -889,11 +990,7 @@ public class InputMethodService extends AbstractInputMethodService { * it is hidden. */ public void setCandidatesViewShown(boolean shown) { - int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility(); - if (mCandidatesVisibility != vis) { - mCandidatesFrame.setVisibility(vis); - mCandidatesVisibility = vis; - } + updateCandidatesVisibility(shown); if (!mShowInputRequested && mWindowVisible != shown) { // If we are being asked to show the candidates view while the app // has not asked for the input view to be shown, then we need @@ -906,17 +1003,26 @@ public class InputMethodService extends AbstractInputMethodService { } } + void updateCandidatesVisibility(boolean shown) { + int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility(); + if (mCandidatesVisibility != vis) { + mCandidatesFrame.setVisibility(vis); + mCandidatesVisibility = vis; + } + } + /** * Returns the visibility mode (either {@link View#INVISIBLE View.INVISIBLE} * or {@link View#GONE View.GONE}) of the candidates view when it is not - * shown. The default implementation returns GONE when in fullscreen mode, + * shown. The default implementation returns GONE when + * {@link #isExtractViewShown} returns true, * otherwise VISIBLE. Be careful if you change this to return GONE in * other situations -- if showing or hiding the candidates view causes * your window to resize, this can cause temporary drawing artifacts as * the resize takes place. */ public int getCandidatesHiddenVisibility() { - return isFullscreenMode() ? View.GONE : View.INVISIBLE; + return isExtractViewShown() ? View.GONE : View.INVISIBLE; } public void showStatusIcon(int iconResId) { @@ -992,20 +1098,6 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * Called by the framework to create a Drawable for the background of - * the input method window. May return null for no background. The default - * implementation returns a non-null standard background only when in - * fullscreen mode. This is called each time the fullscreen mode changes. - */ - public Drawable onCreateBackgroundDrawable() { - if (isFullscreenMode()) { - return getResources().getDrawable( - com.android.internal.R.drawable.input_method_fullscreen_background); - } - return null; - } - - /** * Called by the framework to create the layout for showing extacted text. * Only called when in fullscreen mode. The returned view hierarchy must * have an {@link ExtractEditText} whose ID is @@ -1174,6 +1266,23 @@ public class InputMethodService extends AbstractInputMethodService { + " mWindowCreated=" + mWindowCreated + " mWindowVisible=" + mWindowVisible + " mInputStarted=" + mInputStarted); + + if (mInShowWindow) { + Log.w(TAG, "Re-entrance in to showWindow"); + return; + } + + try { + mWindowWasVisible = mWindowVisible; + mInShowWindow = true; + showWindowInner(showInput); + } finally { + mWindowWasVisible = true; + mInShowWindow = false; + } + } + + void showWindowInner(boolean showInput) { boolean doShowInput = false; boolean wasVisible = mWindowVisible; mWindowVisible = true; @@ -1241,6 +1350,7 @@ public class InputMethodService extends AbstractInputMethodService { mWindow.hide(); mWindowVisible = false; onWindowHidden(); + mWindowWasVisible = false; } } @@ -1559,7 +1669,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean doMovementKey(int keyCode, KeyEvent event, int count) { final ExtractEditText eet = mExtractEditText; - if (isFullscreenMode() && isInputViewShown() && eet != null) { + if (isExtractViewShown() && isInputViewShown() && eet != null) { // If we are in fullscreen mode, the cursor will move around // the extract edit text, but should NOT cause focus to move // to other fields. @@ -1583,10 +1693,10 @@ public class InputMethodService extends AbstractInputMethodService { if (movement.onKeyOther(eet, (Spannable)eet.getText(), event)) { reportExtractedMovement(keyCode, count); } else { - KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN); + KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN); if (movement.onKeyDown(eet, (Spannable)eet.getText(), keyCode, down)) { - KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP); + KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); movement.onKeyUp(eet, (Spannable)eet.getText(), keyCode, up); while (--count > 0) { @@ -1800,18 +1910,52 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * Called when it is time to update the actions available from a full-screen - * IME. You do not need to deal with this if you are using the standard + * Called when the fullscreen-mode extracting editor info has changed, + * to determine whether the extracting (extract text and candidates) portion + * of the UI should be shown. The standard implementation hides or shows + * the extract area depending on whether it makes sense for the + * current editor. In particular, a {@link InputType#TYPE_NULL} + * input type or {@link EditorInfo#IME_FLAG_NO_EXTRACT_UI} flag will + * turn off the extract area since there is no text to be shown. + */ + public void onUpdateExtractingVisibility(EditorInfo ei) { + if (ei.inputType == InputType.TYPE_NULL || + (ei.imeOptions&EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) { + // No reason to show extract UI! + setExtractViewShown(false); + return; + } + + setExtractViewShown(true); + } + + /** + * Called when the fullscreen-mode extracting editor info has changed, + * to update the state of its UI such as the action buttons shown. + * You do not need to deal with this if you are using the standard * full screen extract UI. If replacing it, you will need to re-implement - * this to put the action in your own UI and handle it. + * this to put the appropriate action button in your own UI and handle it, + * and perform any other changes. + * + * <p>The standard implementation turns on or off its accessory area + * depending on whether there is an action button, and hides or shows + * the entire extract area depending on whether it makes sense for the + * current editor. In particular, a {@link InputType#TYPE_NULL} or + * {@link InputType#TYPE_TEXT_VARIATION_FILTER} input type will turn off the + * extract area since there is no text to be shown. */ - public void onUpdateExtractingAccessories(EditorInfo ei) { + public void onUpdateExtractingViews(EditorInfo ei) { + if (!isExtractViewShown()) { + return; + } + if (mExtractAccessories == null) { return; } final boolean hasAction = ei.actionLabel != null || ( (ei.imeOptions&EditorInfo.IME_MASK_ACTION) != EditorInfo.IME_ACTION_NONE && - (ei.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0); + (ei.imeOptions&EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION) == 0 && + ei.inputType != InputType.TYPE_NULL); if (hasAction) { mExtractAccessories.setVisibility(View.VISIBLE); if (ei.actionLabel != null) { @@ -1855,7 +1999,8 @@ public class InputMethodService extends AbstractInputMethodService { try { eet.startInternalChanges(); - onUpdateExtractingAccessories(ei); + onUpdateExtractingVisibility(ei); + onUpdateExtractingViews(ei); int inputType = ei.inputType; if ((inputType&EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) { @@ -1890,8 +2035,10 @@ public class InputMethodService extends AbstractInputMethodService { final Printer p = new PrintWriterPrinter(fout); p.println("Input method service state for " + this + ":"); p.println(" mWindowCreated=" + mWindowCreated - + " mWindowAdded=" + mWindowAdded - + " mWindowVisible=" + mWindowVisible); + + " mWindowAdded=" + mWindowAdded); + p.println(" mWindowVisible=" + mWindowVisible + + " mWindowWasVisible=" + mWindowWasVisible + + " mInShowWindow=" + mInShowWindow); p.println(" Configuration=" + getResources().getConfiguration()); p.println(" mToken=" + mToken); p.println(" mInputBinding=" + mInputBinding); @@ -1914,7 +2061,8 @@ public class InputMethodService extends AbstractInputMethodService { + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags)); p.println(" mCandidatesVisibility=" + mCandidatesVisibility + " mFullscreenApplied=" + mFullscreenApplied - + " mIsFullscreen=" + mIsFullscreen); + + " mIsFullscreen=" + mIsFullscreen + + " mExtractViewHidden=" + mExtractViewHidden); if (mExtractedText != null) { p.println(" mExtractedText:"); diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java index 7a63c0c..9b8b5db 100755 --- a/core/java/android/inputmethodservice/KeyboardView.java +++ b/core/java/android/inputmethodservice/KeyboardView.java @@ -932,7 +932,7 @@ public class KeyboardView extends View implements View.OnClickListener { mMiniKeyboard = (KeyboardView) mMiniKeyboardContainer.findViewById( com.android.internal.R.id.keyboardView); View closeButton = mMiniKeyboardContainer.findViewById( - com.android.internal.R.id.button_close); + com.android.internal.R.id.closeButton); if (closeButton != null) closeButton.setOnClickListener(this); mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() { public void onKey(int primaryCode, int[] keyCodes) { diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java index c37845f..d91ace6 100644 --- a/core/java/android/inputmethodservice/SoftInputWindow.java +++ b/core/java/android/inputmethodservice/SoftInputWindow.java @@ -31,18 +31,6 @@ import android.view.WindowManager; */ class SoftInputWindow extends Dialog { - /** - * Create a DockWindow that uses the default style. - * - * @param context The Context the DockWindow is to run it. In particular, it - * uses the window manager and theme in this context to present its - * UI. - */ - public SoftInputWindow(Context context) { - super(context, com.android.internal.R.style.Theme_InputMethod); - initDockWindow(); - } - public void setToken(IBinder token) { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.token = token; diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java index 0edbe5b..91fa900 100644 --- a/core/java/android/net/http/CertificateChainValidator.java +++ b/core/java/android/net/http/CertificateChainValidator.java @@ -43,7 +43,8 @@ class CertificateChainValidator { /** * The singleton instance of the certificate chain validator */ - private static CertificateChainValidator sInstance; + private static final CertificateChainValidator sInstance + = new CertificateChainValidator(); /** * Default trust manager (used to perform CA certificate validation) @@ -54,10 +55,6 @@ class CertificateChainValidator { * @return The singleton instance of the certificator chain validator */ public static CertificateChainValidator getInstance() { - if (sInstance == null) { - sInstance = new CertificateChainValidator(); - } - return sInstance; } @@ -159,13 +156,11 @@ class CertificateChainValidator { // report back to the user. // try { - synchronized (mDefaultTrustManager) { - mDefaultTrustManager.checkServerTrusted( - serverCertificates, "RSA"); + mDefaultTrustManager.checkServerTrusted( + serverCertificates, "RSA"); - // no errors!!! - return null; - } + // no errors!!! + return null; } catch (CertificateException e) { if (HttpLog.LOGV) { HttpLog.v( @@ -191,10 +186,8 @@ class CertificateChainValidator { // check if the last certificate in the chain (root) is trusted X509Certificate[] rootCertificateChain = { currCertificate }; try { - synchronized (mDefaultTrustManager) { - mDefaultTrustManager.checkServerTrusted( - rootCertificateChain, "RSA"); - } + mDefaultTrustManager.checkServerTrusted( + rootCertificateChain, "RSA"); } catch (CertificateExpiredException e) { String errorMessage = e.getMessage(); if (errorMessage == null) { diff --git a/core/java/android/net/http/HttpsConnection.java b/core/java/android/net/http/HttpsConnection.java index fe02d3e..55b733f 100644 --- a/core/java/android/net/http/HttpsConnection.java +++ b/core/java/android/net/http/HttpsConnection.java @@ -17,61 +17,41 @@ package android.net.http; import android.content.Context; - -import junit.framework.Assert; - -import java.io.IOException; - -import java.security.cert.X509Certificate; - -import java.net.Socket; -import java.net.InetSocketAddress; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - +import android.util.Log; +import org.apache.harmony.xnet.provider.jsse.FileClientSessionCache; +import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache; +import org.apache.harmony.xnet.provider.jsse.SSLContextImpl; import org.apache.http.Header; -import org.apache.http.HttpClientConnection; import org.apache.http.HttpException; import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ParseException; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; -import org.apache.http.impl.DefaultHttpClientConnection; import org.apache.http.message.BasicHttpRequest; import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpParams; import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; -/** - * Simple exception we throw if the SSL connection is closed by the user. - * - * {@hide} - */ -class SSLConnectionClosedByUserException extends SSLException { - - public SSLConnectionClosedByUserException(String reason) { - super(reason); - } -} +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.security.KeyManagementException; +import java.security.cert.X509Certificate; /** * A Connection connecting to a secure http server or tunneling through * a http proxy server to a https server. + * + * @hide */ -class HttpsConnection extends Connection { - - /** - * SSL context - */ - private static SSLContext mSslContext = null; +public class HttpsConnection extends Connection { /** * SSL socket factory @@ -79,42 +59,59 @@ class HttpsConnection extends Connection { private static SSLSocketFactory mSslSocketFactory = null; static { - // initialize the socket factory + // This intiialization happens in the zygote. It triggers some + // lazy initialization that can will benefit later invocations of + // initializeEngine(). + initializeEngine(null); + } + + /** + * @hide + * + * @param sessionDir directory to cache SSL sessions + */ + public static void initializeEngine(File sessionDir) { try { - mSslContext = SSLContext.getInstance("TLS"); - if (mSslContext != null) { - // here, trust managers is a single trust-all manager - TrustManager[] trustManagers = new TrustManager[] { - new X509TrustManager() { - public X509Certificate[] getAcceptedIssuers() { - return null; - } + SSLClientSessionCache cache = null; + if (sessionDir != null) { + Log.d("HttpsConnection", "Caching SSL sessions in " + + sessionDir + "."); + cache = FileClientSessionCache.usingDirectory(sessionDir); + } - public void checkClientTrusted( - X509Certificate[] certs, String authType) { - } + SSLContextImpl sslContext = new SSLContextImpl(); - public void checkServerTrusted( - X509Certificate[] certs, String authType) { - } + // here, trust managers is a single trust-all manager + TrustManager[] trustManagers = new TrustManager[] { + new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; } - }; - mSslContext.init(null, trustManagers, null); - mSslSocketFactory = mSslContext.getSocketFactory(); - } - } catch (Exception t) { - if (HttpLog.LOGV) { - HttpLog.v("HttpsConnection: failed to initialize the socket factory"); + public void checkClientTrusted( + X509Certificate[] certs, String authType) { + } + + public void checkServerTrusted( + X509Certificate[] certs, String authType) { + } + } + }; + + sslContext.engineInit(null, trustManagers, null, cache, null); + + synchronized (HttpsConnection.class) { + mSslSocketFactory = sslContext.engineGetSocketFactory(); } + } catch (KeyManagementException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); } } - /** - * @return The shared SSL context. - */ - /*package*/ static SSLContext getContext() { - return mSslContext; + private synchronized static SSLSocketFactory getSocketFactory() { + return mSslSocketFactory; } /** @@ -252,10 +249,8 @@ class HttpsConnection extends Connection { if (statusCode == HttpStatus.SC_OK) { try { - synchronized (mSslSocketFactory) { - sslSock = (SSLSocket) mSslSocketFactory.createSocket( + sslSock = (SSLSocket) getSocketFactory().createSocket( proxySock, mHost.getHostName(), mHost.getPort(), true); - } } catch(IOException e) { if (sslSock != null) { sslSock.close(); @@ -288,14 +283,11 @@ class HttpsConnection extends Connection { } else { // if we do not have a proxy, we simply connect to the host try { - synchronized (mSslSocketFactory) { - sslSock = (SSLSocket) mSslSocketFactory.createSocket(); - - sslSock.setSoTimeout(SOCKET_TIMEOUT); - sslSock.connect(new InetSocketAddress(mHost.getHostName(), - mHost.getPort())); - - } + sslSock = (SSLSocket) getSocketFactory().createSocket(); + + sslSock.setSoTimeout(SOCKET_TIMEOUT); + sslSock.connect(new InetSocketAddress(mHost.getHostName(), + mHost.getPort())); } catch(IOException e) { if (sslSock != null) { sslSock.close(); @@ -371,6 +363,7 @@ class HttpsConnection extends Connection { BasicHttpParams params = new BasicHttpParams(); params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192); conn.bind(sslSock, params); + return conn; } @@ -425,3 +418,15 @@ class HttpsConnection extends Connection { return "https"; } } + +/** + * Simple exception we throw if the SSL connection is closed by the user. + * + * {@hide} + */ +class SSLConnectionClosedByUserException extends SSLException { + + public SSLConnectionClosedByUserException(String reason) { + super(reason); + } +} diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 7590bfe..b0ae0e6 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -39,6 +39,20 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public static final int SENSOR = 3; + + /** + * A constant indicating a full wifi lock timer + * + * {@hide} + */ + public static final int FULL_WIFI_LOCK = 4; + + /** + * A constant indicating a scan wifi lock timer + * + * {@hide} + */ + public static final int SCAN_WIFI_LOCK = 5; /** * Include all of the data in the stats, including previously saved data. @@ -74,7 +88,10 @@ public abstract class BatteryStats implements Parcelable { private static final String WAKELOCK_DATA = "wakelock"; private static final String NETWORK_DATA = "network"; private static final String BATTERY_DATA = "battery"; + private static final String WIFI_LOCK_DATA = "wifilock"; private static final String MISC_DATA = "misc"; + private static final String SIGNAL_STRENGTH_DATA = "signal"; + private static final String DATA_CONNECTION_DATA = "dataconn"; private final StringBuilder mFormatBuilder = new StringBuilder(8); private final Formatter mFormatter = new Formatter(mFormatBuilder); @@ -105,7 +122,7 @@ public abstract class BatteryStats implements Parcelable { /** * Temporary for debugging. */ - public abstract void logState(); + public abstract void logState(Printer pw, String prefix); } /** @@ -162,6 +179,13 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getTcpBytesSent(int which); + + public abstract void noteFullWifiLockAcquiredLocked(); + public abstract void noteFullWifiLockReleasedLocked(); + public abstract void noteScanWifiLockAcquiredLocked(); + public abstract void noteScanWifiLockReleasedLocked(); + public abstract long getFullWifiLockTime(long batteryRealtime, int which); + public abstract long getScanWifiLockTime(long batteryRealtime, int which); public static abstract class Sensor { // Magic sensor number for the GPS. @@ -268,6 +292,72 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getPhoneOnTime(long batteryRealtime, int which); + + public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0; + public static final int SIGNAL_STRENGTH_POOR = 1; + public static final int SIGNAL_STRENGTH_MODERATE = 2; + public static final int SIGNAL_STRENGTH_GOOD = 3; + public static final int SIGNAL_STRENGTH_GREAT = 4; + + static final String[] SIGNAL_STRENGTH_NAMES = { + "none", "poor", "moderate", "good", "great" + }; + + public static final int NUM_SIGNAL_STRENGTH_BINS = 5; + + /** + * Returns the time in milliseconds that the phone has been running with + * the given signal strength. + * + * {@hide} + */ + public abstract long getPhoneSignalStrengthTime(int strengthBin, + long batteryRealtime, int which); + + public static final int DATA_CONNECTION_NONE = 0; + public static final int DATA_CONNECTION_GPRS = 1; + public static final int DATA_CONNECTION_EDGE = 2; + public static final int DATA_CONNECTION_UMTS = 3; + public static final int DATA_CONNECTION_OTHER = 4; + + static final String[] DATA_CONNECTION_NAMES = { + "none", "gprs", "edge", "umts", "other" + }; + + public static final int NUM_DATA_CONNECTION_TYPES = 5; + + /** + * Returns the time in milliseconds that the phone has been running with + * the given data connection. + * + * {@hide} + */ + public abstract long getPhoneDataConnectionTime(int dataType, + long batteryRealtime, int which); + + /** + * Returns the time in milliseconds that wifi has been on while the device was + * running on battery. + * + * {@hide} + */ + public abstract long getWifiOnTime(long batteryRealtime, int which); + + /** + * Returns the time in milliseconds that wifi has been on and the driver has + * been in the running state while the device was running on battery. + * + * {@hide} + */ + public abstract long getWifiRunningTime(long batteryRealtime, int which); + + /** + * Returns the time in milliseconds that bluetooth has been on while the device was + * running on battery. + * + * {@hide} + */ + public abstract long getBluetoothOnTime(long batteryRealtime, int which); /** * Return whether we are currently running on battery. @@ -292,6 +382,17 @@ public abstract class BatteryStats implements Parcelable { * @param curTime the amount of elapsed realtime in microseconds. */ public abstract long getBatteryRealtime(long curTime); + + /** + * Returns the battery percentage level at the last time the device was unplugged from power, + * or the last time it was booted while unplugged. + */ + public abstract int getUnpluggedStartLevel(); + + /** + * Returns the battery percentage level at the last time the device was plugged into power. + */ + public abstract int getPluggedStartLevel(); /** * Returns the total, last, or current battery uptime in microseconds. @@ -483,6 +584,9 @@ public abstract class BatteryStats implements Parcelable { final long totalUptime = computeUptime(rawUptime, which); final long screenOnTime = getScreenOnTime(batteryRealtime, which); final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + final long wifiOnTime = getWifiOnTime(batteryRealtime, which); + final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which); + final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); StringBuilder sb = new StringBuilder(128); @@ -496,7 +600,27 @@ public abstract class BatteryStats implements Parcelable { // Dump misc stats dumpLine(pw, 0 /* uid */, category, MISC_DATA, - screenOnTime / 1000, phoneOnTime / 1000); + screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000, + wifiRunningTime / 1000, bluetoothOnTime / 1000); + + // Dump signal strength stats + Object[] args = new Object[NUM_SIGNAL_STRENGTH_BINS]; + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000; + } + dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_DATA, args); + + // Dump network type stats + args = new Object[NUM_DATA_CONNECTION_TYPES]; + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000; + } + dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_DATA, args); + + if (which == STATS_UNPLUGGED) { + dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(), + getPluggedStartLevel()); + } SparseArray<? extends Uid> uidStats = getUidStats(); final int NU = uidStats.size(); @@ -506,7 +630,15 @@ public abstract class BatteryStats implements Parcelable { // Dump Network stats per uid, if any long rx = u.getTcpBytesReceived(which); long tx = u.getTcpBytesSent(which); + long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); + long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which); + if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx); + + if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) { + dumpLine(pw, uid, category, WIFI_LOCK_DATA, + fullWifiLockOnTime, scanWifiLockOnTime); + } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); if (wakelocks.size() > 0) { @@ -601,7 +733,7 @@ public abstract class BatteryStats implements Parcelable { final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptime(rawUptime); - final long batteryRealtime = getBatteryUptime(rawRealtime); + final long batteryRealtime = getBatteryRealtime(rawRealtime); final long whichBatteryUptime = computeBatteryUptime(rawUptime, which); final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which); @@ -624,13 +756,79 @@ public abstract class BatteryStats implements Parcelable { + formatTimeMs(totalRealtime / 1000) + "realtime"); - long screenOnTime = getScreenOnTime(batteryRealtime, which); - long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + final long screenOnTime = getScreenOnTime(batteryRealtime, which); + final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which); + final long wifiOnTime = getWifiOnTime(batteryRealtime, which); + final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); pw.println(prefix - + " Time with screen on: " + formatTimeMs(screenOnTime / 1000) + + " Screen on: " + formatTimeMs(screenOnTime / 1000) + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime) - + "), time with phone on: " + formatTimeMs(phoneOnTime / 1000) - + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")"); + + "), Phone on: " + formatTimeMs(phoneOnTime / 1000) + + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime)); + pw.println(prefix + + " Wifi on: " + formatTimeMs(wifiOnTime / 1000) + + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime) + + "), Wifi running: " + formatTimeMs(wifiRunningTime / 1000) + + "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime) + + "), Bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000) + + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")"); + + sb.setLength(0); + sb.append(" Signal strengths: "); + boolean didOne = false; + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which); + if (time == 0) { + continue; + } + if (didOne) sb.append(", "); + didOne = true; + sb.append(SIGNAL_STRENGTH_NAMES[i]); + sb.append(" "); + sb.append(formatTimeMs(time/1000)); + sb.append("("); + sb.append(formatRatioLocked(time, whichBatteryRealtime)); + sb.append(")"); + } + if (!didOne) sb.append("No activity"); + pw.println(sb.toString()); + + sb.setLength(0); + sb.append(" Data types: "); + didOne = false; + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + final long time = getPhoneDataConnectionTime(i, batteryRealtime, which); + if (time == 0) { + continue; + } + if (didOne) sb.append(", "); + didOne = true; + sb.append(DATA_CONNECTION_NAMES[i]); + sb.append(" "); + sb.append(formatTimeMs(time/1000)); + sb.append("("); + sb.append(formatRatioLocked(time, whichBatteryRealtime)); + sb.append(")"); + } + if (!didOne) sb.append("No activity"); + pw.println(sb.toString()); + + pw.println(" "); + + if (which == STATS_UNPLUGGED) { + if (getIsOnBattery()) { + pw.println(prefix + " Device is currently unplugged"); + pw.println(prefix + " Discharge cycle start level: " + + getUnpluggedStartLevel()); + } else { + pw.println(prefix + " Device is currently plugged into power"); + pw.println(prefix + " Last discharge cycle start level: " + + getUnpluggedStartLevel()); + pw.println(prefix + " Last discharge cycle end level: " + + getPluggedStartLevel()); + } + } pw.println(" "); @@ -644,10 +842,23 @@ public abstract class BatteryStats implements Parcelable { long tcpReceived = u.getTcpBytesReceived(which); long tcpSent = u.getTcpBytesSent(which); + long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); + long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which); + if (tcpReceived != 0 || tcpSent != 0) { pw.println(prefix + " Network: " + tcpReceived + " bytes received, " + tcpSent + " bytes sent"); } + if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) { + pw.println(prefix + " Full Wifi Lock Time: " + + formatTimeMs(fullWifiLockOnTime / 1000) + + "(" + formatRatioLocked(fullWifiLockOnTime, + whichBatteryRealtime)+ ")"); + pw.println(prefix + " Scan Wifi Lock Time: " + + formatTimeMs(scanWifiLockOnTime / 1000) + + "(" + formatRatioLocked(scanWifiLockOnTime, + whichBatteryRealtime)+ ")"); + } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); if (wakelocks.size() > 0) { diff --git a/core/java/android/os/Hardware.java b/core/java/android/os/Hardware.java index 3b6c9d7..efc5617 100644 --- a/core/java/android/os/Hardware.java +++ b/core/java/android/os/Hardware.java @@ -21,22 +21,29 @@ package android.os; */ public class Hardware { - /** - * Control the LED. - */ - public static native int setLedState(int colorARGB, int onMS, int offMS); - - /** - * Control the Flashlight - */ + + + /* ******************************************************************************** + * + * + * + * + * + * + * + * + * Don't add anything else to this class. Add it to HardwareService instead. + * + * + * + * + * + * + * + * ********************************************************************************/ + + public static native boolean getFlashlightEnabled(); public static native void setFlashlightEnabled(boolean on); public static native void enableCameraFlash(int milliseconds); - - /** - * Control the backlights - */ - public static native void setScreenBacklight(int brightness); - public static native void setKeyboardBacklight(boolean on); - public static native void setButtonBacklight(boolean on); } diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl index 4f6029f..fb121bb 100755 --- a/core/java/android/os/IHardwareService.aidl +++ b/core/java/android/os/IHardwareService.aidl @@ -29,12 +29,10 @@ interface IHardwareService void setFlashlightEnabled(boolean on); void enableCameraFlash(int milliseconds); - // backlight support - void setScreenBacklight(int brightness); - void setKeyboardBacklight(boolean on); - void setButtonBacklight(boolean on); - - // LED support - void setLedState(int colorARGB, int onMS, int offMS); + // sets the brightness of the backlights (screen, keyboard, button) 0-255 + void setBacklights(int brightness); + + // for the phone + void setAttentionLight(boolean on); } diff --git a/core/java/android/os/LocalPowerManager.java b/core/java/android/os/LocalPowerManager.java index 55d7972..9e88f5a 100644 --- a/core/java/android/os/LocalPowerManager.java +++ b/core/java/android/os/LocalPowerManager.java @@ -20,12 +20,16 @@ package android.os; public interface LocalPowerManager { public static final int OTHER_EVENT = 0; public static final int CHEEK_EVENT = 1; - public static final int TOUCH_EVENT = 2; - public static final int BUTTON_EVENT = 3; // Button and trackball events. + public static final int TOUCH_EVENT = 2; // touch events are TOUCH for 300ms, and then either + // up events or LONG_TOUCH events. + public static final int LONG_TOUCH_EVENT = 3; + public static final int TOUCH_UP_EVENT = 4; + public static final int BUTTON_EVENT = 5; // Button and trackball events. public static final int POKE_LOCK_IGNORE_CHEEK_EVENTS = 0x1; public static final int POKE_LOCK_SHORT_TIMEOUT = 0x2; public static final int POKE_LOCK_MEDIUM_TIMEOUT = 0x4; + public static final int POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS = 0x8; public static final int POKE_LOCK_TIMEOUT_MASK = 0x6; diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java index b53e227..47497e5 100644 --- a/core/java/android/os/Power.java +++ b/core/java/android/os/Power.java @@ -45,26 +45,6 @@ public class Power public static native void releaseWakeLock(String id); /** - * Flag to turn on and off the keyboard light. - */ - public static final int KEYBOARD_LIGHT = 0x00000001; - - /** - * Flag to turn on and off the screen backlight. - */ - public static final int SCREEN_LIGHT = 0x00000002; - - /** - * Flag to turn on and off the button backlight. - */ - public static final int BUTTON_LIGHT = 0x00000004; - - /** - * Flags to turn on and off all the backlights. - */ - public static final int ALL_LIGHTS = (KEYBOARD_LIGHT|SCREEN_LIGHT|BUTTON_LIGHT); - - /** * Brightness value for fully off */ public static final int BRIGHTNESS_OFF = 0; @@ -91,14 +71,6 @@ public class Power public static final int LOW_BATTERY_THRESHOLD = 10; /** - * Set the brightness for one or more lights - * - * @param mask flags indicating which lights to change brightness - * @param brightness new brightness value (0 = off, 255 = fully bright) - */ - public static native int setLightBrightness(int mask, int brightness); - - /** * Turn the screen on or off * * @param on Whether you want the screen on or off diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 04e7ef0..63f6dff 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -211,7 +211,7 @@ public class RemoteCallbackList<E extends IInterface> { for (Callback cb : mCallbacks.values()) { active[i++] = cb.mCallback; } - return N; + return i; } } diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java index d75a25f..4a709f6 100644 --- a/core/java/android/provider/Calendar.java +++ b/core/java/android/provider/Calendar.java @@ -1054,6 +1054,9 @@ public final class Calendar { if (cursor == null) { return; } + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "missed alarms found: " + cursor.getCount()); + } try { while (cursor.moveToNext()) { @@ -1068,6 +1071,8 @@ public final class Calendar { intent.putExtra(android.provider.Calendar.EVENT_END_TIME, end); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + Log.w(TAG, "rescheduling missed alarm, id: " + id + " begin: " + begin + + " end: " + end + " alarmTime: " + alarmTime); manager.set(AlarmManager.RTC_WAKEUP, alarmTime, sender); } } finally { diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 10fe3f5..abd6934 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -22,6 +22,8 @@ import android.content.Context; import android.net.Uri; import android.provider.Contacts.People; import com.android.internal.telephony.CallerInfo; +import com.android.internal.telephony.Connection; + import android.text.TextUtils; import android.util.Log; @@ -137,7 +139,8 @@ public class CallLog { * if the contact is unknown. * @param context the context used to get the ContentResolver * @param number the phone number to be added to the calls db - * @param isPrivateNumber <code>true</code> if the call was marked as private by the network + * @param presentation the number presenting rules set by the network for + * "allowed", "payphone", "restricted" or "unknown" * @param callType enumerated values for "incoming", "outgoing", or "missed" * @param start time stamp for the call in milliseconds * @param duration call duration in seconds @@ -145,12 +148,14 @@ public class CallLog { * {@hide} */ public static Uri addCall(CallerInfo ci, Context context, String number, - boolean isPrivateNumber, int callType, long start, int duration) { + int presentation, int callType, long start, int duration) { final ContentResolver resolver = context.getContentResolver(); if (TextUtils.isEmpty(number)) { - if (isPrivateNumber) { + if (presentation == Connection.PRESENTATION_RESTRICTED) { number = CallerInfo.PRIVATE_NUMBER; + } else if (presentation == Connection.PRESENTATION_PAYPHONE) { + number = CallerInfo.PAYPHONE_NUMBER; } else { number = CallerInfo.UNKNOWN_NUMBER; } diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java index d11a9c5..a87f5fa 100644 --- a/core/java/android/provider/Checkin.java +++ b/core/java/android/provider/Checkin.java @@ -144,6 +144,43 @@ public final class Checkin { TEST, NETWORK_RX_MOBILE, NETWORK_TX_MOBILE, + MARKET_DOWNLOAD_REQUESTED, + MARKET_DOWNLOAD_SCHEDULED, + MARKET_DOWNLOAD_CANCELLED_PENDING, + MARKET_DOWNLOAD_CANCELLED, + MARKET_DOWNLOAD_OK, + MARKET_DOWNLOAD_FAILED, + MARKET_DOWNLOAD_DECLINED, + MARKET_INSTALL_SCHEDULED, + MARKET_INSTALL_FAILED, + MARKET_INSTALL_OK, + MARKET_REMOVE_SCHEDULED, + MARKET_REMOVE_MALICIOUS_SCHEDULED, + MARKET_REMOVE_ABORTED, + MARKET_REMOVE_FAILED, + MARKET_REMOVE_OK, + MARKET_UNINSTALL_SCHEDULED, + MARKET_REFUND_REQUESTED, + MARKET_REFUND_OK, + MARKET_REFUND_FAILED, + MARKET_REASON_ALREADY_EXISTS, + MARKET_REASON_INVALID_APK, + MARKET_REASON_INSUFFICIENT_STORAGE, + MARKET_REASON_DUPLICATE_PACKAGE, + MARKET_REASON_UPDATE_INCOMPATIBLE, + MARKET_REASON_MISSING_SHARED_LIBRARY, + MARKET_REASON_REPLACE_COULDNT_DELETE, + MARKET_REASON_PARSE_NOT_APK, + MARKET_REASON_PARSE_BAD_MANIFEST, + MARKET_REASON_PARSE_NO_CERTIFICATES, + MARKET_REASON_PARSE_INCONSISTENT_CERTIFICATES, + MARKET_REASON_PARSE_CERTIFICATE_ENCODING, + MARKET_REASON_PARSE_BAD_PACKAGE_NAME, + MARKET_REASON_PARSE_BAD_SHARED_USER_ID, + MARKET_REASON_PARSE_MANIFEST_MALFORMED, + MARKET_REASON_PARSE_MANIFEST_EMPTY, + MARKET_REASON_UNKNOWN, + MARKET_STALE_INSTALL_ATTEMPT, } } diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java index e132bee..fe15962 100644 --- a/core/java/android/provider/Contacts.java +++ b/core/java/android/provider/Contacts.java @@ -273,6 +273,18 @@ public class Contacts { Uri.parse("content://contacts/deleted_people"); /** + * The content:// style URL for filtering people that have a specific + * E-mail or IM address. The filter argument should be passed as an + * additional path segment after this URI. This matches any people with + * at least one E-mail or IM {@link ContactMethods} that match the + * filter. + * + * @hide pending API council review + */ + public static final Uri WITH_EMAIL_OR_IM_FILTER_URI = + Uri.parse("content://contacts/people/with_email_or_im_filter"); + + /** * The MIME type of {@link #CONTENT_URI} providing a directory of * people. */ @@ -1459,13 +1471,24 @@ public class Contacts { "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; /** - * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new contact if no matching - * contact found. Otherwise, default behavior is to prompt user with dialog before creating. - * - * <P>Type: BOOLEAN</P> + * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new + * contact if no matching contact found. Otherwise, default behavior is + * to prompt user with dialog before creating. + * <p> + * Type: BOOLEAN */ public static final String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE"; + + /** + * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact + * description to be shown when prompting user about creating a new + * contact. + * <p> + * Type: STRING + */ + public static final String EXTRA_CREATE_DESCRIPTION = + "com.android.contacts.action.CREATE_DESCRIPTION"; /** * Intents related to the Contacts app UI. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b0ee479..4c9471c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2314,6 +2314,11 @@ public final class Settings { public static final String GMAIL_DISALLOW_IMAGE_PREVIEWS = "gmail_disallow_image_previews"; /** + * The maximal size in bytes allowed for attachments when composing messages in Gmail + */ + public static final String GMAIL_MAX_ATTACHMENT_SIZE = "gmail_max_attachment_size_bytes"; + + /** * The timeout in milliseconds that Gmail uses when opening a connection and reading * from it. A missing value or a value of -1 instructs Gmail to use the defaults provided * by GoogleHttpClient. @@ -2532,6 +2537,31 @@ public final class Settings { "vending_use_checkout_qa_service"; /** + * Default value to use for all/free/priced filter in Market. + * Valid values: ALL, FREE, PAID (case insensitive) + */ + public static final String VENDING_DEFAULT_FILTER = "vending_default_filter"; + /** + * Ranking type value to use for the first category tab (currently popular) + */ + public static final String VENDING_TAB_1_RANKING_TYPE = "vending_tab_1_ranking_type"; + + /** + * Title string to use for first category tab. + */ + public static final String VENDING_TAB_1_TITLE = "vending_tab_1_title"; + + /** + * Ranking type value to use for the second category tab (currently newest) + */ + public static final String VENDING_TAB_2_RANKING_TYPE = "vending_tab_2_ranking_type"; + + /** + * Title string to use for second category tab. + */ + public static final String VENDING_TAB_2_TITLE = "vending_tab_2_title"; + + /** * URL that points to the legal terms of service to display in Settings. * <p> * This should be a https URL. For a pretty user-friendly URL, use diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index d802c14..61ab228 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -30,6 +30,7 @@ import android.telephony.gsm.SmsMessage; import android.text.TextUtils; import android.text.util.Regex; import android.util.Config; +import android.util.Log; import java.util.HashSet; import java.util.Set; @@ -233,18 +234,37 @@ public final class Telephony { */ public static boolean moveMessageToFolder(Context context, Uri uri, int folder) { - if ((uri == null) || ((folder != MESSAGE_TYPE_INBOX) - && (folder != MESSAGE_TYPE_OUTBOX) - && (folder != MESSAGE_TYPE_SENT) - && (folder != MESSAGE_TYPE_DRAFT) - && (folder != MESSAGE_TYPE_FAILED) - && (folder != MESSAGE_TYPE_QUEUED))) { + if (uri == null) { + return false; + } + + boolean markAsUnread = false; + boolean markAsRead = false; + switch(folder) { + case MESSAGE_TYPE_INBOX: + case MESSAGE_TYPE_DRAFT: + break; + case MESSAGE_TYPE_OUTBOX: + case MESSAGE_TYPE_SENT: + markAsRead = true; + break; + case MESSAGE_TYPE_FAILED: + case MESSAGE_TYPE_QUEUED: + markAsUnread = true; + break; + default: return false; } - ContentValues values = new ContentValues(1); + ContentValues values = new ContentValues(2); values.put(TYPE, folder); + if (markAsUnread) { + values.put(READ, Integer.valueOf(0)); + } else if (markAsRead) { + values.put(READ, Integer.valueOf(1)); + } + return 1 == SqliteWrapper.update(context, context.getContentResolver(), uri, values, null, null); } @@ -1084,18 +1104,22 @@ public final class Telephony { uriBuilder.appendQueryParameter("recipient", recipient); } + Uri uri = uriBuilder.build(); Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(), - uriBuilder.build(), ID_PROJECTION, null, null, null); + uri, ID_PROJECTION, null, null, null); if (cursor != null) { try { if (cursor.moveToFirst()) { return cursor.getLong(0); + } else { + Log.e(TAG, "getOrCreateThreadId returned no rows!"); } } finally { cursor.close(); } } + Log.e(TAG, "getOrCreateThreadId failed with uri " + uri.toString()); throw new IllegalArgumentException("Unable to find or allocate a thread ID."); } } diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 3aa4078..5c4e56d 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -58,11 +58,18 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private static final String BLUETOOTH_ENABLED = "bluetooth_enabled"; private static final int MESSAGE_CONNECT_TO = 1; + private static final int MESSAGE_DISCONNECT = 2; private final Context mContext; private final IntentFilter mIntentFilter; private HashMap<String, SinkState> mAudioDevices; private final AudioManager mAudioManager; + private final BluetoothDevice mBluetooth; + + // list of disconnected sinks to process after a delay + private final ArrayList<String> mPendingDisconnects = new ArrayList<String>(); + // number of active sinks + private int mSinkCount = 0; private class SinkState { public String address; @@ -75,9 +82,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - BluetoothDevice device = - (BluetoothDevice)mContext.getSystemService(Context.BLUETOOTH_SERVICE); - if (device == null) { + mBluetooth = (BluetoothDevice) mContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (mBluetooth == null) { throw new RuntimeException("Platform does not support Bluetooth"); } @@ -85,13 +91,12 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { throw new RuntimeException("Could not init BluetoothA2dpService"); } - mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION); - mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION); + mIntentFilter = new IntentFilter(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION); mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION); mIntentFilter.addAction(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION); mContext.registerReceiver(mReceiver, mIntentFilter); - if (device.isEnabled()) { + if (mBluetooth.isEnabled()) { onBluetoothEnable(); } } @@ -110,10 +115,17 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); String address = intent.getStringExtra(BluetoothIntent.ADDRESS); - if (action.equals(BluetoothIntent.ENABLED_ACTION)) { - onBluetoothEnable(); - } else if (action.equals(BluetoothIntent.DISABLED_ACTION)) { - onBluetoothDisable(); + if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) { + int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE, + BluetoothError.ERROR); + switch (state) { + case BluetoothDevice.BLUETOOTH_STATE_ON: + onBluetoothEnable(); + break; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF: + onBluetoothDisable(); + break; + } } else if (action.equals(BluetoothIntent.BOND_STATE_CHANGED_ACTION)) { int bondState = intent.getIntExtra(BluetoothIntent.BOND_STATE, BluetoothError.ERROR); @@ -145,9 +157,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { switch (msg.what) { case MESSAGE_CONNECT_TO: String address = (String)msg.obj; - // check device is still preferred, and nothing is currently - // connected - if (getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF && + // check bluetooth is still on, device is still preferred, and + // nothing is currently connected + if (mBluetooth.isEnabled() && + getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF && lookupSinksMatchingStates(new int[] { BluetoothA2dp.STATE_CONNECTING, BluetoothA2dp.STATE_CONNECTED, @@ -157,6 +170,9 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { connectSink(address); } break; + case MESSAGE_DISCONNECT: + handleDeferredDisconnect((String)msg.obj); + break; } } }; @@ -331,6 +347,9 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } private synchronized void onSinkConnected(String path) { + // if we are reconnected, do not process previous disconnect event. + mPendingDisconnects.remove(path); + if (mAudioDevices == null) return; // bluez 3.36 quietly disconnects the previous sink when a new sink // is connected, so we need to mark all previously connected sinks as @@ -356,8 +375,23 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } private synchronized void onSinkDisconnected(String path) { - mAudioManager.setBluetoothA2dpOn(false); - updateState(path, BluetoothA2dp.STATE_DISCONNECTED); + // This is to work around a problem in bluez that results + // sink disconnect events being sent, immediately followed by a reconnect. + // To avoid unnecessary audio routing changes, we defer handling + // sink disconnects until after a short delay. + mPendingDisconnects.add(path); + Message msg = Message.obtain(mHandler, MESSAGE_DISCONNECT, path); + mHandler.sendMessageDelayed(msg, 2000); + } + + private synchronized void handleDeferredDisconnect(String path) { + if (mPendingDisconnects.contains(path)) { + mPendingDisconnects.remove(path); + if (mSinkCount == 1) { + mAudioManager.setBluetoothA2dpOn(false); + } + updateState(path, BluetoothA2dp.STATE_DISCONNECTED); + } } private synchronized void onSinkPlaying(String path) { @@ -425,6 +459,13 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { if (state != prevState) { if (DBG) log("state " + address + " (" + path + ") " + prevState + "->" + state); + + // keep track of the number of active sinks + if (prevState == BluetoothA2dp.STATE_DISCONNECTED) { + mSinkCount++; + } else if (state == BluetoothA2dp.STATE_DISCONNECTED) { + mSinkCount--; + } Intent intent = new Intent(BluetoothA2dp.SINK_STATE_CHANGED_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); @@ -434,7 +475,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { if ((prevState == BluetoothA2dp.STATE_CONNECTED || prevState == BluetoothA2dp.STATE_PLAYING) && - (state != BluetoothA2dp.STATE_CONNECTED && + (state != BluetoothA2dp.STATE_CONNECTING && + state != BluetoothA2dp.STATE_CONNECTED && state != BluetoothA2dp.STATE_PLAYING)) { // disconnected intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY); diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 9e9ba62..f1a7d25 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -37,8 +37,10 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemService; import android.provider.Settings; import android.util.Log; @@ -49,8 +51,11 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import com.android.internal.app.IBatteryStats; + public class BluetoothDeviceService extends IBluetoothDevice.Stub { private static final String TAG = "BluetoothDeviceService"; private static final boolean DBG = true; @@ -59,15 +64,21 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private BluetoothEventLoop mEventLoop; private IntentFilter mIntentFilter; private boolean mIsAirplaneSensitive; + private int mBluetoothState; + private boolean mRestart = false; // need to call enable() after disable() + private final BondState mBondState = new BondState(); // local cache of bondings - private volatile boolean mIsEnabled; // local cache of isEnabledNative() private boolean mIsDiscovering; + private final IBatteryStats mBatteryStats; private final Context mContext; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; + private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; + private static final int MESSAGE_FINISH_DISABLE = 2; + static { classInitNative(); } @@ -75,6 +86,12 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public BluetoothDeviceService(Context context) { mContext = context; + + // Need to do this in place of: + // mBatteryStats = BatteryStatsService.getService(); + // Since we can not import BatteryStatsService from here. This class really needs to be + // moved to java/services/com/android/server/ + mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); } /** Must be called after construction, and before any other method. @@ -87,7 +104,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { disableNative(); } - mIsEnabled = false; + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF); mIsDiscovering = false; mEventLoop = new BluetoothEventLoop(mContext, this); registerForAirplaneMode(); @@ -109,10 +126,16 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public boolean isEnabled() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return mIsEnabled; + return mBluetoothState == BluetoothDevice.BLUETOOTH_STATE_ON; } private native int isEnabledNative(); + public int getBluetoothState() { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + return mBluetoothState; + } + + /** * Bring down bluetooth and disable BT in settings. Returns true on success. */ @@ -124,17 +147,36 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { * Bring down bluetooth. Returns true on success. * * @param saveSetting If true, disable BT in settings - * */ public synchronized boolean disable(boolean saveSetting) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); + switch (mBluetoothState) { + case BluetoothDevice.BLUETOOTH_STATE_OFF: + return true; + case BluetoothDevice.BLUETOOTH_STATE_ON: + break; + default: + return false; + } if (mEnableThread != null && mEnableThread.isAlive()) { return false; } - if (!mIsEnabled) { - return true; + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF); + + // Allow 3 seconds for profiles to gracefully disconnect + // TODO: Introduce a callback mechanism so that each profile can notify + // BluetoothDeviceService when it is done shutting down + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); + return true; + } + + + private synchronized void finishDisable(boolean saveSetting) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) { + return; } mEventLoop.stop(); disableNative(); @@ -148,14 +190,14 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { // Remove remoteServiceChannelCallbacks HashMap<String, IBluetoothDeviceCallback> callbacksMap = mEventLoop.getRemoteServiceChannelCallbacks(); - IBluetoothDeviceCallback callback; - for (String address : callbacksMap.keySet()) { - callback = callbacksMap.get(address); + for (Iterator<String> i = callbacksMap.keySet().iterator(); i.hasNext();) { + String address = i.next(); + IBluetoothDeviceCallback callback = callbacksMap.get(address); try { callback.onGetRemoteServiceChannelResult(address, BluetoothError.ERROR_DISABLED); } catch (RemoteException e) {} - callbacksMap.remove(address); + i.remove(); } // update mode @@ -163,38 +205,42 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mIsEnabled = false; + mIsDiscovering = false; + if (saveSetting) { persistBluetoothOnSetting(false); } - mIsDiscovering = false; - intent = new Intent(BluetoothIntent.DISABLED_ACTION); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - return true; + + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF); + + // Log bluetooth off to battery stats. + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteBluetoothOff(); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + + if (mRestart) { + mRestart = false; + enable(); + } } - /** - * Bring up bluetooth, asynchronously, and enable BT in settings. - * This turns on/off the underlying hardware. - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. - */ - public boolean enable(IBluetoothDeviceCallback callback) { - return enable(callback, true); + /** Bring up BT and persist BT on in settings */ + public boolean enable() { + return enable(true); } /** * Enable this Bluetooth device, asynchronously. * This turns on/off the underlying hardware. * - * @param saveSetting If true, enable BT in settings - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. + * @param saveSetting If true, persist the new state of BT in settings + * @return True on success (so far) */ - public synchronized boolean enable(IBluetoothDeviceCallback callback, - boolean saveSetting) { + public synchronized boolean enable(boolean saveSetting) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); @@ -202,28 +248,60 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { if (mIsAirplaneSensitive && isAirplaneModeOn()) { return false; } - if (mIsEnabled) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_OFF) { return false; } if (mEnableThread != null && mEnableThread.isAlive()) { return false; } - mEnableThread = new EnableThread(callback, saveSetting); + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON); + mEnableThread = new EnableThread(saveSetting); mEnableThread.start(); return true; } - private static final int REGISTER_SDP_RECORDS = 1; + /** Forcibly restart Bluetooth if it is on */ + /* package */ synchronized void restart() { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_ON) { + return; + } + mRestart = true; + if (!disable(false)) { + mRestart = false; + } + } + + private synchronized void setBluetoothState(int state) { + if (state == mBluetoothState) { + return; + } + + if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state); + + Intent intent = new Intent(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION); + intent.putExtra(BluetoothIntent.BLUETOOTH_PREVIOUS_STATE, mBluetoothState); + intent.putExtra(BluetoothIntent.BLUETOOTH_STATE, state); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + + mBluetoothState = state; + + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + } + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { - case REGISTER_SDP_RECORDS: + case MESSAGE_REGISTER_SDP_RECORDS: //TODO: Don't assume HSP/HFP is running, don't use sdptool, if (isEnabled()) { SystemService.start("hsag"); SystemService.start("hfag"); } + break; + case MESSAGE_FINISH_DISABLE: + finishDisable(msg.arg1 != 0); + break; } } }; @@ -231,10 +309,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private EnableThread mEnableThread; private class EnableThread extends Thread { - private final IBluetoothDeviceCallback mEnableCallback; private final boolean mSaveSetting; - public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) { - mEnableCallback = callback; + public EnableThread(boolean saveSetting) { mSaveSetting = saveSetting; } public void run() { @@ -244,7 +320,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { boolean running = false; while ((retryCount-- > 0) && !running) { mEventLoop.start(); - // it may take a momement for the other thread to do its + // it may take a momement for the other thread to do its // thing. Check periodically for a while. int pollCount = 5; while ((pollCount-- > 0) && !running) { @@ -264,36 +340,37 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } } - if (mEnableCallback != null) { - try { - mEnableCallback.onEnableResult(res ? - BluetoothDevice.RESULT_SUCCESS : - BluetoothDevice.RESULT_FAILURE); - } catch (RemoteException e) {} - } if (res) { - mIsEnabled = true; if (mSaveSetting) { persistBluetoothOnSetting(true); } mIsDiscovering = false; mBondState.loadBondState(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS), + 3000); - // Update mode - mEventLoop.onModeChanged(getModeNative()); + // Log bluetooth on to battery stats. + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteBluetoothOn(); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } } - Intent intent = null; + + mEnableThread = null; + + setBluetoothState(res ? + BluetoothDevice.BLUETOOTH_STATE_ON : + BluetoothDevice.BLUETOOTH_STATE_OFF); + if (res) { - intent = new Intent(BluetoothIntent.ENABLED_ACTION); - } else { - intent = new Intent(BluetoothIntent.DISABLED_ACTION); + // Update mode + mEventLoop.onModeChanged(getModeNative()); } - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mEnableThread = null; } } @@ -320,18 +397,25 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private final HashMap<String, Integer> mState = new HashMap<String, Integer>(); private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>(); private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>(); - // List of all the vendor_id prefix of Bluetooth addresses for which - // auto pairing is not attempted + // List of all the vendor_id prefix of Bluetooth addresses for + // which auto pairing is not attempted. + // The following companies are included in the list below: + // ALPS (lexus), Murata (Prius 2007, Nokia 616), TEMIC SDS (Porsche, Audi), + // Parrot, Zhongshan General K-mate Electronics, Great Well + // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi, + // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura), + // Continental Automotive, Harman/Becker private final ArrayList<String> mAutoPairingBlacklisted = new ArrayList<String>(Arrays.asList( - "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS - "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS - "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57",// Murata for Prius 2007 - "00:0E:9F" // TEMIC SDS for Porsche + "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", "00:21:4F", + "00:23:06", "00:24:33", "00:A0:79", "00:0E:6D", "00:13:E0", "00:21:E8", + "00:60:57", "00:0E:9F", "00:12:1C", "00:18:91", "00:18:96", "00:13:04", + "00:16:FD", "00:22:A0", "00:0B:4C", "00:60:6F", "00:23:3D", "00:C0:59", + "00:0A:30", "00:1E:AE", "00:1C:D7" )); public synchronized void loadBondState() { - if (!mIsEnabled) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_ON) { return; } String[] bonds = listBondingsNative(); @@ -1051,7 +1135,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { // If bluetooth is currently expected to be on, then enable or disable bluetooth if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { if (enabled) { - enable(null, false); + enable(false); } else { disable(false); } @@ -1079,52 +1163,63 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mIsEnabled) { - pw.println("\nBluetooth ENABLED: " + getAddress() + " (" + getName() + ")"); - pw.println("\nisDiscovering() = " + isDiscovering()); - - BluetoothHeadset headset = new BluetoothHeadset(mContext, null); - - String[] addresses = listRemoteDevices(); - - pw.println("\n--Known devices--"); - for (String address : addresses) { - pw.printf("%s %10s (%d) %s\n", address, - toBondStateString(mBondState.getBondState(address)), - mBondState.getAttempt(address), - getRemoteName(address)); - } - - addresses = listAclConnections(); - pw.println("\n--ACL connected devices--"); - for (String address : addresses) { - pw.println(address); - } - - // Rather not do this from here, but no-where else and I need this - // dump - pw.println("\n--Headset Service--"); - switch (headset.getState()) { - case BluetoothHeadset.STATE_DISCONNECTED: - pw.println("getState() = STATE_DISCONNECTED"); - break; - case BluetoothHeadset.STATE_CONNECTING: - pw.println("getState() = STATE_CONNECTING"); - break; - case BluetoothHeadset.STATE_CONNECTED: - pw.println("getState() = STATE_CONNECTED"); - break; - case BluetoothHeadset.STATE_ERROR: - pw.println("getState() = STATE_ERROR"); - break; - } - pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress()); - headset.close(); - - } else { - pw.println("\nBluetooth DISABLED"); - } - pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive); + pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n"); + + switch(mBluetoothState) { + case BluetoothDevice.BLUETOOTH_STATE_OFF: + pw.println("\nBluetooth OFF\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_ON: + pw.println("\nBluetooth TURNING ON\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF: + pw.println("\nBluetooth TURNING OFF\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_ON: + pw.println("\nBluetooth ON\n"); + } + + pw.println("\nLocal address = " + getAddress()); + pw.println("\nLocal name = " + getName()); + pw.println("\nisDiscovering() = " + isDiscovering()); + + BluetoothHeadset headset = new BluetoothHeadset(mContext, null); + + String[] addresses = listRemoteDevices(); + + pw.println("\n--Known devices--"); + for (String address : addresses) { + pw.printf("%s %10s (%d) %s\n", address, + toBondStateString(mBondState.getBondState(address)), + mBondState.getAttempt(address), + getRemoteName(address)); + } + + addresses = listAclConnections(); + pw.println("\n--ACL connected devices--"); + for (String address : addresses) { + pw.println(address); + } + + // Rather not do this from here, but no-where else and I need this + // dump + pw.println("\n--Headset Service--"); + switch (headset.getState()) { + case BluetoothHeadset.STATE_DISCONNECTED: + pw.println("getState() = STATE_DISCONNECTED"); + break; + case BluetoothHeadset.STATE_CONNECTING: + pw.println("getState() = STATE_CONNECTING"); + break; + case BluetoothHeadset.STATE_CONNECTED: + pw.println("getState() = STATE_CONNECTED"); + break; + case BluetoothHeadset.STATE_ERROR: + pw.println("getState() = STATE_ERROR"); + break; + } + pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress()); + headset.close(); } /* package */ static int bluezStringToScanMode(String mode) { @@ -1159,3 +1254,4 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { Log.d(TAG, msg); } } + diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 8e77eed..11c297c 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -46,10 +46,10 @@ class BluetoothEventLoop { private Thread mThread; private boolean mStarted; private boolean mInterrupted; - private HashMap<String, Integer> mPasskeyAgentRequestData; - private HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks; - private BluetoothDeviceService mBluetoothService; - private Context mContext; + private final HashMap<String, Integer> mPasskeyAgentRequestData; + private final HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks; + private final BluetoothDeviceService mBluetoothService; + private final Context mContext; private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1; private static final int EVENT_RESTART_BLUETOOTH = 2; @@ -76,8 +76,7 @@ class BluetoothEventLoop { } break; case EVENT_RESTART_BLUETOOTH: - mBluetoothService.disable(); - mBluetoothService.enable(null); + mBluetoothService.restart(); break; } } @@ -170,6 +169,7 @@ class BluetoothEventLoop { if (mode >= 0) { Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION); intent.putExtra(BluetoothIntent.SCAN_MODE, mode); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } } @@ -309,6 +309,12 @@ class BluetoothEventLoop { address = address.toUpperCase(); mPasskeyAgentRequestData.put(address, new Integer(nativeData)); + if (mBluetoothService.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) { + // shutdown path + mBluetoothService.cancelPin(address); + return; + } + if (mBluetoothService.getBondState().getBondState(address) == BluetoothDevice.BOND_BONDING) { // we initiated the bonding @@ -337,7 +343,7 @@ class BluetoothEventLoop { private void onPasskeyAgentCancel(String address) { address = address.toUpperCase(); - mPasskeyAgentRequestData.remove(address); + mBluetoothService.cancelPin(address); Intent intent = new Intent(BluetoothIntent.PAIRING_CANCEL_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); @@ -347,7 +353,7 @@ class BluetoothEventLoop { private boolean onAuthAgentAuthorize(String address, String service, String uuid) { boolean authorized = false; - if (service.endsWith("service_audio")) { + if (mBluetoothService.isEnabled() && service.endsWith("service_audio")) { BluetoothA2dp a2dp = new BluetoothA2dp(mContext); authorized = a2dp.getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF; if (authorized) { diff --git a/core/java/android/syncml/pim/PropertyNode.java b/core/java/android/syncml/pim/PropertyNode.java index 13d4930..cc52499 100644 --- a/core/java/android/syncml/pim/PropertyNode.java +++ b/core/java/android/syncml/pim/PropertyNode.java @@ -16,25 +16,142 @@ package android.syncml.pim; -import java.util.ArrayList; -import java.util.Collection; - import android.content.ContentValues; +import android.util.Log; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class PropertyNode { public String propName; - public String propValue = ""; + public String propValue; - public Collection<String> propValue_vector; + public List<String> propValue_vector; - /** Store value as byte[],after decode. */ - public byte[] propValue_byts; + /** Store value as byte[],after decode. + * Used when propValue is encoded by something like BASE64, QUOTED-PRINTABLE, etc. + */ + public byte[] propValue_bytes; - /** param store: key=paramType, value=paramValue */ - public ContentValues paraMap = new ContentValues(); + /** param store: key=paramType, value=paramValue + * Note that currently PropertyNode class does not support multiple param-values + * defined in vCard 3.0 (See also RFC 2426). multiple-values are stored as + * one String value like "A,B", not ["A", "B"]... + * TODO: fix this. + */ + public ContentValues paramMap; /** Only for TYPE=??? param store. */ - public ArrayList<String> paraMap_TYPE = new ArrayList<String>(); + public Set<String> paramMap_TYPE; + + /** Store group values. Used only in VCard. */ + public Set<String> propGroupSet; + + public PropertyNode() { + propValue = ""; + paramMap = new ContentValues(); + paramMap_TYPE = new HashSet<String>(); + propGroupSet = new HashSet<String>(); + } + + public PropertyNode( + String propName, String propValue, List<String> propValue_vector, + byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE, + Set<String> propGroupSet) { + this.propName = propName; + if (propValue != null) { + this.propValue = propValue; + } else { + this.propValue = ""; + } + this.propValue_vector = propValue_vector; + this.propValue_bytes = propValue_bytes; + if (paramMap != null) { + this.paramMap = paramMap; + } else { + this.paramMap = new ContentValues(); + } + if (paramMap_TYPE != null) { + this.paramMap_TYPE = paramMap_TYPE; + } else { + this.paramMap_TYPE = new HashSet<String>(); + } + if (propGroupSet != null) { + this.propGroupSet = propGroupSet; + } else { + this.propGroupSet = new HashSet<String>(); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof PropertyNode)) { + return false; + } + + PropertyNode node = (PropertyNode)obj; + + if (propName == null || !propName.equals(node.propName)) { + return false; + } else if (!paramMap.equals(node.paramMap)) { + return false; + } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { + return false; + } else if (!propGroupSet.equals(node.propGroupSet)) { + return false; + } + + if (propValue_bytes != null && Arrays.equals(propValue_bytes, node.propValue_bytes)) { + return true; + } else { + // Log.d("@@@", propValue + ", " + node.propValue); + if (!propValue.equals(node.propValue)) { + return false; + } + + // The value in propValue_vector is not decoded even if it should be + // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector + // is 1, the encoded value is stored in propValue, so we do not have to + // check it. + if (propValue_vector != null) { + // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector); + return (propValue_vector.equals(node.propValue_vector) || + (propValue_vector.size() == 1)); + } else if (node.propValue_vector != null) { + // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector); + return (node.propValue_vector.equals(propValue_vector) || + (node.propValue_vector.size() == 1)); + } else { + return true; + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("propName: "); + builder.append(propName); + builder.append(", paramMap: "); + builder.append(paramMap.toString()); + builder.append(", propmMap_TYPE: "); + builder.append(paramMap_TYPE.toString()); + builder.append(", propGroupSet: "); + builder.append(propGroupSet.toString()); + if (propValue_vector != null && propValue_vector.size() > 1) { + builder.append(", propValue_vector size: "); + builder.append(propValue_vector.size()); + } + if (propValue_bytes != null) { + builder.append(", propValue_bytes size: "); + builder.append(propValue_bytes.length); + } + builder.append(", propValue: "); + builder.append(propValue); + return builder.toString(); + } } diff --git a/core/java/android/syncml/pim/VBuilder.java b/core/java/android/syncml/pim/VBuilder.java index 822c2ce..4528645 100644 --- a/core/java/android/syncml/pim/VBuilder.java +++ b/core/java/android/syncml/pim/VBuilder.java @@ -16,7 +16,7 @@ package android.syncml.pim; -import java.util.Collection; +import java.util.List; public interface VBuilder { void start(); @@ -38,9 +38,14 @@ public interface VBuilder { void endProperty(); /** + * @param group + */ + void propertyGroup(String group); + + /** * @param name - * a.N <br> - * a.N + * N <br> + * N */ void propertyName(String name); @@ -58,5 +63,5 @@ public interface VBuilder { */ void propertyParamValue(String value); - void propertyValues(Collection<String> values); + void propertyValues(List<String> values); } diff --git a/core/java/android/syncml/pim/VDataBuilder.java b/core/java/android/syncml/pim/VDataBuilder.java index f0a0cb9..8c67cf5 100644 --- a/core/java/android/syncml/pim/VDataBuilder.java +++ b/core/java/android/syncml/pim/VDataBuilder.java @@ -16,11 +16,19 @@ package android.syncml.pim; +import android.content.ContentValues; +import android.util.Log; + import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.net.QuotedPrintableCodec; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; +import java.util.List; +import java.util.Vector; /** * Store the parse result to custom datastruct: VNode, PropertyNode @@ -29,14 +37,32 @@ import java.util.Collection; * PropertyNode: standy by a property line of a card. */ public class VDataBuilder implements VBuilder { + static private String LOG_TAG = "VDATABuilder"; /** type=VNode */ - public ArrayList<VNode> vNodeList = new ArrayList<VNode>(); - int nodeListPos = 0; - VNode curVNode; - PropertyNode curPropNode; - String curParamType; + public List<VNode> vNodeList = new ArrayList<VNode>(); + private int mNodeListPos = 0; + private VNode mCurrentVNode; + private PropertyNode mCurrentPropNode; + private String mCurrentParamType; + + /** + * Assumes that each String can be encoded into byte array using this encoding. + */ + private String mCharset; + + private boolean mStrictLineBreakParsing; + + public VDataBuilder() { + mCharset = "ISO-8859-1"; + mStrictLineBreakParsing = false; + } + public VDataBuilder(String encoding, boolean strictLineBreakParsing) { + mCharset = encoding; + mStrictLineBreakParsing = strictLineBreakParsing; + } + public void start() { } @@ -48,79 +74,171 @@ public class VDataBuilder implements VBuilder { vnode.parseStatus = 1; vnode.VName = type; vNodeList.add(vnode); - nodeListPos = vNodeList.size()-1; - curVNode = vNodeList.get(nodeListPos); + mNodeListPos = vNodeList.size()-1; + mCurrentVNode = vNodeList.get(mNodeListPos); } public void endRecord() { - VNode endNode = vNodeList.get(nodeListPos); + VNode endNode = vNodeList.get(mNodeListPos); endNode.parseStatus = 0; - while(nodeListPos > 0){ - nodeListPos--; - if((vNodeList.get(nodeListPos)).parseStatus == 1) + while(mNodeListPos > 0){ + mNodeListPos--; + if((vNodeList.get(mNodeListPos)).parseStatus == 1) break; } - curVNode = vNodeList.get(nodeListPos); + mCurrentVNode = vNodeList.get(mNodeListPos); } public void startProperty() { - // System.out.println("+ startProperty. "); + // System.out.println("+ startProperty. "); } public void endProperty() { - // System.out.println("- endProperty. "); + // System.out.println("- endProperty. "); } - + public void propertyName(String name) { - curPropNode = new PropertyNode(); - curPropNode.propName = name; + mCurrentPropNode = new PropertyNode(); + mCurrentPropNode.propName = name; } + // Used only in VCard. + public void propertyGroup(String group) { + mCurrentPropNode.propGroupSet.add(group); + } + public void propertyParamType(String type) { - curParamType = type; + mCurrentParamType = type; } public void propertyParamValue(String value) { - if(curParamType == null) - curPropNode.paraMap_TYPE.add(value); - else if(curParamType.equalsIgnoreCase("TYPE")) - curPropNode.paraMap_TYPE.add(value); - else - curPropNode.paraMap.put(curParamType, value); - - curParamType = null; - } - - public void propertyValues(Collection<String> values) { - curPropNode.propValue_vector = values; - curPropNode.propValue = listToString(values); - //decode value string to propValue_byts - if(curPropNode.paraMap.containsKey("ENCODING")){ - if(curPropNode.paraMap.getAsString("ENCODING"). - equalsIgnoreCase("BASE64")){ - curPropNode.propValue_byts = - Base64.decodeBase64(curPropNode.propValue. + if (mCurrentParamType == null || + mCurrentParamType.equalsIgnoreCase("TYPE")) { + mCurrentPropNode.paramMap_TYPE.add(value); + } else { + mCurrentPropNode.paramMap.put(mCurrentParamType, value); + } + + mCurrentParamType = null; + } + + private String encodeString(String originalString, String targetEncoding) { + Charset charset = Charset.forName(mCharset); + ByteBuffer byteBuffer = charset.encode(originalString); + // byteBuffer.array() "may" return byte array which is larger than + // byteBuffer.remaining(). Here, we keep on the safe side. + byte[] bytes = new byte[byteBuffer.remaining()]; + byteBuffer.get(bytes); + try { + return new String(bytes, targetEncoding); + } catch (UnsupportedEncodingException e) { + return null; + } + } + + public void propertyValues(List<String> values) { + ContentValues paramMap = mCurrentPropNode.paramMap; + + String charsetString = paramMap.getAsString("CHARSET"); + + boolean setupParamValues = false; + //decode value string to propValue_bytes + if (paramMap.containsKey("ENCODING")) { + String encoding = paramMap.getAsString("ENCODING"); + if (encoding.equalsIgnoreCase("BASE64") || + encoding.equalsIgnoreCase("B")) { + if (values.size() > 1) { + Log.e(LOG_TAG, + ("BASE64 encoding is used while " + + "there are multiple values (" + values.size())); + } + mCurrentPropNode.propValue_bytes = + Base64.decodeBase64(values.get(0). replaceAll(" ","").replaceAll("\t",""). replaceAll("\r\n",""). getBytes()); } - if(curPropNode.paraMap.getAsString("ENCODING"). - equalsIgnoreCase("QUOTED-PRINTABLE")){ + + if(encoding.equalsIgnoreCase("QUOTED-PRINTABLE")){ + // if CHARSET is defined, we translate each String into the Charset. + List<String> tmpValues = new ArrayList<String>(); + Vector<byte[]> byteVector = new Vector<byte[]>(); + int size = 0; try{ - curPropNode.propValue_byts = - QuotedPrintableCodec.decodeQuotedPrintable( - curPropNode.propValue. - replaceAll("= ", " ").replaceAll("=\t", "\t"). - getBytes() ); - curPropNode.propValue = - new String(curPropNode.propValue_byts); - }catch(Exception e){ - System.out.println("=Decode quoted-printable exception."); - e.printStackTrace(); + for (String value : values) { + String quotedPrintable = value + .replaceAll("= ", " ").replaceAll("=\t", "\t"); + String[] lines; + if (mStrictLineBreakParsing) { + lines = quotedPrintable.split("\r\n"); + } else { + lines = quotedPrintable + .replace("\r\n", "\n").replace("\r", "\n").split("\n"); + } + StringBuilder builder = new StringBuilder(); + for (String line : lines) { + if (line.endsWith("=")) { + line = line.substring(0, line.length() - 1); + } + builder.append(line); + } + byte[] bytes = QuotedPrintableCodec.decodeQuotedPrintable( + builder.toString().getBytes()); + if (charsetString != null) { + try { + tmpValues.add(new String(bytes, charsetString)); + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString); + tmpValues.add(new String(bytes)); + } + } else { + tmpValues.add(new String(bytes)); + } + byteVector.add(bytes); + size += bytes.length; + } // for (String value : values) { + mCurrentPropNode.propValue_vector = tmpValues; + mCurrentPropNode.propValue = listToString(tmpValues); + + mCurrentPropNode.propValue_bytes = new byte[size]; + + { + byte[] tmpBytes = mCurrentPropNode.propValue_bytes; + int index = 0; + for (byte[] bytes : byteVector) { + int length = bytes.length; + for (int i = 0; i < length; i++, index++) { + tmpBytes[index] = bytes[i]; + } + } + } + setupParamValues = true; + } catch(Exception e) { + Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e); } + } // QUOTED-PRINTABLE + } // ENCODING + + if (!setupParamValues) { + // if CHARSET is defined, we translate each String into the Charset. + if (charsetString != null) { + List<String> tmpValues = new ArrayList<String>(); + for (String value : values) { + String result = encodeString(value, charsetString); + if (result != null) { + tmpValues.add(result); + } else { + Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString); + tmpValues.add(value); + } + } + values = tmpValues; } + + mCurrentPropNode.propValue_vector = values; + mCurrentPropNode.propValue = listToString(values); } - curVNode.propList.add(curPropNode); + mCurrentVNode.propList.add(mCurrentPropNode); } private String listToString(Collection<String> list){ @@ -134,7 +252,7 @@ public class VDataBuilder implements VBuilder { } return typeListB.toString(); } - + public String getResult(){ return null; } diff --git a/core/java/android/syncml/pim/vcard/VCardParser.java b/core/java/android/syncml/pim/vcard/VCardParser.java index 3926243..6dad852d 100644 --- a/core/java/android/syncml/pim/vcard/VCardParser.java +++ b/core/java/android/syncml/pim/vcard/VCardParser.java @@ -26,7 +26,8 @@ import java.io.IOException; public class VCardParser { - VParser mParser = null; + // TODO: fix this. + VCardParser_V21 mParser = null; public final static String VERSION_VCARD21 = "vcard2.1"; diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V21.java b/core/java/android/syncml/pim/vcard/VCardParser_V21.java index b6fa032..f853c5e 100644 --- a/core/java/android/syncml/pim/vcard/VCardParser_V21.java +++ b/core/java/android/syncml/pim/vcard/VCardParser_V21.java @@ -16,21 +16,24 @@ package android.syncml.pim.vcard; -import android.syncml.pim.VParser; +import android.syncml.pim.VBuilder; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This class is used to parse vcard. Please refer to vCard Specification 2.1 */ -public class VCardParser_V21 extends VParser { +public class VCardParser_V21 { /** Store the known-type */ - private static final HashSet<String> mKnownTypeSet = new HashSet<String>( + private static final HashSet<String> sKnownTypeSet = new HashSet<String>( Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK", "PREF", "VOICE", "FAX", "MSG", "CELL", "PAGER", "BBS", "MODEM", "CAR", "ISDN", "VIDEO", "AOL", "APPLELINK", @@ -39,13 +42,40 @@ public class VCardParser_V21 extends VParser { "CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT", "TIFF", "PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI", "WAVE", "AIFF", "PCM", "X509", "PGP")); - - /** Store the name */ - private static final HashSet<String> mName = new HashSet<String>(Arrays - .asList("LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", - "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL", - "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER")); - + + /** Store the known-value */ + private static final HashSet<String> sKnownValueSet = new HashSet<String>( + Arrays.asList("INLINE", "URL", "CONTENT-ID", "CID")); + + /** Store the property name available in vCard 2.1 */ + // NICKNAME is not supported in vCard 2.1, but some vCard may contain. + private static final HashSet<String> sAvailablePropertyNameV21 = + new HashSet<String>(Arrays.asList( + "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", + "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL", + "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER", + "NICKNAME")); + + // Though vCard 2.1 specification does not allow "B" encoding, some data may have it. + // We allow it for safety... + private static final HashSet<String> sAvailableEncodingV21 = + new HashSet<String>(Arrays.asList( + "7BIT", "8BIT", "QUOTED-PRINTABLE", "BASE64", "B")); + + // Used only for parsing END:VCARD. + private String mPreviousLine; + + /** The builder to build parsed data */ + protected VBuilder mBuilder = null; + + /** The encoding type */ + protected String mEncoding = null; + + protected final String sDefaultEncoding = "8BIT"; + + // Should not directly read a line from this. Use getLine() instead. + protected BufferedReader mReader; + /** * Create a new VCard parser. */ @@ -55,916 +85,597 @@ public class VCardParser_V21 extends VParser { /** * Parse the file at the given position - * - * @param offset - * the given position to parse - * @return vcard length + * vcard_file = [wsls] vcard [wsls] */ - protected int parseVFile(int offset) { - return parseVCardFile(offset); + protected void parseVCardFile() throws IOException, VCardException { + while (parseOneVCard()) { + } } + protected String getVersion() { + return "2.1"; + } + /** - * [wsls] vcard [wsls] + * @return true when the propertyName is a valid property name. */ - int parseVCardFile(int offset) { - int ret = 0, sum = 0; - - /* remove \t \r\n */ - while ((ret = parseWsls(offset)) != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseVCard(offset); // BEGIN:VCARD ... END:VCARD - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } else { - return PARSE_ERROR; - } + protected boolean isValidPropertyName(String propertyName) { + return sAvailablePropertyNameV21.contains(propertyName.toUpperCase()); + } - /* remove \t \r\n */ - while ((ret = parseWsls(offset)) != PARSE_ERROR) { - offset += ret; - sum += ret; + /** + * @return true when the encoding is a valid encoding. + */ + protected boolean isValidEncoding(String encoding) { + return sAvailableEncodingV21.contains(encoding.toUpperCase()); + } + + /** + * @return String. It may be null, or its length may be 0 + * @throws IOException + */ + protected String getLine() throws IOException { + return mReader.readLine(); + } + + /** + * @return String with it's length > 0 + * @throws IOException + * @throws VCardException when the stream reached end of line + */ + protected String getNonEmptyLine() throws IOException, VCardException { + String line; + while (true) { + line = getLine(); + if (line == null) { + throw new VCardException("Reached end of buffer."); + } else if (line.trim().length() > 0) { + return line; + } } - return sum; } - + /** - * "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF items *CRLF "END" [ws] ":" - * "VCARD" + * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF + * items *CRLF + * "END" [ws] ":" [ws] "VCARD" */ - private int parseVCard(int offset) { - int ret = 0, sum = 0; - - /* BEGIN */ - ret = parseString(offset, "BEGIN", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + private boolean parseOneVCard() throws IOException, VCardException { + if (!readBeginVCard()) { + return false; } - offset += ret; - sum += ret; - - /* [ws] */ - ret = removeWs(offset); - offset += ret; - sum += ret; - - /* colon */ - ret = parseString(offset, ":", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + parseItems(); + readEndVCard(); + return true; + } + + /** + * @return True when successful. False when reaching the end of line + * @throws IOException + * @throws VCardException + */ + protected boolean readBeginVCard() throws IOException, VCardException { + String line; + while (true) { + line = getLine(); + if (line == null) { + return false; + } else if (line.trim().length() > 0) { + break; + } } - offset += ret; - sum += ret; - - /* [ws] */ - ret = removeWs(offset); - offset += ret; - sum += ret; - - /* VCARD */ - ret = parseString(offset, "VCARD", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + String[] strArray = line.split(":", 2); + + // Though vCard specification does not allow lower cases, + // some data may have them, so we allow it. + if (!(strArray.length == 2 && + strArray[0].trim().equalsIgnoreCase("BEGIN") && + strArray[1].trim().equalsIgnoreCase("VCARD"))) { + throw new VCardException("BEGIN:VCARD != \"" + line + "\""); } - offset += ret; - sum += ret; + if (mBuilder != null) { mBuilder.startRecord("VCARD"); } - /* [ws] */ - ret = removeWs(offset); - offset += ret; - sum += ret; - - /* 1*CRLF */ - ret = parseCrlf(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - while ((ret = parseCrlf(offset)) != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseItems(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - /* *CRLF */ - while ((ret = parseCrlf(offset)) != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - /* END */ - ret = parseString(offset, "END", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - /* [ws] */ - ret = removeWs(offset); - offset += ret; - sum += ret; - - /* colon */ - ret = parseString(offset, ":", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - /* [ws] */ - ret = removeWs(offset); - offset += ret; - sum += ret; - - /* VCARD */ - ret = parseString(offset, "VCARD", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - // offset += ret; - sum += ret; + return true; + } + + protected void readEndVCard() throws VCardException { + // Though vCard specification does not allow lower cases, + // some data may have them, so we allow it. + String[] strArray = mPreviousLine.split(":", 2); + if (!(strArray.length == 2 && + strArray[0].trim().equalsIgnoreCase("END") && + strArray[1].trim().equalsIgnoreCase("VCARD"))) { + throw new VCardException("END:VCARD != \"" + mPreviousLine + "\""); + } + if (mBuilder != null) { mBuilder.endRecord(); } - - return sum; } - + /** - * items *CRLF item / item + * items = *CRLF item + * / item */ - private int parseItems(int offset) { + protected void parseItems() throws IOException, VCardException { /* items *CRLF item / item */ - int ret = 0, sum = 0; - + boolean ended = false; + if (mBuilder != null) { mBuilder.startProperty(); } - ret = parseItem(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.endProperty(); - } - for (;;) { - while ((ret = parseCrlf(offset)) != PARSE_ERROR) { - offset += ret; - sum += ret; + try { + ended = parseItem(); + } finally { + if (mBuilder != null) { + mBuilder.endProperty(); } + } + + while (!ended) { // follow VCARD ,it wont reach endProperty if (mBuilder != null) { mBuilder.startProperty(); } - - ret = parseItem(offset); - if (ret == PARSE_ERROR) { - break; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.endProperty(); + try { + ended = parseItem(); + } finally { + if (mBuilder != null) { + mBuilder.endProperty(); + } } } - - return sum; } /** - * item0 / item1 / item2 + * item = [groups "."] name [params] ":" value CRLF + * / [groups "."] "ADR" [params] ":" addressparts CRLF + * / [groups "."] "ORG" [params] ":" orgparts CRLF + * / [groups "."] "N" [params] ":" nameparts CRLF + * / [groups "."] "AGENT" [params] ":" vcard CRLF */ - private int parseItem(int offset) { - int ret = 0, sum = 0; - mEncoding = mDefaultEncoding; - - ret = parseItem0(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseItem1(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseItem2(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - return PARSE_ERROR; - } - - /** [groups "."] name [params] ":" value CRLF */ - private int parseItem0(int offset) { - int ret = 0, sum = 0, start = offset; - String proName = "", proValue = ""; - - ret = parseGroupsWithDot(offset); - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseName(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - proName = mBuffer.substring(start, offset).trim(); - mBuilder.propertyName(proName); - } - - ret = parseParams(offset); - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseString(offset, ":", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - start = offset; - ret = parseValue(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - proValue = mBuffer.substring(start, offset); - if (proName.equals("VERSION") && !proValue.equals("2.1")) { - return PARSE_ERROR; - } - if (mBuilder != null) { - ArrayList<String> v = new ArrayList<String>(); - v.add(proValue); - mBuilder.propertyValues(v); - } - - ret = parseCrlf(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - sum += ret; - - return sum; - } - - /** "ADR" "ORG" "N" with semi-colon separated content */ - private int parseItem1(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseGroupsWithDot(offset); - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - if ((ret = parseString(offset, "ADR", true)) == PARSE_ERROR - && (ret = parseString(offset, "ORG", true)) == PARSE_ERROR - && (ret = parseString(offset, "N", true)) == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; + protected boolean parseItem() throws IOException, VCardException { + mEncoding = sDefaultEncoding; + + // params = ";" [ws] paramlist + String line = getNonEmptyLine(); + String[] strArray = line.split(":", 2); + if (strArray.length < 2) { + throw new VCardException("Invalid line(\":\" does not exist): " + line); + } + String propertyValue = strArray[1]; + String[] groupNameParamsArray = strArray[0].split(";"); + String groupAndName = groupNameParamsArray[0].trim(); + String[] groupNameArray = groupAndName.split("\\."); + int length = groupNameArray.length; + String propertyName = groupNameArray[length - 1]; if (mBuilder != null) { - mBuilder.propertyName(mBuffer.substring(start, offset).trim()); - } - - ret = parseParams(offset); - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseString(offset, ":", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - start = offset; - ret = parseValue(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - int end = 0; - ArrayList<String> v = new ArrayList<String>(); - Pattern p = Pattern - .compile("([^;\\\\]*(\\\\[\\\\;:,])*[^;\\\\]*)(;?)"); - Matcher m = p.matcher(mBuffer.substring(start, offset)); - while (m.find()) { - String s = escapeTranslator(m.group(1)); - v.add(s); - end = m.end(); - if (offset == start + end) { - String endValue = m.group(3); - if (";".equals(endValue)) { - v.add(""); - } - break; - } + mBuilder.propertyName(propertyName); + for (int i = 0; i < length - 1; i++) { + mBuilder.propertyGroup(groupNameArray[i]); } - mBuilder.propertyValues(v); } - - ret = parseCrlf(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - sum += ret; - - return sum; + if (propertyName.equalsIgnoreCase("END")) { + mPreviousLine = line; + return true; + } + + length = groupNameParamsArray.length; + for (int i = 1; i < length; i++) { + handleParams(groupNameParamsArray[i]); + } + + if (isValidPropertyName(propertyName) || + propertyName.startsWith("X-")) { + if (propertyName.equals("VERSION") && + !propertyValue.equals(getVersion())) { + throw new VCardVersionException("Incompatible version: " + + propertyValue + " != " + getVersion()); + } + handlePropertyValue(propertyName, propertyValue); + return false; + } else if (propertyName.equals("ADR") || + propertyName.equals("ORG") || + propertyName.equals("N")) { + handleMultiplePropertyValue(propertyName, propertyValue); + return false; + } else if (propertyName.equals("AGENT")) { + handleAgent(propertyValue); + return false; + } + + throw new VCardException("Unknown property name: \"" + + propertyName + "\""); } - /** [groups] "." "AGENT" [params] ":" vcard CRLF */ - private int parseItem2(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseGroupsWithDot(offset); - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseString(offset, "AGENT", true); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyName(mBuffer.substring(start, offset)); - } - - ret = parseParams(offset); - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseString(offset, ":", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - ret = parseCrlf(offset); - if (ret != PARSE_ERROR) { - offset += ret; - sum += ret; - } - - ret = parseVCard(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyValues(new ArrayList<String>()); - } - - ret = parseCrlf(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + /** + * params = ";" [ws] paramlist + * paramlist = paramlist [ws] ";" [ws] param + * / param + * param = "TYPE" [ws] "=" [ws] ptypeval + * / "VALUE" [ws] "=" [ws] pvalueval + * / "ENCODING" [ws] "=" [ws] pencodingval + * / "CHARSET" [ws] "=" [ws] charsetval + * / "LANGUAGE" [ws] "=" [ws] langval + * / "X-" word [ws] "=" [ws] word + * / knowntype + */ + protected void handleParams(String params) throws VCardException { + String[] strArray = params.split("=", 2); + if (strArray.length == 2) { + String paramName = strArray[0].trim(); + String paramValue = strArray[1].trim(); + if (paramName.equals("TYPE")) { + handleType(paramValue); + } else if (paramName.equals("VALUE")) { + handleValue(paramValue); + } else if (paramName.equals("ENCODING")) { + handleEncoding(paramValue); + } else if (paramName.equals("CHARSET")) { + handleCharset(paramValue); + } else if (paramName.equals("LANGUAGE")) { + handleLanguage(paramValue); + } else if (paramName.startsWith("X-")) { + handleAnyParam(paramName, paramValue); + } else { + throw new VCardException("Unknown type \"" + paramName + "\""); + } + } else { + handleType(strArray[0]); } - sum += ret; - - return sum; } - - private int parseGroupsWithDot(int offset) { - int ret = 0, sum = 0; - /* [groups "."] */ - ret = parseGroups(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - ret = parseString(offset, ".", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - sum += ret; - - return sum; + + /** + * typeval = knowntype / "X-" word + */ + protected void handleType(String ptypeval) throws VCardException { + if (sKnownTypeSet.contains(ptypeval.toUpperCase()) || + ptypeval.startsWith("X-")) { + if (mBuilder != null) { + mBuilder.propertyParamType("TYPE"); + mBuilder.propertyParamValue(ptypeval.toUpperCase()); + } + } else { + throw new VCardException("Unknown type: \"" + ptypeval + "\""); + } } - - /** ";" [ws] paramlist */ - private int parseParams(int offset) { - int ret = 0, sum = 0; - - ret = parseString(offset, ";", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - ret = removeWs(offset); - offset += ret; - sum += ret; - - ret = parseParamList(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + + /** + * pvalueval = "INLINE" / "URL" / "CONTENT-ID" / "CID" / "X-" word + */ + protected void handleValue(String pvalueval) throws VCardException { + if (sKnownValueSet.contains(pvalueval.toUpperCase()) || + pvalueval.startsWith("X-")) { + if (mBuilder != null) { + mBuilder.propertyParamType("VALUE"); + mBuilder.propertyParamValue(pvalueval); + } + } else { + throw new VCardException("Unknown value \"" + pvalueval + "\""); } - sum += ret; - - return sum; } - + /** - * paramlist [ws] ";" [ws] param / param + * pencodingval = "7BIT" / "8BIT" / "QUOTED-PRINTABLE" / "BASE64" / "X-" word */ - private int parseParamList(int offset) { - int ret = 0, sum = 0; - - ret = parseParam(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - int offsetTemp = offset; - int sumTemp = sum; - for (;;) { - ret = removeWs(offsetTemp); - offsetTemp += ret; - sumTemp += ret; - - ret = parseString(offsetTemp, ";", false); - if (ret == PARSE_ERROR) { - return sum; - } - offsetTemp += ret; - sumTemp += ret; - - ret = removeWs(offsetTemp); - offsetTemp += ret; - sumTemp += ret; - - ret = parseParam(offsetTemp); - if (ret == PARSE_ERROR) { - break; + protected void handleEncoding(String pencodingval) throws VCardException { + if (isValidEncoding(pencodingval) || + pencodingval.startsWith("X-")) { + if (mBuilder != null) { + mBuilder.propertyParamType("ENCODING"); + mBuilder.propertyParamValue(pencodingval); } - offsetTemp += ret; - sumTemp += ret; - - // offset = offsetTemp; - sum = sumTemp; + mEncoding = pencodingval; + } else { + throw new VCardException("Unknown encoding \"" + pencodingval + "\""); } - return sum; } - + /** - * param0 / param1 / param2 / param3 / param4 / param5 / knowntype<BR> - * TYPE / VALUE / ENDCODING / CHARSET / LANGUAGE ... + * vCard specification only allows us-ascii and iso-8859-xxx (See RFC 1521), + * but some vCard contains other charset, so we allow them. */ - private int parseParam(int offset) { - int ret = 0, sum = 0; - - ret = parseParam0(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseParam1(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseParam2(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseParam3(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseParam4(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseParam5(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - int start = offset; - ret = parseKnownType(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; + protected void handleCharset(String charsetval) { if (mBuilder != null) { - mBuilder.propertyParamType(null); - mBuilder.propertyParamValue(mBuffer.substring(start, offset)); + mBuilder.propertyParamType("CHARSET"); + mBuilder.propertyParamValue(charsetval); } - - return sum; } - - /** "TYPE" [ws] "=" [ws] ptypeval */ - private int parseParam0(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseString(offset, "TYPE", true); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamType(mBuffer.substring(start, offset)); - } - - ret = removeWs(offset); - offset += ret; - sum += ret; - - ret = parseString(offset, "=", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + + /** + * See also Section 7.1 of RFC 1521 + */ + protected void handleLanguage(String langval) throws VCardException { + String[] strArray = langval.split("-"); + if (strArray.length != 2) { + throw new VCardException("Invalid Language: \"" + langval + "\""); + } + String tmp = strArray[0]; + int length = tmp.length(); + for (int i = 0; i < length; i++) { + if (!isLetter(tmp.charAt(i))) { + throw new VCardException("Invalid Language: \"" + langval + "\""); + } } - offset += ret; - sum += ret; - - ret = removeWs(offset); - offset += ret; - sum += ret; - - start = offset; - ret = parsePTypeVal(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + tmp = strArray[1]; + length = tmp.length(); + for (int i = 0; i < length; i++) { + if (!isLetter(tmp.charAt(i))) { + throw new VCardException("Invalid Language: \"" + langval + "\""); + } } - offset += ret; - sum += ret; if (mBuilder != null) { - mBuilder.propertyParamValue(mBuffer.substring(start, offset)); + mBuilder.propertyParamType("LANGUAGE"); + mBuilder.propertyParamValue(langval); } - - return sum; - } - /** "VALUE" [ws] "=" [ws] pvalueval */ - private int parseParam1(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseString(offset, "VALUE", true); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamType(mBuffer.substring(start, offset)); - } - - ret = removeWs(offset); - offset += ret; - sum += ret; - - ret = parseString(offset, "=", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - ret = removeWs(offset); - offset += ret; - sum += ret; - - start = offset; - ret = parsePValueVal(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; + /** + * Mainly for "X-" type. This accepts any kind of type without check. + */ + protected void handleAnyParam(String paramName, String paramValue) { if (mBuilder != null) { - mBuilder.propertyParamValue(mBuffer.substring(start, offset)); + mBuilder.propertyParamType(paramName); + mBuilder.propertyParamValue(paramValue); } - - return sum; } - - /** "ENCODING" [ws] "=" [ws] pencodingval */ - private int parseParam2(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseString(offset, "ENCODING", true); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamType(mBuffer.substring(start, offset)); - } - - ret = removeWs(offset); - offset += ret; - sum += ret; - - ret = parseString(offset, "=", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - ret = removeWs(offset); - offset += ret; - sum += ret; - - start = offset; - ret = parsePEncodingVal(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamValue(mBuffer.substring(start, offset)); + + protected void handlePropertyValue( + String propertyName, String propertyValue) throws + IOException, VCardException { + if (mEncoding == null || mEncoding.equalsIgnoreCase("7BIT") + || mEncoding.equalsIgnoreCase("8BIT") + || mEncoding.toUpperCase().startsWith("X-")) { + if (mBuilder != null) { + ArrayList<String> v = new ArrayList<String>(); + v.add(maybeUnescapeText(propertyValue)); + mBuilder.propertyValues(v); + } + } else if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) { + String result = getQuotedPrintable(propertyValue); + if (mBuilder != null) { + ArrayList<String> v = new ArrayList<String>(); + v.add(result); + mBuilder.propertyValues(v); + } + } else if (mEncoding.equalsIgnoreCase("BASE64") || + mEncoding.equalsIgnoreCase("B")) { + String result = getBase64(propertyValue); + if (mBuilder != null) { + ArrayList<String> v = new ArrayList<String>(); + v.add(result); + mBuilder.propertyValues(v); + } + } else { + throw new VCardException("Unknown encoding: \"" + mEncoding + "\""); } - - return sum; - } - - /** "CHARSET" [ws] "=" [ws] charsetval */ - private int parseParam3(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseString(offset, "CHARSET", true); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamType(mBuffer.substring(start, offset)); - } - - ret = removeWs(offset); - offset += ret; - sum += ret; - - ret = parseString(offset, "=", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - ret = removeWs(offset); - offset += ret; - sum += ret; - - start = offset; - ret = parseCharsetVal(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamValue(mBuffer.substring(start, offset)); + + protected String getQuotedPrintable(String firstString) throws IOException, VCardException { + // Specifically, there may be some padding between = and CRLF. + // See the following: + // + // qp-line := *(qp-segment transport-padding CRLF) + // qp-part transport-padding + // qp-segment := qp-section *(SPACE / TAB) "=" + // ; Maximum length of 76 characters + // + // e.g. (from RFC 2045) + // Now's the time = + // for all folk to come= + // to the aid of their country. + if (firstString.trim().endsWith("=")) { + // remove "transport-padding" + int pos = firstString.length() - 1; + while(firstString.charAt(pos) != '=') { + } + StringBuilder builder = new StringBuilder(); + builder.append(firstString.substring(0, pos + 1)); + builder.append("\r\n"); + String line; + while (true) { + line = getLine(); + if (line == null) { + throw new VCardException( + "File ended during parsing quoted-printable String"); + } + if (line.trim().endsWith("=")) { + // remove "transport-padding" + pos = line.length() - 1; + while(line.charAt(pos) != '=') { + } + builder.append(line.substring(0, pos + 1)); + builder.append("\r\n"); + } else { + builder.append(line); + break; + } + } + return builder.toString(); + } else { + return firstString; } - - return sum; } - - /** "LANGUAGE" [ws] "=" [ws] langval */ - private int parseParam4(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseString(offset, "LANGUAGE", true); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamType(mBuffer.substring(start, offset)); - } - - ret = removeWs(offset); - offset += ret; - sum += ret; - - ret = parseString(offset, "=", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - - ret = removeWs(offset); - offset += ret; - sum += ret; - - start = offset; - ret = parseLangVal(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamValue(mBuffer.substring(start, offset)); + + protected String getBase64(String firstString) throws IOException, VCardException { + StringBuilder builder = new StringBuilder(); + builder.append(firstString); + + while (true) { + String line = getLine(); + if (line == null) { + throw new VCardException( + "File ended during parsing BASE64 binary"); + } + if (line.length() == 0) { + break; + } + builder.append(line); } - - return sum; - + + return builder.toString(); } - - /** "X-" word [ws] "=" [ws] word */ - private int parseParam5(int offset) { - int ret = 0, sum = 0, start = offset; - - ret = parseXWord(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; - if (mBuilder != null) { - mBuilder.propertyParamType(mBuffer.substring(start, offset)); - } - - ret = removeWs(offset); - offset += ret; - sum += ret; - - ret = parseString(offset, "=", false); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + + /** + * Mainly for "ADR", "ORG", and "N" + * We do not care the number of strnosemi here. + * + * addressparts = 0*6(strnosemi ";") strnosemi + * ; PO Box, Extended Addr, Street, Locality, Region, + * Postal Code, Country Name + * orgparts = *(strnosemi ";") strnosemi + * ; First is Organization Name, + * remainder are Organization Units. + * nameparts = 0*4(strnosemi ";") strnosemi + * ; Family, Given, Middle, Prefix, Suffix. + * ; Example:Public;John;Q.;Reverend Dr.;III, Esq. + * strnosemi = *(*nonsemi ("\;" / "\" CRLF)) *nonsemi + * ; To include a semicolon in this string, it must be escaped + * ; with a "\" character. + * + * We are not sure whether we should add "\" CRLF to each value. + * For now, we exclude them. + */ + protected void handleMultiplePropertyValue( + String propertyName, String propertyValue) throws IOException, VCardException { + // vCard 2.1 does not allow QUOTED-PRINTABLE here, but some data have it. + if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) { + propertyValue = getQuotedPrintable(propertyValue); + } + + if (propertyValue.endsWith("\\")) { + StringBuilder builder = new StringBuilder(); + // builder.append(propertyValue); + builder.append(propertyValue.substring(0, propertyValue.length() - 1)); + try { + String line; + while (true) { + line = getNonEmptyLine(); + // builder.append("\r\n"); + // builder.append(line); + if (!line.endsWith("\\")) { + builder.append(line); + break; + } else { + builder.append(line.substring(0, line.length() - 1)); + } + } + } catch (IOException e) { + throw new VCardException( + "IOException is throw during reading propertyValue" + e); + } + // Now, propertyValue may contain "\r\n" + propertyValue = builder.toString(); } - offset += ret; - sum += ret; - ret = removeWs(offset); - offset += ret; - sum += ret; - - start = offset; - ret = parseWord(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; - } - offset += ret; - sum += ret; if (mBuilder != null) { - mBuilder.propertyParamValue(mBuffer.substring(start, offset)); + // In String#replaceAll() and Pattern class, "\\\\" means single slash. + + final String IMPOSSIBLE_STRING = "\0"; + // First replace two backslashes with impossible strings. + propertyValue = propertyValue.replaceAll("\\\\\\\\", IMPOSSIBLE_STRING); + + // Now, split propertyValue with ; whose previous char is not back slash. + Pattern pattern = Pattern.compile("(?<!\\\\);"); + // TODO: limit should be set in accordance with propertyName? + String[] strArray = pattern.split(propertyValue, -1); + ArrayList<String> arrayList = new ArrayList<String>(); + for (String str : strArray) { + // Replace impossible strings with original two backslashes + arrayList.add( + unescapeText(str.replaceAll(IMPOSSIBLE_STRING, "\\\\\\\\"))); + } + mBuilder.propertyValues(arrayList); } - - return sum; } - + /** - * knowntype: "DOM" / "INTL" / ... + * vCard 2.1 specifies AGENT allows one vcard entry. It is not encoded at all. */ - private int parseKnownType(int offset) { - String word = getWord(offset); - - if (mKnownTypeSet.contains(word.toUpperCase())) { - return word.length(); - } - return PARSE_ERROR; + protected void handleAgent(String propertyValue) throws IOException, VCardException { + String[] strArray = propertyValue.split(":", 2); + if (!(strArray.length == 2 || + strArray[0].trim().equalsIgnoreCase("BEGIN") && + strArray[1].trim().equalsIgnoreCase("VCARD"))) { + throw new VCardException("BEGIN:VCARD != \"" + propertyValue + "\""); + } + parseItems(); + readEndVCard(); } - - /** knowntype / "X-" word */ - private int parsePTypeVal(int offset) { - int ret = 0, sum = 0; - - ret = parseKnownType(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - - ret = parseXWord(offset); - if (ret != PARSE_ERROR) { - sum += ret; - return sum; - } - sum += ret; - - return sum; + + /** + * For vCard 3.0. + */ + protected String maybeUnescapeText(String text) { + return text; } - - /** "LOGO" /.../ XWord, case insensitive */ - private int parseName(int offset) { - int ret = 0; - ret = parseXWord(offset); - if (ret != PARSE_ERROR) { - return ret; - } - String word = getWord(offset).toUpperCase(); - if (mName.contains(word)) { - return word.length(); - } - return PARSE_ERROR; + + /** + * Convert escaped text into unescaped text. + */ + protected String unescapeText(String text) { + // Original vCard 2.1 specification does not allow transformation + // "\:" -> ":", "\," -> ",", and "\\" -> "\", but previous implementation of + // this class allowed them, so keep it as is. + // In String#replaceAll(), "\\\\" means single slash. + return text.replaceAll("\\\\;", ";") + .replaceAll("\\\\:", ":") + .replaceAll("\\\\,", ",") + .replaceAll("\\\\\\\\", "\\\\"); } + + /** + * Parse the given stream and constructs VCardDataBuilder object. + * Note that vCard 2.1 specification allows "CHARSET" parameter, and some career sets + * local encoding to it. For example, Japanese phone career uses Shift_JIS, which + * is not formally allowed in vCard specification. + * As a result, there is a case where the encoding given here does not do well with + * the "CHARSET". + * + * In order to avoid such cases, It may be fine to use "ISO-8859-1" as an encoding, + * and to encode each localized String afterward. + * + * RFC 2426 "recommends" (not forces) to use UTF-8, so it may be OK to use + * UTF-8 as an encoding when parsing vCard 3.0. But note that some Japanese + * phone uses Shift_JIS as a charset (e.g. W61SH), and another uses + * "CHARSET=SHIFT_JIS", which is explicitly prohibited in vCard 3.0 specification + * (e.g. W53K). + * + * @param is + * The source to parse. + * @param charset + * The charset. + * @param builder + * The v builder which used to construct data. + * @return Return true for success, otherwise false. + * @throws IOException + */ + public boolean parse(InputStream is, String charset, VBuilder builder) + throws IOException, VCardException { + // TODO: If we really need to allow only CRLF as line break, + // we will have to develop our own BufferedReader(). + mReader = new BufferedReader(new InputStreamReader(is, charset)); + + mBuilder = builder; - /** groups "." word / word */ - private int parseGroups(int offset) { - int ret = 0, sum = 0; - - ret = parseWord(offset); - if (ret == PARSE_ERROR) { - return PARSE_ERROR; + if (mBuilder != null) { + mBuilder.start(); } - offset += ret; - sum += ret; - - for (;;) { - ret = parseString(offset, ".", false); - if (ret == PARSE_ERROR) { - break; - } - - int ret1 = parseWord(offset); - if (ret1 == PARSE_ERROR) { - break; - } - offset += ret + ret1; - sum += ret + ret1; + parseVCardFile(); + if (mBuilder != null) { + mBuilder.end(); } - return sum; + return true; } - - /** - * Translate escape characters("\\", "\;") which define in vcard2.1 spec. - * But for fault tolerance, we will translate "\:" and "\,", which isn't - * define in vcard2.1 explicitly, as the same behavior as other client. - * - * @param str: - * the string will be translated. - * @return the string which do not contain any escape character in vcard2.1 - */ - private String escapeTranslator(String str) { - if (null == str) - return null; - - String tmp = str.replace("\\\\", "\n\r\n"); - tmp = tmp.replace("\\;", ";"); - tmp = tmp.replace("\\:", ":"); - tmp = tmp.replace("\\,", ","); - tmp = tmp.replace("\n\r\n", "\\"); - return tmp; + + private boolean isLetter(char ch) { + if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { + return true; + } + return false; } } diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V30.java b/core/java/android/syncml/pim/vcard/VCardParser_V30.java index c56cfed..901bd49 100644 --- a/core/java/android/syncml/pim/vcard/VCardParser_V30.java +++ b/core/java/android/syncml/pim/vcard/VCardParser_V30.java @@ -16,142 +16,270 @@ package android.syncml.pim.vcard; -import android.syncml.pim.VBuilder; - -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; /** * This class is used to parse vcard3.0. <br> - * It get useful data refer from android contact, and alter to vCard 2.1 format. - * Then reuse vcard 2.1 parser to analyze the result.<br> - * Please refer to vCard Specification 3.0 + * Please refer to vCard Specification 3.0 (http://tools.ietf.org/html/rfc2426) */ public class VCardParser_V30 extends VCardParser_V21 { - private static final String V21LINEBREAKER = "\r\n"; - private static final HashSet<String> acceptablePropsWithParam = new HashSet<String>( - Arrays.asList("PHOTO", "LOGO", "TEL", "EMAIL", "ADR")); - - private static final HashSet<String> acceptablePropsWithoutParam = new HashSet<String>( - Arrays.asList("ORG", "NOTE", "TITLE", "FN", "N")); - - private static final HashMap<String, String> propV30ToV21Map = new HashMap<String, String>(); + Arrays.asList( + "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", + "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL", + "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER", // 2.1 + "NAME", "PROFILE", "SOURCE", "NICKNAME", "CLASS", + "SORT-STRING", "CATEGORIES", "PRODID")); // 3.0 + + // Although "7bit" and "BASE64" is not allowed in vCard 3.0, we allow it for safety. + private static final HashSet<String> sAcceptableEncodingV30 = new HashSet<String>( + Arrays.asList("7BIT", "8BIT", "BASE64", "B")); + + // Although RFC 2426 specifies some property must not have parameters, we allow it, + // since there may be some careers which violates the RFC... + private static final HashSet<String> acceptablePropsWithoutParam = new HashSet<String>(); - static { - propV30ToV21Map.put("PHOTO", "PHOTO"); - propV30ToV21Map.put("LOGO", "PHOTO"); + private String mPreviousLine; + + @Override + protected String getVersion() { + return "3.0"; } - + @Override - public boolean parse(InputStream is, String encoding, VBuilder builder) - throws IOException { - // get useful info for android contact, and alter to vCard 2.1 - byte[] bytes = new byte[is.available()]; - is.read(bytes); - String scStr = new String(bytes); - StringBuilder v21str = new StringBuilder(""); - - String[] strlist = splitProperty(scStr); - - if ("BEGIN:vCard".equals(strlist[0]) - || "BEGIN:VCARD".equals(strlist[0])) { - v21str.append("BEGIN:VCARD" + V21LINEBREAKER); + protected boolean isValidPropertyName(String propertyName) { + return acceptablePropsWithParam.contains(propertyName) || + acceptablePropsWithoutParam.contains(propertyName); + } + + @Override + protected boolean isValidEncoding(String encoding) { + return sAcceptableEncodingV30.contains(encoding.toUpperCase()); + } + + @Override + protected String getLine() throws IOException { + if (mPreviousLine != null) { + String ret = mPreviousLine; + mPreviousLine = null; + return ret; } else { - return false; + return mReader.readLine(); } - - for (int i = 1; i < strlist.length - 1; i++) {// for ever property - // line - String propName; - String params; - String value; - - String line = strlist[i]; - if ("".equals(line)) { // line breaker is useful in encoding string - v21str.append(V21LINEBREAKER); - continue; - } - - String[] contentline = line.split(":", 2); - String propNameAndParam = contentline[0]; - value = (contentline.length > 1) ? contentline[1] : ""; - if (propNameAndParam.length() > 0) { - String[] nameAndParams = propNameAndParam.split(";", 2); - propName = nameAndParams[0]; - params = (nameAndParams.length > 1) ? nameAndParams[1] : ""; - - if (acceptablePropsWithParam.contains(propName) - || acceptablePropsWithoutParam.contains(propName)) { - v21str.append(mapContentlineV30ToV21(propName, params, - value)); + } + + /** + * vCard 3.0 requires that the line with space at the beginning of the line + * must be combined with previous line. + */ + @Override + protected String getNonEmptyLine() throws IOException, VCardException { + String line; + StringBuilder builder = null; + while (true) { + line = mReader.readLine(); + if (line == null) { + if (builder != null) { + return builder.toString(); + } else if (mPreviousLine != null) { + String ret = mPreviousLine; + mPreviousLine = null; + return ret; + } + throw new VCardException("Reached end of buffer."); + } else if (line.length() == 0) { + if (builder != null) { + return builder.toString(); + } else if (mPreviousLine != null) { + String ret = mPreviousLine; + mPreviousLine = null; + return ret; + } + } else if (line.charAt(0) == ' ' || line.charAt(0) == '\t') { + if (builder != null) { + // TODO: Check whether MIME requires only one whitespace. + builder.append(line.substring(1)); + } else if (mPreviousLine != null) { + builder = new StringBuilder(); + builder.append(mPreviousLine); + mPreviousLine = null; + builder.append(line.substring(1)); + } else { + throw new VCardException("Space exists at the beginning of the line"); + } + } else { + if (mPreviousLine == null) { + mPreviousLine = line; + } else { + String ret = mPreviousLine; + mPreviousLine = line; + return ret; } } - }// end for - - if ("END:vCard".equals(strlist[strlist.length - 1]) - || "END:VCARD".equals(strlist[strlist.length - 1])) { - v21str.append("END:VCARD" + V21LINEBREAKER); - } else { - return false; } - - return super.parse( - // use vCard 2.1 parser - new ByteArrayInputStream(v21str.toString().getBytes()), - encoding, builder); } - + + /** - * Convert V30 string to V21 string - * - * @param propName - * The name of property - * @param params - * parameter of property - * @param value - * value of property - * @return the converted string + * vcard = [group "."] "BEGIN" ":" "VCARD" 1*CRLF + * 1*(contentline) + * ;A vCard object MUST include the VERSION, FN and N types. + * [group "."] "END" ":" "VCARD" 1*CRLF */ - private String mapContentlineV30ToV21(String propName, String params, - String value) { - String result; + @Override + protected boolean readBeginVCard() throws IOException, VCardException { + // TODO: vCard 3.0 supports group. + return super.readBeginVCard(); + } + + @Override + protected void readEndVCard() throws VCardException { + // TODO: vCard 3.0 supports group. + super.readEndVCard(); + } - if (propV30ToV21Map.containsKey(propName)) { - result = propV30ToV21Map.get(propName); - } else { - result = propName; + /** + * vCard 3.0 allows iana-token as paramType, while vCard 2.1 does not. + */ + @Override + protected void handleParams(String params) throws VCardException { + try { + super.handleParams(params); + } catch (VCardException e) { + // maybe IANA type + String[] strArray = params.split("=", 2); + if (strArray.length == 2) { + handleAnyParam(strArray[0], strArray[1]); + } else { + // Must not come here in the current implementation. + throw new VCardException( + "Unknown params value: " + params); + } + } + } + + @Override + protected void handleAnyParam(String paramName, String paramValue) { + // vCard 3.0 accept comma-separated multiple values, but + // current PropertyNode does not accept it. + // For now, we do not split the values. + // + // TODO: fix this. + super.handleAnyParam(paramName, paramValue); + } + + /** + * vCard 3.0 defines + * + * param = param-name "=" param-value *("," param-value) + * param-name = iana-token / x-name + * param-value = ptext / quoted-string + * quoted-string = DQUOTE QSAFE-CHAR DQUOTE + */ + @Override + protected void handleType(String ptypevalues) { + String[] ptypeArray = ptypevalues.split(","); + mBuilder.propertyParamType("TYPE"); + for (String value : ptypeArray) { + int length = value.length(); + if (length >= 2 && value.startsWith("\"") && value.endsWith("\"")) { + mBuilder.propertyParamValue(value.substring(1, value.length() - 1)); + } else { + mBuilder.propertyParamValue(value); + } } - // Alter parameter part of property to vCard 2.1 format - if (acceptablePropsWithParam.contains(propName) && params.length() > 0) - result = result - + ";" - + params.replaceAll(",", ";").replaceAll("ENCODING=B", - "ENCODING=BASE64").replaceAll("ENCODING=b", - "ENCODING=BASE64"); + } - return result + ":" + value + V21LINEBREAKER; + @Override + protected void handleAgent(String propertyValue) throws VCardException { + // The way how vCard 3.0 supports "AGENT" is completely different from vCard 2.0. + // + // e.g. + // AGENT:BEGIN:VCARD\nFN:Joe Friday\nTEL:+1-919-555-7878\n + // TITLE:Area Administrator\, Assistant\n EMAIL\;TYPE=INTERN\n + // ET:jfriday@host.com\nEND:VCARD\n + // + // TODO: fix this. + // + // issue: + // vCard 3.0 also allows this as an example. + // + // AGENT;VALUE=uri: + // CID:JQPUBLIC.part3.960129T083020.xyzMail@host3.com + // + // This is not VCARD. Should we support this? + throw new VCardException("AGENT in vCard 3.0 is not supported yet."); + } + + // vCard 3.0 supports "B" as BASE64 encoding. + @Override + protected void handlePropertyValue( + String propertyName, String propertyValue) throws + IOException, VCardException { + if (mEncoding != null && mEncoding.equalsIgnoreCase("B")) { + String result = getBase64(propertyValue); + if (mBuilder != null) { + ArrayList<String> v = new ArrayList<String>(); + v.add(result); + mBuilder.propertyValues(v); + } + } + + super.handlePropertyValue(propertyName, propertyValue); + } + + /** + * vCard 3.0 does not require two CRLF at the last of BASE64 data. + * It only requires that data should be MIME-encoded. + */ + @Override + protected String getBase64(String firstString) throws IOException, VCardException { + StringBuilder builder = new StringBuilder(); + builder.append(firstString); + + while (true) { + String line = getLine(); + if (line == null) { + throw new VCardException( + "File ended during parsing BASE64 binary"); + } + if (line.length() == 0) { + break; + } else if (!line.startsWith(" ") && !line.startsWith("\t")) { + mPreviousLine = line; + break; + } + builder.append(line); + } + + return builder.toString(); + } + + /** + * Return unescapeText(text). + * In vCard 3.0, 8bit text is always encoded. + */ + @Override + protected String maybeUnescapeText(String text) { + return unescapeText(text); } /** - * Split ever property line to Stringp[], not split folding line. - * - * @param scStr - * the string to be splitted - * @return a list of splitted string + * ESCAPED-CHAR = "\\" / "\;" / "\," / "\n" / "\N") + * ; \\ encodes \, \n or \N encodes newline + * ; \; encodes ;, \, encodes , */ - private String[] splitProperty(String scStr) { - /* - * Property splitted by \n, and unfold folding lines by removing - * CRLF+LWSP-char - */ - scStr = scStr.replaceAll("\r\n", "\n").replaceAll("\n ", "") - .replaceAll("\n\t", ""); - String[] strs = scStr.split("\n"); - return strs; + @Override + protected String unescapeText(String text) { + // In String#replaceAll(), "\\\\" means single slash. + return text.replaceAll("\\\\;", ";") + .replaceAll("\\\\:", ":") + .replaceAll("\\\\,", ",") + .replaceAll("\\\\n", "\r\n") + .replaceAll("\\\\N", "\r\n") + .replaceAll("\\\\\\\\", "\\\\"); } } diff --git a/core/java/android/syncml/pim/vcard/VCardVersionException.java b/core/java/android/syncml/pim/vcard/VCardVersionException.java new file mode 100644 index 0000000..1ca88d1 --- /dev/null +++ b/core/java/android/syncml/pim/vcard/VCardVersionException.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2009 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.syncml.pim.vcard; + +/** + * VCardException used only when the version of the vCard is different. + */ +public class VCardVersionException extends VCardException { + public VCardVersionException() { + } + + public VCardVersionException(String message) { + super(message); + } +} diff --git a/core/java/android/text/AutoText.java b/core/java/android/text/AutoText.java index 508d740..2fc906a 100644 --- a/core/java/android/text/AutoText.java +++ b/core/java/android/text/AutoText.java @@ -69,6 +69,7 @@ public class AutoText { private char mTrieUsed; private String mText; private Locale mLocale; + private int mSize; private AutoText(Resources resources) { mLocale = resources.getConfiguration().locale; @@ -76,12 +77,12 @@ public class AutoText { } /** - * Retrieves a possible spelling correction for the specified range - * of text. Returns null if no correction can be found. - * The View is used to get the current Locale and Resources. + * Returns the instance of AutoText. If the locale has changed, it will create a new + * instance of AutoText for the locale. + * @param view to get the resources from + * @return the single instance of AutoText */ - public static String get(CharSequence src, final int start, final int end, - View view) { + private static AutoText getInstance(View view) { Resources res = view.getContext().getResources(); Locale locale = res.getConfiguration().locale; AutoText instance; @@ -94,8 +95,36 @@ public class AutoText { sInstance = instance; } } + + return instance; + } + + /** + * Retrieves a possible spelling correction for the specified range + * of text. Returns null if no correction can be found. + * The View is used to get the current Locale and Resources. + */ + public static String get(CharSequence src, final int start, final int end, + View view) { + return getInstance(view).lookup(src, start, end); + } + + /** + * Returns the size of the auto text dictionary. The return value can be zero if there is + * no auto correction data available for the current locale. + * @param view used to retrieve the current Locale and Resources. + * @return the number of entries in the auto text dictionary + */ + public static int getSize(View view) { - return instance.lookup(src, start, end); + return getInstance(view).getSize(); + } + + /** + * Returns the size of the dictionary. + */ + private int getSize() { + return mSize; } private String lookup(CharSequence src, final int start, final int end) { @@ -181,7 +210,9 @@ public class AutoText { private void add(String src, char off) { int slen = src.length(); int herep = TRIE_ROOT; - + // Keep track of the size of the dictionary + mSize++; + for (int i = 0; i < slen; i++) { char c = src.charAt(i); boolean found = false; diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java index 8495714..70e1297 100644 --- a/core/java/android/text/Html.java +++ b/core/java/android/text/Html.java @@ -28,6 +28,8 @@ import org.xml.sax.XMLReader; import android.content.res.Resources; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.text.style.AbsoluteSizeSpan; +import android.text.style.AlignmentSpan; import android.text.style.CharacterStyle; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; @@ -41,6 +43,7 @@ import android.text.style.SuperscriptSpan; import android.text.style.TypefaceSpan; import android.text.style.URLSpan; import android.text.style.UnderlineSpan; +import android.util.Log; import com.android.internal.util.XmlUtils; import java.io.IOException; @@ -137,11 +140,51 @@ public class Html { */ public static String toHtml(Spanned text) { StringBuilder out = new StringBuilder(); + withinHtml(out, text); + return out.toString(); + } + + private static void withinHtml(StringBuilder out, Spanned text) { int len = text.length(); int next; for (int i = 0; i < text.length(); i = next) { - next = text.nextSpanTransition(i, len, QuoteSpan.class); + next = text.nextSpanTransition(i, len, ParagraphStyle.class); + ParagraphStyle[] style = text.getSpans(i, next, ParagraphStyle.class); + String elements = " "; + boolean needDiv = false; + + for(int j = 0; j < style.length; j++) { + if (style[j] instanceof AlignmentSpan) { + Layout.Alignment align = + ((AlignmentSpan) style[j]).getAlignment(); + needDiv = true; + if (align == Layout.Alignment.ALIGN_CENTER) { + elements = "align=\"center\" " + elements; + } else if (align == Layout.Alignment.ALIGN_OPPOSITE) { + elements = "align=\"right\" " + elements; + } else { + elements = "align=\"left\" " + elements; + } + } + } + if (needDiv) { + out.append("<div " + elements + ">"); + } + + withinDiv(out, text, i, next); + + if (needDiv) { + out.append("</div>"); + } + } + } + + private static void withinDiv(StringBuilder out, Spanned text, + int start, int end) { + int next; + for (int i = start; i < end; i = next) { + next = text.nextSpanTransition(i, end, QuoteSpan.class); QuoteSpan[] quotes = text.getSpans(i, next, QuoteSpan.class); for (QuoteSpan quote: quotes) { @@ -154,8 +197,6 @@ public class Html { out.append("</blockquote>\n"); } } - - return out.toString(); } private static void withinBlockquote(StringBuilder out, Spanned text, @@ -234,11 +275,32 @@ public class Html { // Don't output the dummy character underlying the image. i = next; } + if (style[j] instanceof AbsoluteSizeSpan) { + out.append("<font size =\""); + out.append(((AbsoluteSizeSpan) style[j]).getSize() / 6); + out.append("\">"); + } + if (style[j] instanceof ForegroundColorSpan) { + out.append("<font color =\"#"); + String color = Integer.toHexString(((ForegroundColorSpan) + style[j]).getForegroundColor() + 0x01000000); + while (color.length() < 6) { + color = "0" + color; + } + out.append(color); + out.append("\">"); + } } withinStyle(out, text, i, next); for (int j = style.length - 1; j >= 0; j--) { + if (style[j] instanceof ForegroundColorSpan) { + out.append("</font>"); + } + if (style[j] instanceof AbsoluteSizeSpan) { + out.append("</font>"); + } if (style[j] instanceof URLSpan) { out.append("</a>"); } diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 95acf9d..a6ed922 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -16,9 +16,12 @@ package android.text; +import android.emoji.EmojiFactory; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Path; import com.android.internal.util.ArrayUtils; import android.util.Config; @@ -36,6 +39,22 @@ import android.view.KeyEvent; * For text that will not change, use a {@link StaticLayout}. */ public abstract class Layout { + /* package */ static final EmojiFactory EMOJI_FACTORY = + EmojiFactory.newAvailableInstance(); + /* package */ static final int MIN_EMOJI, MAX_EMOJI; + + static { + if (EMOJI_FACTORY != null) { + MIN_EMOJI = EMOJI_FACTORY.getMinimumAndroidPua(); + MAX_EMOJI = EMOJI_FACTORY.getMaximumAndroidPua(); + } else { + MIN_EMOJI = -1; + MAX_EMOJI = -1; + } + }; + + private RectF mEmojiRect; + /** * Return how wide a layout would be necessary to display the * specified text with one line per paragraph. @@ -445,7 +464,9 @@ public abstract class Layout { public abstract int getParagraphDirection(int line); /** - * Returns whether the specified line contains one or more tabs. + * Returns whether the specified line contains one or more + * characters that need to be handled specially, like tabs + * or emoji. */ public abstract boolean getLineContainsTab(int line); @@ -1309,7 +1330,7 @@ public abstract class Layout { return right; } - private static void drawText(Canvas canvas, + private void drawText(Canvas canvas, CharSequence text, int start, int end, int dir, Directions directions, float x, int top, int y, int bottom, @@ -1352,6 +1373,44 @@ public abstract class Layout { h = dir * nextTab(text, start, end, h * dir, parspans); segstart = j + 1; + } else if (hasTabs && buf[j] >= 0xD800 && buf[j] <= 0xDFFF && j + 1 < there) { + int emoji = Character.codePointAt(buf, j); + + if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) { + Bitmap bm = EMOJI_FACTORY. + getBitmapFromAndroidPua(emoji); + + if (bm != null) { + h += Styled.drawText(canvas, text, + start + segstart, start + j, + dir, (i & 1) != 0, x + h, + top, y, bottom, paint, workPaint, + start + j != end); + + if (mEmojiRect == null) { + mEmojiRect = new RectF(); + } + + workPaint.set(paint); + Styled.measureText(paint, workPaint, text, + start + j, start + j + 1, + null); + + float bitmapHeight = bm.getHeight(); + float textHeight = -workPaint.ascent(); + float scale = textHeight / bitmapHeight; + float width = bm.getWidth() * scale; + + mEmojiRect.set(x + h, y - textHeight, + x + h + width, y); + + canvas.drawBitmap(bm, null, mEmojiRect, paint); + h += width; + + j++; + segstart = j + 1; + } + } } } @@ -1394,7 +1453,22 @@ public abstract class Layout { int segstart = here; for (int j = hasTabs ? here : there; j <= there; j++) { - if (j == there || buf[j] == '\t') { + int codept = 0; + Bitmap bm = null; + + if (hasTabs && j < there) { + codept = buf[j]; + } + + if (codept >= 0xD800 && codept <= 0xDFFF && j + 1 < there) { + codept = Character.codePointAt(buf, j); + + if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) { + bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept); + } + } + + if (j == there || codept == '\t' || bm != null) { float segw; if (offset < start + j || @@ -1449,6 +1523,23 @@ public abstract class Layout { h = dir * nextTab(text, start, end, h * dir, tabs); } + if (bm != null) { + workPaint.set(paint); + Styled.measureText(paint, workPaint, text, + offset, offset + 1, null); + + float wid = (float) bm.getWidth() * + -workPaint.ascent() / bm.getHeight(); + + if (dir == DIR_RIGHT_TO_LEFT) { + h -= wid; + } else { + h += wid; + } + + j++; + } + segstart = j + 1; } } @@ -1488,7 +1579,22 @@ public abstract class Layout { } for (int i = hasTabs ? 0 : len; i <= len; i++) { - if (i == len || buf[i] == '\t') { + int codept = 0; + Bitmap bm = null; + + if (hasTabs && i < len) { + codept = buf[i]; + } + + if (codept >= 0xD800 && codept <= 0xDFFF && i < len) { + codept = Character.codePointAt(buf, i); + + if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) { + bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept); + } + } + + if (i == len || codept == '\t' || bm != null) { workPaint.baselineShift = 0; h += Styled.measureText(paint, workPaint, text, @@ -1505,8 +1611,21 @@ public abstract class Layout { } } - if (i != len) - h = nextTab(text, start, end, h, tabs); + if (i != len) { + if (bm == null) { + h = nextTab(text, start, end, h, tabs); + } else { + workPaint.set(paint); + Styled.measureText(paint, workPaint, text, + start + i, start + i + 1, null); + + float wid = (float) bm.getWidth() * + -workPaint.ascent() / bm.getHeight(); + + h += wid; + i++; + } + } if (fm != null) { if (fm.ascent < ab) { @@ -1522,6 +1641,11 @@ public abstract class Layout { if (fm.bottom > bot) { bot = fm.bottom; } + + /* + * No need to take bitmap height into account here, + * since it is scaled to match the text height. + */ } here = i + 1; diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 0fef40b..686e8f5 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -16,6 +16,7 @@ package android.text; +import android.graphics.Bitmap; import android.graphics.Paint; import com.android.internal.util.ArrayUtils; import android.util.Log; @@ -421,11 +422,16 @@ extends Layout // dump(chdirs, n, "final"); - // extra: enforce that all tabs go the primary direction + // extra: enforce that all tabs and surrogate characters go the + // primary direction + // TODO: actually do directions right for surrogates for (int j = 0; j < n; j++) { - if (chs[j] == '\t') + char c = chs[j]; + + if (c == '\t' || (c >= 0xD800 && c <= 0xDFFF)) { chdirs[j] = SOR; + } } // extra: enforce that object replacements go to the @@ -548,16 +554,41 @@ extends Layout char c = chs[j - start]; float before = w; - switch (c) { - case '\n': - break; - - case '\t': + if (c == '\n') { + ; + } else if (c == '\t') { w = Layout.nextTab(sub, start, end, w, null); tab = true; - break; - - default: + } else if (c >= 0xD800 && c <= 0xDFFF && j + 1 < next) { + int emoji = Character.codePointAt(chs, j - start); + + if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) { + Bitmap bm = EMOJI_FACTORY. + getBitmapFromAndroidPua(emoji); + + if (bm != null) { + Paint whichPaint; + + if (spanned == null) { + whichPaint = paint; + } else { + whichPaint = mWorkPaint; + } + + float wid = (float) bm.getWidth() * + -whichPaint.ascent() / + bm.getHeight(); + + w += wid; + tab = true; + j++; + } else { + w += widths[j - start + (end - start)]; + } + } else { + w += widths[j - start + (end - start)]; + } + } else { w += widths[j - start + (end - start)]; } diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java index 17c7a6c..92f6289 100644 --- a/core/java/android/text/method/ArrowKeyMovementMethod.java +++ b/core/java/android/text/method/ArrowKeyMovementMethod.java @@ -18,6 +18,7 @@ package android.text.method; import android.util.Log; import android.view.KeyEvent; +import android.graphics.Rect; import android.text.*; import android.widget.TextView; import android.view.View; @@ -202,23 +203,54 @@ implements MovementMethod public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { + int initialScrollX = -1, initialScrollY = -1; + if (event.getAction() == MotionEvent.ACTION_UP) { + initialScrollX = Touch.getInitialScrollX(widget, buffer); + initialScrollY = Touch.getInitialScrollY(widget, buffer); + } + boolean handled = Touch.onTouchEvent(widget, buffer, event); if (widget.isFocused() && !widget.didTouchFocusSelect()) { if (event.getAction() == MotionEvent.ACTION_UP) { + // If we have scrolled, then the up shouldn't move the cursor, + // but we do need to make sure the cursor is still visible at + // the current scroll offset to avoid the scroll jumping later + // to show it. + if ((initialScrollY >= 0 && initialScrollY != widget.getScrollY()) || + (initialScrollX >= 0 && initialScrollX != widget.getScrollX())) { + widget.moveCursorToVisibleOffset(); + return true; + } + int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); + // Clamp the position to inside of the view. + if (x < 0) { + x = 0; + } else if (x >= (widget.getWidth()-widget.getTotalPaddingRight())) { + x = widget.getWidth()-widget.getTotalPaddingRight() - 1; + } + if (y < 0) { + y = 0; + } else if (y >= (widget.getHeight()-widget.getTotalPaddingBottom())) { + y = widget.getHeight()-widget.getTotalPaddingBottom() - 1; + } + x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); + int off = layout.getOffsetForHorizontal(line, x); + // XXX should do the same adjust for x as we do for the line. + boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java index 65036ad..f2fb9cb 100644 --- a/core/java/android/text/method/Touch.java +++ b/core/java/android/text/method/Touch.java @@ -21,7 +21,6 @@ import android.text.NoCopySpan; import android.text.Layout.Alignment; import android.text.Spannable; import android.view.MotionEvent; -import android.view.View; import android.view.ViewConfiguration; import android.widget.TextView; @@ -82,8 +81,9 @@ public class Touch { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: - buffer.setSpan(new DragState(event.getX(), event.getY()), - 0, 0, Spannable.SPAN_MARK_MARK); + buffer.setSpan(new DragState(event.getX(), event.getY(), + widget.getScrollX(), widget.getScrollY()), + 0, 0, Spannable.SPAN_MARK_MARK); return true; case MotionEvent.ACTION_UP: @@ -142,15 +142,29 @@ public class Touch { return false; } + public static int getInitialScrollX(TextView widget, Spannable buffer) { + DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class); + return ds.length > 0 ? ds[0].mScrollX : -1; + } + + public static int getInitialScrollY(TextView widget, Spannable buffer) { + DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class); + return ds.length > 0 ? ds[0].mScrollY : -1; + } + private static class DragState implements NoCopySpan { public float mX; public float mY; + public int mScrollX; + public int mScrollY; public boolean mFarEnough; public boolean mUsed; - public DragState(float x, float y) { + public DragState(float x, float y, int scrollX, int scrollY) { mX = x; mY = y; + mScrollX = scrollX; + mScrollY = scrollY; } } } diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index f7ac522..23f3e3c 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -201,8 +201,6 @@ public class GestureDetector { private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); - // TODO make new double-tap timeout, and define its events (i.e. either time - // between down-down or time between up-down) private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); // constants for Message.what used by GestureHandler below diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a856b24..5607d4b 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -59,10 +59,13 @@ interface IWindowManager void pauseKeyDispatching(IBinder token); void resumeKeyDispatching(IBinder token); void setEventDispatching(boolean enabled); + void addWindowToken(IBinder token, int type); + void removeWindowToken(IBinder token); void addAppToken(int addPos, IApplicationToken token, int groupId, int requestedOrientation, boolean fullscreen); void setAppGroupId(IBinder token, int groupId); - Configuration updateOrientationFromAppTokens(IBinder freezeThisOneIfNeeded); + Configuration updateOrientationFromAppTokens(in Configuration currentConfig, + IBinder freezeThisOneIfNeeded); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); void setFocusedApp(IBinder token, boolean moveFocusNow); @@ -80,8 +83,6 @@ interface IWindowManager void moveAppToken(int index, IBinder token); void moveAppTokensToTop(in List<IBinder> tokens); void moveAppTokensToBottom(in List<IBinder> tokens); - void addWindowToken(IBinder token, int type); - void removeWindowToken(IBinder token); // these require DISABLE_KEYGUARD permission void disableKeyguard(IBinder token, String tag); @@ -118,9 +119,9 @@ interface IWindowManager * @param alwaysSendConfiguration Flag to force a new configuration to * be evaluated. This can be used when there are other parameters in * configuration that are changing. - * {@link android.view.Surface}. + * @param animFlags Animation flags as per {@link android.view.Surface}. */ - void setRotation(int rotation, boolean alwaysSendConfiguration); + void setRotation(int rotation, boolean alwaysSendConfiguration, int animFlags); /** * Retrieve the current screen orientation, constants as per diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 430cc71..41779ba 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -235,6 +235,22 @@ public class KeyEvent implements Parcelable { public static final int FLAG_KEEP_TOUCH_MODE = 0x4; /** + * This mask is set if an event was known to come from a trusted part + * of the system. That is, the event is known to come from the user, + * and could not have been spoofed by a third party component. + */ + public static final int FLAG_FROM_SYSTEM = 0x8; + + /** + * This mask is used for compatibility, to identify enter keys that are + * coming from an IME whose enter key has been auto-labelled "next" or + * "done". This allows TextView to dispatch these as normal enter keys + * for old applications, but still do the appropriate action when + * receiving them. + */ + public static final int FLAG_EDITOR_ACTION = 0x10; + + /** * Returns the maximum keycode. */ public static int getMaxKeyCode() { @@ -440,6 +456,22 @@ public class KeyEvent implements Parcelable { } /** + * Make an exact copy of an existing key event. + */ + public KeyEvent(KeyEvent origEvent) { + mDownTime = origEvent.mDownTime; + mEventTime = origEvent.mEventTime; + mAction = origEvent.mAction; + mKeyCode = origEvent.mKeyCode; + mRepeatCount = origEvent.mRepeatCount; + mMetaState = origEvent.mMetaState; + mDeviceId = origEvent.mDeviceId; + mScancode = origEvent.mScancode; + mFlags = origEvent.mFlags; + mCharacters = origEvent.mCharacters; + } + + /** * Copy an existing key event, modifying its time and repeat count. * * @param origEvent The existing event to be copied. @@ -461,12 +493,26 @@ public class KeyEvent implements Parcelable { } /** + * Create a new key event that is the same as the given one, but whose + * event time and repeat count are replaced with the given value. + * + * @param event The existing event to be copied. This is not modified. + * @param eventTime The new event time + * (in {@link android.os.SystemClock#uptimeMillis}) of the event. + * @param newRepeat The new repeat count of the event. + */ + public static KeyEvent changeTimeRepeat(KeyEvent event, long eventTime, + int newRepeat) { + return new KeyEvent(event, eventTime, newRepeat); + } + + /** * Copy an existing key event, modifying its action. * * @param origEvent The existing event to be copied. * @param action The new action code of the event. */ - public KeyEvent(KeyEvent origEvent, int action) { + private KeyEvent(KeyEvent origEvent, int action) { mDownTime = origEvent.mDownTime; mEventTime = origEvent.mEventTime; mAction = action; @@ -481,6 +527,30 @@ public class KeyEvent implements Parcelable { } /** + * Create a new key event that is the same as the given one, but whose + * action is replaced with the given value. + * + * @param event The existing event to be copied. This is not modified. + * @param action The new action code of the event. + */ + public static KeyEvent changeAction(KeyEvent event, int action) { + return new KeyEvent(event, action); + } + + /** + * Create a new key event that is the same as the given one, but whose + * flags are replaced with the given value. + * + * @param event The existing event to be copied. This is not modified. + * @param flags The new flags constant. + */ + public static KeyEvent changeFlags(KeyEvent event, int flags) { + event = new KeyEvent(event); + event.mFlags = flags; + return event; + } + + /** * Don't use in new code, instead explicitly check * {@link #getAction()}. * diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 54ccf33..0178d63 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -118,6 +118,12 @@ public class Surface implements Parcelable { public static final int ROTATION_180 = 2; public static final int ROTATION_270 = 3; + /** + * Disable the orientation animation + * {@hide} + */ + public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001; + @SuppressWarnings("unused") private int mSurface; @SuppressWarnings("unused") @@ -226,10 +232,21 @@ public class Surface implements Parcelable { * set the orientation of the given display. * @param display * @param orientation + * @param flags + * {@hide} */ - public static native void setOrientation(int display, int orientation); + public static native void setOrientation(int display, int orientation, int flags); /** + * set the orientation of the given display. + * @param display + * @param orientation + */ + public static void setOrientation(int display, int orientation) { + setOrientation(display, orientation, 0); + } + + /** * set surface parameters. * needs to be inside open/closeTransaction block */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c3e00c4..04447ca 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3409,6 +3409,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback { if (imm != null && (mPrivateFlags & FOCUSED) != 0) { imm.focusOut(this); } + if (mPendingCheckForLongPress != null) { + removeCallbacks(mPendingCheckForLongPress); + } } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) { imm.focusIn(this); } @@ -7656,7 +7659,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { private int mOriginalWindowAttachCount; public void run() { - if (isPressed() && (mParent != null) && hasWindowFocus() + if (isPressed() && (mParent != null) && mOriginalWindowAttachCount == mWindowAttachCount) { if (performLongClick()) { mHasPerformedLongPress = true; diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 6ea7a82..f604bc5 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -19,6 +19,7 @@ package android.view; import android.util.Log; import android.util.DisplayMetrics; import android.content.res.Resources; +import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.os.Environment; @@ -800,7 +801,7 @@ public class ViewDebug { View view = root.getRootView(); if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; - dumpViewHierarchyWithProperties(group, out, 0); + dumpViewHierarchyWithProperties(group.getContext(), group, out, 0); } out.write("DONE."); out.newLine(); @@ -838,9 +839,9 @@ public class ViewDebug { return view.getClass().getName().equals(className) && view.hashCode() == hashCode; } - private static void dumpViewHierarchyWithProperties(ViewGroup group, + private static void dumpViewHierarchyWithProperties(Context context, ViewGroup group, BufferedWriter out, int level) { - if (!dumpViewWithProperties(group, out, level)) { + if (!dumpViewWithProperties(context, group, out, level)) { return; } @@ -848,14 +849,16 @@ public class ViewDebug { for (int i = 0; i < count; i++) { final View view = group.getChildAt(i); if (view instanceof ViewGroup) { - dumpViewHierarchyWithProperties((ViewGroup) view, out, level + 1); + dumpViewHierarchyWithProperties(context, (ViewGroup) view, out, level + 1); } else { - dumpViewWithProperties(view, out, level + 1); + dumpViewWithProperties(context, view, out, level + 1); } } } - private static boolean dumpViewWithProperties(View view, BufferedWriter out, int level) { + private static boolean dumpViewWithProperties(Context context, View view, + BufferedWriter out, int level) { + try { for (int i = 0; i < level; i++) { out.write(' '); @@ -864,7 +867,7 @@ public class ViewDebug { out.write('@'); out.write(Integer.toHexString(view.hashCode())); out.write(' '); - dumpViewProperties(view, out); + dumpViewProperties(context, view, out); out.newLine(); } catch (IOException e) { Log.w("View", "Error while dumping hierarchy tree"); @@ -945,23 +948,26 @@ public class ViewDebug { return methods; } - private static void dumpViewProperties(Object view, BufferedWriter out) throws IOException { - dumpViewProperties(view, out, ""); + private static void dumpViewProperties(Context context, Object view, + BufferedWriter out) throws IOException { + + dumpViewProperties(context, view, out, ""); } - private static void dumpViewProperties(Object view, BufferedWriter out, String prefix) - throws IOException { + private static void dumpViewProperties(Context context, Object view, + BufferedWriter out, String prefix) throws IOException { + Class<?> klass = view.getClass(); do { - exportFields(view, out, klass, prefix); - exportMethods(view, out, klass, prefix); + exportFields(context, view, out, klass, prefix); + exportMethods(context, view, out, klass, prefix); klass = klass.getSuperclass(); } while (klass != Object.class); } - private static void exportMethods(Object view, BufferedWriter out, Class<?> klass, - String prefix) throws IOException { + private static void exportMethods(Context context, Object view, BufferedWriter out, + Class<?> klass, String prefix) throws IOException { final Method[] methods = getExportedPropertyMethods(klass); @@ -976,9 +982,9 @@ public class ViewDebug { if (returnType == int.class) { final ExportedProperty property = sAnnotations.get(method); - if (property.resolveId() && view instanceof View) { + if (property.resolveId() && context != null) { final int id = (Integer) methodValue; - methodValue = resolveId(view, id); + methodValue = resolveId(context, id); } else { final IntToString[] mapping = property.mapping(); if (mapping.length > 0) { @@ -1005,11 +1011,11 @@ public class ViewDebug { final String valuePrefix = prefix + method.getName() + '_'; final String suffix = "()"; - exportUnrolledArray(view, out, property, array, valuePrefix, suffix); + exportUnrolledArray(context, out, property, array, valuePrefix, suffix); } else if (!returnType.isPrimitive()) { final ExportedProperty property = sAnnotations.get(method); if (property.deepExport()) { - dumpViewProperties(methodValue, out, prefix + property.prefix()); + dumpViewProperties(context, methodValue, out, prefix + property.prefix()); continue; } } @@ -1021,8 +1027,9 @@ public class ViewDebug { } } - private static void exportFields(Object view, BufferedWriter out, Class<?> klass, String prefix) - throws IOException { + private static void exportFields(Context context, Object view, BufferedWriter out, + Class<?> klass, String prefix) throws IOException { + final Field[] fields = getExportedPropertyFields(klass); int count = fields.length; @@ -1036,9 +1043,9 @@ public class ViewDebug { if (type == int.class) { final ExportedProperty property = sAnnotations.get(field); - if (property.resolveId() && view instanceof View) { + if (property.resolveId() && context != null) { final int id = field.getInt(view); - fieldValue = resolveId(view, id); + fieldValue = resolveId(context, id); } else { final IntToString[] mapping = property.mapping(); if (mapping.length > 0) { @@ -1063,14 +1070,15 @@ public class ViewDebug { final String valuePrefix = prefix + field.getName() + '_'; final String suffix = ""; - exportUnrolledArray(view, out, property, array, valuePrefix, suffix); + exportUnrolledArray(context, out, property, array, valuePrefix, suffix); // We exit here! return; } else if (!type.isPrimitive()) { final ExportedProperty property = sAnnotations.get(field); if (property.deepExport()) { - dumpViewProperties(field.get(view), out, prefix + property.prefix()); + dumpViewProperties(context, field.get(view), out, + prefix + property.prefix()); continue; } } @@ -1096,7 +1104,7 @@ public class ViewDebug { out.write(' '); } - private static void exportUnrolledArray(Object view, BufferedWriter out, + private static void exportUnrolledArray(Context context, BufferedWriter out, ExportedProperty property, int[] array, String prefix, String suffix) throws IOException { @@ -1106,7 +1114,7 @@ public class ViewDebug { final IntToString[] mapping = property.mapping(); final boolean hasMapping = mapping.length > 0; - final boolean resolveId = property.resolveId() && view instanceof View; + final boolean resolveId = property.resolveId() && context != null; final int valuesCount = array.length; for (int j = 0; j < valuesCount; j++) { @@ -1140,16 +1148,16 @@ public class ViewDebug { } if (resolveId) { - value = (String) resolveId(view, intValue); + value = (String) resolveId(context, intValue); } writeEntry(out, prefix, name, suffix, value); } } - private static Object resolveId(Object view, int id) { + private static Object resolveId(Context context, int id) { Object fieldValue; - final Resources resources = ((View) view).getContext().getResources(); + final Resources resources = context.getResources(); if (id >= 0) { try { fieldValue = resources.getResourceTypeName(id) + '/' + diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index dc7b299..e686d1c 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1208,11 +1208,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; if (clipToPadding) { saveCount = canvas.save(); - final int scrollX = mScrollX; - final int scrollY = mScrollY; - canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop, - scrollX + mRight - mLeft - mPaddingRight, - scrollY + mBottom - mTop - mPaddingBottom); + canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop, + mScrollX + mRight - mLeft - mPaddingRight, + mScrollY + mBottom - mTop - mPaddingBottom); } @@ -1346,9 +1344,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final Animation a = child.getAnimation(); boolean concatMatrix = false; - final int childWidth = cr - cl; - final int childHeight = cb - ct; - if (a != null) { if (mInvalidateRegion == null) { mInvalidateRegion = new RectF(); @@ -1357,8 +1352,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final boolean initialized = a.isInitialized(); if (!initialized) { - a.initialize(childWidth, childHeight, getWidth(), getHeight()); - a.initializeInvalidateRegion(0, 0, childWidth, childHeight); + a.initialize(cr - cl, cb - ct, getWidth(), getHeight()); + a.initializeInvalidateRegion(0, 0, cr - cl, cb - ct); child.onAnimationStart(); } @@ -1382,7 +1377,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager invalidate(cl, ct, cr, cb); } } else { - a.getInvalidateRegion(0, 0, childWidth, childHeight, region, transformToApply); + a.getInvalidateRegion(0, 0, cr - cl, cb - ct, region, transformToApply); // The child need to draw an animation, potentially offscreen, so // make sure we do not cancel invalidate requests @@ -1407,6 +1402,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } + // Clear the flag as early as possible to allow draw() implementations + // to call invalidate() successfully when doing animations + child.mPrivateFlags |= DRAWN; + if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) && (child.mPrivateFlags & DRAW_ANIMATION) == 0) { return more; @@ -1470,16 +1469,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) { if (hasNoCache) { - canvas.clipRect(sx, sy, sx + childWidth, sy + childHeight); + canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct)); } else { - canvas.clipRect(0, 0, childWidth, childHeight); + canvas.clipRect(0, 0, cr - cl, cb - ct); } } - // Clear the flag as early as possible to allow draw() implementations - // to call invalidate() successfully when doing animations - child.mPrivateFlags |= DRAWN; - if (hasNoCache) { // Fast path for layouts with no backgrounds if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { @@ -2327,8 +2322,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION; do { - if (drawAnimation && parent instanceof View) { - ((View) parent).mPrivateFlags |= DRAW_ANIMATION; + if (drawAnimation) { + if (parent instanceof View) { + ((View) parent).mPrivateFlags |= DRAW_ANIMATION; + } else if (parent instanceof ViewRoot) { + ((ViewRoot) parent).mIsAnimating = true; + } } parent = parent.invalidateChildInParent(location, dirty); } while (parent != null); diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index dd2b154..18ee9ae 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -33,7 +33,6 @@ import android.util.Config; import android.util.Log; import android.util.EventLog; import android.util.SparseArray; -import android.util.DisplayMetrics; import android.view.View.MeasureSpec; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; @@ -128,6 +127,7 @@ public final class ViewRoot extends Handler implements ViewParent, int mWidth; int mHeight; Rect mDirty; // will be a graphics.Region soon + boolean mIsAnimating; final View.AttachInfo mAttachInfo; @@ -470,11 +470,20 @@ public final class ViewRoot extends Handler implements ViewParent, void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { synchronized (this) { + int oldSoftInputMode = mWindowAttributes.softInputMode; mWindowAttributes.copyFrom(attrs); if (newView) { mSoftInputMode = attrs.softInputMode; requestLayout(); } + // Don't lose the mode we last auto-computed. + if ((attrs.softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) + == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) { + mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode + & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) + | (oldSoftInputMode + & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST); + } mWindowAttributesChanged = true; scheduleTraversals(); } @@ -1174,7 +1183,7 @@ public final class ViewRoot extends Handler implements ViewParent, } try { - if (!dirty.isEmpty()) { + if (!dirty.isEmpty() || mIsAnimating) { long startTime; if (DEBUG_ORIENTATION || DEBUG_DRAW) { @@ -1201,6 +1210,7 @@ public final class ViewRoot extends Handler implements ViewParent, } dirty.setEmpty(); + mIsAnimating = false; mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); canvas.translate(0, -yoff); mView.mPrivateFlags |= View.DRAWN; @@ -1485,7 +1495,7 @@ public final class ViewRoot extends Handler implements ViewParent, + msg.obj + " to " + mView); deliverKeyEvent((KeyEvent)msg.obj, true); break; - case DISPATCH_POINTER: + case DISPATCH_POINTER: { MotionEvent event = (MotionEvent)msg.obj; boolean didFinish; @@ -1571,7 +1581,7 @@ public final class ViewRoot extends Handler implements ViewParent, // Let the exception fall through -- the looper will catch // it and take care of the bad app for us. } - break; + } break; case DISPATCH_TRACKBALL: deliverTrackballEvent((MotionEvent)msg.obj); break; @@ -1657,12 +1667,19 @@ public final class ViewRoot extends Handler implements ViewParent, case DIE: dispatchDetachedFromWindow(); break; - case DISPATCH_KEY_FROM_IME: + case DISPATCH_KEY_FROM_IME: { if (LOCAL_LOGV) Log.v( "ViewRoot", "Dispatching key " + msg.obj + " from IME to " + mView); + KeyEvent event = (KeyEvent)msg.obj; + if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) { + // The IME is trying to say this event is from the + // system! Bad bad bad! + event = KeyEvent.changeFlags(event, + event.getFlags()&~KeyEvent.FLAG_FROM_SYSTEM); + } deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false); - break; + } break; case FINISH_INPUT_CONNECTION: { InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) { diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index 47b52e4..4230afa 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -18,7 +18,7 @@ package android.view; import android.graphics.Rect; -import java.util.ArrayList; +import java.util.concurrent.CopyOnWriteArrayList; /** * A view tree observer is used to register listeners that can be notified of global @@ -30,12 +30,12 @@ import java.util.ArrayList; * for more information. */ public final class ViewTreeObserver { - private ArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; - private ArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners; - private ArrayList<OnPreDrawListener> mOnPreDrawListeners; - private ArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; - private ArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; - private ArrayList<OnScrollChangedListener> mOnScrollChangedListeners; + private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; + private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners; + private CopyOnWriteArrayList<OnPreDrawListener> mOnPreDrawListeners; + private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; + private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; + private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners; private boolean mAlive = true; @@ -283,7 +283,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalFocusListeners == null) { - mOnGlobalFocusListeners = new ArrayList<OnGlobalFocusChangeListener>(); + mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>(); } mOnGlobalFocusListeners.add(listener); @@ -318,7 +318,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalLayoutListeners == null) { - mOnGlobalLayoutListeners = new ArrayList<OnGlobalLayoutListener>(); + mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>(); } mOnGlobalLayoutListeners.add(listener); @@ -352,7 +352,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnPreDrawListeners == null) { - mOnPreDrawListeners = new ArrayList<OnPreDrawListener>(); + mOnPreDrawListeners = new CopyOnWriteArrayList<OnPreDrawListener>(); } mOnPreDrawListeners.add(listener); @@ -388,7 +388,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnScrollChangedListeners == null) { - mOnScrollChangedListeners = new ArrayList<OnScrollChangedListener>(); + mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>(); } mOnScrollChangedListeners.add(listener); @@ -424,7 +424,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnTouchModeChangeListeners == null) { - mOnTouchModeChangeListeners = new ArrayList<OnTouchModeChangeListener>(); + mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>(); } mOnTouchModeChangeListeners.add(listener); @@ -460,7 +460,8 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnComputeInternalInsetsListeners == null) { - mOnComputeInternalInsetsListeners = new ArrayList<OnComputeInternalInsetsListener>(); + mOnComputeInternalInsetsListeners = + new CopyOnWriteArrayList<OnComputeInternalInsetsListener>(); } mOnComputeInternalInsetsListeners.add(listener); @@ -518,11 +519,14 @@ public final class ViewTreeObserver { * Notifies registered listeners that focus has changed. */ final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) { - final ArrayList<OnGlobalFocusChangeListener> globaFocusListeners = mOnGlobalFocusListeners; - if (globaFocusListeners != null) { - final int count = globaFocusListeners.size(); - for (int i = count - 1; i >= 0; i--) { - globaFocusListeners.get(i).onGlobalFocusChanged(oldFocus, newFocus); + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners; + if (listeners != null) { + for (OnGlobalFocusChangeListener listener : listeners) { + listener.onGlobalFocusChanged(oldFocus, newFocus); } } } @@ -533,11 +537,14 @@ public final class ViewTreeObserver { * not attached to a Window or in the GONE state. */ public final void dispatchOnGlobalLayout() { - final ArrayList<OnGlobalLayoutListener> globaLayoutListeners = mOnGlobalLayoutListeners; - if (globaLayoutListeners != null) { - final int count = globaLayoutListeners.size(); - for (int i = count - 1; i >= 0; i--) { - globaLayoutListeners.get(i).onGlobalLayout(); + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners; + if (listeners != null) { + for (OnGlobalLayoutListener listener : listeners) { + listener.onGlobalLayout(); } } } @@ -551,12 +558,15 @@ public final class ViewTreeObserver { * @return True if the current draw should be canceled and resceduled, false otherwise. */ public final boolean dispatchOnPreDraw() { + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. boolean cancelDraw = false; - final ArrayList<OnPreDrawListener> preDrawListeners = mOnPreDrawListeners; - if (preDrawListeners != null) { - final int count = preDrawListeners.size(); - for (int i = count - 1; i >= 0; i--) { - cancelDraw |= !preDrawListeners.get(i).onPreDraw(); + final CopyOnWriteArrayList<OnPreDrawListener> listeners = mOnPreDrawListeners; + if (listeners != null) { + for (OnPreDrawListener listener : listeners) { + cancelDraw |= !listener.onPreDraw(); } } return cancelDraw; @@ -568,11 +578,15 @@ public final class ViewTreeObserver { * @param inTouchMode True if the touch mode is now enabled, false otherwise. */ final void dispatchOnTouchModeChanged(boolean inTouchMode) { - final ArrayList<OnTouchModeChangeListener> touchModeListeners = mOnTouchModeChangeListeners; - if (touchModeListeners != null) { - final int count = touchModeListeners.size(); - for (int i = count - 1; i >= 0; i--) { - touchModeListeners.get(i).onTouchModeChanged(inTouchMode); + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners = + mOnTouchModeChangeListeners; + if (listeners != null) { + for (OnTouchModeChangeListener listener : listeners) { + listener.onTouchModeChanged(inTouchMode); } } } @@ -581,11 +595,14 @@ public final class ViewTreeObserver { * Notifies registered listeners that something has scrolled. */ final void dispatchOnScrollChanged() { - final ArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners; - + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners; if (listeners != null) { - for (OnScrollChangedListener scl : mOnScrollChangedListeners) { - scl.onScrollChanged(); + for (OnScrollChangedListener listener : listeners) { + listener.onScrollChanged(); } } } @@ -594,7 +611,8 @@ public final class ViewTreeObserver { * Returns whether there are listeners for computing internal insets. */ final boolean hasComputeInternalInsetsListeners() { - final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; + final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = + mOnComputeInternalInsetsListeners; return (listeners != null && listeners.size() > 0); } @@ -602,11 +620,15 @@ public final class ViewTreeObserver { * Calls all listeners to compute the current insets. */ final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) { - final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = + mOnComputeInternalInsetsListeners; if (listeners != null) { - final int count = listeners.size(); - for (int i = count - 1; i >= 0; i--) { - listeners.get(i).onComputeInternalInsets(inoutInfo); + for (OnComputeInternalInsetsListener listener : listeners) { + listener.onComputeInternalInsets(inoutInfo); } } } diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java index f1f5f70..13606e7 100755 --- a/core/java/android/view/WindowOrientationListener.java +++ b/core/java/android/view/WindowOrientationListener.java @@ -80,6 +80,7 @@ public abstract class WindowOrientationListener { } if (mEnabled == false) { if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled"); + mSensorRotation = -1; mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); mEnabled = true; } @@ -95,18 +96,23 @@ public abstract class WindowOrientationListener { } if (mEnabled == true) { if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled"); + mSensorRotation = -1; mSensorManager.unregisterListener(mSensorEventListener); mEnabled = false; } } + public int getCurrentRotation() { + return mSensorRotation; + } + class SensorEventListenerImpl implements SensorEventListener { private static final int _DATA_X = 0; private static final int _DATA_Y = 1; private static final int _DATA_Z = 2; // Angle around x-axis thats considered almost perfect vertical to hold // the device - private static final int PIVOT = 30; + private static final int PIVOT = 20; // Angle around x-asis that's considered almost too vertical. Beyond // this angle will not result in any orientation changes. f phone faces uses, // the device is leaning backward. @@ -114,22 +120,30 @@ public abstract class WindowOrientationListener { // Angle about x-axis that's considered negative vertical. Beyond this // angle will not result in any orientation changes. If phone faces uses, // the device is leaning forward. - private static final int PIVOT_LOWER = 0; + private static final int PIVOT_LOWER = -10; // Upper threshold limit for switching from portrait to landscape - private static final int PL_UPPER = 280; + private static final int PL_UPPER = 295; // Lower threshold limit for switching from landscape to portrait private static final int LP_LOWER = 320; // Lower threshold limt for switching from portrait to landscape - private static final int PL_LOWER = 240; + private static final int PL_LOWER = 270; // Upper threshold limit for switching from landscape to portrait - private static final int LP_UPPER = 360; + private static final int LP_UPPER = 359; + // Minimum angle which is considered landscape + private static final int LANDSCAPE_LOWER = 235; + // Minimum angle which is considered portrait + private static final int PORTRAIT_LOWER = 60; // Internal value used for calculating linear variant - private static final float PL_LINEAR_FACTOR = - ((float)(PL_UPPER-PL_LOWER))/((float)(PIVOT_UPPER-PIVOT_LOWER)); + private static final float PL_LF_UPPER = + ((float)(PL_UPPER-PL_LOWER))/((float)(PIVOT_UPPER-PIVOT)); + private static final float PL_LF_LOWER = + ((float)(PL_UPPER-PL_LOWER))/((float)(PIVOT-PIVOT_LOWER)); // Internal value used for calculating linear variant - private static final float LP_LINEAR_FACTOR = - ((float)(LP_UPPER - LP_LOWER))/((float)(PIVOT_UPPER-PIVOT_LOWER)); + private static final float LP_LF_UPPER = + ((float)(LP_UPPER - LP_LOWER))/((float)(PIVOT_UPPER-PIVOT)); + private static final float LP_LF_LOWER = + ((float)(LP_UPPER - LP_LOWER))/((float)(PIVOT-PIVOT_LOWER)); public void onSensorChanged(SensorEvent event) { float[] values = event.values; @@ -138,8 +152,8 @@ public abstract class WindowOrientationListener { float Z = values[_DATA_Z]; float OneEightyOverPi = 57.29577957855f; float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z); - float zyangle = Math.abs((float)Math.asin(Z/gravity)*OneEightyOverPi); - int rotation = mSensorRotation; + float zyangle = (float)Math.asin(Z/gravity)*OneEightyOverPi; + int rotation = -1; if ((zyangle <= PIVOT_UPPER) && (zyangle >= PIVOT_LOWER)) { // Check orientation only if the phone is flat enough // Don't trust the angle if the magnitude is small compared to the y value @@ -152,24 +166,40 @@ public abstract class WindowOrientationListener { while (orientation < 0) { orientation += 360; } - - float delta = (float)Math.abs(zyangle - PIVOT); - if (((orientation >= 0) && (orientation <= LP_UPPER)) || - (orientation >= PL_LOWER)) { + // Orientation values between LANDSCAPE_LOWER and PL_LOWER + // are considered landscape. + // Ignore orientation values between 0 and LANDSCAPE_LOWER + // For orientation values between LP_UPPER and PL_LOWER, + // the threshold gets set linearly around PIVOT. + if ((orientation >= PL_LOWER) && (orientation <= LP_UPPER)) { float threshold; + float delta = zyangle - PIVOT; if (mSensorRotation == Surface.ROTATION_90) { - threshold = LP_LOWER + (LP_LINEAR_FACTOR * delta) ; + if (delta < 0) { + // Delta is negative + threshold = LP_LOWER - (LP_LF_LOWER * delta); + } else { + threshold = LP_LOWER + (LP_LF_UPPER * delta); + } + rotation = (orientation >= threshold) ? Surface.ROTATION_0 : Surface.ROTATION_90; } else { - threshold = PL_UPPER - (PL_LINEAR_FACTOR * delta); + if (delta < 0) { + // Delta is negative + threshold = PL_UPPER+(PL_LF_LOWER * delta); + } else { + threshold = PL_UPPER-(PL_LF_UPPER * delta); + } + rotation = (orientation <= threshold) ? Surface.ROTATION_90: Surface.ROTATION_0; } - rotation = (orientation >= PL_LOWER && - orientation <= threshold) ? Surface.ROTATION_90 : Surface.ROTATION_0; + } else if ((orientation >= LANDSCAPE_LOWER) && (orientation < LP_LOWER)) { + rotation = Surface.ROTATION_90; + } else if ((orientation >= PL_UPPER) || (orientation <= PORTRAIT_LOWER)) { + rotation = Surface.ROTATION_0; + } + if ((rotation != -1) && (rotation != mSensorRotation)) { + mSensorRotation = rotation; + onOrientationChanged(mSensorRotation); } - - } - if (rotation != mSensorRotation) { - mSensorRotation = rotation; - onOrientationChanged(mSensorRotation); } } diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java index a785d43..d2ff754 100644 --- a/core/java/android/view/animation/TranslateAnimation.java +++ b/core/java/android/view/animation/TranslateAnimation.java @@ -156,7 +156,6 @@ public class TranslateAnimation extends Animation { if (mFromYDelta != mToYDelta) { dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime); } - t.getMatrix().setTranslate(dx, dy); } diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index deca910..11de3e2 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -51,7 +51,6 @@ public class BaseInputConnection implements InputConnection { static final Object COMPOSING = new ComposingText(); final InputMethodManager mIMM; - final Handler mH; final View mTargetView; final boolean mDummyMode; @@ -60,19 +59,17 @@ public class BaseInputConnection implements InputConnection { Editable mEditable; KeyCharacterMap mKeyCharacterMap; - BaseInputConnection(InputMethodManager mgr, boolean dummyMode) { + BaseInputConnection(InputMethodManager mgr, boolean fullEditor) { mIMM = mgr; mTargetView = null; - mH = null; - mDummyMode = dummyMode; + mDummyMode = !fullEditor; } - public BaseInputConnection(View targetView, boolean dummyMode) { + public BaseInputConnection(View targetView, boolean fullEditor) { mIMM = (InputMethodManager)targetView.getContext().getSystemService( Context.INPUT_METHOD_SERVICE); - mH = targetView.getHandler(); mTargetView = targetView; - mDummyMode = dummyMode; + mDummyMode = !fullEditor; } public static final void removeComposingSpans(Spannable text) { @@ -403,7 +400,7 @@ public class BaseInputConnection implements InputConnection { */ public boolean sendKeyEvent(KeyEvent event) { synchronized (mIMM.mH) { - Handler h = mH; + Handler h = mTargetView != null ? mTargetView.getHandler() : null; if (h == null) { if (mIMM.mServedView != null) { h = mIMM.mServedView.getHandler(); diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index b00e565..c718bac 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -78,12 +78,37 @@ public class EditorInfo implements InputType, Parcelable { public static final int IME_ACTION_DONE = 0x00000006; /** + * Flag of {@link #imeOptions}: used to specify that the IME does not need + * to show its extracted text UI. For input methods that may be fullscreen, + * often when in landscape mode, this allows them to be smaller and let part + * of the application be shown behind. Though there will likely be limited + * access to the application available from the user, it can make the + * experience of a (mostly) fullscreen IME less jarring. Note that when + * this flag is specified the IME may <em>not</em> be set up to be able + * to display text, so it should only be used in situations where this is + * not needed. + */ + public static final int IME_FLAG_NO_EXTRACT_UI = 0x10000000; + + /** + * Flag of {@link #imeOptions}: used in conjunction with + * {@link #IME_MASK_ACTION}, this indicates that the action should not + * be available as an accessory button when the input method is full-screen. + * Note that by setting this flag, there can be cases where the action + * is simply never available to the user. Setting this generally means + * that you think showing text being edited is more important than the + * action you have supplied. + */ + public static final int IME_FLAG_NO_ACCESSORY_ACTION = 0x20000000; + + /** * Flag of {@link #imeOptions}: used in conjunction with * {@link #IME_MASK_ACTION}, this indicates that the action should not - * be available in-line as the same as a "enter" key. Typically this is + * be available in-line as a replacement for "enter" key. Typically this is * because the action has such a significant impact or is not recoverable * enough that accidentally hitting it should be avoided, such as sending - * a message. + * a message. Note that {@link android.widget.TextView} will automatically set this + * flag for you on multi-line text views. */ public static final int IME_FLAG_NO_ENTER_ACTION = 0x40000000; diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java index e3d5e62..210559a 100644 --- a/core/java/android/view/inputmethod/InputConnectionWrapper.java +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -24,9 +24,21 @@ import android.view.KeyEvent; * and have fun! */ public class InputConnectionWrapper implements InputConnection { - private final InputConnection mTarget; + private InputConnection mTarget; + final boolean mMutable; - public InputConnectionWrapper(InputConnection target) { + public InputConnectionWrapper(InputConnection target, boolean mutable) { + mMutable = mutable; + mTarget = target; + } + + /** + * Change the target of the input connection. + */ + public void setTarget(InputConnection target) { + if (mTarget != null && !mMutable) { + throw new SecurityException("not mutable"); + } mTarget = target; } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 4de9eef..d797890 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -426,7 +426,7 @@ public final class InputMethodManager { } }; - final InputConnection mDummyInputConnection = new BaseInputConnection(this, true); + final InputConnection mDummyInputConnection = new BaseInputConnection(this, false); InputMethodManager(IInputMethodManager service, Looper looper) { mService = service; diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java index dcf68cd..4528b73 100644 --- a/core/java/android/webkit/CacheManager.java +++ b/core/java/android/webkit/CacheManager.java @@ -282,9 +282,7 @@ public final class CacheManager { CacheResult result = mDataBase.getCache(url); if (result != null) { if (result.contentLength == 0) { - if (result.httpStatusCode != 301 - && result.httpStatusCode != 302 - && result.httpStatusCode != 307) { + if (!checkCacheRedirect(result.httpStatusCode)) { // this should not happen. If it does, remove it. mDataBase.removeCache(url); return null; @@ -350,6 +348,17 @@ public final class CacheManager { return null; } + // according to the rfc 2616, the 303 response MUST NOT be cached. + if (statusCode == 303) { + return null; + } + + // like the other browsers, do not cache redirects containing a cookie + // header. + if (checkCacheRedirect(statusCode) && !headers.getSetCookie().isEmpty()) { + return null; + } + CacheResult ret = parseHeaders(statusCode, headers, mimeType); if (ret != null) { setupFiles(url, ret); @@ -395,9 +404,7 @@ public final class CacheManager { } cacheRet.contentLength = cacheRet.outFile.length(); - if (cacheRet.httpStatusCode == 301 - || cacheRet.httpStatusCode == 302 - || cacheRet.httpStatusCode == 307) { + if (checkCacheRedirect(cacheRet.httpStatusCode)) { // location is in database, no need to keep the file cacheRet.contentLength = 0; cacheRet.localPath = new String(); @@ -471,6 +478,15 @@ public final class CacheManager { } } + private static boolean checkCacheRedirect(int statusCode) { + if (statusCode == 301 || statusCode == 302 || statusCode == 307) { + // as 303 can't be cached, we do not return true + return true; + } else { + return false; + } + } + @SuppressWarnings("deprecation") private static void setupFiles(String url, CacheResult cacheRet) { if (true) { diff --git a/core/java/android/webkit/ContentLoader.java b/core/java/android/webkit/ContentLoader.java index fb01c8c..f6d7f69 100644 --- a/core/java/android/webkit/ContentLoader.java +++ b/core/java/android/webkit/ContentLoader.java @@ -105,6 +105,9 @@ class ContentLoader extends StreamLoader { if (mContentType != null) { headers.setContentType("text/html"); } + // override the cache-control header set by StreamLoader as content can + // change, we don't want WebKit to cache it + headers.setCacheControl("no-store, no-cache"); } /** diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java index 48b9eec..84dc9f0 100644 --- a/core/java/android/webkit/HttpAuthHandler.java +++ b/core/java/android/webkit/HttpAuthHandler.java @@ -80,8 +80,7 @@ public class HttpAuthHandler extends Handler { break; case AUTH_CANCEL: - - mNetwork.resetHandlersAndStopLoading(loader.getFrame()); + loader.handleAuthResponse(null, null); break; } @@ -126,24 +125,6 @@ public class HttpAuthHandler extends Handler { } /** - * Resets the HTTP-authentication request handler, removes - * all loaders that share the same BrowserFrame - * - * @param frame The browser frame - */ - /* package */ void reset(BrowserFrame frame) { - synchronized (mLoaderQueue) { - ListIterator<LoadListener> i = mLoaderQueue.listIterator(0); - while (i.hasNext()) { - LoadListener loader = i.next(); - if (frame == loader.getFrame()) { - i.remove(); - } - } - } - } - - /** * Enqueues the loader, if the loader is the only element * in the queue, starts processing the loader * diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index f9fb0b0..c64200c 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -377,10 +377,6 @@ class LoadListener extends Handler implements EventHandler { } } - // if there is buffered data, commit them in the end - boolean needToCommit = mAuthHeader != null && !mustAuthenticate - && mNativeLoader != 0 && !mDataBuilder.isEmpty(); - // it is only here that we can reset the last mAuthHeader object // (if existed) and start a new one!!! mAuthHeader = null; @@ -415,10 +411,6 @@ class LoadListener extends Handler implements EventHandler { } } commitHeadersCheckRedirect(); - - if (needToCommit) { - commitLoad(); - } } /** @@ -452,6 +444,8 @@ class LoadListener extends Handler implements EventHandler { status.put("minor", minorVersion); status.put("code", code); status.put("reason", reasonPhrase); + // New status means new data. Clear the old. + mDataBuilder.clear(); sendMessageInternal(obtainMessage(MSG_STATUS, status)); } @@ -613,7 +607,6 @@ class LoadListener extends Handler implements EventHandler { // ask for it, so make sure we have a valid CacheLoader // before calling it. if (mCacheLoader != null) { - detachRequestHandle(); mCacheLoader.load(); if (Config.LOGV) { Log.v(LOGTAG, "LoadListener cache load url=" + url()); @@ -738,10 +731,16 @@ class LoadListener extends Handler implements EventHandler { if (mRequestHandle != null) { mRequestHandle.handleSslErrorResponse(proceed); } + if (!proceed) { + // Commit whatever data we have and tear down the loader. + commitLoad(); + tearDown(); + } } /** - * Uses user-supplied credentials to restar a request. + * Uses user-supplied credentials to restart a request. If the credentials + * are null, cancel the request. */ void handleAuthResponse(String username, String password) { if (Config.LOGV) { @@ -780,6 +779,10 @@ class LoadListener extends Handler implements EventHandler { } } } + } else { + // Commit whatever data we have and tear down the loader. + commitLoad(); + tearDown(); } } @@ -944,13 +947,12 @@ class LoadListener extends Handler implements EventHandler { * @return native response pointer */ private int createNativeResponse() { - // The reason we change HTTP_NOT_MODIFIED to HTTP_OK is because we know - // that WebCore never sends the if-modified-since header. Our - // CacheManager does it for us. If the server responds with a 304, then - // we treat it like it was a 200 code and proceed with loading the file - // from the cache. - int statusCode = mStatusCode == HTTP_NOT_MODIFIED - ? HTTP_OK : mStatusCode; + // If WebCore sends if-modified-since, mCacheLoader is null. If + // CacheManager sends it, mCacheLoader is not null. In this case, if the + // server responds with a 304, then we treat it like it was a 200 code + // and proceed with loading the file from the cache. + int statusCode = (mStatusCode == HTTP_NOT_MODIFIED && + mCacheLoader != null) ? HTTP_OK : mStatusCode; // pass content-type content-length and content-encoding final int nativeResponse = nativeCreateResponse( mUrl, statusCode, mStatusText, @@ -1181,8 +1183,6 @@ class LoadListener extends Handler implements EventHandler { // sync. Add 1 to account for the current redirect. mCacheRedirectCount = mRequestHandle.getRedirectCount() + 1; } - // Clear the buffered data since the redirect is valid. - mDataBuilder.clear(); } else { commitHeaders(); commitLoad(); @@ -1197,9 +1197,10 @@ class LoadListener extends Handler implements EventHandler { /** * Parses the content-type header. + * The first part only allows '-' if it follows x or X. */ private static final Pattern CONTENT_TYPE_PATTERN = - Pattern.compile("^([a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$"); + Pattern.compile("^((?:[xX]-)?[a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$"); private void parseContentTypeHeader(String contentType) { if (Config.LOGV) { diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java index c9cc208..85c2275 100644 --- a/core/java/android/webkit/MimeTypeMap.java +++ b/core/java/android/webkit/MimeTypeMap.java @@ -496,6 +496,7 @@ public /* package */ class MimeTypeMap { sMimeTypeMap.loadEntry("video/x-msvideo", "avi", false); sMimeTypeMap.loadEntry("video/x-sgi-movie", "movie", false); sMimeTypeMap.loadEntry("x-conference/x-cooltalk", "ice", false); + sMimeTypeMap.loadEntry("x-epoc/x-sisx-app", "sisx", false); } return sMimeTypeMap; diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java index 74622b3..6fa0775 100644 --- a/core/java/android/webkit/Network.java +++ b/core/java/android/webkit/Network.java @@ -261,24 +261,6 @@ class Network { } /** - * If we need to stop loading done in a handler (here, browser frame), we - * send a message to the handler to stop loading, and remove all loaders - * that share the same CallbackProxy in question from all local - * handlers (such as ssl-error and http-authentication handler). - * @param proxy The CallbackProxy responsible for cancelling the current - * load. - */ - public void resetHandlersAndStopLoading(BrowserFrame frame) { - if (Config.LOGV) { - Log.v(LOGTAG, "Network.resetHandlersAndStopLoading()"); - } - - frame.stopLoading(); - mSslErrorHandler.reset(frame); - mHttpAuthHandler.reset(frame); - } - - /** * Saves the state of network handlers (user SSL and HTTP-authentication * preferences). * @param outState The out-state to save (write) to. diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java index 115434a..2e2fa12 100644 --- a/core/java/android/webkit/SslErrorHandler.java +++ b/core/java/android/webkit/SslErrorHandler.java @@ -118,20 +118,6 @@ public class SslErrorHandler extends Handler { } /** - * Resets the SSL error handler, removes all loaders that - * share the same BrowserFrame. - */ - /* package */ synchronized void reset(BrowserFrame frame) { - ListIterator<LoadListener> i = mLoaderQueue.listIterator(0); - while (i.hasNext()) { - LoadListener loader = i.next(); - if (frame == loader.getFrame()) { - i.remove(); - } - } - } - - /** * Handles SSL error(s) on the way up to the user. */ /* package */ synchronized void handleSslErrorRequest(LoadListener loader) { @@ -244,12 +230,8 @@ public class SslErrorHandler extends Handler { primary > mSslPrefTable.getInt(host)) { mSslPrefTable.putInt(host, new Integer(primary)); } - - loader.handleSslErrorResponse(proceed); - } else { - loader.handleSslErrorResponse(proceed); - mNetwork.resetHandlersAndStopLoading(loader.getFrame()); } + loader.handleSslErrorResponse(proceed); } } } diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 44f382c..bc8e3d9 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -157,6 +157,7 @@ public class WebSettings { private boolean mNeedInitialFocus = true; private boolean mNavDump = false; private boolean mSupportZoom = true; + private boolean mBuiltInZoomControls = false; private boolean mAllowFileAccess = true; // Class to handle messages before WebCore is ready. @@ -368,6 +369,20 @@ public class WebSettings { } /** + * Sets whether the zoom mechanism built into WebView is used. + */ + public void setBuiltInZoomControls(boolean enabled) { + mBuiltInZoomControls = enabled; + } + + /** + * Returns true if the zoom mechanism built into WebView is being used. + */ + public boolean getBuiltInZoomControls() { + return mBuiltInZoomControls; + } + + /** * Enable or disable file access within WebView. File access is enabled by * default. */ diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index d404040..4199854 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -56,17 +56,20 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; +import android.view.animation.AlphaAnimation; import android.view.inputmethod.InputMethodManager; import android.webkit.TextDialog.AutoCompleteAdapter; import android.webkit.WebViewCore.EventHub; import android.widget.AbsoluteLayout; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ListView; import android.widget.Scroller; import android.widget.Toast; import android.widget.ZoomButtonsController; +import android.widget.ZoomControls; import android.widget.AdapterView.OnItemClickListener; import java.io.File; @@ -80,17 +83,17 @@ import java.util.HashMap; import java.util.List; /** - * <p>A View that displays web pages. This class is the basis upon - * which you can roll your own web browser or simply display some - * online content within your Activity. It uses the WebKit rendering - * engine to display web pages and includes methods to navigate - * forward and backward through a history, zoom in and out, perform - * text searches and more.</p> - * - * <p>Note that, in order for your Activity to access the Internet and - * load web pages in a WebView, you must add the <var>INTERNET</var> - * permissions to your Android Manifest file:</p> - * + * <p>A View that displays web pages. This class is the basis upon which you + * can roll your own web browser or simply display some online content within your Activity. + * It uses the WebKit rendering engine to display + * web pages and includes methods to navigate forward and backward + * through a history, zoom in and out, perform text searches and more.</p> + * <p>To enable the built-in zoom, set + * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)} + * (introduced in API version 3). + * <p>Note that, in order for your Activity to access the Internet and load web pages + * in a WebView, you must add the <var>INTERNET</var> permissions to your + * Android Manifest file:</p> * <pre><uses-permission android:name="android.permission.INTERNET" /></pre> * * <p>This must be a child of the <code><manifest></code> element.</p> @@ -206,6 +209,57 @@ public class WebView extends AbsoluteLayout static final boolean DEBUG = false; static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; + private class ExtendedZoomControls extends FrameLayout { + public ExtendedZoomControls(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(com.android.internal.R.layout.zoom_magnify, this, true); + mZoomControls = (ZoomControls) findViewById(com.android.internal.R.id.zoomControls); + mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify); + } + + public void show(boolean showZoom, boolean canZoomOut) { + mZoomControls.setVisibility(showZoom ? View.VISIBLE : View.GONE); + mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE); + fade(View.VISIBLE, 0.0f, 1.0f); + } + + public void hide() { + fade(View.GONE, 1.0f, 0.0f); + } + + private void fade(int visibility, float startAlpha, float endAlpha) { + AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha); + anim.setDuration(500); + startAnimation(anim); + setVisibility(visibility); + } + + public void setIsZoomMagnifyEnabled(boolean isEnabled) { + mZoomMagnify.setEnabled(isEnabled); + } + + public boolean hasFocus() { + return mZoomControls.hasFocus() || mZoomMagnify.hasFocus(); + } + + public void setOnZoomInClickListener(OnClickListener listener) { + mZoomControls.setOnZoomInClickListener(listener); + } + + public void setOnZoomOutClickListener(OnClickListener listener) { + mZoomControls.setOnZoomOutClickListener(listener); + } + + public void setOnZoomMagnifyClickListener(OnClickListener listener) { + mZoomMagnify.setOnClickListener(listener); + } + + ZoomControls mZoomControls; + ImageView mZoomMagnify; + } + /** * Transportation object for returning WebView across thread boundaries. */ @@ -332,6 +386,9 @@ public class WebView extends AbsoluteLayout private static final int LONG_PRESS_TIMEOUT = 1000; // needed to avoid flinging after a pause of no movement private static final int MIN_FLING_TIME = 250; + // The time that the Zoom Controls are visible before fading away + private static final long ZOOM_CONTROLS_TIMEOUT = + ViewConfiguration.getZoomControlsTimeout(); // The amount of content to overlap between two screens when going through // pages with the space bar, in pixels. private static final int PAGE_SCROLL_OVERLAP = 24; @@ -572,6 +629,10 @@ public class WebView extends AbsoluteLayout } } + // The View containing the zoom controls + private ExtendedZoomControls mZoomControls; + private Runnable mZoomControlRunnable; + private ZoomButtonsController mZoomButtonsController; private ImageView mZoomOverviewButton; private ImageView mZoomFitPageButton; @@ -584,11 +645,6 @@ public class WebView extends AbsoluteLayout private ZoomButtonsController.OnZoomListener mZoomListener = new ZoomButtonsController.OnZoomListener() { - public void onCenter(int x, int y) { - // Don't translate when the control is invoked, hence we do nothing - // in this callback - } - public void onVisibilityChanged(boolean visible) { if (visible) { switchOutDrawHistory(); @@ -682,10 +738,26 @@ public class WebView extends AbsoluteLayout } private void updateZoomButtonsEnabled() { - mZoomButtonsController.setZoomInEnabled(mActualScale < mMaxZoomScale); - mZoomButtonsController.setZoomOutEnabled(mActualScale > mMinZoomScale); - mZoomFitPageButton.setEnabled(mActualScale != 1); - mZoomOverviewButton.setEnabled(canZoomScrollOut()); + boolean canZoomIn = mActualScale < mMaxZoomScale; + boolean canZoomOut = mActualScale > mMinZoomScale; + if (!canZoomIn && !canZoomOut) { + // Hide the zoom in and out buttons, as well as the fit to page + // button, if the page cannot zoom + mZoomButtonsController.getZoomControls().setVisibility(View.GONE); + mZoomFitPageButton.setVisibility(View.GONE); + } else { + // Bring back the hidden zoom controls. + mZoomButtonsController.getZoomControls() + .setVisibility(View.VISIBLE); + mZoomFitPageButton.setVisibility(View.VISIBLE); + // Set each one individually, as a page may be able to zoom in + // or out. + mZoomButtonsController.setZoomInEnabled(canZoomIn); + mZoomButtonsController.setZoomOutEnabled(canZoomOut); + mZoomFitPageButton.setEnabled(mActualScale != 1); + } + mZoomOverviewButton.setVisibility(canZoomScrollOut() ? View.VISIBLE: + View.GONE); } private void init() { @@ -1432,7 +1504,13 @@ public class WebView extends AbsoluteLayout return; } clearTextEntry(); - mZoomButtonsController.setVisible(true); + if (getSettings().getBuiltInZoomControls()) { + mZoomButtonsController.setVisible(true); + } else { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + } } /** @@ -2636,8 +2714,17 @@ public class WebView extends AbsoluteLayout private void startZoomScrollOut() { setHorizontalScrollBarEnabled(false); setVerticalScrollBarEnabled(false); - if (mZoomButtonsController.isVisible()) { - mZoomButtonsController.setVisible(false); + if (getSettings().getBuiltInZoomControls()) { + if (mZoomButtonsController.isVisible()) { + mZoomButtonsController.setVisible(false); + } + } else { + if (mZoomControlRunnable != null) { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + } + if (mZoomControls != null) { + mZoomControls.hide(); + } } int width = getViewWidth(); int height = getViewHeight(); @@ -3307,7 +3394,6 @@ public class WebView extends AbsoluteLayout // Clean up the zoom controller mZoomButtonsController.setVisible(false); - ZoomButtonsController.finishZoomTutorial(mContext, false); } // Implementation for OnHierarchyChangeListener @@ -3356,7 +3442,7 @@ public class WebView extends AbsoluteLayout // false for the first parameter } } else { - if (!mZoomButtonsController.isVisible()) { + if (getSettings().getBuiltInZoomControls() && !mZoomButtonsController.isVisible()) { /* * The zoom controls come in their own window, so our window * loses focus. Our policy is to not draw the focus ring if @@ -3628,7 +3714,9 @@ public class WebView extends AbsoluteLayout mWebViewCore .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0); } - if (getSettings().supportZoom() + WebSettings settings = getSettings(); + if (settings.supportZoom() + && settings.getBuiltInZoomControls() && !mZoomButtonsController.isVisible() && (canZoomScrollOut() || mMinZoomScale < mMaxZoomScale)) { @@ -3695,6 +3783,21 @@ public class WebView extends AbsoluteLayout mLastTouchTime = eventTime; mUserScroll = true; } + + if (!getSettings().getBuiltInZoomControls()) { + boolean showPlusMinus = mMinZoomScale < mMaxZoomScale; + boolean showMagnify = canZoomScrollOut(); + if (mZoomControls != null && (showPlusMinus || showMagnify)) { + if (mZoomControls.getVisibility() == View.VISIBLE) { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + } else { + mZoomControls.show(showPlusMinus, showMagnify); + } + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + } + } + if (done) { // return false to indicate that we can't pan out of the // view space @@ -4151,18 +4254,83 @@ public class WebView extends AbsoluteLayout } } - // TODO: deprecate /** * Returns a view containing zoom controls i.e. +/- buttons. The caller is * in charge of installing this view to the view hierarchy. This view will * become visible when the user starts scrolling via touch and fade away if * the user does not interact with it. * <p/> - * From 1.5, WebView change to use ZoomButtonsController. This will return - * an invisible dummy view for backwards compatibility. + * API version 3 introduces a built-in zoom mechanism that is shown + * automatically by the MapView. This is the preferred approach for + * showing the zoom UI. + * + * @deprecated The built-in zoom mechanism is preferred, see + * {@link WebSettings#setBuiltInZoomControls(boolean)}. */ + @Deprecated public View getZoomControls() { - return mZoomButtonsController.getDummyZoomControls(); + if (!getSettings().supportZoom()) { + Log.w(LOGTAG, "This WebView doesn't support zoom."); + return null; + } + if (mZoomControls == null) { + mZoomControls = createZoomControls(); + + /* + * need to be set to VISIBLE first so that getMeasuredHeight() in + * {@link #onSizeChanged()} can return the measured value for proper + * layout. + */ + mZoomControls.setVisibility(View.VISIBLE); + mZoomControlRunnable = new Runnable() { + public void run() { + + /* Don't dismiss the controls if the user has + * focus on them. Wait and check again later. + */ + if (!mZoomControls.hasFocus()) { + mZoomControls.hide(); + } else { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + } + } + }; + } + return mZoomControls; + } + + private ExtendedZoomControls createZoomControls() { + ExtendedZoomControls zoomControls = new ExtendedZoomControls(mContext + , null); + zoomControls.setOnZoomInClickListener(new OnClickListener() { + public void onClick(View v) { + // reset time out + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + zoomIn(); + } + }); + zoomControls.setOnZoomOutClickListener(new OnClickListener() { + public void onClick(View v) { + // reset time out + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + zoomOut(); + } + }); + zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() { + public void onClick(View v) { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + zoomScrollOut(); + } + }); + return zoomControls; } /** @@ -4171,7 +4339,7 @@ public class WebView extends AbsoluteLayout * * @return The instance of {@link ZoomButtonsController} used by this class, * or null if it is unavailable. - * @hide pending API council + * @hide */ public ZoomButtonsController getZoomButtonsController() { return mZoomButtonsController; diff --git a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java index 0569255..529e666 100644 --- a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java +++ b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java @@ -1000,12 +1000,23 @@ public final class ApacheHttpRequestAndroid { return true; } + /** + * Called by the main thread to interrupt the child thread. + * We do not set mConnectionFailed here as we still need the + * ability to receive a null packet for sendPostData(). + */ + public synchronized void abort() { + if (Config.LOGV) { + Log.i(LOG_TAG, "ABORT CALLED"); + } + if (mMethod != null) { + mMethod.abort(); + } + } /** - * Interrupt a blocking IO operation. This will cause the child - * thread to expediently return from an operation if it was stuck at - * the time. Note that this inherently races, and unfortunately - * requires the caller to loop. + * Interrupt a blocking IO operation and wait for the + * thread to complete. */ public synchronized void interrupt() { if (Config.LOGV) { diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index bd4bba8..0563687 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -41,8 +41,10 @@ import android.view.ViewConfiguration; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputConnectionWrapper; import android.view.inputmethod.InputMethodManager; import android.view.ContextMenu.ContextMenuInfo; @@ -429,6 +431,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te private float mDensityScale; + private InputConnection mDefInputConnection; + private InputConnectionWrapper mPublicInputConnection; + /** * Interface definition for a callback to be invoked when the list or grid * has been scrolled. @@ -905,10 +910,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te ((Filterable) getAdapter()).getFilter() == null) { return false; } - final Context context = mContext; - final InputMethodManager inputManager = (InputMethodManager) - context.getSystemService(Context.INPUT_METHOD_SERVICE); - return !inputManager.isFullscreenMode(); + return true; } /** @@ -2904,7 +2906,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te KeyEvent forwardEvent = event; if (forwardEvent.getRepeatCount() > 0) { - forwardEvent = new KeyEvent(event, event.getEventTime(), 0); + forwardEvent = KeyEvent.changeTimeRepeat(event, event.getEventTime(), 0); } int action = event.getAction(); @@ -2935,7 +2937,46 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // InputConnection to proxy to. Unfortunately this means we pretty // much need to make it as soon as a list view gets focus. createTextFilter(false); - return mTextFilter.onCreateInputConnection(outAttrs); + if (mPublicInputConnection == null) { + mDefInputConnection = new BaseInputConnection(this, false); + mPublicInputConnection = new InputConnectionWrapper( + mTextFilter.onCreateInputConnection(outAttrs), true) { + @Override + public boolean reportFullscreenMode(boolean enabled) { + // Use our own input connection, since it is + // the "real" one the IME is talking with. + return mDefInputConnection.reportFullscreenMode(enabled); + } + + @Override + public boolean performEditorAction(int editorAction) { + // The editor is off in its own window; we need to be + // the one that does this. + if (editorAction == EditorInfo.IME_ACTION_DONE) { + InputMethodManager imm = (InputMethodManager) + getContext().getSystemService( + Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.hideSoftInputFromWindow(getWindowToken(), 0); + } + return true; + } + return false; + } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + // Use our own input connection, since the filter + // text view may not be shown in a window so has + // no ViewRoot to dispatch events with. + return mDefInputConnection.sendKeyEvent(event); + } + }; + } + outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT + | EditorInfo.TYPE_TEXT_VARIATION_FILTER; + outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE; + return mPublicInputConnection; } return null; } @@ -2967,6 +3008,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // want to figure out why this is. mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_FILTER); + mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); mTextFilter.addTextChangedListener(this); p.setFocusable(false); p.setTouchable(false); @@ -3021,14 +3063,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** - * For our text watcher that associated with the text filter + * For our text watcher that is associated with the text filter. Does + * nothing. */ public void beforeTextChanged(CharSequence s, int start, int count, int after) { } /** - * For our text watcher that associated with the text filter. Performs the actual - * filtering as the text changes. + * For our text watcher that is associated with the text filter. Performs + * the actual filtering as the text changes, and takes care of hiding and + * showing the popup displaying the currently entered filter text. */ public void onTextChanged(CharSequence s, int start, int before, int count) { if (mPopup != null && isTextFilterEnabled()) { @@ -3040,7 +3084,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mFiltered = true; } else if (showing && length == 0) { // Remove the filter popup if the user has cleared all text - mPopup.dismiss(); + dismissPopup(); mFiltered = false; } if (mAdapter instanceof Filterable) { @@ -3057,7 +3101,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** - * For our text watcher that associated with the text filter + * For our text watcher that is associated with the text filter. Does + * nothing. */ public void afterTextChanged(Editable s) { } diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index 37d5bfe..f92eb99 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -164,7 +164,7 @@ public abstract class AbsSeekBar extends ProgressBar { void onProgressRefresh(float scale, boolean fromUser) { Drawable thumb = mThumb; if (thumb != null) { - setThumbPos(getWidth(), getHeight(), thumb, scale, Integer.MIN_VALUE); + setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE); /* * Since we draw translated, the drawable's bounds that it signals * for invalidation won't be the actual bounds we want invalidated, @@ -189,7 +189,7 @@ public abstract class AbsSeekBar extends ProgressBar { if (thumbHeight > trackHeight) { if (thumb != null) { - setThumbPos(w, h, thumb, scale, 0); + setThumbPos(w, thumb, scale, 0); } int gapForCenteringTrack = (thumbHeight - trackHeight) / 2; if (d != null) { @@ -206,16 +206,15 @@ public abstract class AbsSeekBar extends ProgressBar { } int gap = (trackHeight - thumbHeight) / 2; if (thumb != null) { - setThumbPos(w, h, thumb, scale, gap); + setThumbPos(w, thumb, scale, gap); } } } /** * @param gap If set to {@link Integer#MIN_VALUE}, this will be ignored and - * the old vertical bounds will be used. */ - private void setThumbPos(int w, int h, Drawable thumb, float scale, int gap) { + private void setThumbPos(int w, Drawable thumb, float scale, int gap) { int available = w - mPaddingLeft - mPaddingRight; int thumbWidth = thumb.getIntrinsicWidth(); int thumbHeight = thumb.getIntrinsicHeight(); @@ -348,6 +347,12 @@ public abstract class AbsSeekBar extends ProgressBar { void onStopTrackingTouch() { } + /** + * Called when the user changes the seekbar's progress by using a key event. + */ + void onKeyChange() { + } + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { int progress = getProgress(); @@ -356,11 +361,13 @@ public abstract class AbsSeekBar extends ProgressBar { case KeyEvent.KEYCODE_DPAD_LEFT: if (progress <= 0) break; setProgress(progress - mKeyProgressIncrement, true); + onKeyChange(); return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (progress >= getMax()) break; setProgress(progress + mKeyProgressIncrement, true); + onKeyChange(); return true; } diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java index 898e501..da90a9f 100644 --- a/core/java/android/widget/CursorAdapter.java +++ b/core/java/android/widget/CursorAdapter.java @@ -127,7 +127,7 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, /** * @see android.widget.ListAdapter#getCount() */ - public final int getCount() { + public int getCount() { if (mDataValid && mCursor != null) { return mCursor.getCount(); } else { @@ -138,7 +138,7 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, /** * @see android.widget.ListAdapter#getItem(int) */ - public final Object getItem(int position) { + public Object getItem(int position) { if (mDataValid && mCursor != null) { mCursor.moveToPosition(position); return mCursor; @@ -150,7 +150,7 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, /** * @see android.widget.ListAdapter#getItemId(int) */ - public final long getItemId(int position) { + public long getItemId(int position) { if (mDataValid && mCursor != null) { if (mCursor.moveToPosition(position)) { return mCursor.getLong(mRowIDColumn); diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 8aafee2..47db6f2 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -57,6 +57,9 @@ public class FrameLayout extends ViewGroup { private final Rect mOverlayBounds = new Rect(); private int mForegroundGravity = Gravity.FILL; + /** {@hide} */ + protected boolean mForegroundInPadding = true; + public FrameLayout(Context context) { super(context); } @@ -71,6 +74,9 @@ public class FrameLayout extends ViewGroup { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout, defStyle, 0); + mForegroundGravity = a.getInt( + com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity); + final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground); if (d != null) { setForeground(d); @@ -80,8 +86,8 @@ public class FrameLayout extends ViewGroup { setMeasureAllChildren(true); } - mForegroundGravity = a.getInt(com.android.internal.R.styleable.FrameLayout_foregroundGravity, - mForegroundGravity); + mForegroundInPadding = a.getBoolean( + com.android.internal.R.styleable.FrameLayout_foregroundInsidePadding, true); a.recycle(); } @@ -105,6 +111,23 @@ public class FrameLayout extends ViewGroup { } mForegroundGravity = foregroundGravity; + + + if (mForegroundGravity == Gravity.FILL && mForeground != null) { + Rect padding = new Rect(); + if (mForeground.getPadding(padding)) { + mForegroundPaddingLeft = padding.left; + mForegroundPaddingTop = padding.top; + mForegroundPaddingRight = padding.right; + mForegroundPaddingBottom = padding.bottom; + } + } else { + mForegroundPaddingLeft = 0; + mForegroundPaddingTop = 0; + mForegroundPaddingRight = 0; + mForegroundPaddingBottom = 0; + } + requestLayout(); } } @@ -167,12 +190,14 @@ public class FrameLayout extends ViewGroup { if (drawable.isStateful()) { drawable.setState(getDrawableState()); } - Rect padding = new Rect(); - if (drawable.getPadding(padding)) { - mForegroundPaddingLeft = padding.left; - mForegroundPaddingTop = padding.top; - mForegroundPaddingRight = padding.right; - mForegroundPaddingBottom = padding.bottom; + if (mForegroundGravity == Gravity.FILL) { + Rect padding = new Rect(); + if (drawable.getPadding(padding)) { + mForegroundPaddingLeft = padding.left; + mForegroundPaddingTop = padding.top; + mForegroundPaddingRight = padding.right; + mForegroundPaddingBottom = padding.bottom; + } } } else { setWillNotDraw(true); @@ -309,10 +334,14 @@ public class FrameLayout extends ViewGroup { final Rect selfBounds = mSelfBounds; final Rect overlayBounds = mOverlayBounds; - selfBounds.set(0, 0, w, h); + if (mForegroundInPadding) { + selfBounds.set(0, 0, w, h); + } else { + selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); + } + Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), foreground.getIntrinsicHeight(), selfBounds, overlayBounds); - foreground.setBounds(overlayBounds); } } diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index aced533..a786b3f 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -1060,6 +1060,7 @@ public class ListView extends AbsListView { * UNSPECIFIED/AT_MOST modes, false otherwise. * @hide */ + @ViewDebug.ExportedProperty protected boolean recycleOnMeasure() { return true; } @@ -2054,18 +2055,19 @@ public class ListView extends AbsListView { */ private boolean handleHorizontalFocusWithinListItem(int direction) { if (direction != View.FOCUS_LEFT && direction != View.FOCUS_RIGHT) { - throw new IllegalArgumentException("direction must be one of {View.FOCUS_LEFT, View.FOCUS_RIGHT}"); + throw new IllegalArgumentException("direction must be one of" + + " {View.FOCUS_LEFT, View.FOCUS_RIGHT}"); } final int numChildren = getChildCount(); if (mItemsCanFocus && numChildren > 0 && mSelectedPosition != INVALID_POSITION) { final View selectedView = getSelectedView(); - if (selectedView.hasFocus() && selectedView instanceof ViewGroup) { + if (selectedView != null && selectedView.hasFocus() && + selectedView instanceof ViewGroup) { + final View currentFocus = selectedView.findFocus(); final View nextFocus = FocusFinder.getInstance().findNextFocus( - (ViewGroup) selectedView, - currentFocus, - direction); + (ViewGroup) selectedView, currentFocus, direction); if (nextFocus != null) { // do the math to get interesting rect in next focus' coordinates currentFocus.getFocusedRect(mTempRect); @@ -2079,11 +2081,8 @@ public class ListView extends AbsListView { // if the global result is going to be some other view within this // list. this is to acheive the overall goal of having // horizontal d-pad navigation remain in the current item. - final View globalNextFocus = FocusFinder.getInstance() - .findNextFocus( - (ViewGroup) getRootView(), - currentFocus, - direction); + final View globalNextFocus = FocusFinder.getInstance().findNextFocus( + (ViewGroup) getRootView(), currentFocus, direction); if (globalNextFocus != null) { return isViewAncestorOf(globalNextFocus, this); } @@ -2769,6 +2768,8 @@ public class ListView extends AbsListView { final boolean headerDividers = mHeaderDividersEnabled; final boolean footerDividers = mFooterDividersEnabled; final int first = mFirstPosition; + final boolean areAllItemsSelectable = mAreAllItemsSelectable; + final ListAdapter adapter = mAdapter; if (!mStackFromBottom) { int bottom; @@ -2779,7 +2780,10 @@ public class ListView extends AbsListView { (footerDividers || first + i < footerLimit)) { View child = getChildAt(i); bottom = child.getBottom(); - if (bottom < listBottom) { + // Don't draw dividers next to items that are not enabled + if (bottom < listBottom && (areAllItemsSelectable || + (adapter.isEnabled(first + i) && (i == count - 1 || + adapter.isEnabled(first + i + 1))))) { bounds.top = bottom; bounds.bottom = bottom + dividerHeight; drawDivider(canvas, bounds, i); @@ -2795,7 +2799,10 @@ public class ListView extends AbsListView { (footerDividers || first + i < footerLimit)) { View child = getChildAt(i); top = child.getTop(); - if (top > listTop) { + // Don't draw dividers next to items that are not enabled + if (top > listTop && (areAllItemsSelectable || + (adapter.isEnabled(first + i) && (i == count - 1 || + adapter.isEnabled(first + i + 1))))) { bounds.top = top - dividerHeight; bounds.bottom = top; // Give the method the child ABOVE the divider, so we diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 227fb95..a2ec83f 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -405,6 +405,8 @@ public class MediaController extends FrameLayout { return super.dispatchKeyEvent(event); } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) { hide(); + + return true; } else { show(sDefaultTimeout); } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index a4f729f..f864690 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -1125,17 +1125,16 @@ public class PopupWindow { } /** - * <p>Updates the position and the dimension of the popup window. Width and - * height can be set to -1 to update location only. Calling this function - * also updates the window with the current popup state as - * described for {@link #update()}.</p> + * <p>Updates the position and the dimension of the popup window. Calling this + * function also updates the window with the current popup state as described + * for {@link #update()}.</p> * * @param anchor the popup's anchor view * @param width the new width, can be -1 to ignore * @param height the new height, can be -1 to ignore */ public void update(View anchor, int width, int height) { - update(anchor, 0, 0, width, height); + update(anchor, false, 0, 0, true, width, height); } /** @@ -1153,31 +1152,44 @@ public class PopupWindow { * @param height the new height, can be -1 to ignore */ public void update(View anchor, int xoff, int yoff, int width, int height) { + update(anchor, true, xoff, yoff, true, width, height); + } + + private void update(View anchor, boolean updateLocation, int xoff, int yoff, + boolean updateDimension, int width, int height) { + if (!isShowing() || mContentView == null) { return; } WeakReference<View> oldAnchor = mAnchor; if (oldAnchor == null || oldAnchor.get() != anchor || - mAnchorXoff != xoff || mAnchorYoff != yoff) { + (updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff))) { registerForScrollChanged(anchor, xoff, yoff); } WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams(); - if (width == -1) { - width = mPopupWidth; - } else { - mPopupWidth = width; + if (updateDimension) { + if (width == -1) { + width = mPopupWidth; + } else { + mPopupWidth = width; + } + if (height == -1) { + height = mPopupHeight; + } else { + mPopupHeight = height; + } } - if (height == -1) { - height = mPopupHeight; + + if (updateLocation) { + mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff); } else { - mPopupHeight = height; + mAboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff); } - - mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff); + update(p.x, p.y, width, height); } diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java index ad5ca07..1800c5a 100644 --- a/core/java/android/widget/RatingBar.java +++ b/core/java/android/widget/RatingBar.java @@ -296,7 +296,13 @@ public class RatingBar extends AbsSeekBar { dispatchRatingChange(true); } } - + + @Override + void onKeyChange() { + super.onKeyChange(); + dispatchRatingChange(true); + } + void dispatchRatingChange(boolean fromUser) { if (mOnRatingBarChangeListener != null) { mOnRatingBarChangeListener.onRatingChanged(this, getRating(), diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 52c421c..c4f0abd 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -821,7 +821,10 @@ public class RelativeLayout extends ViewGroup { @ViewDebug.IntToString(from = CENTER_VERTICAL, to = "centerVertical"), @ViewDebug.IntToString(from = LEFT_OF, to = "leftOf"), @ViewDebug.IntToString(from = RIGHT_OF, to = "rightOf") - }, mapping = { @ViewDebug.IntToString(from = TRUE, to = "true") }) + }, mapping = { + @ViewDebug.IntToString(from = TRUE, to = "true"), + @ViewDebug.IntToString(from = 0, to = "NO_ID") + }) private int[] mRules = new int[VERB_COUNT]; private int mLeft, mTop, mRight, mBottom; diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index e000d2e..7936f65 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -669,50 +669,137 @@ public class RemoteViews implements Parcelable, Filter { setInt(viewId, "setTextColor", color); } + /** + * Call a method taking one boolean on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setBoolean(int viewId, String methodName, boolean value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BOOLEAN, value)); } + /** + * Call a method taking one byte on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setByte(int viewId, String methodName, byte value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BYTE, value)); } + /** + * Call a method taking one short on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setShort(int viewId, String methodName, short value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.SHORT, value)); } + /** + * Call a method taking one int on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setInt(int viewId, String methodName, int value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.INT, value)); } + /** + * Call a method taking one long on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setLong(int viewId, String methodName, long value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.LONG, value)); } + /** + * Call a method taking one float on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setFloat(int viewId, String methodName, float value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.FLOAT, value)); } + /** + * Call a method taking one double on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setDouble(int viewId, String methodName, double value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.DOUBLE, value)); } + /** + * Call a method taking one char on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setChar(int viewId, String methodName, char value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR, value)); } + /** + * Call a method taking one String on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setString(int viewId, String methodName, String value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.STRING, value)); } + /** + * Call a method taking one CharSequence on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setCharSequence(int viewId, String methodName, CharSequence value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR_SEQUENCE, value)); } + /** + * Call a method taking one Uri on a view in the layout for this RemoteViews. + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setUri(int viewId, String methodName, Uri value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.URI, value)); } + /** + * Call a method taking one Bitmap on a view in the layout for this RemoteViews. + * @more + * <p class="note">The bitmap will be flattened into the parcel if this object is + * sent across processes, so it may end up using a lot of memory, and may be fairly slow.</p> + * + * @param viewId The id of the view whose text should change + * @param methodName The name of the method to call. + * @param value The value to pass to the method. + */ public void setBitmap(int viewId, String methodName, Bitmap value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BITMAP, value)); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 7b62b50..9c810e1 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -224,7 +224,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private CharSequence mError; private boolean mErrorWasChanged; - private PopupWindow mPopup; + private ErrorPopup mPopup; /** * This flag is set if the TextView tries to display an error before it * is attached to the window (so its position is still unknown). @@ -727,7 +727,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE); } else if (phone) { mInput = DialerKeyListener.getInstance(); - inputType = EditorInfo.TYPE_CLASS_PHONE; + mInputType = inputType = EditorInfo.TYPE_CLASS_PHONE; } else if (numeric != 0) { mInput = DigitsKeyListener.getInstance((numeric & SIGNED) != 0, (numeric & DECIMAL) != 0); @@ -3039,12 +3039,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return; } } - } - if (ict != null || !shouldAdvanceFocusOnEnter()) { + // This is the handling for some default action. // Note that for backwards compatibility we don't do this // default handling if explicit ime options have not been given, - // to instead turn this into the normal enter key codes that an + // instead turning this into the normal enter key codes that an // app may be expecting. if (actionCode == EditorInfo.IME_ACTION_NEXT) { View v = focusSearch(FOCUS_DOWN); @@ -3066,15 +3065,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } Handler h = getHandler(); - long eventTime = SystemClock.uptimeMillis(); - h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, - new KeyEvent(eventTime, eventTime, - KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, - KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE))); - h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, - new KeyEvent(SystemClock.uptimeMillis(), eventTime, - KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, - KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE))); + if (h != null) { + long eventTime = SystemClock.uptimeMillis(); + h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, + new KeyEvent(eventTime, eventTime, + KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, + KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE + | KeyEvent.FLAG_EDITOR_ACTION))); + h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, + new KeyEvent(SystemClock.uptimeMillis(), eventTime, + KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, + KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE + | KeyEvent.FLAG_EDITOR_ACTION))); + } } /** @@ -3222,25 +3225,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint, null); - mPopup = new PopupWindow(err, 200, 50) { - private boolean mAbove = false; - - @Override - public void update(int x, int y, int w, int h, boolean force) { - super.update(x, y, w, h, force); - - boolean above = isAboveAnchor(); - if (above != mAbove) { - mAbove = above; - - if (above) { - err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above); - } else { - err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error); - } - } - } - }; + mPopup = new ErrorPopup(err, 200, 50); mPopup.setFocusable(false); // The user is entering text, so the input method is needed. We // don't want the popup to be displayed on top of it. @@ -3252,6 +3237,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener tv.setText(mError); mPopup.showAsDropDown(this, getErrorX(), getErrorY()); + mPopup.fixDirection(mPopup.isAboveAnchor()); + } + + private static class ErrorPopup extends PopupWindow { + private boolean mAbove = false; + private TextView mView; + + ErrorPopup(TextView v, int width, int height) { + super(v, width, height); + mView = v; + } + + void fixDirection(boolean above) { + mAbove = above; + + if (above) { + mView.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above); + } else { + mView.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error); + } + } + + @Override + public void update(int x, int y, int w, int h, boolean force) { + super.update(x, y, w, h, force); + + boolean above = isAboveAnchor(); + if (above != mAbove) { + fixDirection(above); + } + } } /** @@ -3343,12 +3359,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mPopup.update(this, getErrorX(), getErrorY(), -1, -1); } + restartMarqueeIfNeeded(); + + return result; + } + + private void restartMarqueeIfNeeded() { if (mRestartMarquee && mEllipsize == TextUtils.TruncateAt.MARQUEE) { mRestartMarquee = false; startMarquee(); } - - return result; } /** @@ -3658,6 +3678,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override protected void onDraw(Canvas canvas) { + restartMarqueeIfNeeded(); + // Draw the background for this view super.onDraw(canvas); @@ -4001,7 +4023,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { - KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN); + KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN); int which = doKeyDown(keyCode, down, event); if (which == 0) { @@ -4020,7 +4042,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // of down and up events until we have done the complete repeatCount. // It would be nice if those interfaces had an onKeyMultiple() method, // but adding that is a more complicated change. - KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP); + KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); if (which == 1) { mInput.onKeyUp(this, (Editable)mText, keyCode, up); while (--repeatCount > 0) { @@ -4069,19 +4091,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } - private boolean isInterestingEnter(KeyEvent event) { - if ((event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 && - mInputContentType != null && - (mInputContentType.imeOptions & - EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { - // If this enter key came from a soft keyboard, and the - // text editor has been configured to not do a default - // action for software enter keys, then we aren't interested. - return false; - } - return true; - } - private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) { if (!isEnabled()) { return 0; @@ -4089,18 +4098,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (keyCode) { case KeyEvent.KEYCODE_ENTER: - if (!isInterestingEnter(event)) { - // Ignore enter key we aren't interested in. - return -1; - } - if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0 - && mInputContentType != null - && mInputContentType.onEditorActionListener != null) { - mInputContentType.enterDown = true; - // We are consuming the enter key for them. - return -1; + // If ALT modifier is held, then we always insert a + // newline character. + if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0) { + + // When mInputContentType is set, we know that we are + // running in a "modern" cupcake environment, so don't need + // to worry about the application trying to capture + // enter key events. + if (mInputContentType != null) { + + // If there is an action listener, given them a + // chance to consume the event. + if (mInputContentType.onEditorActionListener != null && + mInputContentType.onEditorActionListener.onEditorAction( + this, EditorInfo.IME_NULL, event)) { + mInputContentType.enterDown = true; + // We are consuming the enter key for them. + return -1; + } + } + + // If our editor should move focus when enter is pressed, or + // this is a generated event from an IME action button, then + // don't let it be inserted into the text. + if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0 + || shouldAdvanceFocusOnEnter()) { + return -1; + } } - // fall through... + break; + case KeyEvent.KEYCODE_DPAD_CENTER: if (shouldAdvanceFocusOnEnter()) { return 0; @@ -4215,7 +4243,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - if (shouldAdvanceFocusOnEnter()) { + if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0 + || shouldAdvanceFocusOnEnter()) { /* * If there is a click listener, just call through to * super, which will invoke it. @@ -4243,7 +4272,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener super.onKeyUp(keyCode, event); return true; } else if ((event.getFlags() - & KeyEvent.FLAG_SOFT_KEYBOARD) != 0) { + & KeyEvent.FLAG_EDITOR_ACTION) != 0) { // No target for next focus, but make sure the IME // if this came from it. InputMethodManager imm = InputMethodManager.peekInstance(); @@ -4302,6 +4331,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION; } } + if ((outAttrs.inputType & (InputType.TYPE_MASK_CLASS + | InputType.TYPE_TEXT_FLAG_MULTI_LINE)) + == (InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_FLAG_MULTI_LINE)) { + // Multi-line text editors should always show an enter key. + outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION; + } outAttrs.hintText = mHint; if (mText instanceof Editable) { InputConnection ic = new EditableInputConnection(this); @@ -5391,6 +5427,62 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return changed; } + /** + * Move the cursor, if needed, so that it is at an offset that is visible + * to the user. This will not move the cursor if it represents more than + * one character (a selection range). This will only work if the + * TextView contains spannable text; otherwise it will do nothing. + */ + public boolean moveCursorToVisibleOffset() { + if (!(mText instanceof Spannable)) { + return false; + } + int start = Selection.getSelectionStart(mText); + int end = Selection.getSelectionEnd(mText); + if (start != end) { + return false; + } + + // First: make sure the line is visible on screen: + + int line = mLayout.getLineForOffset(start); + + final int top = mLayout.getLineTop(line); + final int bottom = mLayout.getLineTop(line+1); + final int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom(); + int vslack = (bottom - top) / 2; + if (vslack > vspace / 4) + vslack = vspace / 4; + final int vs = mScrollY; + + if (top < (vs+vslack)) { + line = mLayout.getLineForVertical(vs+vslack+(bottom-top)); + } else if (bottom > (vspace+vs-vslack)) { + line = mLayout.getLineForVertical(vspace+vs-vslack-(bottom-top)); + } + + // Next: make sure the character is visible on screen: + + final int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(); + final int hs = mScrollX; + final int leftChar = mLayout.getOffsetForHorizontal(line, hs); + final int rightChar = mLayout.getOffsetForHorizontal(line, hspace+hs); + + int newStart = start; + if (newStart < leftChar) { + newStart = leftChar; + } else if (newStart > rightChar) { + newStart = rightChar; + } + + if (newStart != start) { + Selection.setSelection((Spannable)mText, newStart); + return true; + } + + return false; + } + @Override public void computeScroll() { if (mScroller != null) { diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java index 0df919d..c5fa18c 100644 --- a/core/java/android/widget/ZoomButton.java +++ b/core/java/android/widget/ZoomButton.java @@ -19,15 +19,11 @@ package android.widget; import android.content.Context; import android.os.Handler; import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.GestureDetector.SimpleOnGestureListener; import android.view.View.OnLongClickListener; - public class ZoomButton extends ImageButton implements OnLongClickListener { private final Handler mHandler; @@ -39,7 +35,6 @@ public class ZoomButton extends ImageButton implements OnLongClickListener { } } }; - private final GestureDetector mGestureDetector; private long mZoomSpeed = 1000; private boolean mIsInLongpress; @@ -55,19 +50,11 @@ public class ZoomButton extends ImageButton implements OnLongClickListener { public ZoomButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mHandler = new Handler(); - mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() { - @Override - public void onLongPress(MotionEvent e) { - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - onLongClick(ZoomButton.this); - } - }); setOnLongClickListener(this); } @Override public boolean onTouchEvent(MotionEvent event) { - mGestureDetector.onTouchEvent(event); if ((event.getAction() == MotionEvent.ACTION_CANCEL) || (event.getAction() == MotionEvent.ACTION_UP)) { mIsInLongpress = false; diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java index 4daa419..d9fb78b 100644 --- a/core/java/android/widget/ZoomButtonsController.java +++ b/core/java/android/widget/ZoomButtonsController.java @@ -16,23 +16,15 @@ package android.widget; -import android.app.AlertDialog; -import android.app.Dialog; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.graphics.Canvas; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Handler; import android.os.Message; -import android.os.SystemClock; -import android.provider.Settings; import android.util.Log; -import android.view.GestureDetector; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -42,7 +34,6 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewRoot; -import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.view.WindowManager.LayoutParams; @@ -51,29 +42,33 @@ import android.view.WindowManager.LayoutParams; * Implementation notes: * - The zoom controls are displayed in their own window. * (Easier for the client and better performance) - * - This window is not touchable, and by default is not focusable. - * - To make the buttons clickable, it attaches a OnTouchListener to the owner - * view and does the hit detection locally. + * - This window is never touchable, and by default is not focusable. + * Its rect is quite big (fills horizontally) but has empty space between the + * edges and center. Touches there should be given to the owner. Instead of + * having the window touchable and dispatching these empty touch events to the + * owner, we set the window to not touchable and steal events from owner + * via onTouchListener. + * - To make the buttons clickable, it attaches an OnTouchListener to the owner + * view and does the hit detection locally (attaches when visible, detaches when invisible). * - When it is focusable, it forwards uninteresting events to the owner view's * view hierarchy. */ /** * The {@link ZoomButtonsController} handles showing and hiding the zoom - * controls relative to an owner view. It also gives the client access to the - * zoom controls container, allowing for additional accessory buttons to be - * shown in the zoom controls window. + * controls and positioning it relative to an owner view. It also gives the + * client access to the zoom controls container, allowing for additional + * accessory buttons to be shown in the zoom controls window. * <p> - * Typical usage involves the client using the {@link GestureDetector} to - * forward events from - * {@link GestureDetector.OnDoubleTapListener#onDoubleTapEvent(MotionEvent)} to - * {@link #handleDoubleTapEvent(MotionEvent)}. Also, whenever the owner cannot - * be zoomed further, the client should update + * Typically, clients should call {@link #setVisible(boolean) setVisible(true)} + * on a touch down or move (no need to call {@link #setVisible(boolean) + * setVisible(false)} since it will time out on its own). Also, whenever the + * owner cannot be zoomed further, the client should update * {@link #setZoomInEnabled(boolean)} and {@link #setZoomOutEnabled(boolean)}. * <p> * If you are using this with a custom View, please call * {@link #setVisible(boolean) setVisible(false)} from the * {@link View#onDetachedFromWindow}. - * + * * @hide */ public class ZoomButtonsController implements View.OnTouchListener { @@ -88,6 +83,7 @@ public class ZoomButtonsController implements View.OnTouchListener { private Context mContext; private WindowManager mWindowManager; + private boolean mAutoDismissControls = true; /** * The view that is being zoomed by this zoom controller. @@ -118,35 +114,26 @@ public class ZoomButtonsController implements View.OnTouchListener { * The {@link #mTouchTargetView}'s location in window, set on touch down. */ private int[] mTouchTargetWindowLocation = new int[2]; + /** * If the zoom controller is dismissed but the user is still in a touch * interaction, we set this to true. This will ignore all touch events until * up/cancel, and then set the owner's touch listener to null. + * <p> + * Otherwise, the owner view would get mismatched events (i.e., touch move + * even though it never got the touch down.) */ private boolean mReleaseTouchListenerOnUp; - /** - * Whether we are currently in the double-tap gesture, with the second tap - * still being performed (i.e., we're waiting for the second tap's touch up). - */ - private boolean mIsSecondTapDown; - /** Whether the container has been added to the window manager. */ private boolean mIsVisible; private Rect mTempRect = new Rect(); private int[] mTempIntArray = new int[2]; - + private OnZoomListener mCallback; /** - * In 1.0, the ZoomControls were to be added to the UI by the client of - * WebView, MapView, etc. We didn't want apps to break, so we return a dummy - * view in place now. - */ - private InvisibleView mDummyZoomControls; - - /** * When showing the zoom, we add the view as a new window. However, there is * logic that needs to know the size of the zoom which is determined after * it's laid out. Therefore, we must post this logic onto the UI thread so @@ -170,12 +157,6 @@ public class ZoomButtonsController implements View.OnTouchListener { } }; - /** - * The setting name that tracks whether we've shown the zoom tutorial. - */ - private static final String SETTING_NAME_SHOWN_TUTORIAL = "shown_zoom_tutorial"; - private static Dialog sTutorialDialog; - /** When configuration changes, this is called after the UI thread is idle. */ private static final int MSG_POST_CONFIGURATION_CHANGED = 2; /** Used to delay the zoom controller dismissal. */ @@ -215,7 +196,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Constructor for the {@link ZoomButtonsController}. - * + * * @param ownerView The view that is being zoomed by the zoom controls. The * zoom controls will be displayed aligned with this view. */ @@ -227,13 +208,13 @@ public class ZoomButtonsController implements View.OnTouchListener { mTouchPaddingScaledSq = (int) (ZOOM_CONTROLS_TOUCH_PADDING * mContext.getResources().getDisplayMetrics().density); mTouchPaddingScaledSq *= mTouchPaddingScaledSq; - + mContainer = createContainer(); } /** * Whether to enable the zoom in control. - * + * * @param enabled Whether to enable the zoom in control. */ public void setZoomInEnabled(boolean enabled) { @@ -242,7 +223,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Whether to enable the zoom out control. - * + * * @param enabled Whether to enable the zoom out control. */ public void setZoomOutEnabled(boolean enabled) { @@ -251,7 +232,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Sets the delay between zoom callbacks as the user holds a zoom button. - * + * * @param speed The delay in milliseconds between zoom callbacks. */ public void setZoomSpeed(long speed) { @@ -264,7 +245,8 @@ public class ZoomButtonsController implements View.OnTouchListener { lp.gravity = Gravity.TOP | Gravity.LEFT; lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE | LayoutParams.FLAG_NOT_FOCUSABLE | - LayoutParams.FLAG_LAYOUT_NO_LIMITS; + LayoutParams.FLAG_LAYOUT_NO_LIMITS | + LayoutParams.FLAG_ALT_FOCUSABLE_IM; lp.height = LayoutParams.WRAP_CONTENT; lp.width = LayoutParams.FILL_PARENT; lp.type = LayoutParams.TYPE_APPLICATION_PANEL; @@ -299,7 +281,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Sets the {@link OnZoomListener} listener that receives callbacks to zoom. - * + * * @param listener The listener that will be told to zoom. */ public void setOnZoomListener(OnZoomListener listener) { @@ -310,7 +292,7 @@ public class ZoomButtonsController implements View.OnTouchListener { * Sets whether the zoom controls should be focusable. If the controls are * focusable, then trackball and arrow key interactions are possible. * Otherwise, only touch interactions are possible. - * + * * @param focusable Whether the zoom controls should be focusable. */ public void setFocusable(boolean focusable) { @@ -327,8 +309,26 @@ public class ZoomButtonsController implements View.OnTouchListener { } /** + * Whether the zoom controls will be automatically dismissed after showing. + * + * @return Whether the zoom controls will be auto dismissed after showing. + */ + public boolean isAutoDismissed() { + return mAutoDismissControls; + } + + /** + * Sets whether the zoom controls will be automatically dismissed after + * showing. + */ + public void setAutoDismissed(boolean autoDismiss) { + if (mAutoDismissControls == autoDismiss) return; + mAutoDismissControls = autoDismiss; + } + + /** * Whether the zoom controls are visible to the user. - * + * * @return Whether the zoom controls are visible to the user. */ public boolean isVisible() { @@ -337,7 +337,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Sets whether the zoom controls should be visible to the user. - * + * * @param visible Whether the zoom controls should be visible to the user. */ public void setVisible(boolean visible) { @@ -419,7 +419,7 @@ public class ZoomButtonsController implements View.OnTouchListener { * <p> * The client can add other views to this container to link them with the * zoom controls. - * + * * @return The container of the zoom controls. It will be a layout that * respects the gravity of a child's layout parameters. */ @@ -427,43 +427,20 @@ public class ZoomButtonsController implements View.OnTouchListener { return mContainer; } - private void dismissControlsDelayed(int delay) { - mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); - mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); - } - /** - * Should be called by the client for each event belonging to the second tap - * (the down, move, up, and/or cancel events). + * Gets the view for the zoom controls. * - * @param event The event belonging to the second tap. - * @return Whether the event was consumed. + * @return The zoom controls view. */ - public boolean handleDoubleTapEvent(MotionEvent event) { - int action = event.getAction(); + public View getZoomControls() { + return mControls; + } - if (action == MotionEvent.ACTION_DOWN) { - int x = (int) event.getX(); - int y = (int) event.getY(); - - /* - * This class will consume all events in the second tap (down, - * move(s), up). But, the owner already got the second tap's down, - * so cancel that. Do this before setVisible, since that call - * will set us as a touch listener. - */ - MotionEvent cancelEvent = MotionEvent.obtain(event.getDownTime(), - SystemClock.elapsedRealtime(), - MotionEvent.ACTION_CANCEL, 0, 0, 0); - mOwnerView.dispatchTouchEvent(cancelEvent); - cancelEvent.recycle(); - - setVisible(true); - centerPoint(x, y); - mIsSecondTapDown = true; + private void dismissControlsDelayed(int delay) { + if (mAutoDismissControls) { + mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); + mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); } - - return true; } private void refreshPositioningVariables() { @@ -477,7 +454,7 @@ public class ZoomButtonsController implements View.OnTouchListener { mOwnerView.getLocationOnScreen(mOwnerViewRawLocation); mContainerRawLocation[0] = mOwnerViewRawLocation[0]; mContainerRawLocation[1] = mOwnerViewRawLocation[1] + containerOwnerYOffset; - + int[] ownerViewWindowLoc = mTempIntArray; mOwnerView.getLocationInWindow(ownerViewWindowLoc); @@ -488,39 +465,30 @@ public class ZoomButtonsController implements View.OnTouchListener { if (mIsVisible) { mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); } - - } - /** - * Centers the point (in owner view's coordinates). - */ - private void centerPoint(int x, int y) { - if (mCallback != null) { - mCallback.onCenter(x, y); - } } /* This will only be called when the container has focus. */ private boolean onContainerKey(KeyEvent event) { int keyCode = event.getKeyCode(); if (isInterestingKey(keyCode)) { - + if (keyCode == KeyEvent.KEYCODE_BACK) { setVisible(false); } else { dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); } - + // Let the container handle the key return false; - + } else { - + ViewRoot viewRoot = getOwnerViewRoot(); if (viewRoot != null) { viewRoot.dispatchKey(event); } - + // We gave the key to the owner, don't let the container handle this key return true; } @@ -540,13 +508,13 @@ public class ZoomButtonsController implements View.OnTouchListener { return false; } } - + private ViewRoot getOwnerViewRoot() { View rootViewOfOwner = mOwnerView.getRootView(); if (rootViewOfOwner == null) { return null; } - + ViewParent parentOfRootView = rootViewOfOwner.getParent(); if (parentOfRootView instanceof ViewRoot) { return (ViewRoot) parentOfRootView; @@ -562,13 +530,6 @@ public class ZoomButtonsController implements View.OnTouchListener { public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); - // Consume all events during the second-tap interaction (down, move, up/cancel) - boolean consumeEvent = mIsSecondTapDown; - if ((action == MotionEvent.ACTION_UP) || (action == MotionEvent.ACTION_CANCEL)) { - // The second tap can no longer be down - mIsSecondTapDown = false; - } - if (mReleaseTouchListenerOnUp) { // The controls were dismissed but we need to throw away all events until the up if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { @@ -609,18 +570,21 @@ public class ZoomButtonsController implements View.OnTouchListener { mOwnerViewRawLocation[1] - targetViewRawY); /* Disallow negative coordinates (which can occur due to * ZOOM_CONTROLS_TOUCH_PADDING) */ - if (containerEvent.getX() < 0) { - containerEvent.offsetLocation(-containerEvent.getX(), 0); + // These are floats because we need to potentially offset away this exact amount + float containerX = containerEvent.getX(); + float containerY = containerEvent.getY(); + if (containerX < 0 && containerX > -ZOOM_CONTROLS_TOUCH_PADDING) { + containerEvent.offsetLocation(-containerX, 0); } - if (containerEvent.getY() < 0) { - containerEvent.offsetLocation(0, -containerEvent.getY()); + if (containerY < 0 && containerY > -ZOOM_CONTROLS_TOUCH_PADDING) { + containerEvent.offsetLocation(0, -containerY); } boolean retValue = targetView.dispatchTouchEvent(containerEvent); containerEvent.recycle(); - return retValue || consumeEvent; + return retValue; } else { - return consumeEvent; + return false; } } @@ -646,7 +610,7 @@ public class ZoomButtonsController implements View.OnTouchListener { View closestChild = null; int closestChildDistanceSq = Integer.MAX_VALUE; - + for (int i = mContainer.getChildCount() - 1; i >= 0; i--) { View child = mContainer.getChildAt(i); if (child.getVisibility() != View.VISIBLE) { @@ -657,13 +621,23 @@ public class ZoomButtonsController implements View.OnTouchListener { if (frame.contains(containerCoordsX, containerCoordsY)) { return child; } - - int distanceX = Math.min(Math.abs(frame.left - containerCoordsX), + + int distanceX; + if (containerCoordsX >= frame.left && containerCoordsX <= frame.right) { + distanceX = 0; + } else { + distanceX = Math.min(Math.abs(frame.left - containerCoordsX), Math.abs(containerCoordsX - frame.right)); - int distanceY = Math.min(Math.abs(frame.top - containerCoordsY), - Math.abs(containerCoordsY - frame.bottom)); + } + int distanceY; + if (containerCoordsY >= frame.top && containerCoordsY <= frame.bottom) { + distanceY = 0; + } else { + distanceY = Math.min(Math.abs(frame.top - containerCoordsY), + Math.abs(containerCoordsY - frame.bottom)); + } int distanceSq = distanceX * distanceX + distanceY * distanceY; - + if ((distanceSq < mTouchPaddingScaledSq) && (distanceSq < closestChildDistanceSq)) { closestChild = child; @@ -679,130 +653,27 @@ public class ZoomButtonsController implements View.OnTouchListener { refreshPositioningVariables(); } - /* - * This is static so Activities can call this instead of the Views - * (Activities usually do not have a reference to the ZoomButtonsController - * instance.) - */ - /** - * Shows a "tutorial" (some text) to the user teaching her the new zoom - * invocation method. Must call from the main thread. - * <p> - * It checks the global system setting to ensure this has not been seen - * before. Furthermore, if the application does not have privilege to write - * to the system settings, it will store this bit locally in a shared - * preference. - * - * @hide This should only be used by our main apps--browser, maps, and - * gallery - */ - public static void showZoomTutorialOnce(Context context) { - - // TODO: remove this code, but to hit the weekend build, just never show - if (true) return; - - ContentResolver cr = context.getContentResolver(); - if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { - return; - } - - SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); - if (sp.getInt(SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { - return; - } - - if (sTutorialDialog != null && sTutorialDialog.isShowing()) { - sTutorialDialog.dismiss(); - } - - LayoutInflater layoutInflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - TextView textView = (TextView) layoutInflater.inflate( - com.android.internal.R.layout.alert_dialog_simple_text, null) - .findViewById(android.R.id.text1); - textView.setText(com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short); - - sTutorialDialog = new AlertDialog.Builder(context) - .setView(textView) - .setIcon(0) - .create(); - - Window window = sTutorialDialog.getWindow(); - window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); - window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | - WindowManager.LayoutParams.FLAG_BLUR_BEHIND); - window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - - sTutorialDialog.show(); - } - - /** @hide Should only be used by Android platform apps */ - public static void finishZoomTutorial(Context context, boolean userNotified) { - if (sTutorialDialog == null) return; - - sTutorialDialog.dismiss(); - sTutorialDialog = null; - - // Record that they have seen the tutorial - if (userNotified) { - try { - Settings.System.putInt(context.getContentResolver(), SETTING_NAME_SHOWN_TUTORIAL, - 1); - } catch (SecurityException e) { - /* - * The app does not have permission to clear this global flag, make - * sure the user does not see the message when he comes back to this - * same app at least. - */ - SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); - sp.edit().putInt(SETTING_NAME_SHOWN_TUTORIAL, 1).commit(); - } - } - } - - /** @hide Should only be used by Android platform apps */ - public void finishZoomTutorial() { - finishZoomTutorial(mContext, true); - } - - /** @hide Should only be used only be WebView and MapView */ - public View getDummyZoomControls() { - if (mDummyZoomControls == null) { - mDummyZoomControls = new InvisibleView(mContext); - } - return mDummyZoomControls; - } - /** * Interface that will be called when the user performs an interaction that * triggers some action, for example zooming. */ public interface OnZoomListener { - /** - * Called when the given point should be centered. The point will be in - * owner view coordinates. - * - * @param x The x of the point. - * @param y The y of the point. - */ - void onCenter(int x, int y); - + /** * Called when the zoom controls' visibility changes. - * + * * @param visible Whether the zoom controls are visible. */ void onVisibilityChanged(boolean visible); - + /** * Called when the owner view needs to be zoomed. - * + * * @param zoomIn The direction of the zoom: true to zoom in, false to zoom out. */ void onZoom(boolean zoomIn); } - + private class Container extends FrameLayout { public Container(Context context) { super(context); @@ -820,29 +691,4 @@ public class ZoomButtonsController implements View.OnTouchListener { } } - /** - * An InvisibleView is an invisible, zero-sized View for backwards - * compatibility - */ - private final class InvisibleView extends View { - - private InvisibleView(Context context) { - super(context); - setVisibility(GONE); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(0, 0); - } - - @Override - public void draw(Canvas canvas) { - } - - @Override - protected void dispatchDraw(Canvas canvas) { - } - } - } diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java index 84d8f0e..a12aee5 100644 --- a/core/java/android/widget/ZoomControls.java +++ b/core/java/android/widget/ZoomControls.java @@ -30,11 +30,6 @@ import com.android.internal.R; /** * The {@code ZoomControls} class displays a simple set of controls used for zooming and * provides callbacks to register for events. */ -// TODO: pending API council -// * <p> -// * Instead of using this directly, consider using the {@link ZoomButtonsController} which -// * handles displaying the zoom controls. -// */ @Widget public class ZoomControls extends LinearLayout { diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 5c44b2d..57dbb44 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -17,7 +17,6 @@ package com.android.internal.app; import static android.view.ViewGroup.LayoutParams.FILL_PARENT; -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -49,6 +48,7 @@ import android.widget.ScrollView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; +import android.util.AttributeSet; import com.android.internal.R; @@ -361,11 +361,14 @@ public class AlertController { if (mView != null) { customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel); FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom); - custom.addView(mView, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); + custom.addView(mView, new LayoutParams(FILL_PARENT, FILL_PARENT)); if (mViewSpacingSpecified) { custom.setPadding(mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom); } + if (mListView != null) { + ((LinearLayout.LayoutParams) customPanel.getLayoutParams()).weight = 0; + } } else { mWindow.findViewById(R.id.customPanel).setVisibility(View.GONE); } @@ -456,7 +459,9 @@ public class AlertController { if (mListView != null) { contentPanel.removeView(mWindow.findViewById(R.id.scrollView)); - contentPanel.addView(mListView, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT)); + contentPanel.addView(mListView, + new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT)); + contentPanel.setLayoutParams(new LinearLayout.LayoutParams(FILL_PARENT, 0, 1.0f)); } else { contentPanel.setVisibility(View.GONE); } @@ -667,7 +672,28 @@ public class AlertController { } } } - + + public static class RecycleListView extends ListView { + boolean mRecycleOnMeasure = true; + + public RecycleListView(Context context) { + super(context); + } + + public RecycleListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RecycleListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected boolean recycleOnMeasure() { + return mRecycleOnMeasure; + } + } + public static class AlertParams { public final Context mContext; public final LayoutInflater mInflater; @@ -706,7 +732,8 @@ public class AlertController { public boolean mForceInverseBackground; public AdapterView.OnItemSelectedListener mOnItemSelectedListener; public OnPrepareListViewListener mOnPrepareListViewListener; - + public boolean mRecycleOnMeasure = true; + /** * Interface definition for a callback to be invoked before the ListView * will be bound to an adapter. @@ -782,7 +809,8 @@ public class AlertController { } private void createListView(final AlertController dialog) { - final ListView listView = (ListView) mInflater.inflate(R.layout.select_dialog, null); + final RecycleListView listView = (RecycleListView) + mInflater.inflate(R.layout.select_dialog, null); ListAdapter adapter; if (mIsMultiChoice) { @@ -881,6 +909,7 @@ public class AlertController { } else if (mIsMultiChoice) { listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); } + listView.mRecycleOnMeasure = mRecycleOnMeasure; dialog.mListView = listView; } } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index edda1d9..fff8dcf 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -30,7 +30,19 @@ interface IBatteryStats { void noteScreenOff(); void notePhoneOn(); void notePhoneOff(); - void setOnBattery(boolean onBattery); + void notePhoneSignalStrength(int asu); + void notePhoneDataConnectionState(int dataType, boolean hasData); + void noteWifiOn(); + void noteWifiOff(); + void noteWifiRunning(); + void noteWifiStopped(); + void noteBluetoothOn(); + void noteBluetoothOff(); + void noteFullWifiLockAcquired(int uid); + void noteFullWifiLockReleased(int uid); + void noteScanWifiLockAcquired(int uid); + void noteScanWifiLockReleased(int uid); + void setOnBattery(boolean onBattery, int level); long getAwakeTimeBattery(); long getAwakeTimePlugged(); } diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java index 1f8e6f0..5a0fea3 100644 --- a/core/java/com/android/internal/app/RingtonePickerActivity.java +++ b/core/java/com/android/internal/app/RingtonePickerActivity.java @@ -247,9 +247,13 @@ public final class RingtonePickerActivity extends AlertActivity implements } else { setResult(RESULT_CANCELED); } - - mCursor.deactivate(); - + + getWindow().getDecorView().post(new Runnable() { + public void run() { + mCursor.deactivate(); + } + }); + finish(); } diff --git a/core/java/com/android/internal/database/SortCursor.java b/core/java/com/android/internal/database/SortCursor.java index af0efc9..99410bc 100644 --- a/core/java/com/android/internal/database/SortCursor.java +++ b/core/java/com/android/internal/database/SortCursor.java @@ -253,7 +253,15 @@ public class SortCursor extends AbstractCursor if (mCursor != null) { return mCursor.getColumnNames(); } else { - return new String[0]; + // All of the cursors may be empty, but they can still return + // this information. + int length = mCursors.length; + for (int i = 0 ; i < length ; i++) { + if (mCursors[i] != null) { + return mCursors[i].getColumnNames(); + } + } + throw new IllegalStateException("No cursor that can return names"); } } diff --git a/core/java/com/android/internal/logging/AndroidHandler.java b/core/java/com/android/internal/logging/AndroidHandler.java index d9fcf60..c4a1479 100644 --- a/core/java/com/android/internal/logging/AndroidHandler.java +++ b/core/java/com/android/internal/logging/AndroidHandler.java @@ -151,7 +151,7 @@ public class AndroidHandler extends Handler { Log.e("AndroidHandler", "Error logging message.", e); } } - + /** * Converts a {@link java.util.logging.Logger} logging level into an Android one. * @@ -159,20 +159,16 @@ public class AndroidHandler extends Handler { * * @return The resulting Android logging level. */ - static int getAndroidLevel(Level level) - { + static int getAndroidLevel(Level level) { int value = level.intValue(); - - if (value >= Level.SEVERE.intValue()) { + if (value >= 1000) { // SEVERE return Log.ERROR; - } else if (value >= Level.WARNING.intValue()) { + } else if (value >= 900) { // WARNING return Log.WARN; - } else if (value >= Level.INFO.intValue()) { + } else if (value >= 800) { // INFO return Log.INFO; - } else if (value >= Level.CONFIG.intValue()) { + } else { return Log.DEBUG; - } else { - return Log.VERBOSE; } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 7eea8b7..9e07fd8 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -22,6 +22,7 @@ import android.os.Parcel; import android.os.ParcelFormatException; import android.os.Parcelable; import android.os.SystemClock; +import android.telephony.TelephonyManager; import android.util.Log; import android.util.Printer; import android.util.SparseArray; @@ -47,7 +48,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 25; + private static final int VERSION = 29; private final File mFile; private final File mBackupFile; @@ -92,6 +93,21 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mPhoneOn; Timer mPhoneOnTimer; + int mPhoneSignalStrengthBin = -1; + final Timer[] mPhoneSignalStrengthsTimer = new Timer[NUM_SIGNAL_STRENGTH_BINS]; + + int mPhoneDataConnectionType = -1; + final Timer[] mPhoneDataConnectionsTimer = new Timer[NUM_DATA_CONNECTION_TYPES]; + + boolean mWifiOn; + Timer mWifiOnTimer; + + boolean mWifiRunning; + Timer mWifiRunningTimer; + + boolean mBluetoothOn; + Timer mBluetoothOnTimer; + /** * These provide time bases that discount the time the device is plugged * in to power. @@ -106,6 +122,12 @@ public final class BatteryStatsImpl extends BatteryStats { long mUnpluggedBatteryUptime; long mUnpluggedBatteryRealtime; + /* + * These keep track of battery levels (1-100) at the last plug event and the last unplug event. + */ + int mUnpluggedStartLevel; + int mPluggedStartLevel; + long mLastWriteTime = 0; // Milliseconds // For debugging @@ -292,15 +314,15 @@ public final class BatteryStatsImpl extends BatteryStats { return val; } - public void logState() { - Log.i("foo", "mNesting=" + mNesting + " mCount=" + mCount + public void logState(Printer pw, String prefix) { + pw.println(prefix + "mNesting=" + mNesting + " mCount=" + mCount + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount + " mUnpluggedCount=" + mUnpluggedCount); - Log.i("foo", "mTotalTime=" + mTotalTime + pw.println(prefix + "mTotalTime=" + mTotalTime + " mLoadedTime=" + mLoadedTime); - Log.i("foo", "mLastTime=" + mLastTime + pw.println(prefix + "mLastTime=" + mLastTime + " mUnpluggedTime=" + mUnpluggedTime); - Log.i("foo", "mUpdateTime=" + mUpdateTime + pw.println(prefix + "mUpdateTime=" + mUpdateTime + " mAcquireTime=" + mAcquireTime); } @@ -471,6 +493,120 @@ public final class BatteryStatsImpl extends BatteryStats { } } + public void notePhoneSignalStrengthLocked(int asu) { + // Bin the strength. + int bin; + if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; + else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; + else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; + else bin = SIGNAL_STRENGTH_POOR; + if (mPhoneSignalStrengthBin != bin) { + if (mPhoneSignalStrengthBin >= 0) { + mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this); + } + mPhoneSignalStrengthBin = bin; + mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); + } + } + + public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) { + int bin = DATA_CONNECTION_NONE; + if (hasData) { + switch (dataType) { + case TelephonyManager.NETWORK_TYPE_EDGE: + bin = DATA_CONNECTION_EDGE; + break; + case TelephonyManager.NETWORK_TYPE_GPRS: + bin = DATA_CONNECTION_GPRS; + break; + case TelephonyManager.NETWORK_TYPE_UMTS: + bin = DATA_CONNECTION_UMTS; + break; + default: + bin = DATA_CONNECTION_OTHER; + break; + } + } + if (mPhoneDataConnectionType != bin) { + if (mPhoneDataConnectionType >= 0) { + mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); + } + mPhoneDataConnectionType = bin; + mPhoneDataConnectionsTimer[bin].startRunningLocked(this); + } + } + + public void noteWifiOnLocked() { + if (!mWifiOn) { + mWifiOn = true; + mWifiOnTimer.startRunningLocked(this); + } + } + + public void noteWifiOffLocked() { + if (mWifiOn) { + mWifiOn = false; + mWifiOnTimer.stopRunningLocked(this); + } + } + + public void noteWifiRunningLocked() { + if (!mWifiRunning) { + mWifiRunning = true; + mWifiRunningTimer.startRunningLocked(this); + } + } + + public void noteWifiStoppedLocked() { + if (mWifiRunning) { + mWifiRunning = false; + mWifiRunningTimer.stopRunningLocked(this); + } + } + + public void noteBluetoothOnLocked() { + if (!mBluetoothOn) { + mBluetoothOn = true; + mBluetoothOnTimer.startRunningLocked(this); + } + } + + public void noteBluetoothOffLocked() { + if (mBluetoothOn) { + mBluetoothOn = false; + mBluetoothOnTimer.stopRunningLocked(this); + } + } + + public void noteFullWifiLockAcquiredLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteFullWifiLockAcquiredLocked(); + } + } + + public void noteFullWifiLockReleasedLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteFullWifiLockReleasedLocked(); + } + } + + public void noteScanWifiLockAcquiredLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteScanWifiLockAcquiredLocked(); + } + } + + public void noteScanWifiLockReleasedLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteScanWifiLockReleasedLocked(); + } + } + @Override public long getScreenOnTime(long batteryRealtime, int which) { return mScreenOnTimer.getTotalTime(batteryRealtime, which); } @@ -479,6 +615,30 @@ public final class BatteryStatsImpl extends BatteryStats { return mPhoneOnTimer.getTotalTime(batteryRealtime, which); } + @Override public long getPhoneSignalStrengthTime(int strengthBin, + long batteryRealtime, int which) { + return mPhoneSignalStrengthsTimer[strengthBin].getTotalTime( + batteryRealtime, which); + } + + @Override public long getPhoneDataConnectionTime(int dataType, + long batteryRealtime, int which) { + return mPhoneDataConnectionsTimer[dataType].getTotalTime( + batteryRealtime, which); + } + + @Override public long getWifiOnTime(long batteryRealtime, int which) { + return mWifiOnTimer.getTotalTime(batteryRealtime, which); + } + + @Override public long getWifiRunningTime(long batteryRealtime, int which) { + return mWifiRunningTimer.getTotalTime(batteryRealtime, which); + } + + @Override public long getBluetoothOnTime(long batteryRealtime, int which) { + return mBluetoothOnTimer.getTotalTime(batteryRealtime, which); + } + @Override public boolean getIsOnBattery() { return mOnBattery; } @@ -505,6 +665,12 @@ public final class BatteryStatsImpl extends BatteryStats { long mStartedTcpBytesReceived = -1; long mStartedTcpBytesSent = -1; + boolean mFullWifiLockOut; + Timer mFullWifiLockTimer; + + boolean mScanWifiLockOut; + Timer mScanWifiLockTimer; + /** * The statistics we have collected for this uid's wake locks. */ @@ -527,6 +693,8 @@ public final class BatteryStatsImpl extends BatteryStats { public Uid(int uid) { mUid = uid; + mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables); + mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables); } @Override @@ -586,6 +754,47 @@ public final class BatteryStatsImpl extends BatteryStats { } } + @Override + public void noteFullWifiLockAcquiredLocked() { + if (!mFullWifiLockOut) { + mFullWifiLockOut = true; + mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteFullWifiLockReleasedLocked() { + if (mFullWifiLockOut) { + mFullWifiLockOut = false; + mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteScanWifiLockAcquiredLocked() { + if (!mScanWifiLockOut) { + mScanWifiLockOut = true; + mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteScanWifiLockReleasedLocked() { + if (mScanWifiLockOut) { + mScanWifiLockOut = false; + mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + @Override + public long getFullWifiLockTime(long batteryRealtime, int which) { + return mFullWifiLockTimer.getTotalTime(batteryRealtime, which); + } + + @Override + public long getScanWifiLockTime(long batteryRealtime, int which) { + return mScanWifiLockTimer.getTotalTime(batteryRealtime, which); + } + public long computeCurrentTcpBytesSent() { return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); @@ -626,6 +835,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(computeCurrentTcpBytesSent()); out.writeLong(mTcpBytesReceivedAtLastUnplug); out.writeLong(mTcpBytesSentAtLastUnplug); + mFullWifiLockTimer.writeToParcel(out, batteryRealtime); + mScanWifiLockTimer.writeToParcel(out, batteryRealtime); } void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { @@ -671,6 +882,10 @@ public final class BatteryStatsImpl extends BatteryStats { mCurrentTcpBytesSent = in.readLong(); mTcpBytesReceivedAtLastUnplug = in.readLong(); mTcpBytesSentAtLastUnplug = in.readLong(); + mFullWifiLockOut = false; + mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in); + mScanWifiLockOut = false; + mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in); } /** @@ -852,6 +1067,9 @@ public final class BatteryStatsImpl extends BatteryStats { } void writeToParcelLocked(Parcel out) { + final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; + final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); + out.writeLong(mUserTime); out.writeLong(mSystemTime); out.writeInt(mStarts); @@ -1462,6 +1680,15 @@ public final class BatteryStatsImpl extends BatteryStats { mStartCount++; mScreenOnTimer = new Timer(-1, null, mUnpluggables); mPhoneOnTimer = new Timer(-2, null, mUnpluggables); + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + mPhoneSignalStrengthsTimer[i] = new Timer(-100-i, null, mUnpluggables); + } + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + mPhoneDataConnectionsTimer[i] = new Timer(-200-i, null, mUnpluggables); + } + mWifiOnTimer = new Timer(-3, null, mUnpluggables); + mWifiRunningTimer = new Timer(-4, null, mUnpluggables); + mBluetoothOnTimer = new Timer(-5, null, mUnpluggables); mOnBattery = mOnBatteryInternal = false; mTrackBatteryPastUptime = 0; mTrackBatteryPastRealtime = 0; @@ -1469,6 +1696,8 @@ public final class BatteryStatsImpl extends BatteryStats { mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); + mUnpluggedStartLevel = 0; + mPluggedStartLevel = 0; } public BatteryStatsImpl(Parcel p) { @@ -1485,7 +1714,7 @@ public final class BatteryStatsImpl extends BatteryStats { return mOnBattery; } - public void setOnBattery(boolean onBattery) { + public void setOnBattery(boolean onBattery, int level) { synchronized(this) { if (mOnBattery != onBattery) { mOnBattery = mOnBatteryInternal = onBattery; @@ -1498,10 +1727,12 @@ public final class BatteryStatsImpl extends BatteryStats { mTrackBatteryRealtimeStart = realtime; mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); + mUnpluggedStartLevel = level; doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); } else { mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; + mPluggedStartLevel = level; doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); } if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { @@ -1602,6 +1833,28 @@ public final class BatteryStatsImpl extends BatteryStats { public long getBatteryRealtime(long curTime) { return getBatteryRealtimeLocked(curTime); } + + @Override + public int getUnpluggedStartLevel() { + synchronized(this) { + return getUnluggedStartLevelLocked(); + } + } + + public int getUnluggedStartLevelLocked() { + return mUnpluggedStartLevel; + } + + @Override + public int getPluggedStartLevel() { + synchronized(this) { + return getPluggedStartLevelLocked(); + } + } + + public int getPluggedStartLevelLocked() { + return mPluggedStartLevel; + } /** * Retrieve the statistics object for a particular uid, creating if needed. @@ -1762,12 +2015,27 @@ public final class BatteryStatsImpl extends BatteryStats { mLastUptime = in.readLong(); mRealtime = in.readLong(); mLastRealtime = in.readLong(); + mUnpluggedStartLevel = in.readInt(); + mPluggedStartLevel = in.readInt(); + mStartCount++; mScreenOn = false; mScreenOnTimer.readSummaryFromParcelLocked(in); mPhoneOn = false; mPhoneOnTimer.readSummaryFromParcelLocked(in); + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); + } + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in); + } + mWifiOn = false; + mWifiOnTimer.readSummaryFromParcelLocked(in); + mWifiRunning = false; + mWifiRunningTimer.readSummaryFromParcelLocked(in); + mBluetoothOn = false; + mBluetoothOnTimer.readSummaryFromParcelLocked(in); final int NU = in.readInt(); for (int iu = 0; iu < NU; iu++) { @@ -1775,6 +2043,11 @@ public final class BatteryStatsImpl extends BatteryStats { Uid u = new Uid(uid); mUidStats.put(uid, u); + u.mFullWifiLockOut = false; + u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); + u.mScanWifiLockOut = false; + u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); + int NW = in.readInt(); for (int iw = 0; iw < NW; iw++) { String wlName = in.readString(); @@ -1857,15 +2130,30 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); + out.writeInt(mUnpluggedStartLevel); + out.writeInt(mPluggedStartLevel); + mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + } + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + } + mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); final int NU = mUidStats.size(); out.writeInt(NU); for (int iu = 0; iu < NU; iu++) { out.writeInt(mUidStats.keyAt(iu)); Uid u = mUidStats.valueAt(iu); + + u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); int NW = u.mWakelockStats.size(); out.writeInt(NW); @@ -1979,6 +2267,18 @@ public final class BatteryStatsImpl extends BatteryStats { mScreenOnTimer = new Timer(-1, null, mUnpluggables, in); mPhoneOn = false; mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in); + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + mPhoneSignalStrengthsTimer[i] = new Timer(-100-i, null, mUnpluggables, in); + } + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + mPhoneDataConnectionsTimer[i] = new Timer(-200-i, null, mUnpluggables, in); + } + mWifiOn = false; + mWifiOnTimer = new Timer(-2, null, mUnpluggables, in); + mWifiRunning = false; + mWifiRunningTimer = new Timer(-2, null, mUnpluggables, in); + mBluetoothOn = false; + mBluetoothOnTimer = new Timer(-2, null, mUnpluggables, in); mUptime = in.readLong(); mUptimeStart = in.readLong(); mLastUptime = in.readLong(); @@ -1993,6 +2293,8 @@ public final class BatteryStatsImpl extends BatteryStats { mTrackBatteryRealtimeStart = in.readLong(); mUnpluggedBatteryUptime = in.readLong(); mUnpluggedBatteryRealtime = in.readLong(); + mUnpluggedStartLevel = in.readInt(); + mPluggedStartLevel = in.readInt(); mLastWriteTime = in.readLong(); mPartialTimers.clear(); @@ -2028,6 +2330,15 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mBatteryLastRealtime); mScreenOnTimer.writeToParcel(out, batteryRealtime); mPhoneOnTimer.writeToParcel(out, batteryRealtime); + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); + } + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); + } + mWifiOnTimer.writeToParcel(out, batteryRealtime); + mWifiRunningTimer.writeToParcel(out, batteryRealtime); + mBluetoothOnTimer.writeToParcel(out, batteryRealtime); out.writeLong(mUptime); out.writeLong(mUptimeStart); out.writeLong(mLastUptime); @@ -2041,6 +2352,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mTrackBatteryRealtimeStart); out.writeLong(mUnpluggedBatteryUptime); out.writeLong(mUnpluggedBatteryRealtime); + out.writeInt(mUnpluggedStartLevel); + out.writeInt(mPluggedStartLevel); out.writeLong(mLastWriteTime); int size = mUidStats.size(); @@ -2066,10 +2379,24 @@ public final class BatteryStatsImpl extends BatteryStats { public void dumpLocked(Printer pw) { if (DEBUG) { - Log.i(TAG, "*** Screen timer:"); - mScreenOnTimer.logState(); - Log.i(TAG, "*** Phone timer:"); - mPhoneOnTimer.logState(); + pw.println("*** Screen timer:"); + mScreenOnTimer.logState(pw, " "); + pw.println("*** Phone timer:"); + mPhoneOnTimer.logState(pw, " "); + for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { + pw.println("*** Signal strength #" + i + ":"); + mPhoneSignalStrengthsTimer[i].logState(pw, " "); + } + for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { + pw.println("*** Data connection type #" + i + ":"); + mPhoneDataConnectionsTimer[i].logState(pw, " "); + } + pw.println("*** Wifi timer:"); + mWifiOnTimer.logState(pw, " "); + pw.println("*** WifiRunning timer:"); + mWifiRunningTimer.logState(pw, " "); + pw.println("*** Bluetooth timer:"); + mBluetoothOnTimer.logState(pw, " "); } super.dumpLocked(pw); } diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java index 9e1f2ae..66e15c1 100644 --- a/core/java/com/android/internal/view/menu/IconMenuItemView.java +++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java @@ -28,6 +28,7 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewDebug; import android.widget.TextView; +import android.text.Layout; /** * The item view for each item in the {@link IconMenuView}. @@ -236,6 +237,32 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie positionIcon(); } + @Override + protected void onTextChanged(CharSequence text, int start, int before, int after) { + super.onTextChanged(text, start, before, after); + + // our layout params depend on the length of the text + setLayoutParams(getTextAppropriateLayoutParams()); + } + + /** + * @return layout params appropriate for this view. If layout params already exist, it will + * augment them to be appropriate to the current text size. + */ + IconMenuView.LayoutParams getTextAppropriateLayoutParams() { + IconMenuView.LayoutParams lp = (IconMenuView.LayoutParams) getLayoutParams(); + if (lp == null) { + // Default layout parameters + lp = new IconMenuView.LayoutParams( + IconMenuView.LayoutParams.FILL_PARENT, IconMenuView.LayoutParams.FILL_PARENT); + } + + // Set the desired width of item + lp.desiredWidth = (int) Layout.getDesiredWidth(getText(), getPaint()); + + return lp; + } + /** * Positions the icon vertically (horizontal centering is taken care of by * the TextView's gravity). @@ -280,5 +307,5 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie public boolean showsIcon() { return true; } - + } diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java index 781c608..6034a1e 100644 --- a/core/java/com/android/internal/view/menu/IconMenuView.java +++ b/core/java/com/android/internal/view/menu/IconMenuView.java @@ -26,7 +26,6 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; -import android.text.Layout; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.View; @@ -278,14 +277,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi * Adds an IconMenuItemView to this icon menu view. * @param itemView The item's view to add */ - private void addItemView(IconMenuItemView itemView) { - LayoutParams lp = (LayoutParams) itemView.getLayoutParams(); - - if (lp == null) { - // Default layout parameters - lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - } - + private void addItemView(IconMenuItemView itemView) { // Set ourselves on the item view itemView.setIconMenuView(this); @@ -295,10 +287,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi // This class is the invoker for all its item views itemView.setItemInvoker(this); - // Set the desired width of item - lp.desiredWidth = (int) Layout.getDesiredWidth(itemView.getText(), itemView.getPaint()); - - addView(itemView, lp); + addView(itemView, itemView.getTextAppropriateLayoutParams()); } /** diff --git a/core/java/com/android/internal/view/menu/MenuDialogHelper.java b/core/java/com/android/internal/view/menu/MenuDialogHelper.java index bc51cf3..88f7b2f 100644 --- a/core/java/com/android/internal/view/menu/MenuDialogHelper.java +++ b/core/java/com/android/internal/view/menu/MenuDialogHelper.java @@ -67,6 +67,10 @@ public class MenuDialogHelper implements DialogInterface.OnKeyListener, DialogIn // Set the key listener builder.setOnKeyListener(this); + + // Since this is for a menu, disable the recycling of views + // This is done by the menu framework anyway + builder.setRecycleOnMeasureEnabled(false); // Show the menu mDialog = builder.create(); @@ -97,11 +101,8 @@ public class MenuDialogHelper implements DialogInterface.OnKeyListener, DialogIn } // Menu shortcut matching - if (mMenu.performShortcut(keyCode, event, 0)) { - return true; - } - - return false; + return mMenu.performShortcut(keyCode, event, 0); + } /** diff --git a/core/java/com/android/internal/widget/EditStyledText.java b/core/java/com/android/internal/widget/EditStyledText.java index 8a4675a..f0ad7b3 100644 --- a/core/java/com/android/internal/widget/EditStyledText.java +++ b/core/java/com/android/internal/widget/EditStyledText.java @@ -16,21 +16,42 @@ package com.android.internal.widget; +import java.io.InputStream; +import java.util.ArrayList; + import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RectShape; import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.Html; +import android.text.Layout; import android.text.Spannable; +import android.text.Spanned; +import android.text.method.ArrowKeyMovementMethod; import android.text.style.AbsoluteSizeSpan; +import android.text.style.AlignmentSpan; +import android.text.style.CharacterStyle; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; +import android.text.style.ParagraphStyle; +import android.text.style.QuoteSpan; import android.util.AttributeSet; import android.util.Log; +import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import android.widget.TextView; /** * EditStyledText extends EditText for managing the flow and status to edit @@ -40,7 +61,7 @@ import android.widget.EditText; public class EditStyledText extends EditText { private static final String LOG_TAG = "EditStyledText"; - private static final boolean DBG = true; + private static final boolean DBG = false; /** * The modes of editing actions. @@ -57,6 +78,10 @@ public class EditStyledText extends EditText { public static final int MODE_COLOR = 4; /** The mode of selection. */ public static final int MODE_SELECT = 5; + /** The mode of changing alignment. */ + public static final int MODE_ALIGN = 6; + /** The mode of changing cut. */ + public static final int MODE_CUT = 7; /** * The state of selection. @@ -79,12 +104,19 @@ public class EditStyledText extends EditText { public static final int HINT_MSG_SELECT_END = 3; public static final int HINT_MSG_PUSH_COMPETE = 4; + + /** + * The help message strings. + */ + public static final int DEFAULT_BACKGROUND_COLOR = 0x00FFFFFF; + /** * EditStyledTextInterface provides functions for notifying messages to * calling class. */ public interface EditStyledTextNotifier { public void notifyHintMsg(int msgId); + public void notifyStateChanged(int mode, int state); } private EditStyledTextNotifier mESTInterface; @@ -95,7 +127,9 @@ public class EditStyledText extends EditText { */ private EditorManager mManager; private StyledTextConverter mConverter; - private StyledTextToast mToast; + private StyledTextDialog mDialog; + private Drawable mDefaultBackground; + private int mBackgroundColor; /** * EditStyledText extends EditText for managing flow of each editing @@ -130,7 +164,7 @@ public class EditStyledText extends EditText { * Builder for opening Alert Dialog. */ public void setBuilder(Builder builder) { - mToast.setBuilder(builder); + mDialog.setBuilder(builder); } /** @@ -145,7 +179,7 @@ public class EditStyledText extends EditText { */ public void setColorAlertParams(CharSequence colortitle, CharSequence[] colornames, CharSequence[] colorints) { - mToast.setColorAlertParams(colortitle, colornames, colorints); + mDialog.setColorAlertParams(colortitle, colornames, colorints); } /** @@ -163,18 +197,27 @@ public class EditStyledText extends EditText { public void setSizeAlertParams(CharSequence sizetitle, CharSequence[] sizenames, CharSequence[] sizedisplayints, CharSequence[] sizesendints) { - mToast.setSizeAlertParams(sizetitle, sizenames, sizedisplayints, + mDialog.setSizeAlertParams(sizetitle, sizenames, sizedisplayints, sizesendints); } + public void setAlignAlertParams(CharSequence aligntitle, + CharSequence[] alignnames) { + mDialog.setAlignAlertParams(aligntitle, alignnames); + } + @Override public boolean onTouchEvent(MotionEvent event) { + if (mManager.isSoftKeyBlocked() && + event.getAction() == MotionEvent.ACTION_UP) { + cancelLongPress(); + } final boolean superResult = super.onTouchEvent(event); if (event.getAction() == MotionEvent.ACTION_UP) { if (DBG) { Log.d(LOG_TAG, "--- onTouchEvent"); } - mManager.onTouchScreen(); + mManager.onCursorMoved(); } return superResult; } @@ -202,6 +245,13 @@ public class EditStyledText extends EditText { } /** + * Start "Cut" action. + */ + public void onStartCut() { + mManager.onStartCut(); + } + + /** * Start "Paste" action. */ public void onStartPaste() { @@ -223,6 +273,20 @@ public class EditStyledText extends EditText { } /** + * Start changing "BackgroundColor" action. + */ + public void onStartBackgroundColor() { + mManager.onStartBackgroundColor(); + } + + /** + * Start changing "Alignment" action. + */ + public void onStartAlign() { + mManager.onStartAlign(); + } + + /** * Start "Select" action. */ public void onStartSelect() { @@ -237,6 +301,13 @@ public class EditStyledText extends EditText { } /** + * Fix Selected Item. + */ + public void onFixSelectedItem() { + mManager.onFixSelectedItem(); + } + + /** * InsertImage to TextView by using URI * * @param uri @@ -256,13 +327,13 @@ public class EditStyledText extends EditText { mManager.onInsertImage(resId); } - /** - * Fix Selected Item. - */ - public void fixSelectedItem() { - mManager.onFixSelectItem(); + public void onInsertHorizontalLine() { + mManager.onInsertHorizontalLine(); } + public void onClearStyles() { + mManager.onClearStyles(); + } /** * Set Size of the Item. * @@ -283,16 +354,39 @@ public class EditStyledText extends EditText { mManager.setItemColor(color); } - public void onShowColorAlert() { - mToast.onShowColorAlertDialog(); + /** + * Set Alignment of the Item. + * + * @param color + * The color of the Item. + */ + public void setAlignment(Layout.Alignment align) { + mManager.setAlignment(align); } - public void onShowSizeAlert() { - mToast.onShowSizeAlertDialog(); + /** + * Set Background color of View. + * + * @param color + * The background color of view. + */ + @Override + public void setBackgroundColor(int color) { + super.setBackgroundColor(color); + mBackgroundColor = color; } /** - * Check editing is started. + * Set html to EditStyledText. + * + * @param html + * The html to be set. + */ + public void setHtml(String html) { + mConverter.SetHtml(html); + } + /** + * Check whether editing is started or not. * * @return Whether editing is started or not. */ @@ -301,6 +395,23 @@ public class EditStyledText extends EditText { } /** + * Check whether styled text or not. + * + * @return Whether styled text or not. + */ + public boolean isStyledText() { + return mManager.isStyledText(); + } + /** + * Check whether SoftKey is Blocked or not. + * + * @return whether SoftKey is Blocked or not. + */ + public boolean isSoftKeyBlocked() { + return mManager.isSoftKeyBlocked(); + } + + /** * Get the mode of the action. * * @return The mode of the action. @@ -318,8 +429,70 @@ public class EditStyledText extends EditText { return mManager.getSelectState(); } - public String getBody() { - return mConverter.getConvertedBody(); + @Override + public Bundle getInputExtras(boolean create) { + if (DBG) { + Log.d(LOG_TAG, "---getInputExtras"); + } + Bundle bundle = super.getInputExtras(create); + if (bundle != null) { + bundle = new Bundle(); + } + bundle.putBoolean("allowEmoji", true); + return bundle; + } + + /** + * Get the state of the selection. + * + * @return The state of the selection. + */ + public String getHtml() { + return mConverter.getHtml(); + } + + /** + * Get the state of the selection. + * + * @param uris + * The array of used uris. + * @return The state of the selection. + */ + public String getHtml(ArrayList<Uri> uris) { + mConverter.getUriArray(uris, getText()); + return mConverter.getHtml(); + } + + /** + * Get Background color of View. + * + * @return The background color of View. + */ + public int getBackgroundColor() { + return mBackgroundColor; + } + + /** + * Get Foreground color of View. + * + * @return The background color of View. + */ + public int getForeGroundColor(int pos) { + if (DBG) { + Log.d(LOG_TAG, "---getForeGroundColor: " + pos); + } + if (pos < 0 || pos > getText().length()) { + Log.e(LOG_TAG, "---getForeGroundColor: Illigal position."); + return DEFAULT_BACKGROUND_COLOR; + } else { + ForegroundColorSpan[] spans = + getText().getSpans(pos, pos, ForegroundColorSpan.class); + if (spans.length > 0) { + return spans[0].getForegroundColor(); + } else { + return DEFAULT_BACKGROUND_COLOR; + } + } } /** @@ -328,11 +501,44 @@ public class EditStyledText extends EditText { private void init() { if (DBG) { Log.d(LOG_TAG, "--- init"); - requestFocus(); } + requestFocus(); + mDefaultBackground = getBackground(); + mBackgroundColor = DEFAULT_BACKGROUND_COLOR; mManager = new EditorManager(this); mConverter = new StyledTextConverter(this); - mToast = new StyledTextToast(this); + mDialog = new StyledTextDialog(this); + setMovementMethod(new StyledTextArrowKeyMethod(mManager)); + mManager.blockSoftKey(); + mManager.unblockSoftKey(); + } + + /** + * Show Foreground Color Selecting Dialog. + */ + private void onShowForegroundColorAlert() { + mDialog.onShowForegroundColorAlertDialog(); + } + + /** + * Show Background Color Selecting Dialog. + */ + private void onShowBackgroundColorAlert() { + mDialog.onShowBackgroundColorAlertDialog(); + } + + /** + * Show Size Selecting Dialog. + */ + private void onShowSizeAlert() { + mDialog.onShowSizeAlertDialog(); + } + + /** + * Show Alignment Selecting Dialog. + */ + private void onShowAlignAlert() { + mDialog.onShowAlignAlertDialog(); } /** @@ -347,27 +553,31 @@ public class EditStyledText extends EditText { } } - @Override - public Bundle getInputExtras(boolean create) { - Bundle bundle = super.getInputExtras(create); - if (bundle != null) { - bundle.putBoolean("allowEmoji", true); + /** + * Notify the event that the mode and state are changed. + * + * @param mode + * Mode of the editing action. + * @param state + * Mode of the selection state. + */ + private void notifyStateChanged(int mode, int state) { + if (mESTInterface != null) { + mESTInterface.notifyStateChanged(mode, state); } - return bundle; } /** - * Object which manages the flow and status of editing actions. + * EditorManager manages the flow and status of editing actions. */ private class EditorManager { private boolean mEditFlag = false; + private boolean mSoftKeyBlockFlag = false; private int mMode = 0; private int mState = 0; private int mCurStart = 0; private int mCurEnd = 0; private EditStyledText mEST; - private Editable mTextSelectBuffer; - private CharSequence mTextCopyBufer; EditorManager(EditStyledText est) { mEST = est; @@ -375,64 +585,75 @@ public class EditStyledText extends EditText { public void onStartEdit() { if (DBG) { - Log.d(LOG_TAG, "--- onEdit"); + Log.d(LOG_TAG, "--- onStartEdit"); } + Log.d(LOG_TAG, "--- onstartedit:"); handleResetEdit(); + mEST.notifyStateChanged(mMode, mState); } public void onEndEdit() { if (DBG) { - Log.d(LOG_TAG, "--- onClickCancel"); + Log.d(LOG_TAG, "--- onEndEdit"); } handleCancel(); + mEST.notifyStateChanged(mMode, mState); } public void onStartCopy() { if (DBG) { - Log.d(LOG_TAG, "--- onClickCopy"); + Log.d(LOG_TAG, "--- onStartCopy"); } handleCopy(); + mEST.notifyStateChanged(mMode, mState); + } + + public void onStartCut() { + if (DBG) { + Log.d(LOG_TAG, "--- onStartCut"); + } + handleCut(); + mEST.notifyStateChanged(mMode, mState); } public void onStartPaste() { if (DBG) { - Log.d(LOG_TAG, "--- onClickPaste"); + Log.d(LOG_TAG, "--- onStartPaste"); } handlePaste(); + mEST.notifyStateChanged(mMode, mState); } public void onStartSize() { if (DBG) { - Log.d(LOG_TAG, "--- onClickSize"); + Log.d(LOG_TAG, "--- onStartSize"); } handleSize(); + mEST.notifyStateChanged(mMode, mState); } - public void setItemSize(int size) { + public void onStartAlign() { if (DBG) { - Log.d(LOG_TAG, "--- onClickSizeItem"); - } - if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) { - changeSizeSelectedText(size); - handleResetEdit(); + Log.d(LOG_TAG, "--- onStartAlignRight"); } + handleAlign(); + mEST.notifyStateChanged(mMode, mState); } - public void setItemColor(int color) { + public void onStartColor() { if (DBG) { - Log.d(LOG_TAG, "--- onClickColorItem"); - } - if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) { - changeColorSelectedText(color); - handleResetEdit(); + Log.d(LOG_TAG, "--- onClickColor"); } + handleColor(); + mEST.notifyStateChanged(mMode, mState); } - public void onStartColor() { + public void onStartBackgroundColor() { if (DBG) { Log.d(LOG_TAG, "--- onClickColor"); } - handleColor(); + mEST.onShowBackgroundColorAlert(); + mEST.notifyStateChanged(mMode, mState); } public void onStartSelect() { @@ -443,32 +664,36 @@ public class EditStyledText extends EditText { if (mState == STATE_SELECT_OFF) { handleSelect(); } else { - offSelect(); + unsetSelect(); handleSelect(); } + mEST.notifyStateChanged(mMode, mState); } - public void onStartSelectAll() { - if (DBG) { - Log.d(LOG_TAG, "--- onClickSelectAll"); - } - handleSelectAll(); - } - - public void onTouchScreen() { + public void onCursorMoved() { if (DBG) { Log.d(LOG_TAG, "--- onClickView"); } if (mState == STATE_SELECT_ON || mState == STATE_SELECTED) { handleSelect(); + mEST.notifyStateChanged(mMode, mState); } } - public void onFixSelectItem() { + public void onStartSelectAll() { + if (DBG) { + Log.d(LOG_TAG, "--- onClickSelectAll"); + } + handleSelectAll(); + mEST.notifyStateChanged(mMode, mState); + } + + public void onFixSelectedItem() { if (DBG) { Log.d(LOG_TAG, "--- onClickComplete"); } handleComplete(); + mEST.notifyStateChanged(mMode, mState); } public void onInsertImage(Uri uri) { @@ -476,27 +701,100 @@ public class EditStyledText extends EditText { Log.d(LOG_TAG, "--- onInsertImage by URI: " + uri.getPath() + "," + uri.toString()); } - - mEST.getText().append("a"); - mEST.getText().setSpan(new ImageSpan(mEST.getContext(), uri), - mEST.getText().length() - 1, mEST.getText().length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + insertImageSpan(new ImageSpan(mEST.getContext(), uri)); + mEST.notifyStateChanged(mMode, mState); } public void onInsertImage(int resID) { if (DBG) { Log.d(LOG_TAG, "--- onInsertImage by resID"); } - mEST.getText().append("b"); - mEST.getText().setSpan(new ImageSpan(mEST.getContext(), resID), - mEST.getText().length() - 1, mEST.getText().length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + insertImageSpan(new ImageSpan(mEST.getContext(), resID)); + mEST.notifyStateChanged(mMode, mState); + } + + public void onInsertHorizontalLine() { + if (DBG) { + Log.d(LOG_TAG, "--- onInsertHorizontalLine:"); + } + insertImageSpan(new HorizontalLineSpan(0xFF000000, mEST)); + mEST.notifyStateChanged(mMode, mState); + } + + public void onClearStyles() { + if (DBG) { + Log.d(LOG_TAG, "--- onClearStyles"); + } + Editable txt = mEST.getText(); + int len = txt.length(); + Object[] styles = txt.getSpans(0, len, Object.class); + for (Object style : styles) { + if (style instanceof ParagraphStyle || + style instanceof QuoteSpan || + style instanceof CharacterStyle) { + if (style instanceof ImageSpan) { + int start = txt.getSpanStart(style); + int end = txt.getSpanEnd(style); + txt.replace(start, end, ""); + } + txt.removeSpan(style); + } + } + mEST.setBackgroundDrawable(mEST.mDefaultBackground); + mEST.mBackgroundColor = DEFAULT_BACKGROUND_COLOR; + } + + public void setItemSize(int size) { + if (DBG) { + Log.d(LOG_TAG, "--- onClickSizeItem"); + } + if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) { + changeSizeSelectedText(size); + handleResetEdit(); + } + } + + public void setItemColor(int color) { + if (DBG) { + Log.d(LOG_TAG, "--- onClickColorItem"); + } + if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) { + changeColorSelectedText(color); + handleResetEdit(); + } + } + + public void setAlignment(Layout.Alignment align) { + if (DBG) { + Log.d(LOG_TAG, "--- onClickColorItem"); + } + if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) { + changeAlign(align); + handleResetEdit(); + } } public boolean isEditting() { return mEditFlag; } + /* If the style of the span is added, add check case for that style */ + public boolean isStyledText() { + Editable txt = mEST.getText(); + int len = txt.length(); + if (txt.getSpans(0, len -1, ParagraphStyle.class).length > 0 || + txt.getSpans(0, len -1, QuoteSpan.class).length > 0 || + txt.getSpans(0, len -1, CharacterStyle.class).length > 0 || + mEST.mBackgroundColor != DEFAULT_BACKGROUND_COLOR) { + return true; + } + return false; + } + + public boolean isSoftKeyBlocked() { + return mSoftKeyBlockFlag; + } + public int getEditMode() { return mMode; } @@ -505,6 +803,42 @@ public class EditStyledText extends EditText { return mState; } + public int getSelectionStart() { + return mCurStart; + } + + public int getSelectionEnd() { + return mCurEnd; + } + + private void doNextHandle() { + if (DBG) { + Log.d(LOG_TAG, "--- doNextHandle: " + mMode + "," + mState); + } + switch (mMode) { + case MODE_COPY: + handleCopy(); + break; + case MODE_CUT: + handleCut(); + break; + case MODE_PASTE: + handlePaste(); + break; + case MODE_SIZE: + handleSize(); + break; + case MODE_COLOR: + handleColor(); + break; + case MODE_ALIGN: + handleAlign(); + break; + default: + break; + } + } + private void handleCancel() { if (DBG) { Log.d(LOG_TAG, "--- handleCancel"); @@ -512,7 +846,9 @@ public class EditStyledText extends EditText { mMode = MODE_NOTHING; mState = STATE_SELECT_OFF; mEditFlag = false; - offSelect(); + Log.d(LOG_TAG, "--- handleCancel:" + mEST.getInputType()); + unblockSoftKey(); + unsetSelect(); } private void handleComplete() { @@ -525,122 +861,115 @@ public class EditStyledText extends EditText { if (mState == STATE_SELECTED) { mState = STATE_SELECT_FIX; } - switch (mMode) { - case MODE_COPY: - handleCopy(); - break; - case MODE_COLOR: - handleColor(); - break; - case MODE_SIZE: - handleSize(); - break; - default: - break; - } + doNextHandle(); } - private void handleCopy() { + private void handleTextViewFunc(int mode, int id) { if (DBG) { - Log.d(LOG_TAG, "--- handleCopy: " + mMode + "," + mState); + Log.d(LOG_TAG, "--- handleTextView: " + mMode + "," + mState + + "," + id); } if (!mEditFlag) { return; } if (mMode == MODE_NOTHING || mMode == MODE_SELECT) { - mMode = MODE_COPY; + mMode = mode; if (mState == STATE_SELECTED) { mState = STATE_SELECT_FIX; - storeSelectedText(); + handleTextViewFunc(mode, id); } else { handleSelect(); } - } else if (mMode != MODE_COPY) { + } else if (mMode != mode) { handleCancel(); - mMode = MODE_COPY; - handleCopy(); + mMode = mode; + handleTextViewFunc(mode, id); } else if (mState == STATE_SELECT_FIX) { - mEST.setHintMessage(HINT_MSG_NULL); - storeSelectedText(); + mEST.onTextContextMenuItem(id); handleResetEdit(); } } - private void handlePaste() { + private void handleCopy() { if (DBG) { - Log.d(LOG_TAG, "--- handlePaste"); - } - if (!mEditFlag) { - return; + Log.d(LOG_TAG, "--- handleCopy: " + mMode + "," + mState); } - if (mTextSelectBuffer != null && mTextCopyBufer.length() > 0) { - mTextSelectBuffer.insert(mEST.getSelectionStart(), - mTextCopyBufer); - } else { - mEST.setHintMessage(HINT_MSG_COPY_BUF_BLANK); + handleTextViewFunc(MODE_COPY, android.R.id.copy); + } + + private void handleCut() { + if (DBG) { + Log.d(LOG_TAG, "--- handleCopy: " + mMode + "," + mState); } + handleTextViewFunc(MODE_CUT, android.R.id.cut); } - private void handleSize() { + private void handlePaste() { if (DBG) { - Log.d(LOG_TAG, "--- handleSize: " + mMode + "," + mState); + Log.d(LOG_TAG, "--- handlePaste"); } if (!mEditFlag) { - Log.e(LOG_TAG, "--- Editing is not started for handlesize."); return; } - if (mMode == MODE_NOTHING || mMode == MODE_SELECT) { - mMode = MODE_SIZE; - if (mState == STATE_SELECTED) { - mState = STATE_SELECT_FIX; - handleSize(); - } else { - handleSelect(); - } - } else if (mMode != MODE_SIZE) { - handleCancel(); - mMode = MODE_SIZE; - handleSize(); - } else { - if (mState == STATE_SELECT_FIX) { - mEST.setHintMessage(HINT_MSG_NULL); - mEST.onShowSizeAlert(); - } else { - Log.d(LOG_TAG, "--- handlesize: do nothing"); - } - } + mEST.onTextContextMenuItem(android.R.id.paste); } - private void handleColor() { + private void handleSetSpan(int mode) { if (DBG) { - Log.d(LOG_TAG, "--- handleSize: " + mMode + "," + mState); + Log.d(LOG_TAG, "--- handleSetSpan:" + mEditFlag + "," + + mState + ',' + mMode); } if (!mEditFlag) { - Log.e(LOG_TAG, "--- Editing is not started for handlecolor."); + Log.e(LOG_TAG, "--- handleSetSpan: Editing is not started."); return; } if (mMode == MODE_NOTHING || mMode == MODE_SELECT) { - mMode = MODE_COLOR; + mMode = mode; if (mState == STATE_SELECTED) { mState = STATE_SELECT_FIX; - handleColor(); + handleSetSpan(mode); } else { handleSelect(); } - } else if (mMode != MODE_COLOR) { + } else if (mMode != mode) { handleCancel(); - mMode = MODE_COLOR; - handleSize(); + mMode = mode; + handleSetSpan(mode); } else { if (mState == STATE_SELECT_FIX) { mEST.setHintMessage(HINT_MSG_NULL); - mEST.onShowColorAlert(); + switch (mode) { + case MODE_COLOR: + mEST.onShowForegroundColorAlert(); + break; + case MODE_SIZE: + mEST.onShowSizeAlert(); + break; + case MODE_ALIGN: + mEST.onShowAlignAlert(); + break; + default: + Log.e(LOG_TAG, "--- handleSetSpan: invalid mode."); + break; + } } else { - Log.d(LOG_TAG, "--- handlecolor: do nothing"); + Log.d(LOG_TAG, "--- handleSetSpan: do nothing."); } } } + private void handleSize() { + handleSetSpan(MODE_SIZE); + } + + private void handleColor() { + handleSetSpan(MODE_COLOR); + } + + private void handleAlign() { + handleSetSpan(MODE_ALIGN); + } + private void handleSelect() { if (DBG) { Log.d(LOG_TAG, "--- handleSelect:" + mEditFlag + "," + mState); @@ -653,19 +982,20 @@ public class EditStyledText extends EditText { Log.e(LOG_TAG, "Selection is off, but selected"); } setSelectStartPos(); + blockSoftKey(); mEST.setHintMessage(HINT_MSG_SELECT_END); } else if (mState == STATE_SELECT_ON) { if (isTextSelected()) { Log.e(LOG_TAG, "Selection now start, but selected"); } - setSelectEndPos(); + setSelectedEndPos(); mEST.setHintMessage(HINT_MSG_PUSH_COMPETE); doNextHandle(); } else if (mState == STATE_SELECTED) { if (!isTextSelected()) { Log.e(LOG_TAG, "Selection is done, but not selected"); } - setSelectEndPos(); + setSelectedEndPos(); doNextHandle(); } } @@ -678,47 +1008,30 @@ public class EditStyledText extends EditText { return; } mEST.selectAll(); - } - - private void doNextHandle() { - if (DBG) { - Log.d(LOG_TAG, "--- doNextHandle: " + mMode + "," + mState); - } - switch (mMode) { - case MODE_COPY: - handleCopy(); - break; - case MODE_PASTE: - handlePaste(); - break; - case MODE_SIZE: - handleSize(); - break; - case MODE_COLOR: - handleColor(); - break; - default: - break; - } + mState = STATE_SELECTED; } private void handleResetEdit() { if (DBG) { Log.d(LOG_TAG, "Reset Editor"); } + blockSoftKey(); handleCancel(); mEditFlag = true; mEST.setHintMessage(HINT_MSG_SELECT_START); } - // Methods of selection - private void onSelect() { + private void setSelection() { if (DBG) { Log.d(LOG_TAG, "--- onSelect:" + mCurStart + "," + mCurEnd); } if (mCurStart >= 0 && mCurStart <= mEST.getText().length() && mCurEnd >= 0 && mCurEnd <= mEST.getText().length()) { - mEST.setSelection(mCurStart, mCurEnd); + if (mCurStart < mCurEnd) { + mEST.setSelection(mCurStart, mCurEnd); + } else { + mEST.setSelection(mCurEnd, mCurStart); + } mState = STATE_SELECTED; } else { Log.e(LOG_TAG, @@ -728,7 +1041,7 @@ public class EditStyledText extends EditText { } } - private void offSelect() { + private void unsetSelect() { if (DBG) { Log.d(LOG_TAG, "--- offSelect"); } @@ -745,22 +1058,23 @@ public class EditStyledText extends EditText { mState = STATE_SELECT_ON; } - private void setSelectEndPos() { + private void setSelectedEndPos() { if (DBG) { - Log.d(LOG_TAG, "--- setSelectEndPos:" - + mEST.getSelectionStart()); + Log.d(LOG_TAG, "--- setSelectEndPos:"); } - int curpos = mEST.getSelectionStart(); - if (curpos < mCurStart) { - if (DBG) { - Log.d(LOG_TAG, "--- setSelectEndPos: swap is done."); - } - mCurEnd = mCurStart; - mCurStart = curpos; + if (mEST.getSelectionStart() == mCurStart) { + setSelectedEndPos(mEST.getSelectionEnd()); } else { - mCurEnd = curpos; + setSelectedEndPos(mEST.getSelectionStart()); } - onSelect(); + } + + public void setSelectedEndPos(int pos) { + if (DBG) { + Log.d(LOG_TAG, "--- setSelectedEndPos:"); + } + mCurEnd = pos; + setSelection(); } private boolean isTextSelected() { @@ -773,30 +1087,113 @@ public class EditStyledText extends EditText { mState == STATE_SELECT_FIX); } - private void storeSelectedText() { + private void setStyledTextSpan(Object span, int start, int end) { if (DBG) { - Log.d(LOG_TAG, "--- storeSelectedText"); + Log.d(LOG_TAG, "--- setStyledTextSpan:" + mMode + "," + + start + "," + end); + } + if (start < end) { + mEST.getText().setSpan(span, start, end, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + mEST.getText().setSpan(span, end, start, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } - mTextSelectBuffer = mEST.getText(); - mTextCopyBufer = mTextSelectBuffer.subSequence(mCurStart, mCurEnd); } private void changeSizeSelectedText(int size) { if (DBG) { - Log.d(LOG_TAG, "--- changeSizeSelectedText:" + size + "," - + mCurStart + "," + mCurEnd); + Log.d(LOG_TAG, "--- changeSize:" + size); } - mEST.getText().setSpan(new AbsoluteSizeSpan(size), mCurStart, - mCurEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + setStyledTextSpan(new AbsoluteSizeSpan(size), + mCurStart, mCurEnd); } private void changeColorSelectedText(int color) { if (DBG) { - Log.d(LOG_TAG, "--- changeCollorSelectedText:" + color + "," - + mCurStart + "," + mCurEnd); + Log.d(LOG_TAG, "--- changeColor:" + color); + } + setStyledTextSpan(new ForegroundColorSpan(color), + mCurStart, mCurEnd); + } + + private void changeAlign(Layout.Alignment align) { + if (DBG) { + Log.d(LOG_TAG, "--- changeAlign:" + align); + } + setStyledTextSpan(new AlignmentSpan.Standard(align), + findLineStart(mEST.getText(), mCurStart), + findLineEnd(mEST.getText(), mCurEnd)); + } + + private int findLineStart(Editable text, int current) { + if (DBG) { + Log.d(LOG_TAG, "--- findLineStart: curr:" + current + + ", length:" + text.length()); + } + int pos = current; + for (; pos > 0; pos--) { + if (text.charAt(pos - 1) == '\n') { + break; + } + } + return pos; + } + + private void insertImageSpan(ImageSpan span) { + if (DBG) { + Log.d(LOG_TAG, "--- insertImageSpan"); + } + if (span != null) { + Log.d(LOG_TAG, "--- insertimagespan:" + span.getDrawable().getIntrinsicHeight() + "," + span.getDrawable().getIntrinsicWidth()); + Log.d(LOG_TAG, "--- insertimagespan:" + span.getDrawable().getClass()); + int curpos = mEST.getSelectionStart(); + mEST.getText().insert(curpos, "\uFFFC"); + mEST.getText().setSpan(span, curpos, curpos + 1, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + mEST.notifyStateChanged(mMode, mState); + } else { + Log.e(LOG_TAG, "--- insertImageSpan: null span was inserted"); + } + } + + private int findLineEnd(Editable text, int current) { + if (DBG) { + Log.d(LOG_TAG, "--- findLineEnd: curr:" + current + + ", length:" + text.length()); + } + int pos = current; + for (; pos < text.length(); pos++) { + if (pos > 0 && text.charAt(pos - 1) == '\n') { + break; + } + } + return pos; + } + + private void blockSoftKey() { + if (DBG) { + Log.d(LOG_TAG, "--- blockSoftKey:"); + } + InputMethodManager imm = (InputMethodManager) mEST.getContext(). + getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mEST.getWindowToken(), 0); + mEST.setOnClickListener( + new OnClickListener() { + public void onClick(View v) { + Log.d(LOG_TAG, "--- ontrackballclick:"); + onFixSelectedItem(); + } + }); + mSoftKeyBlockFlag = true; + } + + private void unblockSoftKey() { + if (DBG) { + Log.d(LOG_TAG, "--- unblockSoftKey:"); } - mEST.getText().setSpan(new ForegroundColorSpan(color), mCurStart, - mCurEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + mEST.setOnClickListener(null); + mSoftKeyBlockFlag = false; } } @@ -807,24 +1204,77 @@ public class EditStyledText extends EditText { mEST = est; } - public String getConvertedBody() { + public String getHtml() { String htmlBody = Html.toHtml(mEST.getText()); + if (DBG) { + Log.d(LOG_TAG, "--- getConvertedBody:" + htmlBody); + } return htmlBody; } + + public void getUriArray(ArrayList<Uri> uris, Editable text) { + uris.clear(); + if (DBG) { + Log.d(LOG_TAG, "--- getUriArray:"); + } + int len = text.length(); + int next; + for (int i = 0; i < text.length(); i = next) { + next = text.nextSpanTransition(i, len, ImageSpan.class); + ImageSpan[] images = text.getSpans(i, next, ImageSpan.class); + for (int j = 0; j < images.length; j++) { + if (DBG) { + Log.d(LOG_TAG, "--- getUriArray: foundArray" + + ((ImageSpan) images[j]).getSource()); + } + uris.add(Uri.parse( + ((ImageSpan) images[j]).getSource())); + } + } + } + + public void SetHtml (String html) { + final Spanned spanned = Html.fromHtml(html, new Html.ImageGetter() { + public Drawable getDrawable(String src) { + Log.d(LOG_TAG, "--- sethtml: src="+src); + if (src.startsWith("content://")) { + Uri uri = Uri.parse(src); + try { + InputStream is = mEST.getContext().getContentResolver().openInputStream(uri); + Bitmap bitmap = BitmapFactory.decodeStream(is); + Drawable drawable = new BitmapDrawable(bitmap); + drawable.setBounds(0, 0, + drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight()); + is.close(); + return drawable; + } catch (Exception e) { + Log.e(LOG_TAG, "--- set html: Failed to loaded content " + uri, e); + return null; + } + } + Log.d(LOG_TAG, " unknown src="+src); + return null; + } + }, null); + mEST.setText(spanned); + } } - private class StyledTextToast { + private class StyledTextDialog { Builder mBuilder; CharSequence mColorTitle; CharSequence mSizeTitle; + CharSequence mAlignTitle; CharSequence[] mColorNames; CharSequence[] mColorInts; CharSequence[] mSizeNames; CharSequence[] mSizeDisplayInts; CharSequence[] mSizeSendInts; + CharSequence[] mAlignNames; EditStyledText mEST; - public StyledTextToast(EditStyledText est) { + public StyledTextDialog(EditStyledText est) { mEST = est; } @@ -848,7 +1298,13 @@ public class EditStyledText extends EditText { mSizeSendInts = sizesendints; } - public boolean checkColorAlertParams() { + public void setAlignAlertParams(CharSequence aligntitle, + CharSequence[] alignnames) { + mAlignTitle = aligntitle; + mAlignNames = alignnames; + } + + private boolean checkColorAlertParams() { if (DBG) { Log.d(LOG_TAG, "--- checkParams"); } @@ -867,26 +1323,43 @@ public class EditStyledText extends EditText { return true; } - public boolean checkSizeAlertParams() { + private boolean checkSizeAlertParams() { if (DBG) { Log.d(LOG_TAG, "--- checkParams"); } if (mBuilder == null) { Log.e(LOG_TAG, "--- builder is null."); + return false; } else if (mSizeTitle == null || mSizeNames == null || mSizeDisplayInts == null || mSizeSendInts == null) { Log.e(LOG_TAG, "--- size alert params are null."); + return false; } else if (mSizeNames.length != mSizeDisplayInts.length && mSizeSendInts.length != mSizeDisplayInts.length) { Log.e(LOG_TAG, "--- the length of size alert params are " + "different."); + return false; } return true; } - private void onShowColorAlertDialog() { + private boolean checkAlignAlertParams() { if (DBG) { - Log.d(LOG_TAG, "--- onShowAlertDialog"); + Log.d(LOG_TAG, "--- checkAlignAlertParams"); + } + if (mBuilder == null) { + Log.e(LOG_TAG, "--- builder is null."); + return false; + } else if (mAlignTitle == null) { + Log.e(LOG_TAG, "--- align alert params are null."); + return false; + } + return true; + } + + private void onShowForegroundColorAlertDialog() { + if (DBG) { + Log.d(LOG_TAG, "--- onShowForegroundColorAlertDialog"); } if (!checkColorAlertParams()) { return; @@ -906,20 +1379,42 @@ public class EditStyledText extends EditText { mBuilder.show(); } - private void onShowSizeAlertDialog() { + private void onShowBackgroundColorAlertDialog() { if (DBG) { - Log.d(LOG_TAG, "--- onShowAlertDialog"); + Log.d(LOG_TAG, "--- onShowBackgroundColorAlertDialog"); } if (!checkColorAlertParams()) { return; } + mBuilder.setTitle(mColorTitle); + mBuilder.setIcon(0); + mBuilder. + setItems(mColorNames, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + Log.d("EETVM", "mBuilder.onclick:" + which); + int color = Integer.parseInt( + (String) mColorInts[which], 16) - 0x01000000; + mEST.setBackgroundColor(color); + } + }); + mBuilder.show(); + } + + private void onShowSizeAlertDialog() { + if (DBG) { + Log.d(LOG_TAG, "--- onShowSizeAlertDialog"); + } + if (!checkSizeAlertParams()) { + return; + } mBuilder.setTitle(mSizeTitle); mBuilder.setIcon(0); mBuilder. setItems(mSizeNames, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { - Log.d("EETVM", "mBuilder.onclick:" + which); + Log.d(LOG_TAG, "mBuilder.onclick:" + which); int size = Integer .parseInt((String) mSizeDisplayInts[which]); mEST.setItemSize(size); @@ -927,5 +1422,241 @@ public class EditStyledText extends EditText { }); mBuilder.show(); } + + private void onShowAlignAlertDialog() { + if (DBG) { + Log.d(LOG_TAG, "--- onShowAlignAlertDialog"); + } + if (!checkAlignAlertParams()) { + return; + } + mBuilder.setTitle(mAlignTitle); + mBuilder.setIcon(0); + mBuilder. + setItems(mAlignNames, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + Log.d(LOG_TAG, "mBuilder.onclick:" + which); + Layout.Alignment align = Layout.Alignment.ALIGN_NORMAL; + switch (which) { + case 0: + align = Layout.Alignment.ALIGN_NORMAL; + break; + case 1: + align = Layout.Alignment.ALIGN_CENTER; + break; + case 2: + align = Layout.Alignment.ALIGN_OPPOSITE; + break; + default: + break; + } + mEST.setAlignment(align); + } + }); + mBuilder.show(); + } + } + + private class StyledTextArrowKeyMethod extends ArrowKeyMovementMethod { + EditorManager mManager; + StyledTextArrowKeyMethod(EditorManager manager) { + super(); + mManager = manager; + } + + @Override + public boolean onKeyDown(TextView widget, Spannable buffer, + int keyCode, KeyEvent event) { + if (!mManager.isSoftKeyBlocked()) { + return super.onKeyDown(widget, buffer, keyCode, event); + } + if (executeDown(widget, buffer, keyCode)) { + return true; + } + return false; + } + + private int getEndPos(TextView widget) { + int end; + if (widget.getSelectionStart() == mManager.getSelectionStart()) { + end = widget.getSelectionEnd(); + } else { + end = widget.getSelectionStart(); + } + return end; + } + + private boolean up(TextView widget, Spannable buffer) { + if (DBG) { + Log.d(LOG_TAG, "--- up:"); + } + Layout layout = widget.getLayout(); + int end = getEndPos(widget); + int line = layout.getLineForOffset(end); + if (line > 0) { + int to; + if (layout.getParagraphDirection(line) == + layout.getParagraphDirection(line - 1)) { + float h = layout.getPrimaryHorizontal(end); + to = layout.getOffsetForHorizontal(line - 1, h); + } else { + to = layout.getLineStart(line - 1); + } + mManager.setSelectedEndPos(to); + mManager.onCursorMoved(); + return true; + } + return false; + } + + private boolean down(TextView widget, Spannable buffer) { + if (DBG) { + Log.d(LOG_TAG, "--- down:"); + } + Layout layout = widget.getLayout(); + int end = getEndPos(widget); + int line = layout.getLineForOffset(end); + if (line < layout.getLineCount() - 1) { + int to; + if (layout.getParagraphDirection(line) == + layout.getParagraphDirection(line + 1)) { + float h = layout.getPrimaryHorizontal(end); + to = layout.getOffsetForHorizontal(line + 1, h); + } else { + to = layout.getLineStart(line + 1); + } + mManager.setSelectedEndPos(to); + mManager.onCursorMoved(); + return true; + } + return false; + } + + private boolean left(TextView widget, Spannable buffer) { + if (DBG) { + Log.d(LOG_TAG, "--- left:"); + } + Layout layout = widget.getLayout(); + int to = layout.getOffsetToLeftOf(getEndPos(widget)); + mManager.setSelectedEndPos(to); + mManager.onCursorMoved(); + return true; + } + + private boolean right(TextView widget, Spannable buffer) { + if (DBG) { + Log.d(LOG_TAG, "--- right:"); + } + Layout layout = widget.getLayout(); + int to = layout.getOffsetToRightOf(getEndPos(widget)); + mManager.setSelectedEndPos(to); + mManager.onCursorMoved(); + return true; + } + + private boolean executeDown(TextView widget, Spannable buffer, + int keyCode) { + if (DBG) { + Log.d(LOG_TAG, "--- executeDown: " + keyCode); + } + boolean handled = false; + + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_UP: + handled |= up(widget, buffer); + break; + case KeyEvent.KEYCODE_DPAD_DOWN: + handled |= down(widget, buffer); + break; + case KeyEvent.KEYCODE_DPAD_LEFT: + handled |= left(widget, buffer); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled |= right(widget, buffer); + break; + case KeyEvent.KEYCODE_DPAD_CENTER: + mManager.onFixSelectedItem(); + handled = true; + break; + } + return handled; + } + } + + public class HorizontalLineSpan extends ImageSpan { + public HorizontalLineSpan(int color, View view) { + super(new HorizontalLineDrawable(color, view)); + } + } + public class HorizontalLineDrawable extends ShapeDrawable { + private View mView; + public HorizontalLineDrawable(int color, View view) { + super(new RectShape()); + mView = view; + renewColor(color); + renewBounds(view); + } + @Override + public void draw(Canvas canvas) { + if (DBG) { + Log.d(LOG_TAG, "--- draw:"); + } + renewColor(); + renewBounds(mView); + super.draw(canvas); + } + + private void renewBounds(View view) { + if (DBG) { + int width = mView.getBackground().getBounds().width(); + int height = mView.getBackground().getBounds().height(); + Log.d(LOG_TAG, "--- renewBounds:" + width + "," + height); + Log.d(LOG_TAG, "--- renewBounds:" + mView.getClass()); + } + int width = mView.getWidth(); + if (width > 20) { + width -= 20; + } + setBounds(0, 0, width, 2); + } + private void renewColor(int color) { + if (DBG) { + Log.d(LOG_TAG, "--- renewColor:" + color); + } + getPaint().setColor(color); + } + private void renewColor() { + if (DBG) { + Log.d(LOG_TAG, "--- renewColor:"); + } + if (mView instanceof View) { + ImageSpan parent = getParentSpan(); + Editable text = ((EditStyledText)mView).getText(); + int start = text.getSpanStart(parent); + ForegroundColorSpan[] spans = text.getSpans(start, start, ForegroundColorSpan.class); + if (spans.length > 0) { + renewColor(spans[spans.length - 1].getForegroundColor()); + } + } + } + private ImageSpan getParentSpan() { + if (DBG) { + Log.d(LOG_TAG, "--- getParentSpan:"); + } + if (mView instanceof EditStyledText) { + Editable text = ((EditStyledText)mView).getText(); + ImageSpan[] images = text.getSpans(0, text.length(), ImageSpan.class); + if (images.length > 0) { + for (ImageSpan image: images) { + if (image.getDrawable() == this) { + return image; + } + } + } + } + Log.e(LOG_TAG, "---renewBounds: Couldn't find"); + return null; + } } } diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index f2ec064..ad329d1 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -33,7 +33,7 @@ public class EditableInputConnection extends BaseInputConnection { private final TextView mTextView; public EditableInputConnection(TextView textview) { - super(textview, false); + super(textview, true); mTextView = textview; } diff --git a/core/java/com/android/internal/widget/Smileys.java b/core/java/com/android/internal/widget/Smileys.java new file mode 100644 index 0000000..d5e8d03 --- /dev/null +++ b/core/java/com/android/internal/widget/Smileys.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009 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.internal.widget; + +import com.android.internal.R; + +/** + * Temp stupidity until we have a real emoticon API. + */ +public class Smileys { + private static final int[] sIconIds = { + R.drawable.emo_im_happy, + R.drawable.emo_im_sad, + R.drawable.emo_im_winking, + R.drawable.emo_im_tongue_sticking_out, + R.drawable.emo_im_surprised, + R.drawable.emo_im_kissing, + R.drawable.emo_im_yelling, + R.drawable.emo_im_cool, + R.drawable.emo_im_money_mouth, + R.drawable.emo_im_foot_in_mouth, + R.drawable.emo_im_embarrassed, + R.drawable.emo_im_angel, + R.drawable.emo_im_undecided, + R.drawable.emo_im_crying, + R.drawable.emo_im_lips_are_sealed, + R.drawable.emo_im_laughing, + R.drawable.emo_im_wtf + }; + + public static int HAPPY = 0; + public static int SAD = 1; + public static int WINKING = 2; + public static int TONGUE_STICKING_OUT = 3; + public static int SURPRISED = 4; + public static int KISSING = 5; + public static int YELLING = 6; + public static int COOL = 7; + public static int MONEY_MOUTH = 8; + public static int FOOT_IN_MOUTH = 9; + public static int EMBARRASSED = 10; + public static int ANGEL = 11; + public static int UNDECIDED = 12; + public static int CRYING = 13; + public static int LIPS_ARE_SEALED = 14; + public static int LAUGHING = 15; + public static int WTF = 16; + + public static int getSmileyResource(int which) { + return sIconIds[which]; + } +} diff --git a/core/java/com/google/android/gdata/client/AndroidGDataClient.java b/core/java/com/google/android/gdata/client/AndroidGDataClient.java index fe7d860..998f940 100644 --- a/core/java/com/google/android/gdata/client/AndroidGDataClient.java +++ b/core/java/com/google/android/gdata/client/AndroidGDataClient.java @@ -51,7 +51,7 @@ public class AndroidGDataClient implements GDataClient { private static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override"; - private static final String USER_AGENT_APP_VERSION = "Android-GData/1.0"; + private static final String DEFAULT_USER_AGENT_APP_VERSION = "Android-GData/1.1"; private static final int MAX_REDIRECTS = 10; @@ -121,7 +121,7 @@ public class AndroidGDataClient implements GDataClient { * @deprecated Use AndroidGDAtaClient(Context) instead. */ public AndroidGDataClient(ContentResolver resolver) { - mHttpClient = new GoogleHttpClient(resolver, USER_AGENT_APP_VERSION, + mHttpClient = new GoogleHttpClient(resolver, DEFAULT_USER_AGENT_APP_VERSION, true /* gzip capable */); mHttpClient.enableCurlLogging(TAG, Log.VERBOSE); mResolver = resolver; @@ -136,7 +136,21 @@ public class AndroidGDataClient implements GDataClient { * SSL session persistence. */ public AndroidGDataClient(Context context) { - mHttpClient = new GoogleHttpClient(context, USER_AGENT_APP_VERSION, + this(context, DEFAULT_USER_AGENT_APP_VERSION); + } + + /** + * Creates a new AndroidGDataClient. + * + * @param context The ContentResolver to get URL rewriting rules from + * through the Android proxy server, using null to indicate not using proxy. + * The context will also be used by GoogleHttpClient for configuration of + * SSL session persistence. + * @param appAndVersion The application name and version to be used as the basis of the + * User-Agent. e.g., Android-GData/1.5.0. + */ + public AndroidGDataClient(Context context, String appAndVersion) { + mHttpClient = new GoogleHttpClient(context, appAndVersion, true /* gzip capable */); mHttpClient.enableCurlLogging(TAG, Log.VERBOSE); mResolver = context.getContentResolver(); diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp index a1059e5..41044db 100644 --- a/core/jni/android/opengl/util.cpp +++ b/core/jni/android/opengl/util.cpp @@ -599,6 +599,44 @@ static int getInternalFormat(SkBitmap::Config config) } } +static int getType(SkBitmap::Config config) +{ + switch(config) { + case SkBitmap::kA8_Config: + return GL_UNSIGNED_BYTE; + case SkBitmap::kARGB_4444_Config: + return GL_UNSIGNED_SHORT_4_4_4_4; + case SkBitmap::kARGB_8888_Config: + return GL_UNSIGNED_BYTE; + case SkBitmap::kIndex8_Config: + return -1; // No type for compressed data. + case SkBitmap::kRGB_565_Config: + return GL_UNSIGNED_SHORT_5_6_5; + default: + return -1; + } +} + +static jint util_getInternalFormat(JNIEnv *env, jclass clazz, + jobject jbitmap) +{ + SkBitmap const * nativeBitmap = + (SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID); + const SkBitmap& bitmap(*nativeBitmap); + SkBitmap::Config config = bitmap.getConfig(); + return getInternalFormat(config); +} + +static jint util_getType(JNIEnv *env, jclass clazz, + jobject jbitmap) +{ + SkBitmap const * nativeBitmap = + (SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID); + const SkBitmap& bitmap(*nativeBitmap); + SkBitmap::Config config = bitmap.getConfig(); + return getType(config); +} + static jint util_texImage2D(JNIEnv *env, jclass clazz, jint target, jint level, jint internalformat, jobject jbitmap, jint type, jint border) @@ -610,6 +648,9 @@ static jint util_texImage2D(JNIEnv *env, jclass clazz, if (internalformat < 0) { internalformat = getInternalFormat(config); } + if (type < 0) { + type = getType(config); + } int err = checkFormat(config, internalformat, type); if (err) return err; @@ -694,6 +735,8 @@ static JNINativeMethod gVisiblityMethods[] = { static JNINativeMethod gUtilsMethods[] = { {"nativeClassInit", "()V", (void*)nativeUtilsClassInit }, + { "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat }, + { "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType }, { "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D }, { "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D }, }; diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp index dee3fdd..f0b35e9 100644 --- a/core/jni/android_location_GpsLocationProvider.cpp +++ b/core/jni/android_location_GpsLocationProvider.cpp @@ -35,6 +35,7 @@ static jmethodID method_xtraDownloadRequest; static const GpsInterface* sGpsInterface = NULL; static const GpsXtraInterface* sGpsXtraInterface = NULL; +static const GpsSuplInterface* sGpsSuplInterface = NULL; // data written to by GPS callbacks static GpsLocation sGpsLocation; @@ -144,9 +145,10 @@ static void android_location_GpsLocationProvider_cleanup(JNIEnv* env, jobject ob sGpsInterface->cleanup(); } -static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jboolean singleFix, jint fixFrequency) +static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jint positionMode, + jboolean singleFix, jint fixFrequency) { - int result = sGpsInterface->set_position_mode(GPS_POSITION_MODE_STANDALONE, (singleFix ? 0 : fixFrequency)); + int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency)); if (result) { return result; } @@ -267,6 +269,33 @@ static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, j env->ReleaseByteArrayElements(data, bytes, 0); } +static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj, + jint addr, jint port) +{ + if (!sGpsSuplInterface) { + sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + } + if (sGpsSuplInterface) { + sGpsSuplInterface->set_server(addr, port); + } +} + +static void android_location_GpsLocationProvider_set_supl_apn(JNIEnv* env, jobject obj, jstring apn) +{ + if (!sGpsSuplInterface) { + sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + } + if (sGpsSuplInterface) { + if (apn == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + return; + } + const char *apnStr = env->GetStringUTFChars(apn, NULL); + sGpsSuplInterface->set_apn(apnStr); + env->ReleaseStringUTFChars(apn, apnStr); + } +} + static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, @@ -274,7 +303,7 @@ static JNINativeMethod sMethods[] = { {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, {"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable}, {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, - {"native_start", "(ZI)Z", (void*)android_location_GpsLocationProvider_start}, + {"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start}, {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, {"native_set_fix_frequency", "(I)V", (void*)android_location_GpsLocationProvider_set_fix_frequency}, {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data}, @@ -283,6 +312,8 @@ static JNINativeMethod sMethods[] = { {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, + {"native_set_supl_server", "(II)V", (void*)android_location_GpsLocationProvider_set_supl_server}, + {"native_set_supl_apn", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_set_supl_apn}, }; int register_android_location_GpsLocationProvider(JNIEnv* env) diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index f625ffb..b8d6586 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -744,6 +744,7 @@ static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thi // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSamplingRate); + if (minBufCount < 2) minBufCount = 2; uint32_t minFrameCount = (afFrameCount*sampleRateInHertz*minBufCount)/afSamplingRate; int minBuffSize = minFrameCount * (audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1) diff --git a/core/jni/android_media_JetPlayer.cpp b/core/jni/android_media_JetPlayer.cpp index e345af6..3727f4b 100644 --- a/core/jni/android_media_JetPlayer.cpp +++ b/core/jni/android_media_JetPlayer.cpp @@ -14,8 +14,7 @@ * limitations under the License. */ -//FIXME: remove log before release -#define LOG_NDEBUG 0 +//#define LOG_NDEBUG 0 #define LOG_TAG "JET_JNI" diff --git a/core/jni/android_os_Hardware.cpp b/core/jni/android_os_Hardware.cpp index bc8af78..8007662 100644 --- a/core/jni/android_os_Hardware.cpp +++ b/core/jni/android_os_Hardware.cpp @@ -15,7 +15,6 @@ */ #include <hardware_legacy/flashlight.h> -#include <hardware_legacy/led.h> #include <hardware_legacy/power.h> #include <nativehelper/jni.h> @@ -24,12 +23,6 @@ namespace android { -static jboolean -setLedState(JNIEnv *env, jobject clazz, jint colorARGB, jint onMS, jint offMS) -{ - return set_led_state(colorARGB, onMS, offMS); -} - static jint getFlashlightEnabled(JNIEnv *env, jobject clazz) { @@ -48,24 +41,6 @@ enableCameraFlash(JNIEnv *env, jobject clazz, jint milliseconds) enable_camera_flash(milliseconds); } -static void -setScreenBacklight(JNIEnv *env, jobject clazz, jint brightness) -{ - set_light_brightness(SCREEN_LIGHT, brightness); -} - -static void -setKeyboardBacklight(JNIEnv *env, jobject clazz, jboolean on) -{ - set_light_brightness(KEYBOARD_LIGHT, (on ? 255 : 0)); -} - -static void -setButtonBacklight(JNIEnv *env, jobject clazz, jboolean on) -{ - set_light_brightness(BUTTON_LIGHT, (on ? 255 : 0)); -} - // ============================================================================ /* * JNI registration. @@ -73,13 +48,9 @@ setButtonBacklight(JNIEnv *env, jobject clazz, jboolean on) static JNINativeMethod g_methods[] = { /* name, signature, funcPtr */ - { "setLedState", "(III)I", (void*)setLedState }, { "getFlashlightEnabled", "()Z", (void*)getFlashlightEnabled }, { "setFlashlightEnabled", "(Z)V", (void*)setFlashlightEnabled }, { "enableCameraFlash", "(I)V", (void*)enableCameraFlash }, - { "setScreenBacklight", "(I)V", (void*)setScreenBacklight }, - { "setKeyboardBacklight", "(Z)V", (void*)setKeyboardBacklight }, - { "setButtonBacklight", "(Z)V", (void*)setButtonBacklight }, }; int register_android_os_Hardware(JNIEnv* env) diff --git a/core/jni/android_os_Power.cpp b/core/jni/android_os_Power.cpp index c2d75b1..df5edba 100644 --- a/core/jni/android_os_Power.cpp +++ b/core/jni/android_os_Power.cpp @@ -70,12 +70,6 @@ setLastUserActivityTimeout(JNIEnv *env, jobject clazz, jlong timeMS) } static int -setLightBrightness(JNIEnv *env, jobject clazz, jint mask, jint brightness) -{ - return set_light_brightness(mask, brightness); -} - -static int setScreenState(JNIEnv *env, jobject clazz, jboolean on) { return set_screen_state(on); @@ -109,7 +103,6 @@ static JNINativeMethod method_table[] = { { "acquireWakeLock", "(ILjava/lang/String;)V", (void*)acquireWakeLock }, { "releaseWakeLock", "(Ljava/lang/String;)V", (void*)releaseWakeLock }, { "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout }, - { "setLightBrightness", "(II)I", (void*)setLightBrightness }, { "setScreenState", "(Z)I", (void*)setScreenState }, { "shutdown", "()V", (void*)android_os_Power_shutdown }, { "reboot", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot }, diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 8baaa84..076775f 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -324,9 +324,9 @@ static void Surface_closeTransaction( } static void Surface_setOrientation( - JNIEnv* env, jobject clazz, jint display, jint orientation) + JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags) { - int err = SurfaceComposerClient::setOrientation(display, orientation); + int err = SurfaceComposerClient::setOrientation(display, orientation, flags); if (err < 0) { doThrow(env, "java/lang/IllegalArgumentException", NULL); } @@ -565,7 +565,7 @@ static JNINativeMethod gSurfaceMethods[] = { {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas }, {"openTransaction", "()V", (void*)Surface_openTransaction }, {"closeTransaction", "()V", (void*)Surface_closeTransaction }, - {"setOrientation", "(II)V", (void*)Surface_setOrientation }, + {"setOrientation", "(III)V", (void*)Surface_setOrientation }, {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay }, {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay }, {"setLayer", "(I)V", (void*)Surface_setLayer }, diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp index fbbd852..4452065 100644 --- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp @@ -2,16 +2,16 @@ ** ** Copyright 2006, 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 +** 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 +** 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 +** 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. */ @@ -89,7 +89,7 @@ static void nativeClassInit(JNIEnv *_env, jclass eglImplClass) gConfig_class = make_globalref(_env, "com/google/android/gles_jni/EGLConfigImpl"); gConfig_ctorID = _env->GetMethodID(gConfig_class, "<init>", "(I)V"); - + gDisplay_EGLDisplayFieldID = _env->GetFieldID(gDisplay_class, "mEGLDisplay", "I"); gContext_EGLContextFieldID = _env->GetFieldID(gContext_class, "mEGLContext", "I"); gSurface_EGLSurfaceFieldID = _env->GetFieldID(gSurface_class, "mEGLSurface", "I"); @@ -100,12 +100,46 @@ static void nativeClassInit(JNIEnv *_env, jclass eglImplClass) gSurface_SurfaceFieldID = _env->GetFieldID(surface_class, "mSurface", "I"); jclass bitmap_class = _env->FindClass("android/graphics/Bitmap"); - gBitmap_NativeBitmapFieldID = _env->GetFieldID(bitmap_class, "mNativeBitmap", "I"); + gBitmap_NativeBitmapFieldID = _env->GetFieldID(bitmap_class, "mNativeBitmap", "I"); +} + +static const jint gNull_attrib_base[] = {EGL_NONE}; + +static bool validAttribList(JNIEnv *_env, jintArray attrib_list) { + if (attrib_list == NULL) { + return true; + } + jsize len = _env->GetArrayLength(attrib_list); + if (len < 1) { + return false; + } + jint item = 0; + _env->GetIntArrayRegion(attrib_list, len-1, 1, &item); + return item == EGL_NONE; +} + +static jint* beginNativeAttribList(JNIEnv *_env, jintArray attrib_list) { + if (attrib_list != NULL) { + return (jint *)_env->GetPrimitiveArrayCritical(attrib_list, (jboolean *)0); + } else { + return(jint*) gNull_attrib_base; + } } -jboolean jni_eglInitialize(JNIEnv *_env, jobject _this, jobject display, +static void endNativeAttributeList(JNIEnv *_env, jintArray attrib_list, jint* attrib_base) { + if (attrib_list != NULL) { + _env->ReleasePrimitiveArrayCritical(attrib_list, attrib_base, JNI_ABORT); + } +} + +static jboolean jni_eglInitialize(JNIEnv *_env, jobject _this, jobject display, jintArray major_minor) { - + if (display == NULL || (major_minor != NULL && + _env->GetArrayLength(major_minor) < 2)) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } + EGLDisplay dpy = getDisplay(_env, display); jboolean success = eglInitialize(dpy, NULL, NULL); if (success && major_minor) { @@ -121,14 +155,15 @@ jboolean jni_eglInitialize(JNIEnv *_env, jobject _this, jobject display, return success; } -jboolean jni_eglQueryContext(JNIEnv *_env, jobject _this, jobject display, +static jboolean jni_eglQueryContext(JNIEnv *_env, jobject _this, jobject display, jobject context, jint attribute, jintArray value) { - EGLDisplay dpy = getDisplay(_env, display); - EGLContext ctx = getContext(_env, context); - if (value == NULL) { - doThrow(_env, "java/lang/NullPointerException"); + if (display == NULL || context == NULL || value == NULL + || _env->GetArrayLength(value) < 1) { + doThrow(_env, "java/lang/IllegalArgumentException"); return JNI_FALSE; } + EGLDisplay dpy = getDisplay(_env, display); + EGLContext ctx = getContext(_env, context); jboolean success = JNI_FALSE; int len = _env->GetArrayLength(value); if (len) { @@ -138,15 +173,17 @@ jboolean jni_eglQueryContext(JNIEnv *_env, jobject _this, jobject display, } return success; } - -jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display, + +static jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display, jobject surface, jint attribute, jintArray value) { - EGLDisplay dpy = getDisplay(_env, display); - EGLContext sur = getSurface(_env, surface); - if (value == NULL) { - doThrow(_env, "java/lang/NullPointerException"); + if (display == NULL || surface == NULL || value == NULL + || _env->GetArrayLength(value) < 1) { + doThrow(_env, "java/lang/IllegalArgumentException"); return JNI_FALSE; } + EGLDisplay dpy = getDisplay(_env, display); + EGLContext sur = getSurface(_env, surface); + jboolean success = JNI_FALSE; int len = _env->GetArrayLength(value); if (len) { @@ -157,60 +194,69 @@ jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display, return success; } -jboolean jni_eglChooseConfig(JNIEnv *_env, jobject _this, jobject display, - jintArray attrib_list, jobjectArray configs, jint config_size, jintArray num_config) { - EGLDisplay dpy = getDisplay(_env, display); - if (attrib_list==NULL || configs==NULL || num_config==NULL) { - doThrow(_env, "java/lang/NullPointerException"); +static jboolean jni_eglChooseConfig(JNIEnv *_env, jobject _this, jobject display, + jintArray attrib_list, jobjectArray configs, jint config_size, jintArray num_config) { + if (display == NULL + || !validAttribList(_env, attrib_list) + || (configs != NULL && _env->GetArrayLength(configs) < config_size) + || (num_config != NULL && _env->GetArrayLength(num_config) < 1)) { + doThrow(_env, "java/lang/IllegalArgumentException"); return JNI_FALSE; } + EGLDisplay dpy = getDisplay(_env, display); jboolean success = JNI_FALSE; - jint* attrib_base = (jint *)_env->GetPrimitiveArrayCritical(attrib_list, (jboolean *)0); - jint* num_base = (jint *)_env->GetPrimitiveArrayCritical(num_config, (jboolean *)0); + + if (configs == NULL) { + config_size = 0; + } EGLConfig nativeConfigs[config_size]; - success = eglChooseConfig(dpy, attrib_base, nativeConfigs, config_size, num_base); - int num = num_base[0]; - _env->ReleasePrimitiveArrayCritical(num_config, num_base, JNI_ABORT); - _env->ReleasePrimitiveArrayCritical(attrib_list, attrib_base, JNI_ABORT); - if (success) { + + int num = 0; + jint* attrib_base = beginNativeAttribList(_env, attrib_list); + success = eglChooseConfig(dpy, attrib_base, configs ? nativeConfigs : 0, config_size, &num); + endNativeAttributeList(_env, attrib_list, attrib_base); + + if (num_config != NULL) { + _env->SetIntArrayRegion(num_config, 0, 1, (jint*) &num); + } + + if (success && configs!=NULL) { for (int i=0 ; i<num ; i++) { jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]); _env->SetObjectArrayElement(configs, i, obj); } } return success; -} +} -jint jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display, +static jint jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display, jobject config, jobject share_context, jintArray attrib_list) { + if (display == NULL || config == NULL || share_context == NULL + || !validAttribList(_env, attrib_list)) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); EGLConfig cnf = getConfig(_env, config); EGLContext shr = getContext(_env, share_context); - jint* base = 0; - if (attrib_list) { - // XXX: if array is malformed, we should return an NPE instead of segfault - base = (jint *)_env->GetPrimitiveArrayCritical(attrib_list, (jboolean *)0); - } + jint* base = beginNativeAttribList(_env, attrib_list); EGLContext ctx = eglCreateContext(dpy, cnf, shr, base); - if (attrib_list) { - _env->ReleasePrimitiveArrayCritical(attrib_list, base, JNI_ABORT); - } + endNativeAttributeList(_env, attrib_list, base); return (jint)ctx; } -jint jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display, +static jint jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display, jobject config, jintArray attrib_list) { + if (display == NULL || config == NULL + || !validAttribList(_env, attrib_list)) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); EGLConfig cnf = getConfig(_env, config); - jint* base = 0; - if (attrib_list) { - // XXX: if array is malformed, we should return an NPE instead of segfault - base = (jint *)_env->GetPrimitiveArrayCritical(attrib_list, (jboolean *)0); - } + jint* base = beginNativeAttribList(_env, attrib_list); EGLSurface sur = eglCreatePbufferSurface(dpy, cnf, base); - if (attrib_list) { - _env->ReleasePrimitiveArrayCritical(attrib_list, base, JNI_ABORT); - } + endNativeAttributeList(_env, attrib_list, base); return (jint)sur; } @@ -225,10 +271,15 @@ static PixelFormat convertPixelFormat(SkBitmap::Config format) } } -void jni_eglCreatePixmapSurface(JNIEnv *_env, jobject _this, jobject out_sur, +static void jni_eglCreatePixmapSurface(JNIEnv *_env, jobject _this, jobject out_sur, jobject display, jobject config, jobject native_pixmap, - jintArray attrib_list) + jintArray attrib_list) { + if (display == NULL || config == NULL || native_pixmap == NULL + || !validAttribList(_env, attrib_list)) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return; + } EGLDisplay dpy = getDisplay(_env, display); EGLConfig cnf = getConfig(_env, config); jint* base = 0; @@ -238,13 +289,13 @@ void jni_eglCreatePixmapSurface(JNIEnv *_env, jobject _this, jobject out_sur, gBitmap_NativeBitmapFieldID); SkPixelRef* ref = nativeBitmap ? nativeBitmap->pixelRef() : 0; if (ref == NULL) { - doThrow(_env, "java/lang/NullPointerException", "Bitmap has no PixelRef"); + doThrow(_env, "java/lang/IllegalArgumentException", "Bitmap has no PixelRef"); return; } - + ref->safeRef(); ref->lockPixels(); - + egl_native_pixmap_t pixmap; pixmap.version = sizeof(pixmap); pixmap.width = nativeBitmap->width(); @@ -252,15 +303,10 @@ void jni_eglCreatePixmapSurface(JNIEnv *_env, jobject _this, jobject out_sur, pixmap.stride = nativeBitmap->rowBytes() / nativeBitmap->bytesPerPixel(); pixmap.format = convertPixelFormat(nativeBitmap->config()); pixmap.data = (uint8_t*)ref->pixels(); - - if (attrib_list) { - // XXX: if array is malformed, we should return an NPE instead of segfault - base = (jint *)_env->GetPrimitiveArrayCritical(attrib_list, (jboolean *)0); - } + + base = beginNativeAttribList(_env, attrib_list); EGLSurface sur = eglCreatePixmapSurface(dpy, cnf, &pixmap, base); - if (attrib_list) { - _env->ReleasePrimitiveArrayCritical(attrib_list, base, JNI_ABORT); - } + endNativeAttributeList(_env, attrib_list, base); if (sur != EGL_NO_SURFACE) { _env->SetIntField(out_sur, gSurface_EGLSurfaceFieldID, (int)sur); @@ -271,14 +317,19 @@ void jni_eglCreatePixmapSurface(JNIEnv *_env, jobject _this, jobject out_sur, } } -jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display, +static jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display, jobject config, jobject native_window, jintArray attrib_list) { + if (display == NULL || config == NULL + || !validAttribList(_env, attrib_list)) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); EGLContext cnf = getConfig(_env, config); Surface* window = 0; if (native_window == NULL) { not_valid_surface: - doThrow(_env, "java/lang/NullPointerException", + doThrow(_env, "java/lang/IllegalArgumentException", "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface"); return 0; } @@ -286,50 +337,48 @@ not_valid_surface: if (window == NULL) goto not_valid_surface; - jint* base = 0; - if (attrib_list) { - // XXX: if array is malformed, we should return an NPE instead of segfault - base = (jint *)_env->GetPrimitiveArrayCritical(attrib_list, (jboolean *)0); - } + jint* base = beginNativeAttribList(_env, attrib_list); EGLSurface sur = eglCreateWindowSurface(dpy, cnf, new EGLNativeWindowSurface(window), base); - if (attrib_list) { - _env->ReleasePrimitiveArrayCritical(attrib_list, base, JNI_ABORT); - } + endNativeAttributeList(_env, attrib_list, base); return (jint)sur; } -jboolean jni_eglGetConfigAttrib(JNIEnv *_env, jobject _this, jobject display, +static jboolean jni_eglGetConfigAttrib(JNIEnv *_env, jobject _this, jobject display, jobject config, jint attribute, jintArray value) { - EGLDisplay dpy = getDisplay(_env, display); - EGLContext cnf = getConfig(_env, config); - if (value == NULL) { - doThrow(_env, "java/lang/NullPointerException"); + if (display == NULL || config == NULL + || (value == NULL || _env->GetArrayLength(value) < 1)) { + doThrow(_env, "java/lang/IllegalArgumentException"); return JNI_FALSE; } + EGLDisplay dpy = getDisplay(_env, display); + EGLContext cnf = getConfig(_env, config); jboolean success = JNI_FALSE; - int len = _env->GetArrayLength(value); - if (len) { - jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0); - success = eglGetConfigAttrib(dpy, cnf, attribute, base); - _env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT); + jint localValue; + success = eglGetConfigAttrib(dpy, cnf, attribute, &localValue); + if (success) { + _env->SetIntArrayRegion(value, 0, 1, &localValue); } return success; } -jboolean jni_eglGetConfigs(JNIEnv *_env, jobject _this, jobject display, +static jboolean jni_eglGetConfigs(JNIEnv *_env, jobject _this, jobject display, jobjectArray configs, jint config_size, jintArray num_config) { + if (display == NULL || (configs != NULL && _env->GetArrayLength(configs) < config_size) + || (num_config != NULL && _env->GetArrayLength(num_config) < 1)) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); jboolean success = JNI_FALSE; - if (num_config == NULL) { - doThrow(_env, "java/lang/NullPointerException"); - return JNI_FALSE; + if (configs == NULL) { + config_size = 0; } - jint* num_base = (jint *)_env->GetPrimitiveArrayCritical(num_config, (jboolean *)0); EGLConfig nativeConfigs[config_size]; - success = eglGetConfigs(dpy, configs ? nativeConfigs : 0, config_size, num_base); - int num = num_base[0]; - _env->ReleasePrimitiveArrayCritical(num_config, num_base, JNI_ABORT); - + int num; + success = eglGetConfigs(dpy, configs ? nativeConfigs : 0, config_size, &num); + if (num_config != NULL) { + _env->SetIntArrayRegion(num_config, 0, 1, (jint*) &num); + } if (success && configs) { for (int i=0 ; i<num ; i++) { jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]); @@ -338,31 +387,43 @@ jboolean jni_eglGetConfigs(JNIEnv *_env, jobject _this, jobject display, } return success; } - -jint jni_eglGetError(JNIEnv *_env, jobject _this) { + +static jint jni_eglGetError(JNIEnv *_env, jobject _this) { EGLint error = eglGetError(); return error; } -jint jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) { +static jint jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) { return (jint)eglGetCurrentContext(); } -jint jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) { +static jint jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) { return (jint)eglGetCurrentDisplay(); } -jint jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) { +static jint jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) { + if (!(readdraw == EGL_READ) || (readdraw == EGL_DRAW)) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return 0; + } return (jint)eglGetCurrentSurface(readdraw); } -jboolean jni_eglDestroyContext(JNIEnv *_env, jobject _this, jobject display, jobject context) { +static jboolean jni_eglDestroyContext(JNIEnv *_env, jobject _this, jobject display, jobject context) { + if (display == NULL || context == NULL) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); EGLContext ctx = getContext(_env, context); return eglDestroyContext(dpy, ctx); } -jboolean jni_eglDestroySurface(JNIEnv *_env, jobject _this, jobject display, jobject surface) { +static jboolean jni_eglDestroySurface(JNIEnv *_env, jobject _this, jobject display, jobject surface) { + if (display == NULL || surface == NULL) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); EGLSurface sur = getSurface(_env, surface); @@ -377,11 +438,15 @@ jboolean jni_eglDestroySurface(JNIEnv *_env, jobject _this, jobject display, job return eglDestroySurface(dpy, sur); } -jint jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) { +static jint jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) { return (jint)eglGetDisplay(EGL_DEFAULT_DISPLAY); } -jboolean jni_eglMakeCurrent(JNIEnv *_env, jobject _this, jobject display, jobject draw, jobject read, jobject context) { +static jboolean jni_eglMakeCurrent(JNIEnv *_env, jobject _this, jobject display, jobject draw, jobject read, jobject context) { + if (display == NULL || draw == NULL || read == NULL || context == NULL) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); EGLSurface sdr = getSurface(_env, draw); EGLSurface srd = getSurface(_env, read); @@ -389,34 +454,50 @@ jboolean jni_eglMakeCurrent(JNIEnv *_env, jobject _this, jobject display, jobjec return eglMakeCurrent(dpy, sdr, srd, ctx); } -jstring jni_eglQueryString(JNIEnv *_env, jobject _this, jobject display, jint name) { +static jstring jni_eglQueryString(JNIEnv *_env, jobject _this, jobject display, jint name) { + if (display == NULL) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return NULL; + } EGLDisplay dpy = getDisplay(_env, display); const char* chars = eglQueryString(dpy, name); return _env->NewStringUTF(chars); } -jboolean jni_eglSwapBuffers(JNIEnv *_env, jobject _this, jobject display, jobject surface) { +static jboolean jni_eglSwapBuffers(JNIEnv *_env, jobject _this, jobject display, jobject surface) { + if (display == NULL || surface == NULL) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); EGLSurface sur = getSurface(_env, surface); return eglSwapBuffers(dpy, sur); } -jboolean jni_eglTerminate(JNIEnv *_env, jobject _this, jobject display) { +static jboolean jni_eglTerminate(JNIEnv *_env, jobject _this, jobject display) { + if (display == NULL) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } EGLDisplay dpy = getDisplay(_env, display); return eglTerminate(dpy); } -jboolean jni_eglCopyBuffers(JNIEnv *_env, jobject _this, jobject display, +static jboolean jni_eglCopyBuffers(JNIEnv *_env, jobject _this, jobject display, jobject surface, jobject native_pixmap) { - // TODO: implement me + if (display == NULL || surface == NULL || native_pixmap == NULL) { + doThrow(_env, "java/lang/IllegalArgumentException"); + return JNI_FALSE; + } + // TODO: Implement this return JNI_FALSE; } -jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) { +static jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) { return eglWaitGL(); } -jboolean jni_eglWaitNative(JNIEnv *_env, jobject _this, jint engine, jobject bindTarget) { +static jboolean jni_eglWaitNative(JNIEnv *_env, jobject _this, jint engine, jobject bindTarget) { return eglWaitNative(engine); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1b145af..3a70d9a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -797,7 +797,7 @@ <permission android:name="android.permission.INSTALL_PACKAGES" android:label="@string/permlab_installPackages" android:description="@string/permdesc_installPackages" - android:protectionLevel="signature" /> + android:protectionLevel="signatureOrSystem" /> <!-- Allows an application to clear user data --> <permission android:name="android.permission.CLEAR_APP_USER_DATA" @@ -815,7 +815,7 @@ <permission android:name="android.permission.DELETE_PACKAGES" android:label="@string/permlab_deletePackages" android:description="@string/permdesc_deletePackages" - android:protectionLevel="signature" /> + android:protectionLevel="signatureOrSystem" /> <!-- Allows an application to change whether an application component (other than its own) is enabled or not. --> @@ -909,14 +909,14 @@ <permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES" android:label="@string/permlab_checkinProperties" android:description="@string/permdesc_checkinProperties" - android:protectionLevel="signature" /> + android:protectionLevel="signatureOrSystem" /> <!-- Allows an application to collect component usage - statistics --> + statistics @hide --> <permission android:name="android.permission.PACKAGE_USAGE_STATS" android:label="@string/permlab_pkgUsageStats" android:description="@string/permdesc_pkgUsageStats" - android:protectionLevel="normal" /> + android:protectionLevel="signature" /> <!-- Allows an application to collect battery statistics --> <permission android:name="android.permission.BATTERY_STATS" diff --git a/core/res/assets/images/android-logo-mask.png b/core/res/assets/images/android-logo-mask.png Binary files differnew file mode 100644 index 0000000..1e8ab95 --- /dev/null +++ b/core/res/assets/images/android-logo-mask.png diff --git a/core/res/assets/images/android-logo-shine.png b/core/res/assets/images/android-logo-shine.png Binary files differnew file mode 100644 index 0000000..60144f1 --- /dev/null +++ b/core/res/assets/images/android-logo-shine.png diff --git a/core/res/assets/images/android_320x480.png b/core/res/assets/images/android_320x480.png Binary files differdeleted file mode 100644 index d2665bb..0000000 --- a/core/res/assets/images/android_320x480.png +++ /dev/null diff --git a/core/res/assets/images/boot_robot.png b/core/res/assets/images/boot_robot.png Binary files differdeleted file mode 100644 index f4555af..0000000 --- a/core/res/assets/images/boot_robot.png +++ /dev/null diff --git a/core/res/assets/images/boot_robot_glow.png b/core/res/assets/images/boot_robot_glow.png Binary files differdeleted file mode 100644 index 2a67a3f..0000000 --- a/core/res/assets/images/boot_robot_glow.png +++ /dev/null diff --git a/core/res/assets/images/cylon_dot.png b/core/res/assets/images/cylon_dot.png Binary files differdeleted file mode 100644 index 150b8b1..0000000 --- a/core/res/assets/images/cylon_dot.png +++ /dev/null diff --git a/core/res/assets/images/cylon_left.png b/core/res/assets/images/cylon_left.png Binary files differdeleted file mode 100644 index 50c6296..0000000 --- a/core/res/assets/images/cylon_left.png +++ /dev/null diff --git a/core/res/assets/images/cylon_right.png b/core/res/assets/images/cylon_right.png Binary files differdeleted file mode 100644 index 89b7d71..0000000 --- a/core/res/assets/images/cylon_right.png +++ /dev/null diff --git a/core/res/assets/webkit/youtube.html b/core/res/assets/webkit/youtube.html index 5a40c1e..2aaaa15 100644 --- a/core/res/assets/webkit/youtube.html +++ b/core/res/assets/webkit/youtube.html @@ -43,7 +43,7 @@ <table height="100%" width="100%"> <tr> <td align="center" valign="middle" height="100%"> - <a id="url" href="youtube:VIDEO_ID" target="_top"> + <a id="url" href="vnd.youtube:VIDEO_ID" target="_top"> <img src="play.png" style="border:0px"/> </a> </td> diff --git a/core/res/res/drawable/progress_indeterminate_small.xml b/core/res/res/anim/input_method_extract_enter.xml index a55fe35..96b049f 100644 --- a/core/res/res/drawable/progress_indeterminate_small.xml +++ b/core/res/res/anim/input_method_extract_enter.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/drawable/progress.xml +/* //device/apps/common/res/anim/fade_in.xml ** ** Copyright 2007, The Android Open Source Project ** @@ -18,15 +18,7 @@ */ --> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item - android:drawable="@android:drawable/progress_circular_background_small" /> - - <item><rotate - android:pivotX="50%" - android:pivotY="50%" - android:fromDegrees="0" - android:toDegrees="360" - android:drawable="@android:drawable/progress_circular_indeterminate_small" /> - </item> -</layer-list> +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@anim/decelerate_interpolator" + android:fromAlpha="0.0" android:toAlpha="1.0" + android:duration="@android:integer/config_shortAnimTime" /> diff --git a/core/res/res/anim/slide_in_bottom.xml b/core/res/res/anim/input_method_extract_exit.xml index d111854..26db13f 100644 --- a/core/res/res/anim/slide_in_bottom.xml +++ b/core/res/res/anim/input_method_extract_exit.xml @@ -1,26 +1,25 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/slide_in_right.xml +/* //device/apps/common/res/anim/fade_out.xml ** ** Copyright 2007, 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 +** 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 +** 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 +** 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. */ --> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromYDelta="50%p" android:toYDelta="0" - android:duration="@android:integer/config_mediumAnimTime"/> - <alpha android:fromAlpha="0.0" android:toAlpha="1.0" - android:duration="@android:integer/config_mediumAnimTime" /> -</set> +<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator" + android:fromAlpha="1.0" + android:toAlpha="0.0" + android:duration="@android:integer/config_shortAnimTime" +/> diff --git a/core/res/res/anim/slide_in_top.xml b/core/res/res/anim/slide_in_top.xml deleted file mode 100644 index f4810ab..0000000 --- a/core/res/res/anim/slide_in_top.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/res/anim/slide_in_left.xml -** -** Copyright 2007, 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. -*/ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromYDelta="-50%p" android:toYDelta="0" - android:duration="@android:integer/config_mediumAnimTime"/> - <alpha android:fromAlpha="0.0" android:toAlpha="1.0" - android:duration="@android:integer/config_mediumAnimTime" /> -</set> diff --git a/core/res/res/anim/slide_out_bottom.xml b/core/res/res/anim/slide_out_bottom.xml deleted file mode 100644 index 8ddcd59..0000000 --- a/core/res/res/anim/slide_out_bottom.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/res/anim/slide_out_right.xml -** -** Copyright 2007, 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. -*/ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromYDelta="0" android:toYDelta="50%p" - android:duration="@android:integer/config_mediumAnimTime"/> - <alpha android:fromAlpha="1.0" android:toAlpha="0.0" - android:duration="@android:integer/config_mediumAnimTime" /> -</set> diff --git a/core/res/res/anim/slide_out_top.xml b/core/res/res/anim/slide_out_top.xml deleted file mode 100644 index 3134a57..0000000 --- a/core/res/res/anim/slide_out_top.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/res/anim/slide_out_left.xml -** -** Copyright 2007, 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. -*/ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromYDelta="0" android:toYDelta="-50%p" - android:duration="@android:integer/config_mediumAnimTime"/> - <alpha android:fromAlpha="1.0" android:toAlpha="0.0" - android:duration="@android:integer/config_mediumAnimTime" /> -</set> diff --git a/core/res/res/color/widget_edittext_dark_hint.xml b/core/res/res/color/widget_edittext_dark_hint.xml deleted file mode 100644 index 094025e..0000000 --- a/core/res/res/color/widget_edittext_dark_hint.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - - <item android:state_enabled="false" android:color="#A0A0A0"/> <!-- not enabled --> - <item android:color="#7c7c7c"/> - -</selector> - diff --git a/core/res/res/color/widget_textview_spinneritem_dark.xml b/core/res/res/color/widget_textview_spinneritem_dark.xml deleted file mode 100644 index d98fa46..0000000 --- a/core/res/res/color/widget_textview_spinneritem_dark.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2007 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_selected="true" android:color="#ff000000"/> - <item android:color="#ffffffff"/> <!-- unselected --> -</selector> diff --git a/core/res/res/drawable-land/statusbar_background.png b/core/res/res/drawable-land/statusbar_background.png Binary files differindex 2a351a5..ef61e52 100644 --- a/core/res/res/drawable-land/statusbar_background.png +++ b/core/res/res/drawable-land/statusbar_background.png diff --git a/core/res/res/drawable/blank_tile.png b/core/res/res/drawable/blank_tile.png Binary files differdeleted file mode 100644 index 63b9296..0000000 --- a/core/res/res/drawable/blank_tile.png +++ /dev/null diff --git a/core/res/res/drawable/boot_robot.png b/core/res/res/drawable/boot_robot.png Binary files differdeleted file mode 100644 index f4555af..0000000 --- a/core/res/res/drawable/boot_robot.png +++ /dev/null diff --git a/core/res/res/drawable/btn_circle_longpress.png b/core/res/res/drawable/btn_circle_longpress.png Binary files differdeleted file mode 100644 index f27d411..0000000 --- a/core/res/res/drawable/btn_circle_longpress.png +++ /dev/null diff --git a/core/res/res/drawable/btn_code_lock_default_trackball_pressed.png b/core/res/res/drawable/btn_code_lock_default_trackball_pressed.png Binary files differdeleted file mode 100755 index 0d3f094..0000000 --- a/core/res/res/drawable/btn_code_lock_default_trackball_pressed.png +++ /dev/null diff --git a/core/res/res/drawable/btn_star_big_buttonless_off.png b/core/res/res/drawable/btn_star_big_buttonless_off.png Binary files differdeleted file mode 100755 index 5b9cd81..0000000 --- a/core/res/res/drawable/btn_star_big_buttonless_off.png +++ /dev/null diff --git a/core/res/res/drawable/btn_star_big_buttonless_on.png b/core/res/res/drawable/btn_star_big_buttonless_on.png Binary files differdeleted file mode 100755 index 5957c65..0000000 --- a/core/res/res/drawable/btn_star_big_buttonless_on.png +++ /dev/null diff --git a/core/res/res/drawable/btn_star_buttonless.xml b/core/res/res/drawable/btn_star_buttonless.xml deleted file mode 100644 index 8d60ed2..0000000 --- a/core/res/res/drawable/btn_star_buttonless.xml +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_checked="false" android:state_window_focused="false" - android:drawable="@drawable/btn_star_big_buttonless_off" /> - <item android:state_checked="true" android:state_window_focused="false" - android:drawable="@drawable/btn_star_big_buttonless_on" /> -<!-- - <item android:state_checked="true" android:state_window_focused="false" - android:state_enabled="false" android:drawable="@drawable/btn_star_big_on_disable" /> - <item android:state_checked="false" android:state_window_focused="false" - android:state_enabled="false" android:drawable="@drawable/btn_star_big_off_disable" /> - - <item android:state_checked="true" android:state_pressed="true" - android:drawable="@drawable/btn_star_big_on_pressed" /> - <item android:state_checked="false" android:state_pressed="true" - android:drawable="@drawable/btn_star_big_off_pressed" /> - - <item android:state_checked="true" android:state_focused="true" - android:drawable="@drawable/btn_star_big_on_selected" /> - <item android:state_checked="false" android:state_focused="true" - android:drawable="@drawable/btn_star_big_off_selected" /> - - <item android:state_checked="true" android:state_focused="true" android:state_enabled="false" - android:drawable="@drawable/btn_star_big_on_disable_focused" /> - <item android:state_checked="true" android:state_focused="false" android:state_enabled="false" - android:drawable="@drawable/btn_star_big_on_disable" /> - - <item android:state_checked="false" android:state_focused="true" android:state_enabled="false" - android:drawable="@drawable/btn_star_big_off_disable_focused" /> - <item android:state_checked="false" android:state_focused="false" android:state_enabled="false" - android:drawable="@drawable/btn_star_big_off_disable" /> ---> - - <item android:state_checked="false" android:drawable="@drawable/btn_star_big_buttonless_off" /> - <item android:state_checked="true" android:drawable="@drawable/btn_star_big_buttonless_on" /> -</selector> diff --git a/core/res/res/drawable/btn_zoom_down_longpress.9.png b/core/res/res/drawable/btn_zoom_down_longpress.9.png Binary files differdeleted file mode 100644 index 09a3bb3..0000000 --- a/core/res/res/drawable/btn_zoom_down_longpress.9.png +++ /dev/null diff --git a/core/res/res/drawable/btn_zoom_up_longpress.9.png b/core/res/res/drawable/btn_zoom_up_longpress.9.png Binary files differdeleted file mode 100644 index 8de48d1..0000000 --- a/core/res/res/drawable/btn_zoom_up_longpress.9.png +++ /dev/null diff --git a/core/res/res/drawable/code_lock_left.9.png b/core/res/res/drawable/code_lock_left.9.png Binary files differindex a53264a..215dcc8 100644 --- a/core/res/res/drawable/code_lock_left.9.png +++ b/core/res/res/drawable/code_lock_left.9.png diff --git a/core/res/res/drawable/expander_ic_maximized.9.png b/core/res/res/drawable/expander_ic_maximized.9.png Binary files differindex bad4b82..eb461e9 100644 --- a/core/res/res/drawable/expander_ic_maximized.9.png +++ b/core/res/res/drawable/expander_ic_maximized.9.png diff --git a/core/res/res/drawable/expander_ic_minimized.9.png b/core/res/res/drawable/expander_ic_minimized.9.png Binary files differindex af89072..e3cec8d 100644 --- a/core/res/res/drawable/expander_ic_minimized.9.png +++ b/core/res/res/drawable/expander_ic_minimized.9.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_disabled.png b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_disabled.png Binary files differindex 326397c..914662d 100644 --- a/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_disabled.png +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_disabled.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_normal.png b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_normal.png Binary files differindex 5583401..3b67c6d 100644 --- a/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_normal.png +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_normal.png diff --git a/core/res/res/color/widget_button.xml b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml index 66f37cb..2db3203 100644 --- a/core/res/res/color/widget_button.xml +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml @@ -15,6 +15,6 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_focused="true" android:color="#ff000000"/> - <item android:color="#ff000000"/> <!-- unfocused --> -</selector> + <item android:state_enabled="false" android:drawable="@drawable/ic_btn_square_browser_zoom_page_overview_disabled" /> + <item android:drawable="@drawable/ic_btn_square_browser_zoom_page_overview_normal" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png Binary files differnew file mode 100644 index 0000000..859900a --- /dev/null +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_normal.png Binary files differindex 4e8ff35..4e8ff35 100644 --- a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_normal.png diff --git a/core/res/res/drawable/ic_emergency.png b/core/res/res/drawable/ic_emergency.png Binary files differindex d99abf8..45d0f21 100755 --- a/core/res/res/drawable/ic_emergency.png +++ b/core/res/res/drawable/ic_emergency.png diff --git a/core/res/res/drawable/ic_settings_indicator_next_page.png b/core/res/res/drawable/ic_settings_indicator_next_page.png Binary files differdeleted file mode 100755 index c30e6e4..0000000 --- a/core/res/res/drawable/ic_settings_indicator_next_page.png +++ /dev/null diff --git a/core/res/res/drawable/keyboard_suggest_strip_shadow.9.png b/core/res/res/drawable/keyboard_suggest_strip_shadow.9.png Binary files differdeleted file mode 100644 index d231ae6..0000000 --- a/core/res/res/drawable/keyboard_suggest_strip_shadow.9.png +++ /dev/null diff --git a/core/res/res/drawable/loading_tile.png b/core/res/res/drawable/loading_tile.png Binary files differdeleted file mode 100644 index f5a80c9..0000000 --- a/core/res/res/drawable/loading_tile.png +++ /dev/null diff --git a/core/res/res/drawable/no_tile_128.png b/core/res/res/drawable/no_tile_128.png Binary files differdeleted file mode 100644 index a9b007d..0000000 --- a/core/res/res/drawable/no_tile_128.png +++ /dev/null diff --git a/core/res/res/drawable/padlock.png b/core/res/res/drawable/padlock.png Binary files differdeleted file mode 100644 index 558340b..0000000 --- a/core/res/res/drawable/padlock.png +++ /dev/null diff --git a/core/res/res/drawable/panel_separator.9.png b/core/res/res/drawable/panel_separator.9.png Binary files differdeleted file mode 100644 index 0c07bf8..0000000 --- a/core/res/res/drawable/panel_separator.9.png +++ /dev/null diff --git a/core/res/res/drawable/progress_circular_indeterminate_small.png b/core/res/res/drawable/progress_circular_indeterminate_small.png Binary files differdeleted file mode 100644 index 15418cb..0000000 --- a/core/res/res/drawable/progress_circular_indeterminate_small.png +++ /dev/null diff --git a/core/res/res/drawable/scrollbar_vertical.9.png b/core/res/res/drawable/scrollbar_vertical.9.png Binary files differdeleted file mode 100755 index 08f5ca9..0000000 --- a/core/res/res/drawable/scrollbar_vertical.9.png +++ /dev/null diff --git a/core/res/res/drawable/status_bar_background.9.png b/core/res/res/drawable/status_bar_background.9.png Binary files differdeleted file mode 100644 index fd754a8..0000000 --- a/core/res/res/drawable/status_bar_background.9.png +++ /dev/null diff --git a/core/res/res/drawable/scrollbar_horizontal.9.png b/core/res/res/drawable/status_bar_background.png Binary files differindex 40faa82..cd11166 100644 --- a/core/res/res/drawable/scrollbar_horizontal.9.png +++ b/core/res/res/drawable/status_bar_background.png diff --git a/core/res/res/drawable/status_bar_close_on.9.png b/core/res/res/drawable/status_bar_close_on.9.png Binary files differindex e91e4fa..9cbd9fe 100644 --- a/core/res/res/drawable/status_bar_close_on.9.png +++ b/core/res/res/drawable/status_bar_close_on.9.png diff --git a/core/res/res/drawable/status_bar_divider_shadow.9.png b/core/res/res/drawable/status_bar_header_background.9.png Binary files differindex ad58dbe..fa9a90c 100644 --- a/core/res/res/drawable/status_bar_divider_shadow.9.png +++ b/core/res/res/drawable/status_bar_header_background.9.png diff --git a/core/res/res/drawable/status_bar_item_background_normal.9.png b/core/res/res/drawable/status_bar_item_background_normal.9.png Binary files differindex 6b76740..b8e399d 100644 --- a/core/res/res/drawable/status_bar_item_background_normal.9.png +++ b/core/res/res/drawable/status_bar_item_background_normal.9.png diff --git a/core/res/res/drawable/statusbar_background.png b/core/res/res/drawable/statusbar_background.png Binary files differindex 2d8aa7a..204d76a 100644 --- a/core/res/res/drawable/statusbar_background.png +++ b/core/res/res/drawable/statusbar_background.png diff --git a/core/res/res/drawable/timepicker_down_disabled.9.png b/core/res/res/drawable/timepicker_down_disabled.9.png Binary files differindex 7d8e0b9..596294b 100755 --- a/core/res/res/drawable/timepicker_down_disabled.9.png +++ b/core/res/res/drawable/timepicker_down_disabled.9.png diff --git a/core/res/res/drawable/timepicker_down_disabled_focused.9.png b/core/res/res/drawable/timepicker_down_disabled_focused.9.png Binary files differindex 6f2373e..662cffd 100755 --- a/core/res/res/drawable/timepicker_down_disabled_focused.9.png +++ b/core/res/res/drawable/timepicker_down_disabled_focused.9.png diff --git a/core/res/res/drawable/timepicker_down_normal.9.png b/core/res/res/drawable/timepicker_down_normal.9.png Binary files differindex a946355..f17e8f9 100755 --- a/core/res/res/drawable/timepicker_down_normal.9.png +++ b/core/res/res/drawable/timepicker_down_normal.9.png diff --git a/core/res/res/drawable/timepicker_down_pressed.9.png b/core/res/res/drawable/timepicker_down_pressed.9.png Binary files differindex fb4d817..777bcf5 100755 --- a/core/res/res/drawable/timepicker_down_pressed.9.png +++ b/core/res/res/drawable/timepicker_down_pressed.9.png diff --git a/core/res/res/drawable/timepicker_down_selected.9.png b/core/res/res/drawable/timepicker_down_selected.9.png Binary files differindex 1db8bc1..b45db62 100755 --- a/core/res/res/drawable/timepicker_down_selected.9.png +++ b/core/res/res/drawable/timepicker_down_selected.9.png diff --git a/core/res/res/drawable/timepicker_up_disabled.9.png b/core/res/res/drawable/timepicker_up_disabled.9.png Binary files differindex 93d0db4..327b0b5 100755 --- a/core/res/res/drawable/timepicker_up_disabled.9.png +++ b/core/res/res/drawable/timepicker_up_disabled.9.png diff --git a/core/res/res/drawable/timepicker_up_disabled_focused.9.png b/core/res/res/drawable/timepicker_up_disabled_focused.9.png Binary files differindex b5bf68d..4c96680 100755 --- a/core/res/res/drawable/timepicker_up_disabled_focused.9.png +++ b/core/res/res/drawable/timepicker_up_disabled_focused.9.png diff --git a/core/res/res/drawable/timepicker_up_normal.9.png b/core/res/res/drawable/timepicker_up_normal.9.png Binary files differindex 978251d..dcd26e0 100755 --- a/core/res/res/drawable/timepicker_up_normal.9.png +++ b/core/res/res/drawable/timepicker_up_normal.9.png diff --git a/core/res/res/drawable/timepicker_up_pressed.9.png b/core/res/res/drawable/timepicker_up_pressed.9.png Binary files differindex 924b03c..7dac778 100755 --- a/core/res/res/drawable/timepicker_up_pressed.9.png +++ b/core/res/res/drawable/timepicker_up_pressed.9.png diff --git a/core/res/res/drawable/timepicker_up_selected.9.png b/core/res/res/drawable/timepicker_up_selected.9.png Binary files differindex 5c94d0d..35dae8e 100755 --- a/core/res/res/drawable/timepicker_up_selected.9.png +++ b/core/res/res/drawable/timepicker_up_selected.9.png diff --git a/core/res/res/drawable/title_bar_portrait.9.png b/core/res/res/drawable/title_bar_portrait.9.png Binary files differnew file mode 100644 index 0000000..482d82e --- /dev/null +++ b/core/res/res/drawable/title_bar_portrait.9.png diff --git a/core/res/res/layout/alert_dialog_simple_text.xml b/core/res/res/layout/alert_dialog_simple_text.xml deleted file mode 100644 index ab82be7..0000000 --- a/core/res/res/layout/alert_dialog_simple_text.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2009 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. ---> - -<!-- This layout can be set as the AlertDialog's view to display vertically centered text. --> -<TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/text1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:padding="10dip" - /> - - diff --git a/core/res/res/layout/always_use_checkbox.xml b/core/res/res/layout/always_use_checkbox.xml index 20fc403..1f8d256 100644 --- a/core/res/res/layout/always_use_checkbox.xml +++ b/core/res/res/layout/always_use_checkbox.xml @@ -16,18 +16,18 @@ <!-- Check box that is displayed in the activity resolver UI for the user to make their selection the preferred activity. --> -<RelativeLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="14dip" - android:paddingRight="15dip"> + android:paddingRight="15dip" + android:orientation="vertical"> <CheckBox android:id="@+id/alwaysUse" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" android:focusable="true" android:clickable="true" /> @@ -38,6 +38,5 @@ android:textAppearance="?android:attr/textAppearanceSmall" android:paddingLeft="36dip" android:visibility="gone" - android:layout_below="@id/alwaysUse" android:text="@string/clearDefaultHintMsg" /> -</RelativeLayout> +</LinearLayout> diff --git a/core/res/res/layout/input_method.xml b/core/res/res/layout/input_method.xml index a21bbe8..1a701e9 100644 --- a/core/res/res/layout/input_method.xml +++ b/core/res/res/layout/input_method.xml @@ -25,19 +25,28 @@ android:orientation="vertical" > - <FrameLayout android:id="@android:id/extractArea" - android:layout_width="fill_parent" - android:layout_height="0px" - android:layout_weight="1" - android:visibility="gone"> - </FrameLayout> - - <FrameLayout android:id="@android:id/candidatesArea" + <LinearLayout + android:id="@+id/fullscreenArea" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:visibility="invisible"> - </FrameLayout> - + android:orientation="vertical" + > + + <FrameLayout android:id="@android:id/extractArea" + android:layout_width="fill_parent" + android:layout_height="0px" + android:layout_weight="1" + android:visibility="gone"> + </FrameLayout> + + <FrameLayout android:id="@android:id/candidatesArea" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:visibility="invisible"> + </FrameLayout> + + </LinearLayout> + <FrameLayout android:id="@android:id/inputArea" android:layout_width="fill_parent" android:layout_height="wrap_content" diff --git a/core/res/res/layout/keyboard_popup_keyboard.xml b/core/res/res/layout/keyboard_popup_keyboard.xml index 0cdd9da..1092cc0 100644 --- a/core/res/res/layout/keyboard_popup_keyboard.xml +++ b/core/res/res/layout/keyboard_popup_keyboard.xml @@ -35,7 +35,7 @@ android:popupLayout="@layout/keyboard_popup_keyboard" android:keyTextSize="22sp" /> - <ImageButton android:id="@android:id/button_close" + <ImageButton android:id="@android:id/closeButton" android:background="@android:color/transparent" android:src="@drawable/btn_close" android:layout_width="wrap_content" diff --git a/core/res/res/layout/keyguard_screen_glogin_unlock.xml b/core/res/res/layout/keyguard_screen_glogin_unlock.xml index 4834b28..74ff3b0 100644 --- a/core/res/res/layout/keyguard_screen_glogin_unlock.xml +++ b/core/res/res/layout/keyguard_screen_glogin_unlock.xml @@ -120,7 +120,7 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" android:text="@android:string/lockscreen_emergency_call" /> diff --git a/core/res/res/layout/keyguard_screen_lock.xml b/core/res/res/layout/keyguard_screen_lock.xml index 952fc5d..b5fbace 100644 --- a/core/res/res/layout/keyguard_screen_lock.xml +++ b/core/res/res/layout/keyguard_screen_lock.xml @@ -211,7 +211,7 @@ android:layout_marginTop="5dip" android:layout_gravity="center_horizontal" android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" android:text="@android:string/lockscreen_emergency_call" /> diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml index 881652b..4c583d8 100644 --- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml +++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml @@ -87,12 +87,7 @@ android:layout_weight="1.0" android:layout_marginBottom="8dip" android:layout_marginRight="8dip" - android:paddingLeft="4dip" - android:paddingRight="4dip" - android:paddingTop="8dip" - android:paddingBottom="8dip" android:textSize="18sp" - android:drawablePadding="3dip" /> <Button android:id="@+id/emergencyCall" @@ -104,13 +99,9 @@ android:layout_weight="1.0" android:layout_marginBottom="8dip" android:layout_marginLeft="8dip" - android:paddingLeft="4dip" - android:paddingRight="4dip" - android:paddingTop="8dip" - android:paddingBottom="8dip" android:textSize="18sp" android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" /> </LinearLayout> diff --git a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml index fc82e3f..ac404f2 100644 --- a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml +++ b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml @@ -76,6 +76,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/topDisplayGroup" + android:layout_marginTop="10dip" android:orientation="vertical" > @@ -249,7 +250,7 @@ android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:drawableLeft="@android:drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" android:text="@android:string/lockscreen_emergency_call" /> diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml index ba1640a..929d0a2 100644 --- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml +++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml @@ -85,7 +85,7 @@ android:text="@android:string/lockscreen_emergency_call" android:textSize="14sp" android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" /> </RelativeLayout> @@ -108,16 +108,16 @@ android:text="@android:string/lockscreen_emergency_call" android:textSize="14sp" android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" /> </LinearLayout> </FrameLayout> </LinearLayout> - <!--View + <View android:background="@android:drawable/code_lock_left" android:layout_width="2dip" - android:layout_height="fill_parent" /--> + android:layout_height="fill_parent" /> <!-- right side: lock pattern --> <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern" diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml index f09c422..a6c31b6 100644 --- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml +++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml @@ -53,18 +53,18 @@ android:textSize="18sp"/> </LinearLayout> - <!--View + <View android:background="@android:drawable/code_lock_top" android:layout_width="fill_parent" - android:layout_height="2dip" /--> + android:layout_height="2dip" /> <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern" android:layout_width="wrap_content" android:layout_height="wrap_content" /> - <!--View + <View android:background="@android:drawable/code_lock_bottom" android:layout_width="fill_parent" - android:layout_height="8dip" /--> + android:layout_height="8dip" /> <!-- footer --> <FrameLayout @@ -85,7 +85,7 @@ android:text="@android:string/lockscreen_emergency_call" android:textSize="14sp" android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" /> </RelativeLayout> @@ -108,7 +108,7 @@ android:text="@android:string/lockscreen_emergency_call" android:textSize="14sp" android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="3dip" + android:drawablePadding="8dip" /> <Button android:id="@+id/forgotPattern" android:layout_width="0dip" diff --git a/core/res/res/layout/menu_item_divider.xml b/core/res/res/layout/menu_item_divider.xml deleted file mode 100644 index 042662f..0000000 --- a/core/res/res/layout/menu_item_divider.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/assets/res/any/layout/menu_item.xml -** -** Copyright 2006, 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. -*/ ---> -<Divider xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/separator" - android:paddingLeft="0dip" android:paddingTop="4dip" - android:paddingRight="0dip" android:paddingBottom="4dip" - android:src="@drawable/menu_separator" - android:layout_width="fill_parent" - android:layout_height="wrap_content"/> diff --git a/core/res/res/layout/number_picker_edit.xml b/core/res/res/layout/number_picker_edit.xml deleted file mode 100644 index f3af6e9..0000000 --- a/core/res/res/layout/number_picker_edit.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?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. -*/ ---> - -<EditText xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:gravity="center_horizontal" - android:singleLine="true" - style="?android:attr/textAppearanceLargeInverse" - android:textColor="@android:color/primary_text_light" - android:textSize="30sp" - android:background="@drawable/timepicker_input" - /> diff --git a/core/res/res/layout/popup_menu_layout.xml b/core/res/res/layout/popup_menu_layout.xml deleted file mode 100644 index 1e8083a..0000000 --- a/core/res/res/layout/popup_menu_layout.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2007 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. ---> - -<PopupMenuView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="320sp" - android:layout_height="wrap_content" - android:orientation="vertical" - android:padding="0sp"> - - <LinearLayout - android:id="@+id/header" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" /> - - <ListView - android:id="@+id/listview" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_weight="1" /> - -</PopupMenuView> diff --git a/core/res/res/layout/screen_simple.xml b/core/res/res/layout/screen_simple.xml index 62e737a..df511c6 100644 --- a/core/res/res/layout/screen_simple.xml +++ b/core/res/res/layout/screen_simple.xml @@ -22,7 +22,8 @@ enabled. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/content" - android:fitsSystemWindows="true"> -</FrameLayout> - + android:id="@android:id/content" + android:fitsSystemWindows="true" + android:foregroundInsidePadding="false" + android:foregroundGravity="fill_horizontal|top" + android:foreground="?android:attr/windowContentOverlay" />
\ No newline at end of file diff --git a/core/res/res/layout/select_dialog.xml b/core/res/res/layout/select_dialog.xml index 8e48ae2..249b527 100644 --- a/core/res/res/layout/select_dialog.xml +++ b/core/res/res/layout/select_dialog.xml @@ -23,7 +23,8 @@ This layout file is inflated and used as the ListView to display the items. Assign an ID so its state will be saved/restored. --> -<ListView xmlns:android="http://schemas.android.com/apk/res/android" +<view class="com.android.internal.app.AlertController$RecycleListView" + xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+android:id/select_dialog_listview" android:layout_width="fill_parent" android:layout_height="fill_parent" diff --git a/core/res/res/layout/setting_list_category.xml b/core/res/res/layout/setting_list_category.xml deleted file mode 100644 index e605d17..0000000 --- a/core/res/res/layout/setting_list_category.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2007 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. ---> - -<!-- List item layout for an unexpanded category --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingLeft="32dip" - android:paddingBottom="5dip" - android:paddingTop="5dip"> - - <TextView - android:id="@+id/category_name" - android:textStyle="bold" - android:layout_width="fill_parent" - android:layout_height="wrap_content" /> - - <TextView - android:id="@+id/category_description" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:lines="1" - android:textColor="@color/darker_gray" /> - -</LinearLayout> diff --git a/core/res/res/layout/setting_list_expanded_category.xml b/core/res/res/layout/setting_list_expanded_category.xml deleted file mode 100644 index 64de0e6..0000000 --- a/core/res/res/layout/setting_list_expanded_category.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2007 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. ---> - -<!-- List item layout for an expanded category --> -<TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/category_name" - android:textStyle="bold" - android:paddingLeft="32dip" - android:paddingBottom="5dip" - android:paddingTop="5dip"/> diff --git a/core/res/res/layout/setting_list_setting.xml b/core/res/res/layout/setting_list_setting.xml deleted file mode 100644 index 6b7d254..0000000 --- a/core/res/res/layout/setting_list_setting.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2007 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. ---> - -<!-- List item layout for a setting --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingLeft="48dip" - android:paddingTop="3dip" - android:paddingBottom="3dip" - android:orientation="vertical"> - - <TextView - android:id="@+id/setting_name" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textColor="@color/lighter_gray" /> - - <LinearLayout - android:id="@+id/setting_value_layout" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingLeft="10dip" /> - -</LinearLayout> diff --git a/core/res/res/layout/setting_list_setting_value_text.xml b/core/res/res/layout/setting_list_setting_value_text.xml deleted file mode 100644 index 621298e..0000000 --- a/core/res/res/layout/setting_list_setting_value_text.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2007 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. ---> - -<!-- Template for the generic static text in a setting's value --> -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/setting_value_text" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textColor="@color/darker_gray" /> diff --git a/core/res/res/layout/status_bar.xml b/core/res/res/layout/status_bar.xml index 9a6b7e8..0bc0dac 100644 --- a/core/res/res/layout/status_bar.xml +++ b/core/res/res/layout/status_bar.xml @@ -97,7 +97,7 @@ android:gravity="center_vertical|left" android:paddingLeft="6px" android:paddingRight="6px" - android:textColor="#ff000000" + android:textColor="?android:attr/textColorPrimaryInverse" android:background="@drawable/statusbar_background" /> </com.android.server.status.StatusBarView> diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml index a6a188e..fd9d26e 100644 --- a/core/res/res/layout/status_bar_expanded.xml +++ b/core/res/res/layout/status_bar_expanded.xml @@ -31,12 +31,13 @@ android:paddingTop="3dp" android:paddingBottom="5dp" android:paddingRight="3dp" - android:background="@drawable/status_bar_divider_shadow" + android:background="@drawable/status_bar_header_background" > <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" + android:layout_marginTop="1dp" android:layout_marginLeft="5dp" android:layout_gravity="center_vertical" android:paddingBottom="1dp" @@ -46,86 +47,99 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:textSize="18sp" - android:textStyle="bold" - android:textColor="#ff000000" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="?android:attr/textColorSecondaryInverse" + android:paddingLeft="4dp" /> <TextView android:id="@+id/spnLabel" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="18sp" - android:textStyle="bold" - android:textColor="#ff000000" - android:paddingBottom="1dp" + android:layout_gravity="center_vertical" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="?android:attr/textColorSecondaryInverse" + android:paddingLeft="4dp" /> </LinearLayout> <TextView android:id="@+id/clear_all_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" + android:layout_marginTop="4dp" + android:layout_marginBottom="1dp" android:textSize="14sp" android:textColor="#ff000000" android:text="@string/status_bar_clear_all_button" style="?android:attr/buttonStyle" + android:paddingLeft="15dp" + android:paddingRight="15dp" + android:background="@drawable/btn_default_small" /> </LinearLayout> - - <!-- This view has the same background as the tracking view. Normally it isn't shown, - except in the case where our copy of the close button is visible. That button is - translucent. Even though it moves up and down, it's only visible when it's aligned - at the bottom. - --> - <ScrollView - android:id="@+id/scroll" - android:layout_width="fill_parent" + <FrameLayout + android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_weight="1" > - <com.android.server.status.NotificationLinearLayout - android:id="@+id/notificationLinearLayout" + <ScrollView + android:id="@+id/scroll" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" - android:orientation="vertical" + android:fadingEdge="none" > - - <TextView android:id="@+id/noNotificationsTitle" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="#ff888888" - android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" - android:text="@string/status_bar_no_notifications_title" - /> - - <TextView android:id="@+id/ongoingTitle" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="#ff888888" - android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" - android:text="@string/status_bar_ongoing_events_title" - /> - <LinearLayout android:id="@+id/ongoingItems" + <com.android.server.status.NotificationLinearLayout + android:id="@+id/notificationLinearLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_weight="1" android:orientation="vertical" - /> + > + + <TextView android:id="@+id/noNotificationsTitle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="@drawable/title_bar_portrait" + android:paddingLeft="5dp" + android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:text="@string/status_bar_no_notifications_title" + /> - <TextView android:id="@+id/latestTitle" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="#ff888888" - android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" - android:text="@string/status_bar_latest_events_title" - /> - <LinearLayout android:id="@+id/latestItems" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - /> - </com.android.server.status.NotificationLinearLayout> - </ScrollView> + <TextView android:id="@+id/ongoingTitle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="@drawable/title_bar_portrait" + android:paddingLeft="5dp" + android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:text="@string/status_bar_ongoing_events_title" + /> + <LinearLayout android:id="@+id/ongoingItems" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + /> + + <TextView android:id="@+id/latestTitle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="@drawable/title_bar_portrait" + android:paddingLeft="5dp" + android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:text="@string/status_bar_latest_events_title" + /> + <LinearLayout android:id="@+id/latestItems" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + /> + </com.android.server.status.NotificationLinearLayout> + </ScrollView> + + <ImageView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:src="@drawable/title_bar_shadow" + android:scaleType="fitXY" + /> + + </FrameLayout> </com.android.server.status.ExpandedView> diff --git a/core/res/res/layout/status_bar_tracking.xml b/core/res/res/layout/status_bar_tracking.xml index 661ce86..aa3b733 100644 --- a/core/res/res/layout/status_bar_tracking.xml +++ b/core/res/res/layout/status_bar_tracking.xml @@ -20,13 +20,12 @@ android:visibility="gone" android:focusable="true" android:descendantFocusability="afterDescendants" - android:background="@drawable/status_bar_background" android:paddingBottom="0px" android:paddingLeft="0px" android:paddingRight="0px" > - <View + <com.android.server.status.TrackingPatternView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" @@ -37,11 +36,6 @@ android:layout_height="wrap_content" android:orientation="vertical" > - - <View - android:layout_width="fill_parent" - android:layout_height="5dp" - /> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" diff --git a/core/res/res/layout/submenu_item.xml b/core/res/res/layout/submenu_item.xml deleted file mode 100644 index 3ec474a..0000000 --- a/core/res/res/layout/submenu_item.xml +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/assets/res/any/layout/menu_item.xml -** -** Copyright 2006, 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. -*/ ---> -<MenuItemView xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:focusable="true"> - - <TextView android:id="@+id/index" - android:paddingLeft="0dip" android:paddingTop="1dip" - android:paddingRight="8dip" android:paddingBottom="0dip" - android:layout_width="17dip" android:layout_height="wrap_content" - android:includeFontPadding="false" /> - - <ImageView android:id="@+id/check" - android:paddingLeft="3dip" android:paddingTop="3dip" - android:paddingRight="3dip" android:paddingBottom="0dip" - android:src="@drawable/menuitem_checkbox" android:scaleType="fitCenter" - android:layout_width="wrap_content" android:layout_height="wrap_content" /> - - <TextView android:id="@+id/title" - android:paddingLeft="0dip" android:paddingTop="1dip" - android:paddingRight="0dip" android:paddingBottom="2dip" - android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_weight="1" android:includeFontPadding="false"/> - - <ImageView android:id="@+id/arrow" - android:paddingLeft="8dip" android:paddingTop="3dip" - android:paddingRight="0dip" android:paddingBottom="0dip" - android:src="@drawable/submenu_arrow" android:scaleType="fitCenter" - android:layout_width="wrap_content" android:layout_height="wrap_content" /> - -</MenuItemView> - diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml index c601e0e..6ba5e81 100644 --- a/core/res/res/layout/time_picker.xml +++ b/core/res/res/layout/time_picker.xml @@ -49,10 +49,8 @@ android:id="@+id/amPm" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="46dip" + android:layout_marginTop="43dip" android:layout_marginLeft="5dip" - android:paddingTop="2dip" - android:paddingBottom="2dip" android:paddingLeft="20dip" android:paddingRight="20dip" style="?android:attr/textAppearanceLargeInverse" diff --git a/core/res/res/values-ar-rEG/arrays.xml b/core/res/res/values-ar-rEG/arrays.xml new file mode 100644 index 0000000..1180cb3 --- /dev/null +++ b/core/res/res/values-ar-rEG/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>26820553</item> + <item>30802498</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-ar-rIL/arrays.xml b/core/res/res/values-ar-rIL/arrays.xml new file mode 100644 index 0000000..87c1231 --- /dev/null +++ b/core/res/res/values-ar-rIL/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>31046051</item> + <item>34851612</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-bg-rBG/arrays.xml b/core/res/res/values-bg-rBG/arrays.xml new file mode 100644 index 0000000..3cfcbfd --- /dev/null +++ b/core/res/res/values-bg-rBG/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>42733883</item> + <item>25485830</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-ca-rES/arrays.xml b/core/res/res/values-ca-rES/arrays.xml new file mode 100644 index 0000000..7f5667c --- /dev/null +++ b/core/res/res/values-ca-rES/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>40413496</item> + <item>-3713379</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>6</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-cs-rCZ/arrays.xml b/core/res/res/values-cs-rCZ/arrays.xml new file mode 100644 index 0000000..484c9b3 --- /dev/null +++ b/core/res/res/values-cs-rCZ/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>50083333</item> + <item>14416667</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 13aca371..b3fca3e 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Ve výchozÃm nastavenà nenà identifikace volajÃcÃho omezena. PÅ™ÃÅ¡tà hovor: Neomezeno"</string> <string name="serviceNotProvisioned">"Služba nenà zÅ™Ãzena."</string> <string name="CLIRPermanent">"Nelze zmÄ›nit nastavenà identifikace volajÃcÃho."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Hlas"</string> <string name="serviceClassData">"Data"</string> <string name="serviceClassFAX">"FAX"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Tichý režim"</string> <string name="global_action_silent_mode_on_status">"Zvuk je VYPNUTÃ."</string> <string name="global_action_silent_mode_off_status">"Zvuk je zapnutý"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Režim V letadle"</string> + <string name="global_actions_airplane_mode_on_status">"Režim V letadle je ZAPNUTÃ"</string> + <string name="global_actions_airplane_mode_off_status">"Režim V letadle je VYPNUTÃ"</string> <string name="safeMode">"Nouzový režim"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Systém Android"</string> <string name="permgrouplab_costMoney">"ZpoplatnÄ›né služby"</string> <string name="permgroupdesc_costMoney">"Umožňuje aplikacÃm provádÄ›t Äinnosti, které vás mohou stát penÃze."</string> <string name="permgrouplab_messages">"VaÅ¡e zprávy"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Umožňuje povolit Äi zakázat aktualizace polohy prostÅ™ednictvÃm bezdrátového pÅ™ipojenÃ. Aplikace toto nastavenà obvykle nepoužÃvajÃ."</string> <string name="permlab_checkinProperties">"pÅ™Ãstup k vlastnostem Checkin"</string> <string name="permdesc_checkinProperties">"Umožňuje Ätenà i zápis vlastnostà nahraných službou Checkin. Běžné aplikace toto nastavenà obvykle nevyužÃvajÃ."</string> - <string name="permlab_bindGadget">"zvolit gadgety"</string> - <string name="permdesc_bindGadget">"Umožňuje aplikaci sdÄ›lit systému, které aplikace mohou použÃt které gadgety. Aplikace s tÃmto oprávnÄ›nÃm mohou zpÅ™Ãstupnit osobnà údaje jiným aplikacÃm. Nenà urÄeno pro normálnà aplikace."</string> + <string name="permlab_bindGadget">"zvolit widgety"</string> + <string name="permdesc_bindGadget">"Umožňuje aplikaci sdÄ›lit systému, které aplikace mohou použÃvat které widgety. Aplikace s tÃmto oprávnÄ›nÃm mohou zpÅ™Ãstupnit osobnà údaje jiným aplikacÃm. Nenà urÄeno pro běžné aplikace."</string> <string name="permlab_modifyPhoneState">"zmÄ›ny stavu telefonu"</string> <string name="permdesc_modifyPhoneState">"Umožňuje aplikaci ovládat telefonnà funkce zaÅ™ÃzenÃ. Aplikace s tÃmto oprávnÄ›nÃm může pÅ™epÃnat sÃtÄ› nebo zapnout Äi vypnout bezdrátové pÅ™ipojenà telefonu bez vaÅ¡eho svolenÃ."</string> <string name="permlab_readPhoneState">"zjistit stav telefonu"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"TÃsňové volánÃ"</string> <string name="lockscreen_pattern_correct">"SprávnÄ›!"</string> <string name="lockscreen_pattern_wrong">"Zkuste to prosÃm znovu"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"NabÃjenà (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"PÅ™ipojte dobÃjecà zaÅ™ÃzenÃ."</string> <string name="lockscreen_missing_sim_message_short">"Nenà vložena SIM karta."</string> <string name="lockscreen_missing_sim_message">"V telefonu nenà žádná karta SIM."</string> <string name="lockscreen_missing_sim_instructions">"ProsÃm vložte kartu SIM."</string> <string name="lockscreen_network_locked_message">"SÃÅ¥ je blokována"</string> <string name="lockscreen_sim_puk_locked_message">"Karta SIM je zablokována pomocà kódu PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"ProsÃm kontaktujte podporu zákaznÃků."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"Karta SIM je zablokována."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Odblokovánà karty SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"<xliff:g id="NUMBER_0">%d</xliff:g>krát jste nakreslili nesprávné bezpeÄnostnà gesto. "\n\n"Opakujte prosÃm akci za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Sekundy zbývajÃcà do dalÅ¡Ãho pokusu: <xliff:g id="NUMBER">%d</xliff:g>."</string> <string name="lockscreen_forgot_pattern_button_text">"ZapomnÄ›li jste gesto?"</string> <string name="lockscreen_glogin_too_many_attempts">"Gesta: PÅ™ÃliÅ¡ mnoho pokusů"</string> - <string name="lockscreen_glogin_instructions">"Chcete-li telefon odemknout,"\n"pÅ™ihlaste se pomocà svého úÄtu Google"</string> + <string name="lockscreen_glogin_instructions">"Chcete-li telefon odemknout, pÅ™ihlaste se pomocà svého úÄtu Google"</string> <string name="lockscreen_glogin_username_hint">"Uživatelské jméno (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"Heslo"</string> <string name="lockscreen_glogin_submit_button">"PÅ™ihlásit se"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Vymazat oznámenÃ"</string> <string name="status_bar_no_notifications_title">"Žádná oznámenÃ"</string> <string name="status_bar_ongoing_events_title">"ProbÃhajÃcÃ"</string> <string name="status_bar_latest_events_title">"OznámenÃ"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"NabÃjenÃ..."</string> <string name="battery_low_title">"ProsÃm pÅ™ipojte dobÃjecà zaÅ™ÃzenÃ"</string> <string name="battery_low_subtitle">"Baterie je vybitá:"</string> @@ -552,6 +555,7 @@ <string name="monthly">"MÄ›sÃÄnÄ›"</string> <string name="yearly">"RoÄnÄ›"</string> <string name="VideoView_error_title">"Video nelze pÅ™ehrát"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Omlouváme se, ale toto video nelze pÅ™enášet datovým proudem do tohoto zaÅ™ÃzenÃ."</string> <string name="VideoView_error_text_unknown">"Toto video bohužel nelze pÅ™ehrát."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"dop."</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"poledne"</string> <string name="Noon">"Poledne"</string> <string name="midnight">"půlnoc"</string> <string name="Midnight">"Půlnoc"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"nedÄ›le"</string> <string name="day_of_week_long_monday">"pondÄ›lÃ"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"Nebyly nalezeny žádné odpovÃdajÃcà aktivity."</string> <string name="permlab_pkgUsageStats">"aktualizovat statistiku použità souÄástÃ"</string> <string name="permdesc_pkgUsageStats">"Umožňuje zmÄ›nu shromáždÄ›ných statistických údajů o použità souÄástÃ. Nenà urÄeno pro běžné aplikace."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"PoklepánÃm můžete ovládat pÅ™iblÞenÃ"</string> + <string name="gadget_host_error_inflating">"Chyba pÅ™i spouÅ¡tÄ›nà widgetu"</string> + <string name="ime_action_go">"PÅ™ejÃt"</string> + <string name="ime_action_search">"Hledat"</string> + <string name="ime_action_send">"Odeslat"</string> + <string name="ime_action_next">"DalÅ¡Ã"</string> + <string name="ime_action_done">"Hotovo"</string> + <string name="ime_action_default">"Spustit"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-da-rDK/arrays.xml b/core/res/res/values-da-rDK/arrays.xml new file mode 100644 index 0000000..4d0abd0 --- /dev/null +++ b/core/res/res/values-da-rDK/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>55679423</item> + <item>12577114</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-de-rAT/arrays.xml b/core/res/res/values-de-rAT/arrays.xml new file mode 100644 index 0000000..e8855cf --- /dev/null +++ b/core/res/res/values-de-rAT/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>48209206</item> + <item>16372778</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-de-rCH/arrays.xml b/core/res/res/values-de-rCH/arrays.xml new file mode 100644 index 0000000..f2982e9 --- /dev/null +++ b/core/res/res/values-de-rCH/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>46948020</item> + <item>7448206</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-de-rDE/arrays.xml b/core/res/res/values-de-rDE/arrays.xml new file mode 100644 index 0000000..3680fd3 --- /dev/null +++ b/core/res/res/values-de-rDE/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>55679423</item> + <item>9735672</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-de-rLI/arrays.xml b/core/res/res/values-de-rLI/arrays.xml new file mode 100644 index 0000000..0481b76 --- /dev/null +++ b/core/res/res/values-de-rLI/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>47141076</item> + <item>9521482</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index cda8cbc..54e8864 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Nicht beschränkt"</string> <string name="serviceNotProvisioned">"Dienst nicht eingerichtet."</string> <string name="CLIRPermanent">"Die Einstellung für die Anrufer-ID kann nicht geändert werden."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Sprachnotiz"</string> <string name="serviceClassData">"Daten"</string> <string name="serviceClassFAX">"FAX"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Lautlos"</string> <string name="global_action_silent_mode_on_status">"Ton ist bereits AUS"</string> <string name="global_action_silent_mode_off_status">"Ton ist momentan AN"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Flugzeugmodus"</string> + <string name="global_actions_airplane_mode_on_status">"Flugzeugmodus ist AN"</string> + <string name="global_actions_airplane_mode_off_status">"Flugzeugmodus ist AUS"</string> <string name="safeMode">"Abgesicherter Modus"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Android System"</string> <string name="permgrouplab_costMoney">"Kostenpflichtige Dienste"</string> <string name="permgroupdesc_costMoney">"Ermöglicht Anwendungen die Ausführung eventuell kostenpflichtiger Aktionen."</string> <string name="permgrouplab_messages">"Ihre Nachrichten"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Ermöglicht die Aktivierung/Deaktivierung der Radio-Benachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen."</string> <string name="permlab_checkinProperties">"Auf Check-In-Eigenschaften zugreifen"</string> <string name="permdesc_checkinProperties">"Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Anwendungen vorgesehen."</string> - <string name="permlab_bindGadget">"Gadgets auswählen"</string> - <string name="permdesc_bindGadget">"Bei dieser Option meldet die Anwendung dem System, welche Gadgets von welcher Anwendung verwendet werden können. Mit dieser Genehmigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten geben. Nicht für normale Anwendungen vorgesehen."</string> + <string name="permlab_bindGadget">"Widgets auswählen"</string> + <string name="permdesc_bindGadget">"Ermöglicht der Anwendung, dem System zu melden, welche Widgets von welcher Anwendung verwendet werden können. Mit dieser Berechtigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten gewähren. Nicht für normale Anwendungen vorgesehen."</string> <string name="permlab_modifyPhoneState">"Telefonstatus ändern"</string> <string name="permdesc_modifyPhoneState">"Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string> <string name="permlab_readPhoneState">"Telefonstatus lesen"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"Notruf"</string> <string name="lockscreen_pattern_correct">"Korrekt!"</string> <string name="lockscreen_pattern_wrong">"Tut uns leid. Versuchen Sie es noch einmal."</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"Wird geladen (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Bitte Ladegerät anschließen"</string> <string name="lockscreen_missing_sim_message_short">"Keine SIM-Karte."</string> <string name="lockscreen_missing_sim_message">"Keine SIM-Karte im Telefon."</string> <string name="lockscreen_missing_sim_instructions">"Bitte legen Sie eine SIM-Karte ein."</string> <string name="lockscreen_network_locked_message">"Netzwerk gesperrt"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Wenden Sie sich an den Kunden-Support."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-Karte ist gesperrt."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM-Karte wird entsperrt..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. "\n\n"Versuchen Sie es in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden erneut."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Versuchen Sie es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden erneut."</string> <string name="lockscreen_forgot_pattern_button_text">"Muster vergessen?"</string> <string name="lockscreen_glogin_too_many_attempts">"Zu viele Versuche!"</string> - <string name="lockscreen_glogin_instructions">"Melden Sie sich zum Entsperren"\n"mit Ihrem Google-Konto an."</string> + <string name="lockscreen_glogin_instructions">"Melden Sie sich zum Entsperren mit Ihrem Google-Konto an."</string> <string name="lockscreen_glogin_username_hint">"Nutzername (E-Mail)"</string> <string name="lockscreen_glogin_password_hint">"Passwort"</string> <string name="lockscreen_glogin_submit_button">"Anmelden"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Benachrichtigungen löschen"</string> <string name="status_bar_no_notifications_title">"Keine Benachrichtigungen"</string> <string name="status_bar_ongoing_events_title">"Aktuell"</string> <string name="status_bar_latest_events_title">"Benachrichtigungen"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"Wird aufgeladen..."</string> <string name="battery_low_title">"Ladegerät anschließen"</string> <string name="battery_low_subtitle">"Akku ist fast leer."</string> @@ -552,6 +555,7 @@ <string name="monthly">"Monatlich"</string> <string name="yearly">"Jährlich"</string> <string name="VideoView_error_title">"Video kann nicht wiedergegeben werden."</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Leider ist dieses Video nicht für Streaming auf diesem Gerät gültig."</string> <string name="VideoView_error_text_unknown">"Dieses Video kann leider nicht abgespielt werden."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"Mittag"</string> <string name="Noon">"Mittag"</string> <string name="midnight">"Mitternacht"</string> <string name="Midnight">"Mitternacht"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Sonntag"</string> <string name="day_of_week_long_monday">"Montag"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"Keine passenden Aktivitäten gefunden"</string> <string name="permlab_pkgUsageStats">"Nutzungsstatistik der Komponente aktualisieren"</string> <string name="permdesc_pkgUsageStats">"Ermöglicht die Änderung von gesammelten Nutzungsstatistiken der Komponente. Nicht für normale Anwendungen vorgesehen."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Für Zoomeinstellung zweimal berühren"</string> + <string name="gadget_host_error_inflating">"Fehler beim Vergrößern des Widgets"</string> + <string name="ime_action_go">"Los"</string> + <string name="ime_action_search">"Suchen"</string> + <string name="ime_action_send">"Senden"</string> + <string name="ime_action_next">"Weiter"</string> + <string name="ime_action_done">"Fertig"</string> + <string name="ime_action_default">"Ausführen"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-el-rGR/arrays.xml b/core/res/res/values-el-rGR/arrays.xml new file mode 100644 index 0000000..0329ca3 --- /dev/null +++ b/core/res/res/values-el-rGR/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>39074208</item> + <item>21824312</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-en-rCA/arrays.xml b/core/res/res/values-en-rCA/arrays.xml new file mode 100644 index 0000000..00c7ca4 --- /dev/null +++ b/core/res/res/values-en-rCA/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>49875832</item> + <item>-97150726</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-en-rIN/arrays.xml b/core/res/res/values-en-rIN/arrays.xml new file mode 100644 index 0000000..d5b2889 --- /dev/null +++ b/core/res/res/values-en-rIN/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>20593684</item> + <item>78962880</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-en-rNZ/arrays.xml b/core/res/res/values-en-rNZ/arrays.xml new file mode 100644 index 0000000..6340b95 --- /dev/null +++ b/core/res/res/values-en-rNZ/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>-41286480</item> + <item>174776217</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 495f8aa..8cacdc4 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: No restringido"</string> <string name="serviceNotProvisioned">"El servicio no se suministra."</string> <string name="CLIRPermanent">"El ID del emisor no se puede modificar."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Voz"</string> <string name="serviceClassData">"Datos"</string> <string name="serviceClassFAX">"FAX"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Modo silencio"</string> <string name="global_action_silent_mode_on_status">"El sonido está desactivado. Activar."</string> <string name="global_action_silent_mode_off_status">"El sonido está activado. Desactivar."</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Modo avión"</string> + <string name="global_actions_airplane_mode_on_status">"Modo avión ACTIVADO"</string> + <string name="global_actions_airplane_mode_off_status">"Modo avión DESACTIVADO"</string> <string name="safeMode">"Modo seguro"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Sistema Android"</string> <string name="permgrouplab_costMoney">"Servicios por los que tienes que pagar"</string> <string name="permgroupdesc_costMoney">"Permite que las aplicaciones realicen acciones por las que puede que tengas que pagar."</string> <string name="permgrouplab_messages">"Tus mensajes"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Permite habilitar/inhabilitar las notificaciones de actualización de la señal móvil. No está destinado al uso por parte de aplicaciones normales."</string> <string name="permlab_checkinProperties">"acceder a propiedades de registro"</string> <string name="permdesc_checkinProperties">"Permite el acceso de lectura/escritura a las propiedades cargadas por el servicio de registro. No está destinado al uso por parte de aplicaciones normales."</string> - <string name="permlab_bindGadget">"seleccionar gadgets"</string> - <string name="permdesc_bindGadget">"Permite a la aplicación indicar al sistema qué gadgets puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden permitir a otras aplicaciones acceder a datos personales. No está destinado al uso por parte de aplicaciones normales."</string> + <string name="permlab_bindGadget">"seleccionar widgets"</string> + <string name="permdesc_bindGadget">"Permite que una aplicación indique al sistema los widgets que puede utilizar cada aplicación. Se trata de un permiso que no pueden utilizar las aplicaciones normales y que permite que una aplicación conceda acceso a datos personales a otras aplicaciones."</string> <string name="permlab_modifyPhoneState">"modificar estado del teléfono"</string> <string name="permdesc_modifyPhoneState">"Permite que la aplicación controle las funciones de teléfono del dispositivo. Una aplicación con este permiso puede cambiar redes, activar y desactivar la señal móvil, etc., sin necesidad de notificar al usuario."</string> <string name="permlab_readPhoneState">"leer el estado del teléfono"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"Llamada de emergencia"</string> <string name="lockscreen_pattern_correct">"Correcto"</string> <string name="lockscreen_pattern_wrong">"Inténtalo de nuevo"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Conecta el cargador"</string> <string name="lockscreen_missing_sim_message_short">"Falta la tarjeta SIM"</string> <string name="lockscreen_missing_sim_message">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string> <string name="lockscreen_missing_sim_instructions">"Inserta una tarjeta SIM."</string> <string name="lockscreen_network_locked_message">"Bloqueada para la red"</string> <string name="lockscreen_sim_puk_locked_message">"La tarjeta SIM está bloqueada con el código PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Ponte en contacto con el servicio de atención al cliente."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"La tarjeta SIM está bloqueada."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Desbloqueando tarjeta SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación de un patrón de desbloqueo. "\n\n"Inténtalo de nuevo dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Espera <xliff:g id="NUMBER">%d</xliff:g> segundos y vuelve a intentarlo."</string> <string name="lockscreen_forgot_pattern_button_text">"¿Has olvidado el patrón?"</string> <string name="lockscreen_glogin_too_many_attempts">"Se han realizado demasiados intentos incorrectos de creación del patrón."</string> - <string name="lockscreen_glogin_instructions">"Para desbloquear el teléfono,"\n"accede a tu cuenta de Google"</string> + <string name="lockscreen_glogin_instructions">"Para desbloquear el teléfono, accede a tu cuenta de Google."</string> <string name="lockscreen_glogin_username_hint">"Nombre de usuario (correo electrónico)"</string> <string name="lockscreen_glogin_password_hint">"Contraseña"</string> <string name="lockscreen_glogin_submit_button">"Acceder"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Cerrar notificaciones"</string> <string name="status_bar_no_notifications_title">"No tienes notificaciones"</string> <string name="status_bar_ongoing_events_title">"Entrante"</string> <string name="status_bar_latest_events_title">"Notificaciones"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"Cargando..."</string> <string name="battery_low_title">"Conecta el cargador"</string> <string name="battery_low_subtitle">"Se está agotando la baterÃa:"</string> @@ -552,6 +555,7 @@ <string name="monthly">"Mensualmente"</string> <string name="yearly">"Anualmente"</string> <string name="VideoView_error_title">"No se puede reproducir el vÃdeo."</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Este vÃdeo no se puede transmitir al dispositivo."</string> <string name="VideoView_error_text_unknown">"Este vÃdeo no se puede reproducir."</string> <string name="VideoView_error_button">"Aceptar"</string> <string name="am">"a.m."</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"mediodÃa"</string> <string name="Noon">"MediodÃa"</string> <string name="midnight">"medianoche"</string> <string name="Midnight">"Medianoche"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> de <xliff:g id="MONTH">%b</xliff:g> de <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Domingo"</string> <string name="day_of_week_long_monday">"Lunes"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"No se ha encontrado ninguna actividad coincidente."</string> <string name="permlab_pkgUsageStats">"actualizar estadÃsticas de uso de componentes"</string> <string name="permdesc_pkgUsageStats">"Permite la modificación de estadÃsticas recopiladas sobre el uso de componentes. No está destinado al uso por parte de aplicaciones normales."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Pulsa dos veces para acceder al control de zoom."</string> + <string name="gadget_host_error_inflating">"Error al aumentar el widget"</string> + <string name="ime_action_go">"Ir"</string> + <string name="ime_action_search">"Buscar"</string> + <string name="ime_action_send">"Enviar"</string> + <string name="ime_action_next">"Siguiente"</string> + <string name="ime_action_done">"Hecho"</string> + <string name="ime_action_default">"Ejecutar"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-fi-rFI/arrays.xml b/core/res/res/values-fi-rFI/arrays.xml new file mode 100644 index 0000000..2e23953 --- /dev/null +++ b/core/res/res/values-fi-rFI/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>60169653</item> + <item>24939480</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-fr-rBE/arrays.xml b/core/res/res/values-fr-rBE/arrays.xml new file mode 100644 index 0000000..9e93a09 --- /dev/null +++ b/core/res/res/values-fr-rBE/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>50854509</item> + <item>4376678</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>5</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-fr-rCA/arrays.xml b/core/res/res/values-fr-rCA/arrays.xml new file mode 100644 index 0000000..00c7ca4 --- /dev/null +++ b/core/res/res/values-fr-rCA/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>49875832</item> + <item>-97150726</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-fr-rCH/arrays.xml b/core/res/res/values-fr-rCH/arrays.xml new file mode 100644 index 0000000..f2982e9 --- /dev/null +++ b/core/res/res/values-fr-rCH/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>46948020</item> + <item>7448206</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 8bd064d..6e76fe7 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Par défaut, les identifiants d\'appelant ne sont pas restreints. Appel suivant : non restreint"</string> <string name="serviceNotProvisioned">"Ce service n\'est pas pris en charge."</string> <string name="CLIRPermanent">"Le paramètre Identifiant d\'appelant ne peut pas être modifié."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Voix"</string> <string name="serviceClassData">"Données"</string> <string name="serviceClassFAX">"Télécopie"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Mode silencieux"</string> <string name="global_action_silent_mode_on_status">"Le son est désactivé."</string> <string name="global_action_silent_mode_off_status">"Le son est activé."</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Mode Avion"</string> + <string name="global_actions_airplane_mode_on_status">"Le mode Avion est activé."</string> + <string name="global_actions_airplane_mode_off_status">"Le mode Avion est désactivé."</string> <string name="safeMode">"Mode sécurisé"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Système Android"</string> <string name="permgrouplab_costMoney">"Services payants"</string> <string name="permgroupdesc_costMoney">"Permet aux applications d\'effectuer des opérations payantes."</string> <string name="permgrouplab_messages">"Vos messages"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant de la radio. Les applications normales n\'utilisent pas cette fonctionnalité."</string> <string name="permlab_checkinProperties">"Accès aux propriétés d\'enregistrement"</string> <string name="permdesc_checkinProperties">"Permet un accès en lecture/écriture à des propriétés envoyées par le service d\'inscription. Les applications normales n\'utilisent pas cette fonctionnalité."</string> - <string name="permlab_bindGadget">"choisir les gadgets"</string> - <string name="permdesc_bindGadget">"Permet à l\'application de signaler au système quels gadgets peuvent être utilisés pour quelle application. Cette autorisation permet aux applications de fournir l\'accès à des données personnelles à d\'autres applications. Cette option n\'est pas utilisée par les applications standard."</string> + <string name="permlab_bindGadget">"choisir les widgets"</string> + <string name="permdesc_bindGadget">"Permet à l\'application de signaler au système quels widgets peuvent être utilisés par quelle application. Grâce à cette autorisation, les applications peuvent accorder l\'accès à des données personnelles à d\'autres applications. Cette option n\'est pas utilisée par les applications standard."</string> <string name="permlab_modifyPhoneState">"Modification de l\'état du téléphone"</string> <string name="permdesc_modifyPhoneState">"Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer la radio du téléphone, etc., sans vous en avertir."</string> <string name="permlab_readPhoneState">"Lecture de l\'état du téléphone"</string> @@ -397,23 +403,23 @@ <string name="lockscreen_emergency_call">"Appel d\'urgence"</string> <string name="lockscreen_pattern_correct">"Combinaison correcte !"</string> <string name="lockscreen_pattern_wrong">"Désolé. Merci de réessayer."</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"Chargement (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Branchez votre chargeur."</string> <string name="lockscreen_missing_sim_message_short">"Aucune carte SIM n\'a été trouvée."</string> <string name="lockscreen_missing_sim_message">"Aucune carte SIM n\'est insérée dans le téléphone."</string> <string name="lockscreen_missing_sim_instructions">"Insérez une carte SIM."</string> - <string name="lockscreen_network_locked_message">"Réseau bloqué"</string> + <string name="lockscreen_network_locked_message">"Réseau verrouillé"</string> <string name="lockscreen_sim_puk_locked_message">"La carte SIM est verrouillée par code PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Veuillez contacter l\'assistance clientèle."</string> - <string name="lockscreen_sim_locked_message">"La carte SIM est bloquée."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> + <string name="lockscreen_sim_locked_message">"Téléphone verrouillé"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Déblocage de la carte SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Vous avez mal reproduit le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string> <string name="lockscreen_failed_attempts_almost_glogin">"Vous avez mal saisi le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. Au bout de <xliff:g id="NUMBER_1">%d</xliff:g> tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string> <string name="lockscreen_too_many_failed_attempts_countdown">"Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string> <string name="lockscreen_forgot_pattern_button_text">"Motif oublié ?"</string> <string name="lockscreen_glogin_too_many_attempts">"Trop de tentatives de motif !"</string> - <string name="lockscreen_glogin_instructions">"Pour débloquer votre téléphone,"\n"connectez-vous à l\'aide de votre compte Google"</string> + <string name="lockscreen_glogin_instructions">"Pour déverrouiller le téléphone, connectez-vous à l\'aide de votre compte Google."</string> <string name="lockscreen_glogin_username_hint">"Nom d\'utilisateur (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"Mot de passe"</string> <string name="lockscreen_glogin_submit_button">"Se connecter"</string> @@ -421,15 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Effacer les notifications"</string> <string name="status_bar_no_notifications_title">"Aucune notification"</string> <string name="status_bar_ongoing_events_title">"En cours"</string> <string name="status_bar_latest_events_title">"Notifications"</string> - <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"Chargement..."</string> <string name="battery_low_title">"Branchez le chargeur"</string> <string name="battery_low_subtitle">"Le niveau de la batterie est bas :"</string> @@ -551,6 +555,7 @@ <string name="monthly">"Tous les mois"</string> <string name="yearly">"Tous les ans"</string> <string name="VideoView_error_title">"Échec de la lecture de la vidéo"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Désolé, cette vidéo ne peut être lue sur cet appareil."</string> <string name="VideoView_error_text_unknown">"Désolé, impossible de lire cette vidéo."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -572,17 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"midi"</string> <string name="Noon">"Midi"</string> <string name="midnight">"minuit"</string> <string name="Midnight">"Minuit"</string> - <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> @@ -610,10 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"dimanche"</string> <string name="day_of_week_long_monday">"lundi"</string> @@ -795,17 +798,16 @@ <string name="activity_list_empty">"Aucune activité correspondante trouvée"</string> <string name="permlab_pkgUsageStats">"mettre à jour les données statistiques du composant"</string> <string name="permdesc_pkgUsageStats">"Permet de modifier les données statistiques collectées du composant. Cette option n\'est pas utilisée par les applications standard."</string> - <string name="tutorial_double_tap_to_zoom_message_short">"Tapez deux fois pour le zoom"</string> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Appuyer deux fois pour régler le zoom"</string> + <string name="gadget_host_error_inflating">"Erreur lors de l\'agrandissement du widget"</string> + <string name="ime_action_go">"OK"</string> + <string name="ime_action_search">"Rechercher"</string> + <string name="ime_action_send">"Envoyer"</string> + <string name="ime_action_next">"Suivant"</string> + <string name="ime_action_done">"Terminé"</string> + <string name="ime_action_default">"Exécuter"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-he-rIL/arrays.xml b/core/res/res/values-he-rIL/arrays.xml new file mode 100644 index 0000000..87c1231 --- /dev/null +++ b/core/res/res/values-he-rIL/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>31046051</item> + <item>34851612</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-hi-rIN/arrays.xml b/core/res/res/values-hi-rIN/arrays.xml new file mode 100644 index 0000000..d5b2889 --- /dev/null +++ b/core/res/res/values-hi-rIN/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>20593684</item> + <item>78962880</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-hu-rHU/arrays.xml b/core/res/res/values-hu-rHU/arrays.xml new file mode 100644 index 0000000..833bb24 --- /dev/null +++ b/core/res/res/values-hu-rHU/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>47162494</item> + <item>19503304</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-id-rID/arrays.xml b/core/res/res/values-id-rID/arrays.xml new file mode 100644 index 0000000..512cace --- /dev/null +++ b/core/res/res/values-id-rID/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>-789275</item> + <item>113921327</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-it-rCH/arrays.xml b/core/res/res/values-it-rCH/arrays.xml new file mode 100644 index 0000000..f2982e9 --- /dev/null +++ b/core/res/res/values-it-rCH/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>46948020</item> + <item>7448206</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index b4cf458..50e25c0 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"ID chiamante generalmente non limitato. Prossima chiamata: non limitato"</string> <string name="serviceNotProvisioned">"Servizio non fornito."</string> <string name="CLIRPermanent">"Impossibile modificare l\'impostazione dell\'ID del chiamante."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Voce"</string> <string name="serviceClassData">"Dati"</string> <string name="serviceClassFAX">"FAX"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Modalità silenziosa"</string> <string name="global_action_silent_mode_on_status">"Audio non attivo"</string> <string name="global_action_silent_mode_off_status">"Audio attivo"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Modalità in volo"</string> + <string name="global_actions_airplane_mode_on_status">"Modalità in volo attiva"</string> + <string name="global_actions_airplane_mode_off_status">"Modalità in volo non attiva"</string> <string name="safeMode">"Modalità provvisoria"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Sistema Android"</string> <string name="permgrouplab_costMoney">"Servizi che prevedono un costo"</string> <string name="permgroupdesc_costMoney">"Consentono alle applicazioni di svolgere operazioni che possono comportare un costo."</string> <string name="permgrouplab_messages">"I tuoi messaggi"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Consente l\'attivazione/disattivazione delle notifiche di aggiornamento della posizione dal segnale cellulare. Da non usare per normali applicazioni."</string> <string name="permlab_checkinProperties">"accesso a proprietà di archiviazione"</string> <string name="permdesc_checkinProperties">"Consente l\'accesso di lettura/scrittura alle proprietà caricate dal servizio di archiviazione. Da non usare per normali applicazioni."</string> - <string name="permlab_bindGadget">"scegliere gadget"</string> - <string name="permdesc_bindGadget">"Consente all\'applicazione di indicare al sistema quali gadget possono essere utilizzati e da quale applicazione. Con questa autorizzazione, le applicazioni possono consentire ad altre applicazioni di accedere a dati personali. Da non usare per normali applicazioni."</string> + <string name="permlab_bindGadget">"scegliere widget"</string> + <string name="permdesc_bindGadget">"Consente all\'applicazione di indicare al sistema quali widget possono essere utilizzati e da quale applicazione. Con questa autorizzazione, le applicazioni possono consentire ad altre applicazioni di accedere a dati personali. Da non usare per normali applicazioni."</string> <string name="permlab_modifyPhoneState">"modifica stato del telefono"</string> <string name="permdesc_modifyPhoneState">"Consente all\'applicazione di controllare le funzioni telefoniche del dispositivo. Un\'applicazione con questa autorizzazione può cambiare rete, attivare e disattivare il segnale cellulare e così via, senza alcuna notifica."</string> <string name="permlab_readPhoneState">"lettura stato del telefono"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"Chiamata di emergenza"</string> <string name="lockscreen_pattern_correct">"Corretta."</string> <string name="lockscreen_pattern_wrong">"Riprova"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"In carica (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Collegare il caricabatterie."</string> <string name="lockscreen_missing_sim_message_short">"Nessuna SIM presente."</string> <string name="lockscreen_missing_sim_message">"Nessuna SIM presente nel telefono."</string> <string name="lockscreen_missing_sim_instructions">"Inserisci una SIM."</string> <string name="lockscreen_network_locked_message">"Rete bloccata"</string> <string name="lockscreen_sim_puk_locked_message">"La SIM è bloccata tramite PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Contatta il servizio clienti."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"La SIM è bloccata."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Sblocco SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi di inserimento della sequenza di sblocco. "\n\n"Riprova fra <xliff:g id="NUMBER_1">%d</xliff:g> secondi."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi."</string> <string name="lockscreen_forgot_pattern_button_text">"Hai dimenticato la sequenza?"</string> <string name="lockscreen_glogin_too_many_attempts">"Troppi tentativi di inserimento della sequenza."</string> - <string name="lockscreen_glogin_instructions">"Per sbloccare,"\n"accedi tramite il tuo account Google"</string> + <string name="lockscreen_glogin_instructions">"Per sbloccare, accedi tramite il tuo account Google"</string> <string name="lockscreen_glogin_username_hint">"Nome utente (email)"</string> <string name="lockscreen_glogin_password_hint">"Password"</string> <string name="lockscreen_glogin_submit_button">"Accedi"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Cancella notifiche"</string> <string name="status_bar_no_notifications_title">"Nessuna notifica"</string> <string name="status_bar_ongoing_events_title">"In corso"</string> <string name="status_bar_latest_events_title">"Notifiche"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"In carica..."</string> <string name="battery_low_title">"Collegare il caricabatterie"</string> <string name="battery_low_subtitle">"Batteria quasi scarica:"</string> @@ -552,6 +555,7 @@ <string name="monthly">"Mensilmente"</string> <string name="yearly">"Annualmente"</string> <string name="VideoView_error_title">"Impossibile riprodurre il video"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Spiacenti, questo video non è valido per lo streaming su questo dispositivo."</string> <string name="VideoView_error_text_unknown">"Spiacenti. Impossibile riprodurre il video."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"mezzogiorno"</string> <string name="Noon">"Mezzogiorno"</string> <string name="midnight">"mezzanotte"</string> <string name="Midnight">"Mezzanotte"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Domenica"</string> <string name="day_of_week_long_monday">"Lunedì"</string> @@ -725,7 +725,7 @@ <string name="anr_activity_process">"L\'attività <xliff:g id="ACTIVITY">%1$s</xliff:g> (nel processo <xliff:g id="PROCESS">%2$s</xliff:g>) non risponde."</string> <string name="anr_application_process">"L\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> (nel processo <xliff:g id="PROCESS">%2$s</xliff:g>) non risponde."</string> <string name="anr_process">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> non risponde."</string> - <string name="force_close">"Forza chiusura"</string> + <string name="force_close">"Termina"</string> <string name="wait">"Attendi"</string> <string name="debug">"Debug"</string> <string name="sendText">"Seleziona un\'azione per il testo"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"Nessuna attività corrispondente trovata"</string> <string name="permlab_pkgUsageStats">"aggiornare le statistiche di utilizzo dei componenti"</string> <string name="permdesc_pkgUsageStats">"Consente la modifica delle statistiche di utilizzo dei componenti raccolte. Da non usare per normali applicazioni."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Tocca due volte per il comando dello zoom"</string> + <string name="gadget_host_error_inflating">"Errore durante l\'ampliamento del widget"</string> + <string name="ime_action_go">"Vai"</string> + <string name="ime_action_search">"Cerca"</string> + <string name="ime_action_send">"Invia"</string> + <string name="ime_action_next">"Avanti"</string> + <string name="ime_action_done">"Fine"</string> + <string name="ime_action_default">"Esegui"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 2a21bd3..ccc7f19 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"既定: 発信者番å·é€šçŸ¥ã€æ¬¡ã®ç™ºä¿¡: 通知"</string> <string name="serviceNotProvisioned">"æä¾›å¯èƒ½ãªã‚µãƒ¼ãƒ“スãŒã‚りã¾ã›ã‚“。"</string> <string name="CLIRPermanent">"発信者番å·ã®è¨å®šã¯å¤‰æ›´ã§ãã¾ã›ã‚“。"</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"音声"</string> <string name="serviceClassData">"データ"</string> <string name="serviceClassFAX">"FAX"</string> @@ -69,7 +79,7 @@ <string name="cfTemplateRegisteredTime">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転é€ã§ãã¾ã›ã‚“"</string> <string name="httpErrorOk">"OK"</string> <string name="httpError">"ウェブページã«ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã™ã€‚"</string> - <string name="httpErrorLookup">"URLãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"</string> + <string name="httpErrorLookup">"URLãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"</string> <string name="httpErrorUnsupportedAuthScheme">"ã“ã®ã‚µã‚¤ãƒˆã®èªè¨¼æ–¹å¼ã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。"</string> <string name="httpErrorAuth">"èªè¨¼ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"</string> <string name="httpErrorProxyAuth">"プãƒã‚シサーãƒãƒ¼ã‚’使用ã—ãŸèªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"</string> @@ -93,25 +103,21 @@ <string name="turn_on_radio">"ワイヤレス接続をONã«ã™ã‚‹"</string> <string name="turn_off_radio">"ワイヤレス接続をOFFã«ã™ã‚‹"</string> <string name="screen_lock">"ç”»é¢ã‚’ãƒãƒƒã‚¯"</string> - <string name="power_off">"é›»æºã‚ªãƒ•"</string> + <string name="power_off">"é›»æºã‚’切る"</string> <string name="shutdown_progress">"シャットダウンä¸..."</string> - <string name="shutdown_confirm">"æºå¸¯é›»è©±ã®é›»æºã‚’オフã«ã—ã¾ã™ã€‚"</string> + <string name="shutdown_confirm">"æºå¸¯é›»è©±ã®é›»æºã‚’切りã¾ã™ã€‚"</string> <string name="no_recent_tasks">"最近使ã£ãŸã‚¢ãƒ—リケーションã¯ã‚りã¾ã›ã‚“。"</string> <string name="global_actions">"æºå¸¯é›»è©±ã‚ªãƒ—ション"</string> <string name="global_action_lock">"ç”»é¢ãƒãƒƒã‚¯"</string> - <string name="global_action_power_off">"é›»æºã‚ªãƒ•"</string> + <string name="global_action_power_off">"é›»æºã‚’切る"</string> <string name="global_action_toggle_silent_mode">"マナーモード"</string> - <string name="global_action_silent_mode_on_status">"音声オフ"</string> - <string name="global_action_silent_mode_off_status">"サウンド:オン"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_action_silent_mode_on_status">"サウンドOFF"</string> + <string name="global_action_silent_mode_off_status">"サウンドON"</string> + <string name="global_actions_toggle_airplane_mode">"機内モード"</string> + <string name="global_actions_airplane_mode_on_status">"機内モードON"</string> + <string name="global_actions_airplane_mode_off_status">"機内モードOFF"</string> <string name="safeMode">"セーフモード"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Androidシステム"</string> <string name="permgrouplab_costMoney">"料金ã®ç™ºç”Ÿã™ã‚‹ã‚µãƒ¼ãƒ“ス"</string> <string name="permgroupdesc_costMoney">"料金ã®ç™ºç”Ÿã™ã‚‹æ“作をアプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> <string name="permgrouplab_messages">"é€å—ä¿¡ã—ãŸãƒ¡ãƒƒã‚»ãƒ¼ã‚¸"</string> @@ -279,22 +285,22 @@ <string name="permlab_hardware_test">"ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®ãƒ†ã‚¹ãƒˆ"</string> <string name="permdesc_hardware_test">"ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®ãƒ†ã‚¹ãƒˆã®ãŸã‚ã«ã•ã¾ã–ã¾ãªå‘¨è¾ºæ©Ÿå™¨ã‚’制御ã™ã‚‹ã“ã¨ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> <string name="permlab_callPhone">"電話番å·ç™ºä¿¡"</string> - <string name="permdesc_callPhone">"アプリケーションãŒé›»è©±ã‚’自動発信ã™ã‚‹ã“ã¨ã‚’許å¯ã—ã¾ã™ã€‚悪æ„ã®ã‚ã‚‹ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæ„図ã—ãªã„電話をã‹ã‘ã¦æ–™é‡‘ãŒç™ºç”Ÿã™ã‚‹æã‚ŒãŒã‚りã¾ã™ã€‚緊急呼ã¸ã®ç™ºä¿¡ã¯è¨±å¯ã—ã¾ã›ã‚“。"</string> + <string name="permdesc_callPhone">"電話番å·ã®è‡ªå‹•発信をアプリケーションã«è¨±å¯ã—ã¾ã™ã€‚悪æ„ã®ã‚ã‚‹ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæ„図ã—ãªã„電話をã‹ã‘ã¦æ–™é‡‘ãŒç™ºç”Ÿã™ã‚‹æã‚ŒãŒã‚りã¾ã™ã€‚ç·Šæ€¥é€šå ±ã¸ã®ç™ºä¿¡ã¯è¨±å¯ã—ã¾ã›ã‚“。"</string> <string name="permlab_callPrivileged">"電話番å·ç™ºä¿¡"</string> - <string name="permdesc_callPrivileged">"緊急呼をå«ã‚ã‚らゆる電話番å·ã«è‡ªå‹•発信ã™ã‚‹ã“ã¨ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚悪æ„ã®ã‚るアプリケーションãŒç·Šæ€¥ã‚µãƒ¼ãƒ“スã«ä¸æ£ãªé€šå ±ã‚’ã™ã‚‹æã‚ŒãŒã‚りã¾ã™ã€‚"</string> + <string name="permdesc_callPrivileged">"ç·Šæ€¥é€šå ±ã‚’å«ã‚ã‚らゆる電話番å·ã«è‡ªå‹•発信ã™ã‚‹ã“ã¨ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚悪æ„ã®ã‚るアプリケーションãŒç·Šæ€¥ã‚µãƒ¼ãƒ“スã«ä¸æ£ãªé€šå ±ã‚’ã™ã‚‹æã‚ŒãŒã‚りã¾ã™ã€‚"</string> <string name="permlab_locationUpdates">"ä½ç½®æƒ…å ±ã®æ›´æ–°é€šçŸ¥"</string> <string name="permdesc_locationUpdates">"無線通信ã‹ã‚‰ã®ä½ç½®æ›´æ–°é€šçŸ¥ã‚’有効/無効ã«ã™ã‚‹ã“ã¨ã‚’許å¯ã—ã¾ã™ã€‚通常ã®ã‚¢ãƒ—リケーションã§ã¯ä½¿ç”¨ã—ã¾ã›ã‚“。"</string> <string name="permlab_checkinProperties">"ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³ãƒ—ãƒãƒ‘ティã¸ã®ã‚¢ã‚¯ã‚»ã‚¹"</string> <string name="permdesc_checkinProperties">"ãƒã‚§ãƒƒã‚¯ã‚¤ãƒ³ã‚µãƒ¼ãƒ“スãŒã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã—ãŸãƒ—ãƒãƒ‘ティã¸ã®èªã¿æ›¸ãを許å¯ã—ã¾ã™ã€‚通常ã®ã‚¢ãƒ—リケーションã§ã¯ä½¿ç”¨ã—ã¾ã›ã‚“。"</string> - <string name="permlab_bindGadget">"ガジェットã®é¸æŠž"</string> - <string name="permdesc_bindGadget">"特定ã®ã‚¢ãƒ—リケーションã§ä½¿ç”¨å¯èƒ½ãªã‚¬ã‚¸ã‚§ãƒƒãƒˆã‚’ã‚·ã‚¹ãƒ†ãƒ ã«æŒ‡å®šã™ã‚‹ã“ã¨ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚ã“ã®è¨±å¯ã‚’å—ã‘ãŸã‚¢ãƒ—リケーションã¯ã€ä»–ã®ã‚¢ãƒ—リケーションã«å€‹äººãƒ‡ãƒ¼ã‚¿ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚通常ã®ã‚¢ãƒ—リケーションã§ã¯ä½¿ç”¨ã—ã¾ã›ã‚“。"</string> + <string name="permlab_bindGadget">"ウィジェットã®é¸æŠž"</string> + <string name="permdesc_bindGadget">"ã©ã®ã‚¢ãƒ—リケーションãŒã©ã®ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆã‚’使用ã§ãã‚‹ã‹ã‚·ã‚¹ãƒ†ãƒ ã«æŒ‡å®šã™ã‚‹ã“ã¨ã‚’ã“ã®ã‚¢ãƒ—リケーションã«è¨±å¯ã—ã¾ã™ã€‚ã“れã«ã‚ˆã‚Šã€ã‚¢ãƒ—リケーション間ã§å€‹äººãƒ‡ãƒ¼ã‚¿ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚通常ã®ã‚¢ãƒ—リケーションã§ã¯ä½¿ç”¨ã—ã¾ã›ã‚“。"</string> <string name="permlab_modifyPhoneState">"端末ステータスã®å¤‰æ›´"</string> <string name="permdesc_modifyPhoneState">"端末ã®é›»è©±æ©Ÿèƒ½ã®ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚アプリケーションã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®åˆ‡ã‚Šæ›¿ãˆã€æºå¸¯é›»è©±ã®ç„¡ç·šé€šä¿¡ã®ã‚ªãƒ³/オフãªã©ã‚’通知ã›ãšã«è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚"</string> <string name="permlab_readPhoneState">"端末ステータスã®èªã¿å–り"</string> <string name="permdesc_readPhoneState">"端末ã®é›»è©±æ©Ÿèƒ½ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚アプリケーションã¯ã€ã“ã®æºå¸¯é›»è©±ã®é›»è©±ç•ªå·ã€é€šè©±ä¸ã‹ã©ã†ã‹ã€é€šè©±ç›¸æ‰‹ã®é›»è©±ç•ªå·ãªã©ã‚’特定ã§ãã¾ã™ã€‚"</string> <string name="permlab_wakeLock">"端末ã®ã‚¹ãƒªãƒ¼ãƒ—を無効ã«ã™ã‚‹"</string> <string name="permdesc_wakeLock">"端末ã®ã‚¹ãƒªãƒ¼ãƒ—を無効ã«ã™ã‚‹ã“ã¨ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> - <string name="permlab_devicePower">"æºå¸¯é›»è©±ã®é›»æºã®ã‚ªãƒ³/オフ"</string> + <string name="permlab_devicePower">"é›»æºã®ON/OFF"</string> <string name="permdesc_devicePower">"æºå¸¯é›»è©±ã®é›»æºã®ã‚ªãƒ³/オフをアプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> <string name="permlab_factoryTest">"å‡ºè·æ™‚試験モードã§ã®å®Ÿè¡Œ"</string> <string name="permdesc_factoryTest">"æºå¸¯é›»è©±ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’完全ã«è¨±å¯ã—ã¦ã€ä½Žãƒ¬ãƒ™ãƒ«ã®ãƒ¡ãƒ¼ã‚«ãƒ¼ãƒ†ã‚¹ãƒˆã¨ã—ã¦å®Ÿè¡Œã—ã¾ã™ã€‚メーカーã®ãƒ†ã‚¹ãƒˆãƒ¢ãƒ¼ãƒ‰ã§æºå¸¯é›»è©±ã‚’使用ã™ã‚‹ã¨ãã®ã¿åˆ©ç”¨ã§ãã¾ã™ã€‚"</string> @@ -316,7 +322,7 @@ <string name="permdesc_writeApnSettings">"APNã®ãƒ—ãƒã‚ã‚·ã‚„ãƒãƒ¼ãƒˆãªã©ã®APNè¨å®šã®å¤‰æ›´ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> <string name="permlab_changeNetworkState">"ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šã®å¤‰æ›´"</string> <string name="permdesc_changeNetworkState">"ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®æŽ¥ç¶šçŠ¶æ…‹ã®å¤‰æ›´ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> - <string name="permlab_changeBackgroundDataSetting">"ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ãƒ‡ãƒ¼ã‚¿ä½¿ç”¨ã®è¨å®šã®å¤‰æ›´"</string> + <string name="permlab_changeBackgroundDataSetting">"ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ãƒ‡ãƒ¼ã‚¿ä½¿ç”¨è¨å®šã®å¤‰æ›´"</string> <string name="permdesc_changeBackgroundDataSetting">"ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ãƒ‡ãƒ¼ã‚¿ä½¿ç”¨ã®è¨å®šã®å¤‰æ›´ã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> <string name="permlab_accessWifiState">"Wi-Fi状態ã®è¡¨ç¤º"</string> <string name="permdesc_accessWifiState">"Wi-Fi状態ã«é–¢ã™ã‚‹æƒ…å ±ã®è¡¨ç¤ºã‚’アプリケーションã«è¨±å¯ã—ã¾ã™ã€‚"</string> @@ -387,25 +393,25 @@ </string-array> <string name="keyguard_password_enter_pin_code">"PINコードを入力"</string> <string name="keyguard_password_wrong_pin_code">"PINã‚³ãƒ¼ãƒ‰ãŒæ£ã—ãã‚りã¾ã›ã‚“。"</string> - <string name="keyguard_label_text">"ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹ã«ã¯MENUã€0ã‚ーã®é †ã«æŠ¼ã—ã¾ã™ã€‚"</string> - <string name="emergency_call_dialog_number_for_display">"緊急呼番å·"</string> - <string name="lockscreen_carrier_default">"(サービス登録ãªã—)"</string> + <string name="keyguard_label_text">"MENUã€0ã‚ーã§ãƒãƒƒã‚¯è§£é™¤"</string> + <string name="emergency_call_dialog_number_for_display">"ç·Šæ€¥é€šå ±ç•ªå·"</string> + <string name="lockscreen_carrier_default">"(通信サービスãªã—)"</string> <string name="lockscreen_screen_locked">"ç”»é¢ãƒãƒƒã‚¯ä¸"</string> - <string name="lockscreen_instructions_when_pattern_enabled">"MENUã‚ーã§ãƒãƒƒã‚¯è§£é™¤ï¼ˆã¾ãŸã¯ç·Šæ€¥å‘¼ï¼‰"</string> + <string name="lockscreen_instructions_when_pattern_enabled">"MENUã‚ーã§ãƒãƒƒã‚¯è§£é™¤ï¼ˆã¾ãŸã¯ç·Šæ€¥é€šå ±ï¼‰"</string> <string name="lockscreen_instructions_when_pattern_disabled">"MENUã‚ーã§ãƒãƒƒã‚¯è§£é™¤"</string> <string name="lockscreen_pattern_instructions">"ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹ãƒ‘ターンを入力"</string> - <string name="lockscreen_emergency_call">"緊急呼"</string> + <string name="lockscreen_emergency_call">"ç·Šæ€¥é€šå ±"</string> <string name="lockscreen_pattern_correct">"一致ã—ã¾ã—ãŸ"</string> <string name="lockscreen_pattern_wrong">"やり直ã—ã¦ãã ã•ã„"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"å……é›»ä¸ï¼ˆ<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"å……é›»ã—ã¦ãã ã•ã„。"</string> <string name="lockscreen_missing_sim_message_short">"SIMã‚«ãƒ¼ãƒ‰ãŒæŒ¿å…¥ã•れã¦ã„ã¾ã›ã‚“"</string> <string name="lockscreen_missing_sim_message">"SIMã‚«ãƒ¼ãƒ‰ãŒæŒ¿å…¥ã•れã¦ã„ã¾ã›ã‚“"</string> <string name="lockscreen_missing_sim_instructions">"SIMカードを挿入ã—ã¦ãã ã•ã„。"</string> <string name="lockscreen_network_locked_message">"ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãŒãƒãƒƒã‚¯ã•れã¾ã—ãŸ"</string> <string name="lockscreen_sim_puk_locked_message">"SIMカードã¯PUKã§ãƒãƒƒã‚¯ã•れã¦ã„ã¾ã™ã€‚"</string> - <string name="lockscreen_sim_puk_locked_instructions">"ãŠå®¢æ§˜ã‚µãƒãƒ¼ãƒˆã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。"</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIMカードã¯ãƒãƒƒã‚¯ã•れã¦ã„ã¾ã™ã€‚"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIMカードã®ãƒãƒƒã‚¯è§£é™¤ä¸..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"ãƒãƒƒã‚¯è§£é™¤ã®ãƒ‘ターンã¯<xliff:g id="NUMBER_0">%d</xliff:g>回ã¨ã‚‚æ£ã—ãæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後ã«ã‚‚ã†ä¸€åº¦æŒ‡å®šã—ã¦ãã ã•ã„。"</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g>秒後ã«ã‚„り直ã—ã¦ãã ã•ã„。"</string> <string name="lockscreen_forgot_pattern_button_text">"パターンを忘れãŸå ´åˆ"</string> <string name="lockscreen_glogin_too_many_attempts">"パターンã®ã‚¨ãƒ©ãƒ¼ãŒå¤šã™ãŽã¾ã™"</string> - <string name="lockscreen_glogin_instructions">"ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹ã«ã¯ã€"\n"Googleアカウントã§ãƒã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„。"</string> + <string name="lockscreen_glogin_instructions">"Googleアカウントã§ãƒã‚°ã‚¤ãƒ³ã—ã¦ãƒãƒƒã‚¯è§£é™¤"</string> <string name="lockscreen_glogin_username_hint">"ユーザーå (メール)"</string> <string name="lockscreen_glogin_password_hint">"パスワード"</string> <string name="lockscreen_glogin_submit_button">"ãƒã‚°ã‚¤ãƒ³"</string> @@ -421,27 +427,24 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"通知を消去"</string> <string name="status_bar_no_notifications_title">"通知ãªã—"</string> - <string name="status_bar_ongoing_events_title">"継続ä¸"</string> + <string name="status_bar_ongoing_events_title">"æ“作ä¸"</string> <string name="status_bar_latest_events_title">"通知"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"å……é›»ä¸..."</string> <string name="battery_low_title">"å……é›»ã—ã¦ãã ã•ã„"</string> <string name="battery_low_subtitle">"é›»æ± ãŒæ®‹ã‚Šå°‘ãªããªã£ã¦ã„ã¾ã™:"</string> - <string name="battery_low_percent_format">"残り<xliff:g id="NUMBER">%d%%</xliff:g>未満"</string> + <string name="battery_low_percent_format">"残é‡<xliff:g id="NUMBER">%d%%</xliff:g>以下"</string> <string name="factorytest_failed">"å‡ºè·æ™‚試験ãŒå¤±æ•—"</string> <string name="factorytest_not_system">"FACTORY_TESTæ“作ã¯ã€/system/appã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れãŸãƒ‘ッケージã®ã¿ãŒå¯¾è±¡ã§ã™ã€‚"</string> <string name="factorytest_no_action">"FACTORY_TESTæ“作を行ã†ãƒ‘ッケージã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"</string> <string name="factorytest_reboot">"å†èµ·å‹•"</string> <string name="js_dialog_title">"ページ「<xliff:g id="TITLE">%s</xliff:g>ã€ã®è¨˜è¿°:"</string> <string name="js_dialog_title_default">"JavaScript"</string> - <string name="js_dialog_before_unload">"ã“ã®ãƒšãƒ¼ã‚¸ã‹ã‚‰ç§»å‹•ã—ã¾ã™ã‹ï¼Ÿ"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"続行ã™ã‚‹å ´åˆã¯[OK]ã€ä»Šã®ãƒšãƒ¼ã‚¸ã«æ®‹ã‚‹å ´åˆã¯[ã‚ャンセル]ã‚’é¸æŠžã—ã¦ãã ã•ã„。"</string> + <string name="js_dialog_before_unload">"ã“ã®ãƒšãƒ¼ã‚¸ã‹ã‚‰ç§»å‹•ã—ã¾ã™ã‹ï¼Ÿ"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"移動ã™ã‚‹å ´åˆã¯[OK]ã€ä»Šã®ãƒšãƒ¼ã‚¸ã«æ®‹ã‚‹å ´åˆã¯[ã‚ャンセル]ã‚’é¸æŠžã—ã¦ãã ã•ã„。"</string> <string name="save_password_label">"確èª"</string> <string name="save_password_message">"ã“ã®ãƒ‘スワードをブラウザã§ä¿å˜ã—ã¾ã™ã‹ï¼Ÿ"</string> <string name="save_password_notnow">"今ã¯ä¿å˜ã—ãªã„"</string> @@ -498,7 +501,7 @@ </plurals> <plurals name="abbrev_num_minutes_ago"> <item quantity="one">"1分å‰"</item> - <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g>分後"</item> + <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g>分å‰"</item> </plurals> <plurals name="abbrev_num_hours_ago"> <item quantity="one">"1時間å‰"</item> @@ -552,6 +555,7 @@ <string name="monthly">"毎月"</string> <string name="yearly">"毎年"</string> <string name="VideoView_error_title">"動画をå†ç”Ÿã§ãã¾ã›ã‚“"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"ã“ã®å‹•ç”»ã¯ã”使用ã®ç«¯æœ«ã§ã‚¹ãƒˆãƒªãƒ¼ãƒŸãƒ³ã‚°ã§ãã¾ã›ã‚“。"</string> <string name="VideoView_error_text_unknown">"ã“ã®å‹•ç”»ã¯å†ç”Ÿã§ãã¾ã›ã‚“。"</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -561,30 +565,28 @@ <string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string> <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string> <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g>~<xliff:g id="TIME2">%2$s</xliff:g>"</string> + <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> - <xliff:g id="TIME2">%2$s</xliff:g>"</string> <string name="time_wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g><xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> <string name="wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> <string name="time_date">"<xliff:g id="DATE">%3$s</xliff:g>ã€<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>ã€<xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>ã€<xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>ã€<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> <string name="full_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'/'<xliff:g id="MONTH">MMMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>"</string> <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'å¹´'<xliff:g id="MONTH">MMMM</xliff:g>'月'<xliff:g id="DAY">d</xliff:g>'æ—¥'"</string> <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>'å¹´'"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'/'<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"æ£åˆ"</string> <string name="Noon">"æ£åˆ"</string> <string name="midnight">"åˆå‰0時"</string> <string name="Midnight">"åˆå‰0時"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>æ—¥"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>å¹´<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>æ—¥"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g>å¹´<xliff:g id="MONTH">%B</xliff:g>月"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%B</xliff:g>/<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>月<xliff:g id="DAY1">%3$s</xliff:g>日~<xliff:g id="MONTH2">%7$s</xliff:g>月<xliff:g id="DAY2">%8$s</xliff:g>æ—¥"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%b</xliff:g>/<xliff:g id="DAY">%-d</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g>å¹´<xliff:g id="MONTH">%b</xliff:g>月"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g>/<xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"日曜日"</string> <string name="day_of_week_long_monday">"月曜日"</string> @@ -632,20 +632,20 @@ <string name="day_of_week_medium_thursday">"(木)"</string> <string name="day_of_week_medium_friday">"(金)"</string> <string name="day_of_week_medium_saturday">"(土)"</string> - <string name="day_of_week_short_sunday">"(日)"</string> - <string name="day_of_week_short_monday">"(月)"</string> - <string name="day_of_week_short_tuesday">"(ç«ï¼‰"</string> - <string name="day_of_week_short_wednesday">"(水)"</string> - <string name="day_of_week_short_thursday">"(木)"</string> - <string name="day_of_week_short_friday">"(金)"</string> - <string name="day_of_week_short_saturday">"(土)"</string> - <string name="day_of_week_shorter_sunday">"(日)"</string> + <string name="day_of_week_short_sunday">"æ—¥"</string> + <string name="day_of_week_short_monday">"月"</string> + <string name="day_of_week_short_tuesday">"ç«"</string> + <string name="day_of_week_short_wednesday">"æ°´"</string> + <string name="day_of_week_short_thursday">"木"</string> + <string name="day_of_week_short_friday">"金"</string> + <string name="day_of_week_short_saturday">"土"</string> + <string name="day_of_week_shorter_sunday">"æ—¥"</string> <string name="day_of_week_shorter_monday">"月"</string> - <string name="day_of_week_shorter_tuesday">"(ç«ï¼‰"</string> + <string name="day_of_week_shorter_tuesday">"ç«"</string> <string name="day_of_week_shorter_wednesday">"æ°´"</string> - <string name="day_of_week_shorter_thursday">"(木)"</string> + <string name="day_of_week_shorter_thursday">"木"</string> <string name="day_of_week_shorter_friday">"金"</string> - <string name="day_of_week_shorter_saturday">"(土)"</string> + <string name="day_of_week_shorter_saturday">"土"</string> <string name="day_of_week_shortest_sunday">"æ—¥"</string> <string name="day_of_week_shortest_monday">"月"</string> <string name="day_of_week_shortest_tuesday">"ç«"</string> @@ -710,9 +710,9 @@ <string name="yes">"OK"</string> <string name="no">"ã‚ャンセル"</string> <string name="dialog_alert_title">"注æ„"</string> - <string name="capital_on">"オン"</string> - <string name="capital_off">"オフ"</string> - <string name="whichApplication">"æ“作ã®å®Œäº†ã«ä½¿ç”¨"</string> + <string name="capital_on">"ON"</string> + <string name="capital_off">"OFF"</string> + <string name="whichApplication">"ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’é¸æŠž"</string> <string name="alwaysUse">"常ã«ã“ã®æ“作ã§ä½¿ç”¨ã™ã‚‹"</string> <string name="clearDefaultHintMsg">"ホームã®[è¨å®š]>[アプリケーション]>[アプリケーションã®ç®¡ç†]ã§ãƒ‡ãƒ•ォルトè¨å®šã‚’クリアã—ã¾ã™ã€‚"</string> <string name="chooseActivity">"æ“作ã®é¸æŠž"</string> @@ -728,18 +728,18 @@ <string name="force_close">"強制終了"</string> <string name="wait">"待機"</string> <string name="debug">"デãƒãƒƒã‚°"</string> - <string name="sendText">"テã‚ã‚¹ãƒˆã®æ“作"</string> - <string name="volume_ringtone">"ç€ä¿¡éŸ³ã®éŸ³é‡"</string> + <string name="sendText">"ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’é¸æŠž"</string> + <string name="volume_ringtone">"ç€ä¿¡éŸ³é‡"</string> <string name="volume_music">"メディアã®éŸ³é‡"</string> <string name="volume_music_hint_playing_through_bluetooth">"Bluetooth経由ã§å†ç”Ÿä¸ã§ã™"</string> - <string name="volume_call">"ç€ä¿¡éŸ³ã®éŸ³é‡"</string> - <string name="volume_bluetooth_call">"Bluetoothç€ä¿¡éŸ³ã®éŸ³é‡"</string> + <string name="volume_call">"ç€ä¿¡éŸ³é‡"</string> + <string name="volume_bluetooth_call">"Bluetoothç€ä¿¡éŸ³é‡"</string> <string name="volume_alarm">"アラームã®éŸ³é‡"</string> - <string name="volume_notification">"通知音ã®éŸ³é‡"</string> + <string name="volume_notification">"通知音é‡"</string> <string name="volume_unknown">"音é‡"</string> <string name="ringtone_default">"デフォルトã®ç€ä¿¡éŸ³"</string> - <string name="ringtone_default_with_actual">"端末既定ã®ç€ä¿¡éŸ³ï¼ˆ<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> - <string name="ringtone_silent">"無音"</string> + <string name="ringtone_default_with_actual">"端末ã®åŸºæœ¬ç€ä¿¡éŸ³ï¼ˆ<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> + <string name="ringtone_silent">"サイレント"</string> <string name="ringtone_picker_title">"ç€ä¿¡éŸ³"</string> <string name="ringtone_unknown">"䏿˜Žãªç€ä¿¡éŸ³"</string> <plurals name="wifi_available"> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"一致ã™ã‚‹ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"</string> <string name="permlab_pkgUsageStats">"コンãƒãƒ¼ãƒãƒ³ãƒˆä½¿ç”¨çжæ³ã«é–¢ã™ã‚‹çµ±è¨ˆæƒ…å ±ã®æ›´æ–°"</string> <string name="permdesc_pkgUsageStats">"åŽé›†ã•れãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆä½¿ç”¨çжæ³ã«é–¢ã™ã‚‹çµ±è¨ˆæƒ…å ±ã®å¤‰æ›´ã‚’許å¯ã—ã¾ã™ã€‚通常ã®ã‚¢ãƒ—リケーションã§ã¯ä½¿ç”¨ã—ã¾ã›ã‚“。"</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"ダブルタップã§ã‚ºãƒ¼ãƒ ã—ã¾ã™"</string> + <string name="gadget_host_error_inflating">"ウィジェットã®å±•開エラー"</string> + <string name="ime_action_go">"移動"</string> + <string name="ime_action_search">"検索"</string> + <string name="ime_action_send">"é€ä¿¡"</string> + <string name="ime_action_next">"次ã¸"</string> + <string name="ime_action_done">"完了"</string> + <string name="ime_action_default">"実行"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-ko-rKR/arrays.xml b/core/res/res/values-ko-rKR/arrays.xml new file mode 100644 index 0000000..e245def --- /dev/null +++ b/core/res/res/values-ko-rKR/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>37560908</item> + <item>126987705</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 8fc7d12..f44332a 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"ë°œì‹ ìž ë²ˆí˜¸ê°€ 기본ì 으로 ì œí•œë˜ì§€ 않ìŒìœ¼ë¡œ ì„¤ì •ë©ë‹ˆë‹¤. ë‹¤ìŒ í†µí™”: ì œí•œë˜ì§€ 않ìŒ"</string> <string name="serviceNotProvisioned">"서비스가 준비ë˜ì§€ 않았습니다."</string> <string name="CLIRPermanent">"ë°œì‹ ìž ë²ˆí˜¸ ì„¤ì •ì„ ë³€ê²½í• ìˆ˜ 없습니다."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"ìŒì„±"</string> <string name="serviceClassData">"ë°ì´í„°"</string> <string name="serviceClassFAX">"팩스"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"ë¬´ìŒ ëª¨ë“œ"</string> <string name="global_action_silent_mode_on_status">"소리 꺼ì§"</string> <string name="global_action_silent_mode_off_status">"소리 켜ì§"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"비행기 모드"</string> + <string name="global_actions_airplane_mode_on_status">"비행기 모드 사용 안함"</string> + <string name="global_actions_airplane_mode_off_status">"비행기 모드 사용"</string> <string name="safeMode">"ì•ˆì „ 모드"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Android 시스템"</string> <string name="permgrouplab_costMoney">"ìš”ê¸ˆì´ ë¶€ê³¼ë˜ëŠ” 서비스"</string> <string name="permgroupdesc_costMoney">"ì‘ìš©í”„ë¡œê·¸ëž¨ì´ ìš”ê¸ˆì´ ë¶€ê³¼ë 수 있는 ìž‘ì—…ì„ í• ìˆ˜ 있습니다."</string> <string name="permgrouplab_messages">"메시지"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"ë¬´ì„ ì˜ ìœ„ì¹˜ ì—…ë°ì´íЏ ì•Œë¦¼ì„ í™œì„±í™”í•˜ê±°ë‚˜ ë¹„í™œì„±í™”í• ìˆ˜ 있습니다. ì¼ë°˜ ì‘용프로그램ì—서는 사용하지 않습니다."</string> <string name="permlab_checkinProperties">"ì²´í¬ì¸ ì†ì„± 액세스"</string> <string name="permdesc_checkinProperties">"ì²´í¬ì¸ 서비스ì—서 업로드한 ì†ì„±ì— 대한 ì½ê¸°/쓰기 액세스를 허용합니다. ì¼ë°˜ ì‘용프로그램ì—서는 사용하지 않습니다."</string> - <string name="permlab_bindGadget">"ê°€ì ¯ ì„ íƒ"</string> - <string name="permdesc_bindGadget">"ì–´ëŠ ì‘ìš©í”„ë¡œê·¸ëž¨ì´ ì–´ëŠ ê°€ì ¯ì„ ì‚¬ìš©í• ìˆ˜ 있는지 ì‹œìŠ¤í…œì— ì•Œë ¤ 주는 ê¶Œí•œì„ ë³¸ ì‘ìš©í”„ë¡œê·¸ëž¨ì— ë¶€ì—¬í•©ë‹ˆë‹¤. ì´ ê¶Œí•œì„ ì‚¬ìš©í•˜ë©´ ì‘ìš©í”„ë¡œê·¸ëž¨ì´ ê°œì¸ ë°ì´í„°ì— 대한 액세스 ê¶Œí•œì„ ë‹¤ë¥¸ ì‘ìš©í”„ë¡œê·¸ëž¨ì— ì œê³µí• ìˆ˜ 있습니다. ì¼ë°˜ ì‘ìš©í”„ë¡œê·¸ëž¨ì€ ì´ ê¶Œí•œì„ ì‚¬ìš©í• ìˆ˜ 없습니다."</string> + <string name="permlab_bindGadget">"ìœ„ì ¯ ì„ íƒ"</string> + <string name="permdesc_bindGadget">"ì‘ìš©í”„ë¡œê·¸ëž¨ì´ ì‘용프로그램ì—서 ì‚¬ìš©í• ìˆ˜ 있는 ìœ„ì ¯ì„ ì‹œìŠ¤í…œì— ì•Œë¦´ 수 있습니다. ì´ ê¶Œí•œì„ ê°–ëŠ” ì‘ìš©í”„ë¡œê·¸ëž¨ì€ ê°œì¸ ë°ì´í„°ì— 대한 액세스 ê¶Œí•œì„ ë‹¤ë¥¸ ì‘ìš©í”„ë¡œê·¸ëž¨ì— ë¶€ì—¬í• ìˆ˜ 있습니다. ì¼ë°˜ ì‘용프로그램ì—서는 사용하지 않습니다."</string> <string name="permlab_modifyPhoneState">"ì „í™”ê¸° ìƒíƒœ ìˆ˜ì •"</string> <string name="permdesc_modifyPhoneState">"ì‘ìš©í”„ë¡œê·¸ëž¨ì´ ìž¥ì¹˜ì˜ ì „í™” ê¸°ëŠ¥ì„ ì œì–´í• ìˆ˜ 있습니다. ì´ ê¶Œí•œì„ ê°–ëŠ” ì‘ìš©í”„ë¡œê·¸ëž¨ì€ ì‚¬ìš©ìžì—게 알리지 ì•Šê³ ë„¤íŠ¸ì›Œí¬ë¥¼ ì „í™˜í•˜ê±°ë‚˜, ì „í™” ë¬´ì„ ê¸°ëŠ¥ì„ ì¼œê³ ëŒ ìˆ˜ 있습니다."</string> <string name="permlab_readPhoneState">"ì „í™”ê¸° ìƒíƒœ ì½ê¸°"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"ë¹„ìƒ ì „í™”"</string> <string name="lockscreen_pattern_correct">"맞습니다."</string> <string name="lockscreen_pattern_wrong">"죄송합니다. 다시 시ë„하세요."</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"ì¶©ì „ 중(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"ì¶©ì „ê¸°ë¥¼ 연결하세요."</string> <string name="lockscreen_missing_sim_message_short">"SIM 카드가 없습니다."</string> <string name="lockscreen_missing_sim_message">"ì „í™”ê¸°ì— SIM 카드가 없습니다."</string> <string name="lockscreen_missing_sim_instructions">"SIM 카드를 삽입하세요."</string> <string name="lockscreen_network_locked_message">"ë„¤íŠ¸ì›Œí¬ ìž ê¹€"</string> <string name="lockscreen_sim_puk_locked_message">"SIM ì¹´ë“œì˜ PUKê°€ ìž ê²¨ 있습니다."</string> - <string name="lockscreen_sim_puk_locked_instructions">"ê³ ê°ì§€ì›íŒ€ì— 문ì˜í•˜ì„¸ìš”."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM 카드가 ìž ê²¨ 있습니다."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM 카드 ìž ê¸ˆí•´ì œ 중..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"ìž ê¸ˆí•´ì œ íŒ¨í„´ì„ <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 ê°€ì ¸ì™”ìŠµë‹ˆë‹¤. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>ì´ˆ í›„ì— ë‹¤ì‹œ 시ë„하세요."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g>ì´ˆ í›„ì— ë‹¤ì‹œ ìž…ë ¥í•˜ì„¸ìš”."</string> <string name="lockscreen_forgot_pattern_button_text">"íŒ¨í„´ì„ ìžŠìœ¼ì…¨ë‚˜ìš”?"</string> <string name="lockscreen_glogin_too_many_attempts">"íŒ¨í„´ì„ ë„ˆë¬´ ë§Žì´ ì‹œë„했습니다."</string> - <string name="lockscreen_glogin_instructions">"ìž ê¸ˆí•´ì œí•˜ë ¤ë©´"\n"Google ê³„ì •ìœ¼ë¡œ 로그ì¸í•˜ì„¸ìš”."</string> + <string name="lockscreen_glogin_instructions">"ìž ê¸ˆí•´ì œí•˜ë ¤ë©´ Google ê³„ì •ìœ¼ë¡œ 로그ì¸í•˜ì„¸ìš”."</string> <string name="lockscreen_glogin_username_hint">"ì‚¬ìš©ìž ì´ë¦„(ì´ë©”ì¼)"</string> <string name="lockscreen_glogin_password_hint">"비밀번호"</string> <string name="lockscreen_glogin_submit_button">"로그ì¸"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"알림 지우기"</string> <string name="status_bar_no_notifications_title">"알림 ì—†ìŒ"</string> <string name="status_bar_ongoing_events_title">"사용 중"</string> <string name="status_bar_latest_events_title">"알림"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"ì¶©ì „ 중..."</string> <string name="battery_low_title">"ì¶©ì „ê¸°ë¥¼ 연결하세요."</string> <string name="battery_low_subtitle">"배터리 ì „ì›ì´ 부족합니다."</string> @@ -552,6 +555,7 @@ <string name="monthly">"매월"</string> <string name="yearly">"매년"</string> <string name="VideoView_error_title">"ë™ì˜ìƒ ìž¬ìƒ ì•ˆ ë¨"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"죄송합니다. ì´ ê¸°ê¸°ë¡œì˜ ìŠ¤íŠ¸ë¦¬ë°ì— ì 합하지 ì•Šì€ ë™ì˜ìƒìž…니다."</string> <string name="VideoView_error_text_unknown">"죄송합니다. ë™ì˜ìƒì„ 재ìƒí• 수 없습니다."</string> <string name="VideoView_error_button">"확ì¸"</string> <string name="am">"AM"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"ì •ì˜¤"</string> <string name="Noon">"ì •ì˜¤"</string> <string name="midnight">"ìžì •"</string> <string name="Midnight">"ìžì •"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> <xliff:g id="MONTH">%b</xliff:g>, <xliff:g id="DAY">%-d</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"ì¼ìš”ì¼"</string> <string name="day_of_week_long_monday">"월요ì¼"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"ì¼ì¹˜í•˜ëŠ” 활ë™ì´ 없습니다."</string> <string name="permlab_pkgUsageStats">"구성요소 사용 통계 ì—…ë°ì´íЏ"</string> <string name="permdesc_pkgUsageStats">"ìˆ˜ì§‘ëœ êµ¬ì„±ìš”ì†Œ 사용 통계를 ìˆ˜ì •í• ìˆ˜ 있는 ê¶Œí•œì„ ë¶€ì—¬í•©ë‹ˆë‹¤. ì¼ë°˜ ì‘ìš©í”„ë¡œê·¸ëž¨ì€ ì´ ê¶Œí•œì„ ì‚¬ìš©í• ìˆ˜ 없습니다."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"확대/ì¶•ì†Œí•˜ë ¤ë©´ ë‘ ë²ˆ íƒí•˜ì„¸ìš”."</string> + <string name="gadget_host_error_inflating">"ìœ„ì ¯ì„ í™•ìž¥í•˜ëŠ” 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."</string> + <string name="ime_action_go">"ì´ë™"</string> + <string name="ime_action_search">"검색"</string> + <string name="ime_action_send">"ì „ì†¡"</string> + <string name="ime_action_next">"다ìŒ"</string> + <string name="ime_action_done">"완료"</string> + <string name="ime_action_default">"실행"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-lt-rLT/arrays.xml b/core/res/res/values-lt-rLT/arrays.xml new file mode 100644 index 0000000..0d5a3aa --- /dev/null +++ b/core/res/res/values-lt-rLT/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>55169438</item> + <item>23881275</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-lv-rLV/arrays.xml b/core/res/res/values-lv-rLV/arrays.xml new file mode 100644 index 0000000..d9ba7a4 --- /dev/null +++ b/core/res/res/values-lv-rLV/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>55879635</item> + <item>24603189</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index c1944a4..7bed159 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Nummervisning er ikke begrenset som standard. Neste anrop: Ikke begrenset"</string> <string name="serviceNotProvisioned">"SIM-kortet er ikke tilrettelagt for tjenesten."</string> <string name="CLIRPermanent">"Kunne ikke endre innstilling for nummervisning."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Tale"</string> <string name="serviceClassData">"Data"</string> <string name="serviceClassFAX">"Fax"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Stillemodus"</string> <string name="global_action_silent_mode_on_status">"Lyden er av"</string> <string name="global_action_silent_mode_off_status">"Lyden er pÃ¥"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Flymodus"</string> + <string name="global_actions_airplane_mode_on_status">"Flymodus er pÃ¥"</string> + <string name="global_actions_airplane_mode_off_status">"Flymodus er av"</string> <string name="safeMode">"Sikkermodus"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Android-system"</string> <string name="permgrouplab_costMoney">"Betaltjenester"</string> <string name="permgroupdesc_costMoney">"Lar applikasjoner utføre operasjoner som kan koste deg penger."</string> <string name="permgrouplab_messages">"Meldinger"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"Nødanrop"</string> <string name="lockscreen_pattern_correct">"Riktig!"</string> <string name="lockscreen_pattern_wrong">"Beklager, prøv igjen:"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"Lader (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Koble til en batterilader."</string> <string name="lockscreen_missing_sim_message_short">"Mangler SIM-kort."</string> <string name="lockscreen_missing_sim_message">"Ikke noe SIM-kort i telefonen."</string> <string name="lockscreen_missing_sim_instructions">"Sett inn et SIM-kort."</string> <string name="lockscreen_network_locked_message">"Nettverk ikke tillatt"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-kortet er PUK-lÃ¥st."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Vennligst ring kundeservice."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-kortet er lÃ¥st."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"LÃ¥ser opp SIM-kort…"</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Please try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Prøv igjen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string> <string name="lockscreen_forgot_pattern_button_text">"Glemt mønsteret?"</string> <string name="lockscreen_glogin_too_many_attempts">"Too many pattern attempts!"</string> - <string name="lockscreen_glogin_instructions">"To unlock,"\n"sign in with your Google account"</string> + <string name="lockscreen_glogin_instructions">"To unlock,BREAKsign in with your Google account"</string> <string name="lockscreen_glogin_username_hint">"Username (email)"</string> <string name="lockscreen_glogin_password_hint">"Password"</string> <string name="lockscreen_glogin_submit_button">"Sign in"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Fjern varslinger"</string> <string name="status_bar_no_notifications_title">"Ingen varslinger"</string> <string name="status_bar_ongoing_events_title">"Aktiviteter"</string> <string name="status_bar_latest_events_title">"Varslinger"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"Lader…"</string> <string name="battery_low_title">"Koble til en lader"</string> <string name="battery_low_subtitle">"Batteriet er nesten tomt:"</string> @@ -551,8 +554,9 @@ <string name="weekly">"Hver <xliff:g id="DAY">%s</xliff:g>"</string> <string name="monthly">"En gang i mÃ¥neden"</string> <string name="yearly">"En gang i Ã¥ret"</string> - <string name="VideoView_error_title">"Cannot play video"</string> - <string name="VideoView_error_text_unknown">"Sorry, this video cannot be played."</string> + <string name="VideoView_error_title">"Kan ikke spille video"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Beklager, denne videoen er ikke gyldig for streaming til denne enheten."</string> + <string name="VideoView_error_text_unknown">"Beklager, kan ikke spille denne videoen."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> <string name="pm">"PM"</string> @@ -573,18 +577,17 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"middag"</string> <string name="Noon">"Middag"</string> <string name="midnight">"midnatt"</string> <string name="Midnight">"Midnatt"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> @@ -612,11 +615,10 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"søndag"</string> <string name="day_of_week_long_monday">"mandag"</string> @@ -798,18 +800,16 @@ <string name="activity_list_empty">"Fant ingen tilsvarende aktiviteter"</string> <string name="permlab_pkgUsageStats">"oppdater statistikk over komponentbruk"</string> <string name="permdesc_pkgUsageStats">"Tillater endring av innsamlet data om bruk av komponenter. Ikke ment for vanlige applikasjoner."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Trykk to ganger for zoomkontroll"</string> + <string name="gadget_host_error_inflating">"Feil under oppakking av gadget"</string> + <string name="ime_action_go">"GÃ¥"</string> + <string name="ime_action_search">"Søk"</string> + <string name="ime_action_send">"Send"</string> + <string name="ime_action_next">"Neste"</string> + <string name="ime_action_done">"Utført"</string> + <string name="ime_action_default">"Utfør"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-nl-rBE/arrays.xml b/core/res/res/values-nl-rBE/arrays.xml new file mode 100644 index 0000000..9e93a09 --- /dev/null +++ b/core/res/res/values-nl-rBE/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>50854509</item> + <item>4376678</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>5</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-nl-rNL/arrays.xml b/core/res/res/values-nl-rNL/arrays.xml new file mode 100644 index 0000000..fe5422b --- /dev/null +++ b/core/res/res/values-nl-rNL/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>51589256</item> + <item>4774396</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 725e369..fc7ddca 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Beller-id standaard ingesteld op \'onbeperkt\'. Volgende oproep: onbeperkt."</string> <string name="serviceNotProvisioned">"Service niet voorzien."</string> <string name="CLIRPermanent">"De instelling voor beller-id kan niet worden gewijzigd."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Spraak"</string> <string name="serviceClassData">"Gegevens"</string> <string name="serviceClassFAX">"FAX"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Stille modus"</string> <string name="global_action_silent_mode_on_status">"Geluid is UIT"</string> <string name="global_action_silent_mode_off_status">"Geluid is AAN"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Vliegmodus"</string> + <string name="global_actions_airplane_mode_on_status">"Vliegmodus is AAN"</string> + <string name="global_actions_airplane_mode_off_status">"Vliegmodus is UIT"</string> <string name="safeMode">"Veilige modus"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Android-systeem"</string> <string name="permgrouplab_costMoney">"Services waarvoor u moet betalen"</string> <string name="permgroupdesc_costMoney">"Toepassingen toestaan activiteiten uit te voeren waarvoor mogelijk kosten in rekening worden gebracht."</string> <string name="permgrouplab_messages">"Uw berichten"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Hiermee kunnen updatemeldingen voor locaties van de radio worden ingeschakeld/uitgeschakeld. Niet voor gebruik door normale toepassingen."</string> <string name="permlab_checkinProperties">"toegang tot checkin-eigenschappen"</string> <string name="permdesc_checkinProperties">"Hiermee wordt lees-/schrijftoegang gegeven tot eigenschappen die door de checkin-service zijn geüpload. Niet voor gebruik door normale toepassingen."</string> - <string name="permlab_bindGadget">"gadgets kiezen"</string> - <string name="permdesc_bindGadget">"Hiermee kan een toepassing het systeem melden welke gadgets door welke toepassing kunnen worden gebruikt. Met deze toestemming kunnen toepassingen andere toepassingen toegang geven tot persoonlijke gegevens. Niet voor gebruik door normale toepassingen."</string> + <string name="permlab_bindGadget">"widgets kiezen"</string> + <string name="permdesc_bindGadget">"Hiermee kan een toepassing het systeem melden welke widgets door welke toepassing kunnen worden gebruikt. Met deze toestemming kunnen toepassingen andere toepassingen toegang geven tot persoonlijke gegevens. Niet voor gebruik door normale toepassingen."</string> <string name="permlab_modifyPhoneState">"telefoonstatus wijzigen"</string> <string name="permdesc_modifyPhoneState">"Hiermee kan de toepassing de telefoonfuncties van het apparaat beheren. Een toepassing met deze machtiging kan schakelen tussen netwerken, de radio van de telefoon in- of uitschakelen en dergelijke zonder dat u hiervan op de hoogte wordt gesteld."</string> <string name="permlab_readPhoneState">"telefoonstatus lezen"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"Noodoproep"</string> <string name="lockscreen_pattern_correct">"Juist!"</string> <string name="lockscreen_pattern_wrong">"Probeer het opnieuw"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"Opladen (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Sluit de oplader aan."</string> <string name="lockscreen_missing_sim_message_short">"Geen SIM-kaart."</string> <string name="lockscreen_missing_sim_message">"Geen SIM-kaart in telefoon."</string> <string name="lockscreen_missing_sim_instructions">"Plaats een SIM-kaart."</string> <string name="lockscreen_network_locked_message">"Netwerk geblokkeerd"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-kaart is geblokkeerd met PUK-code."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Neem contact op met de klantenservice."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-kaart is geblokkeerd."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM-kaart ontgrendelen..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"U heeft uw deblokkeringspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. "\n\n"Probeer het over <xliff:g id="NUMBER_1">%d</xliff:g> seconden opnieuw."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Probeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw."</string> <string name="lockscreen_forgot_pattern_button_text">"Patroon vergeten?"</string> <string name="lockscreen_glogin_too_many_attempts">"Te veel patroonpogingen!"</string> - <string name="lockscreen_glogin_instructions">"U moet zich aanmelden bij uw Google-account"\n"om te ontgrendelen"</string> + <string name="lockscreen_glogin_instructions">"Om te ontgrendelen, moet U zich eerst bij uw Google-account aanmelden"</string> <string name="lockscreen_glogin_username_hint">"Gebruikersnaam (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"Wachtwoord"</string> <string name="lockscreen_glogin_submit_button">"Aanmelden"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Meldingen wissen"</string> <string name="status_bar_no_notifications_title">"Geen meldingen"</string> <string name="status_bar_ongoing_events_title">"Actief"</string> <string name="status_bar_latest_events_title">"Meldingen"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"Opladen..."</string> <string name="battery_low_title">"Sluit de oplader aan"</string> <string name="battery_low_subtitle">"De accu raakt op:"</string> @@ -552,6 +555,7 @@ <string name="monthly">"Maandelijks"</string> <string name="yearly">"Jaarlijks"</string> <string name="VideoView_error_title">"Video kan niet worden afgespeeld"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Deze video kan helaas niet worden gestreamd naar dit apparaat."</string> <string name="VideoView_error_text_unknown">"Deze video kan niet worden afgespeeld."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"am"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"twaalf uur \'s middags"</string> <string name="Noon">"Twaalf uur \'s middags"</string> <string name="midnight">"middernacht"</string> <string name="Midnight">"Middernacht"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Zondag"</string> <string name="day_of_week_long_monday">"Maandag"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"Geen overeenkomende activiteiten gevonden"</string> <string name="permlab_pkgUsageStats">"gebruiksstatistieken van component bijwerken"</string> <string name="permdesc_pkgUsageStats">"Hiermee kunnen verzamelde gebruiksstatistieken van een component worden gewijzigd. Niet voor gebruik door normale toepassingen."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Tik twee keer voor zoomregeling"</string> + <string name="gadget_host_error_inflating">"Fout bij uitbreiden van widget"</string> + <string name="ime_action_go">"Ga"</string> + <string name="ime_action_search">"Zoeken"</string> + <string name="ime_action_send">"Verzenden"</string> + <string name="ime_action_next">"Volgende"</string> + <string name="ime_action_done">"Gereed"</string> + <string name="ime_action_default">"Uitvoeren"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-no-rNO/arrays.xml b/core/res/res/values-no-rNO/arrays.xml new file mode 100644 index 0000000..500e8e1 --- /dev/null +++ b/core/res/res/values-no-rNO/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>59910761</item> + <item>10749092</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-pl-rPL/arrays.xml b/core/res/res/values-pl-rPL/arrays.xml new file mode 100644 index 0000000..950248c --- /dev/null +++ b/core/res/res/values-pl-rPL/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>52235474</item> + <item>21004057</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 641d335..9ac2795 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Identyfikator dzwoniÄ…cego ustawiony jest domyÅ›lnie na „nie zastrzeżonyâ€. NastÄ™pne połączenie: nie zastrzeżony"</string> <string name="serviceNotProvisioned">"UsÅ‚uga nie jest Å›wiadczona."</string> <string name="CLIRPermanent">"Nie można zmienić ustawienia identyfikatora dzwoniÄ…cego."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"GÅ‚os"</string> <string name="serviceClassData">"Dane"</string> <string name="serviceClassFAX">"FAKS"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Tryb cichy"</string> <string name="global_action_silent_mode_on_status">"DźwiÄ™k jest wyłączony"</string> <string name="global_action_silent_mode_off_status">"DźwiÄ™k jest włączony"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Tryb lotniczy"</string> + <string name="global_actions_airplane_mode_on_status">"Tryb lotniczy jest włączony"</string> + <string name="global_actions_airplane_mode_off_status">"Tryb lotniczy jest wyłączony"</string> <string name="safeMode">"Tryb awaryjny"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"System Android"</string> <string name="permgrouplab_costMoney">"UsÅ‚ugi pÅ‚atne"</string> <string name="permgroupdesc_costMoney">"Pozwól aplikacjom na wykonywanie pÅ‚atnych operacji."</string> <string name="permgrouplab_messages">"Twoje wiadomoÅ›ci"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Pozwala włączyć/wyłączyć powiadomienia o aktualizacji poÅ‚ożenia przez radio. Nie wykorzystywane przez normalne aplikacje."</string> <string name="permlab_checkinProperties">"dostÄ™p do wÅ‚aÅ›ciwoÅ›ci usÅ‚ugi rezerwacji"</string> <string name="permdesc_checkinProperties">"Pozwala na dostÄ™p z uprawnieniami do odczytu/zapisu do wÅ‚aÅ›ciwoÅ›ci przesÅ‚anych przez usÅ‚ugÄ™ rezerwacji. Nie wykorzystywane przez normalne aplikacje."</string> - <string name="permlab_bindGadget">"wybieranie gadżetów"</string> - <string name="permdesc_bindGadget">"Zezwala aplikacjom na wskazywanie systemowi, które gadżety mogÄ… być używane przez inne aplikacje. Z użyciem tego pozwolenia aplikacje mogÄ… udzielać dostÄ™pu do danych osobistych innym aplikacjom. Nie jest ono przeznaczone dla zwykÅ‚ych aplikacji."</string> + <string name="permlab_bindGadget">"wybieranie widżetów"</string> + <string name="permdesc_bindGadget">"Zezwala aplikacjom na wskazywanie systemowi, które widżety mogÄ… być używane przez inne aplikacje. Z użyciem tego pozwolenia aplikacje mogÄ… udzielać dostÄ™pu do danych osobistych innym aplikacjom. Nie jest ono przeznaczone dla zwykÅ‚ych aplikacji."</string> <string name="permlab_modifyPhoneState">"zmiana stanu telefonu"</string> <string name="permdesc_modifyPhoneState">"Pozwala aplikacji na kontrolowanie funkcji telefonu w urzÄ…dzeniu. Aplikacja z tymi uprawnieniami może przełączać sieci, włączać i wyłączać radio itp. bez informowania użytkownika."</string> <string name="permlab_readPhoneState">"czytanie stanu telefonu"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"Połączenie alarmowe"</string> <string name="lockscreen_pattern_correct">"Poprawnie!"</string> <string name="lockscreen_pattern_wrong">"Niestety, spróbuj ponownie"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"Åadowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Podłącz Å‚adowarkÄ™."</string> <string name="lockscreen_missing_sim_message_short">"Brak karty SIM."</string> <string name="lockscreen_missing_sim_message">"Brak karty SIM w telefonie."</string> <string name="lockscreen_missing_sim_instructions">"Włóż kartÄ™ SIM."</string> <string name="lockscreen_network_locked_message">"Sieć zablokowana"</string> <string name="lockscreen_sim_puk_locked_message">"Karta SIM jest zablokowana kodem PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Skontaktuj siÄ™ z dziaÅ‚em obsÅ‚ugi klienta."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"Karta SIM jest zablokowana."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Odblokowywanie karty SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Wzór odblokowania zostaÅ‚ nieprawidÅ‚owo narysowany <xliff:g id="NUMBER_0">%d</xliff:g> razy. "\n\n"Spróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> sekund."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> sekund."</string> <string name="lockscreen_forgot_pattern_button_text">"ZapomniaÅ‚eÅ› wzoru?"</string> <string name="lockscreen_glogin_too_many_attempts">"Zbyt wiele prób narysowania wzoru!"</string> - <string name="lockscreen_glogin_instructions">"Aby odblokować,"\n"zaloguj siÄ™ na koncie Google"</string> + <string name="lockscreen_glogin_instructions">"Aby odblokować, zaloguj siÄ™ za pomocÄ… konta Google"</string> <string name="lockscreen_glogin_username_hint">"Nazwa użytkownika (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"HasÅ‚o"</string> <string name="lockscreen_glogin_submit_button">"Zaloguj"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Wyczyść powiadomienia"</string> <string name="status_bar_no_notifications_title">"Brak powiadomieÅ„"</string> <string name="status_bar_ongoing_events_title">"TrwajÄ…ce"</string> <string name="status_bar_latest_events_title">"Powiadomienia"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"Åadowanie..."</string> <string name="battery_low_title">"Podłącz Å‚adowarkÄ™"</string> <string name="battery_low_subtitle">"Bateria siÄ™ rozÅ‚adowuje:"</string> @@ -552,6 +555,7 @@ <string name="monthly">"MiesiÄ™cznie"</string> <string name="yearly">"Co roku"</string> <string name="VideoView_error_title">"Nie można odtworzyć filmu wideo"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"Przepraszamy, ten film wideo nie nadaje siÄ™ do przesyÅ‚ania strumieniowego do tego urzÄ…dzenia."</string> <string name="VideoView_error_text_unknown">"Niestety, nie można odtworzyć tego filmu wideo."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"rano"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"poÅ‚udnie"</string> <string name="Noon">"PoÅ‚udnie"</string> <string name="midnight">"północ"</string> <string name="Midnight">"Północ"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"niedziela"</string> <string name="day_of_week_long_monday">"poniedziaÅ‚ek"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"Nie znaleziono pasujÄ…cych dziaÅ‚aÅ„"</string> <string name="permlab_pkgUsageStats">"aktualizowanie statystyk użycia komponentu"</string> <string name="permdesc_pkgUsageStats">"Zezwala na modyfikacje zebranych statystyk użycia komponentu. Nieprzeznaczone dla zwykÅ‚ych aplikacji."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Dotknij dwukrotnie, aby sterować powiÄ™kszeniem"</string> + <string name="gadget_host_error_inflating">"Błąd podczas wyodrÄ™bniania widżetu"</string> + <string name="ime_action_go">"Przejdź"</string> + <string name="ime_action_search">"Szukaj"</string> + <string name="ime_action_send">"WyÅ›lij"</string> + <string name="ime_action_next">"Dalej"</string> + <string name="ime_action_done">"Gotowe"</string> + <string name="ime_action_default">"Wykonaj"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-pt-rBR/arrays.xml b/core/res/res/values-pt-rBR/arrays.xml new file mode 100644 index 0000000..389d0c4 --- /dev/null +++ b/core/res/res/values-pt-rBR/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>-22863878</item> + <item>-43244097</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-pt-rPT/arrays.xml b/core/res/res/values-pt-rPT/arrays.xml new file mode 100644 index 0000000..a1ba15a --- /dev/null +++ b/core/res/res/values-pt-rPT/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>38707163</item> + <item>-9135517</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-ro-rRO/arrays.xml b/core/res/res/values-ro-rRO/arrays.xml new file mode 100644 index 0000000..c5579d0 --- /dev/null +++ b/core/res/res/values-ro-rRO/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>45943161</item> + <item>24966760</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-ru-rRU/arrays.xml b/core/res/res/values-ru-rRU/arrays.xml new file mode 100644 index 0000000..733fdc0 --- /dev/null +++ b/core/res/res/values-ru-rRU/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>55750449</item> + <item>37621136</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>2</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index ba88667..07b58ed 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Идентификатор звонÑщего по умолчанию не ограничен. Следующий вызов: не ограничен"</string> <string name="serviceNotProvisioned">"УÑлуга не предоÑтавлÑетÑÑ."</string> <string name="CLIRPermanent">"ÐÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ наÑтройки идентификатора звонÑщего."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"ГолоÑ"</string> <string name="serviceClassData">"Данные"</string> <string name="serviceClassFAX">"ФÐКС"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"Беззвучный режим"</string> <string name="global_action_silent_mode_on_status">"Звук выключен"</string> <string name="global_action_silent_mode_off_status">"Звук включен"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"Режим полета"</string> + <string name="global_actions_airplane_mode_on_status">"Режим полета ВКЛЮЧЕÐ"</string> + <string name="global_actions_airplane_mode_off_status">"Режим полета ВЫКЛЮЧЕÐ"</string> <string name="safeMode">"БезопаÑный режим"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"СиÑтема Android"</string> <string name="permgrouplab_costMoney">"Платные Ñлужбы"</string> <string name="permgroupdesc_costMoney">"Разрешить приложениÑм выполнÑть дейÑтвиÑ, за которые может взиматьÑÑ Ð¿Ð»Ð°Ñ‚Ð°."</string> <string name="permgrouplab_messages">"СообщениÑ"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"Разрешает включение/отключение уведомлений о меÑтоположении по радиоÑвÑзи. Ðе иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string> <string name="permlab_checkinProperties">"открывать ÑвойÑтва проверки"</string> <string name="permdesc_checkinProperties">"Разрешает доÑтуп на чтение и запиÑÑŒ к ÑвойÑтвам, загруженным Ñлужбой проверки. Ðе иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string> - <string name="permlab_bindGadget">"выбирать гаджеты"</string> - <string name="permdesc_bindGadget">"ПозволÑет приложению Ñообщить ÑиÑтеме, какие Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ иÑпользовать какие гаджеты. Ðто разрешение позволÑет приложениÑм предоÑтавлÑть другим приложениÑм доÑтуп к личной информации. Ðе предназначено Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string> + <string name="permlab_bindGadget">"выбирать виджеты"</string> + <string name="permdesc_bindGadget">"ПозволÑет приложению Ñообщить ÑиÑтеме, какие Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ иÑпользовать какие виджеты. Ðто разрешение позволÑет приложениÑм предоÑтавлÑть другим приложениÑм доÑтуп к личной информации. Ðе предназначено Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string> <string name="permlab_modifyPhoneState">"изменÑть ÑоÑтоÑние телефона"</string> <string name="permdesc_modifyPhoneState">"ПозволÑет приложению управлÑть телефонными функциÑми уÑтройÑтва. Приложение Ñ Ñ‚Ð°ÐºÐ¸Ð¼Ð¸ полномочиÑми может переключать Ñети, включать и выключать радиоÑвÑзь и Ñ‚.д., не ÑÐ¾Ð¾Ð±Ñ‰Ð°Ñ Ð²Ð°Ð¼ об Ñтом."</string> <string name="permlab_readPhoneState">"Ñчитывать ÑоÑтоÑние телефона"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"ÐкÑтренный вызов"</string> <string name="lockscreen_pattern_correct">"Верно!"</string> <string name="lockscreen_pattern_wrong">"Ðеверно, попробуйте еще раз"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"Идет зарÑдка (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"Подключите зарÑдное уÑтройÑтво."</string> <string name="lockscreen_missing_sim_message_short">"Ðет SIM-карты."</string> <string name="lockscreen_missing_sim_message">"Ð’ телефоне нет SIM-карты."</string> <string name="lockscreen_missing_sim_instructions">"Ð’Ñтавьте SIM-карту."</string> <string name="lockscreen_network_locked_message">"Заблокирована Ñетью"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-карта заблокирована PUK-кодом."</string> - <string name="lockscreen_sim_puk_locked_instructions">"СвÑжитеÑÑŒ Ñо Ñлужбой поддержки."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-карта заблокирована."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Разблокировка SIM-карты..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Ð’Ñ‹ неправильно воÑпроизвели комбинацию разблокировки <xliff:g id="NUMBER_0">%d</xliff:g> раз. "\n\n"Повторите попытку через <xliff:g id="NUMBER_1">%d</xliff:g> Ñек."</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> Ñек."</string> <string name="lockscreen_forgot_pattern_button_text">"Забыли комбинацию?"</string> <string name="lockscreen_glogin_too_many_attempts">"Слишком много попыток ввеÑти комбинацию!"</string> - <string name="lockscreen_glogin_instructions">"Ð”Ð»Ñ Ñ€Ð°Ð·Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸"\n"войдите Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñвоего аккаунта Google"</string> + <string name="lockscreen_glogin_instructions">"Ð”Ð»Ñ Ñ€Ð°Ð·Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸ войдите Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñвоего аккаунта Google"</string> <string name="lockscreen_glogin_username_hint">"Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (Ð°Ð´Ñ€ÐµÑ Ñлектронной почты)"</string> <string name="lockscreen_glogin_password_hint">"Пароль"</string> <string name="lockscreen_glogin_submit_button">"Войти"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"ОчиÑтить уведомлениÑ"</string> <string name="status_bar_no_notifications_title">"Ðет уведомлений"</string> <string name="status_bar_ongoing_events_title">"Текущие"</string> <string name="status_bar_latest_events_title">"УведомлениÑ"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"Идет зарÑдка..."</string> <string name="battery_low_title">"Подключите зарÑдное уÑтройÑтво"</string> <string name="battery_low_subtitle">"Ð‘Ð°Ñ‚Ð°Ñ€ÐµÑ ÑадитÑÑ:"</string> @@ -552,6 +555,7 @@ <string name="monthly">"ЕжемеÑÑчно"</string> <string name="yearly">"Ежегодно"</string> <string name="VideoView_error_title">"Ðе удаетÑÑ Ð²Ð¾ÑпроизвеÑти видео"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"К Ñожалению, Ñто видео не подходит Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾ÐºÐ¾Ð²Ð¾Ð³Ð¾ воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð½Ð° данном уÑтройÑтве."</string> <string name="VideoView_error_text_unknown">"К Ñожалению, Ñто видео Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ð¾ÑпроизвеÑти."</string> <string name="VideoView_error_button">"ОК"</string> <string name="am">"AM"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"полдень"</string> <string name="Noon">"Полдень"</string> <string name="midnight">"полночь"</string> <string name="Midnight">"Полночь"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> <xliff:g id="MONTH">%B</xliff:g> г."</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g> г."</string> + <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"воÑкреÑенье"</string> <string name="day_of_week_long_monday">"понедельник"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"ПодходÑщих дейÑтвий не найдено"</string> <string name="permlab_pkgUsageStats">"обновлÑть ÑтатиÑтику иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ‚Ð¾Ð²"</string> <string name="permdesc_pkgUsageStats">"ПозволÑет изменÑть Ñобранную ÑтатиÑтику иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ‚Ð¾Ð². Ðе предназначено Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"Ðажмите дважды Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð°Ñштаба"</string> + <string name="gadget_host_error_inflating">"Ошибка при наполнении виджета"</string> + <string name="ime_action_go">"Выбрать"</string> + <string name="ime_action_search">"ПоиÑк"</string> + <string name="ime_action_send">"Отправить"</string> + <string name="ime_action_next">"Далее"</string> + <string name="ime_action_done">"Готово"</string> + <string name="ime_action_default">"Выполнить"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-sk-rSK/arrays.xml b/core/res/res/values-sk-rSK/arrays.xml new file mode 100644 index 0000000..b065ba5 --- /dev/null +++ b/core/res/res/values-sk-rSK/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>48669026</item> + <item>19699024</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-sl-rSI/arrays.xml b/core/res/res/values-sl-rSI/arrays.xml new file mode 100644 index 0000000..4158157 --- /dev/null +++ b/core/res/res/values-sl-rSI/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>46151241</item> + <item>14995463</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-sr-rRS/arrays.xml b/core/res/res/values-sr-rRS/arrays.xml new file mode 100644 index 0000000..98dc954 --- /dev/null +++ b/core/res/res/values-sr-rRS/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>44016521</item> + <item>21005859</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-sv-rSE/arrays.xml b/core/res/res/values-sv-rSE/arrays.xml new file mode 100644 index 0000000..988d356 --- /dev/null +++ b/core/res/res/values-sv-rSE/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>59330650</item> + <item>18067360</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-th-rTH/arrays.xml b/core/res/res/values-th-rTH/arrays.xml new file mode 100644 index 0000000..fe76592 --- /dev/null +++ b/core/res/res/values-th-rTH/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>15870032</item> + <item>100992541</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-tl-rPH/arrays.xml b/core/res/res/values-tl-rPH/arrays.xml new file mode 100644 index 0000000..2edac64 --- /dev/null +++ b/core/res/res/values-tl-rPH/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>12879721</item> + <item>121774017</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-tr-rTR/arrays.xml b/core/res/res/values-tr-rTR/arrays.xml new file mode 100644 index 0000000..f045cff --- /dev/null +++ b/core/res/res/values-tr-rTR/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>41034435</item> + <item>28977556</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-uk-rUA/arrays.xml b/core/res/res/values-uk-rUA/arrays.xml new file mode 100644 index 0000000..746befd --- /dev/null +++ b/core/res/res/values-uk-rUA/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>48379433</item> + <item>31165580</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-vi-rVN/arrays.xml b/core/res/res/values-vi-rVN/arrays.xml new file mode 100644 index 0000000..6b22081 --- /dev/null +++ b/core/res/res/values-vi-rVN/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>14058324</item> + <item>108277199</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-zh-rCN/arrays.xml b/core/res/res/values-zh-rCN/arrays.xml new file mode 100644 index 0000000..16da6d9 --- /dev/null +++ b/core/res/res/values-zh-rCN/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>39937795</item> + <item>116387224</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>2</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 346e254..54b0b97 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"呼å«è€… ID 默认情况下ä¸å—é™åˆ¶ã€‚下一个呼å«ï¼šä¸å—é™åˆ¶"</string> <string name="serviceNotProvisioned">"未æä¾›æœåŠ¡ã€‚"</string> <string name="CLIRPermanent">"ä¸èƒ½æ›´æ”¹å‘¼å«è€… ID 设置。"</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"è¯éŸ³"</string> <string name="serviceClassData">"æ•°æ®"</string> <string name="serviceClassFAX">"ä¼ çœŸ"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"é™éŸ³æ¨¡å¼"</string> <string name="global_action_silent_mode_on_status">"声音已关é—"</string> <string name="global_action_silent_mode_off_status">"声音已开å¯"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"飞行模å¼"</string> + <string name="global_actions_airplane_mode_on_status">"飞行模å¼å·²å¼€å¯"</string> + <string name="global_actions_airplane_mode_off_status">"飞行模å¼å·²å…³é—"</string> <string name="safeMode">"安全模å¼"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Android 系统"</string> <string name="permgrouplab_costMoney">"éœ€è¦æ‚¨æ”¯ä»˜è´¹ç”¨çš„æœåŠ¡"</string> <string name="permgroupdesc_costMoney">"å…è®¸åº”ç”¨ç¨‹åºæ‰§è¡Œå¯èƒ½éœ€è¦æ‚¨æ”¯ä»˜è´¹ç”¨çš„æ“ä½œã€‚"</string> <string name="permgrouplab_messages">"您的信æ¯"</string> @@ -286,8 +292,8 @@ <string name="permdesc_locationUpdates">"å…许å¯ç”¨/ç¦ç”¨æ¥è‡ªæ”¶éŸ³æœºçš„ä½ç½®æ›´æ–°é€šçŸ¥ã€‚普通应用程åºä¸èƒ½ä½¿ç”¨æ¤æƒé™ã€‚"</string> <string name="permlab_checkinProperties">"访问检入属性"</string> <string name="permdesc_checkinProperties">"å…许对检入æœåŠ¡ä¸Šä¼ çš„å±žæ€§è¿›è¡Œè¯»/写访问。普通应用程åºä¸èƒ½ä½¿ç”¨æ¤æƒé™ã€‚"</string> - <string name="permlab_bindGadget">"选择å°å·¥å…·"</string> - <string name="permdesc_bindGadget">"å…许应用程åºå‘Šè¯‰ç³»ç»Ÿå“ªäº›åº”用程åºå¯ä»¥ä½¿ç”¨å“ªäº›å°å·¥å…·ã€‚应用程åºå¯ä»¥å€Ÿæ¤æŽˆäºˆå…¶ä»–应用程åºè®¿é—®ä¸ªäººæ•°æ®çš„æƒé™ã€‚普通应用程åºä¸èƒ½ä½¿ç”¨æ¤æƒé™ã€‚"</string> + <string name="permlab_bindGadget">"选择窗å£å°éƒ¨ä»¶"</string> + <string name="permdesc_bindGadget">"å…许应用程åºå‘Šè¯‰ç³»ç»Ÿå“ªä¸ªåº”用程åºå¯ä»¥ä½¿ç”¨å“ªäº›çª—å£å°éƒ¨ä»¶ã€‚具有该æƒé™çš„应用程åºå¯ä»¥å…许其他应用程åºè®¿é—®ä¸ªäººæ•°æ®ã€‚普通应用程åºä¸é€‚åˆä½¿ç”¨æ¤æƒé™ã€‚"</string> <string name="permlab_modifyPhoneState">"修改手机状æ€"</string> <string name="permdesc_modifyPhoneState">"å…è®¸åº”ç”¨ç¨‹åºæŽ§åˆ¶è®¾å¤‡çš„æ‰‹æœºåŠŸèƒ½ã€‚å…·æœ‰æ¤æƒé™çš„应用程åºå¯èƒ½ä¼šåˆ‡æ¢ç½‘ç»œï¼Œæ‰“å¼€å’Œå…³é—æ‰‹æœºæ”¶éŸ³æœºä»¥åŠç±»ä¼¼æ“作,而ä¸ä¼šé€šçŸ¥æ‚¨ã€‚"</string> <string name="permlab_readPhoneState">"è¯»å–æ‰‹æœºçжæ€"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"紧急电è¯"</string> <string name="lockscreen_pattern_correct">"æ£ç¡®ï¼"</string> <string name="lockscreen_pattern_wrong">"很抱æ‰ï¼Œè¯·é‡è¯•"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"æ£åœ¨å……电 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"连接您的充电器。"</string> <string name="lockscreen_missing_sim_message_short">"没有 SIM å¡ã€‚"</string> <string name="lockscreen_missing_sim_message">"æ‰‹æœºä¸æ— SIM å¡ã€‚"</string> <string name="lockscreen_missing_sim_instructions">"请æ’å…¥ SIM å¡ã€‚"</string> <string name="lockscreen_network_locked_message">"网络已é”定"</string> <string name="lockscreen_sim_puk_locked_message">"已对 SIM å¡è¿›è¡Œ PUK ç é”定。"</string> - <string name="lockscreen_sim_puk_locked_instructions">"请è”系客æœéƒ¨é—¨ã€‚"</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM å¡å·²è¢«é”定。"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"æ£åœ¨è§£é” SIM å¡..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"您 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了您的解é”图案。"\n\n"请在 <xliff:g id="NUMBER_1">%d</xliff:g> ç§’åŽé‡è¯•。"</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g> ç§’åŽé‡è¯•。"</string> <string name="lockscreen_forgot_pattern_button_text">"忘记了图案?"</string> <string name="lockscreen_glogin_too_many_attempts">"图案å°è¯•次数太多ï¼"</string> - <string name="lockscreen_glogin_instructions">"è¦è§£é”,"\n"请用您的 Google 叿ˆ·ç™»å½•"</string> + <string name="lockscreen_glogin_instructions">"è¦è§£é™¤é”定,请使用您的 Google 叿ˆ·ç™»å½•"</string> <string name="lockscreen_glogin_username_hint">"用户å(电å邮件)"</string> <string name="lockscreen_glogin_password_hint">"密ç "</string> <string name="lockscreen_glogin_submit_button">"登录"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="AMPM">%P</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string> + <string name="hour_cap_ampm">"<xliff:g id="AMPM">%p</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string> <string name="status_bar_clear_all_button">"清除通知"</string> <string name="status_bar_no_notifications_title">"æ— é€šçŸ¥"</string> <string name="status_bar_ongoing_events_title">"æ£åœ¨è¿›è¡Œçš„"</string> <string name="status_bar_latest_events_title">"通知"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"æ£åœ¨å……电..."</string> <string name="battery_low_title">"请连接充电器"</string> <string name="battery_low_subtitle">"电é‡åœ¨å‡å°‘:"</string> @@ -552,6 +555,7 @@ <string name="monthly">"æ¯æœˆ"</string> <string name="yearly">"æ¯å¹´"</string> <string name="VideoView_error_title">"æ— æ³•æ’æ”¾è§†é¢‘"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"抱æ‰ï¼Œè¯¥è§†é¢‘ä¸é€‚åˆåœ¨æ¤è®¾å¤‡ä¸Šæ’放。"</string> <string name="VideoView_error_text_unknown">"很抱æ‰ï¼Œæ¤è§†é¢‘ä¸èƒ½æ’放。"</string> <string name="VideoView_error_button">"确定"</string> <string name="am">"上åˆ"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' å¹´ '<xliff:g id="MONTH">MMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' æ—¥'"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' å¹´ '<xliff:g id="DAY">d</xliff:g>' 月 '<xliff:g id="MONTH">MMM</xliff:g>' æ—¥'"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"ä¸åˆ"</string> <string name="Noon">"ä¸åˆ"</string> <string name="midnight">"åˆå¤œ"</string> <string name="Midnight">"åˆå¤œ"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> æ—¥"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> å¹´ <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> æ—¥"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> å¹´ <xliff:g id="MONTH">%B</xliff:g> 月"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g> å¹´ <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> æ—¥ <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> æ—¥"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> å¹´ <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> æ—¥ <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> å¹´ <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> æ—¥ <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> å¹´ <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> æ—¥<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> å¹´ <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> æ—¥<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> å¹´ <xliff:g id="MONTH">%b</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> æ—¥"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g> å¹´ <xliff:g id="MONTH">%b</xliff:g> 月"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> æ—¥"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"周日"</string> <string name="day_of_week_long_monday">"周一"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"找ä¸åˆ°åŒ¹é…的活动"</string> <string name="permlab_pkgUsageStats">"更新组件使用情况统计"</string> <string name="permdesc_pkgUsageStats">"å…许修改收集的组件使用情况统计。普通应用程åºä¸èƒ½ä½¿ç”¨æ¤æƒé™ã€‚"</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"åŒå‡»å¯ä»¥è¿›è¡Œç¼©æ”¾æŽ§åˆ¶"</string> + <string name="gadget_host_error_inflating">"放大窗å£å°éƒ¨ä»¶æ—¶å‡ºé”™"</string> + <string name="ime_action_go">"开始"</string> + <string name="ime_action_search">"æœç´¢"</string> + <string name="ime_action_send">"å‘é€"</string> + <string name="ime_action_next">"下一æ¥"</string> + <string name="ime_action_done">"完æˆ"</string> + <string name="ime_action_default">"执行"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values-zh-rTW/arrays.xml b/core/res/res/values-zh-rTW/arrays.xml new file mode 100644 index 0000000..be0795b --- /dev/null +++ b/core/res/res/values-zh-rTW/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, Google Inc. +** +** 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> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>25022112</item> + <item>121478019</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>3</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 6d4b821..d02f4b1 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"é è¨é¡¯ç¤ºæœ¬æ©Ÿè™Ÿç¢¼ï¼Œä¸‹ä¸€é€šä¹Ÿé¡¯ç¤ºã€‚"</string> <string name="serviceNotProvisioned">"æœå‹™æœªè¨å®šå®Œæˆã€‚"</string> <string name="CLIRPermanent">"本機號碼è¨å®šç„¡æ³•變更。"</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"語音"</string> <string name="serviceClassData">"資料"</string> <string name="serviceClassFAX">"傳真"</string> @@ -103,15 +113,11 @@ <string name="global_action_toggle_silent_mode">"éœéŸ³æ¨¡å¼"</string> <string name="global_action_silent_mode_on_status">"音效已關閉"</string> <string name="global_action_silent_mode_off_status">"è²éŸ³å·²é–‹å•Ÿ"</string> - <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> - <skip /> - <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> - <skip /> + <string name="global_actions_toggle_airplane_mode">"飛航模å¼"</string> + <string name="global_actions_airplane_mode_on_status">"飛航模å¼ç‚º [開啟]"</string> + <string name="global_actions_airplane_mode_off_status">"飛航模å¼ç‚º [關閉]"</string> <string name="safeMode">"安全模å¼"</string> - <!-- no translation found for android_system_label (6577375335728551336) --> - <skip /> + <string name="android_system_label">"Android 系統"</string> <string name="permgrouplab_costMoney">"需è¦é¡å¤–費用的æœå‹™ã€‚"</string> <string name="permgroupdesc_costMoney">"若您å…許應用程å¼åŸ·è¡Œæ¤æ“作,å¯èƒ½éœ€è¦æ”¯ä»˜ä¸€äº›è²»ç”¨ã€‚"</string> <string name="permgrouplab_messages">"您的簡訊"</string> @@ -287,7 +293,7 @@ <string name="permlab_checkinProperties">"å˜å–登機é¸é …"</string> <string name="permdesc_checkinProperties">"å…許讀寫登機æœå‹™ä¸Šå‚³çš„資料。一般應用程å¼ä¸æœƒä½¿ç”¨æ¤åŠŸèƒ½ã€‚"</string> <string name="permlab_bindGadget">"鏿“‡å°å·¥å…·"</string> - <string name="permdesc_bindGadget">"å…許應用程å¼å‘ŠçŸ¥ç³»çµ±å“ªäº›æ‡‰ç”¨ç¨‹å¼å¯ä»¥ä½¿ç”¨å“ªäº›å°å·¥å…·ã€‚æ“æœ‰æ¤æ¬Šé™çš„æ‡‰ç”¨ç¨‹å¼å¯ä»¥è®“其他應用程å¼ä½¿ç”¨å€‹äººè³‡æ–™ã€‚一般應用程å¼ä¸æœƒä½¿ç”¨æ¤åŠŸèƒ½ã€‚"</string> + <string name="permdesc_bindGadget">"å…許應用程å¼å‘ŠçŸ¥ç³»çµ±å“ªå€‹æ‡‰ç”¨ç¨‹å¼å¯ä»¥ä½¿ç”¨å“ªäº›å°å·¥å…·ã€‚é–‹å•Ÿæ¤æ¬Šé™å¾Œï¼Œæ‡‰ç”¨ç¨‹å¼æœƒè®“其他程å¼ä½¿ç”¨å€‹äººè³‡æ–™ï¼Œä½†ä¸€èˆ¬æ‡‰ç”¨ç¨‹å¼ä¸é©åˆä½¿ç”¨æ¤åŠŸèƒ½ã€‚"</string> <string name="permlab_modifyPhoneState">"修改手機狀態"</string> <string name="permdesc_modifyPhoneState">"å…è¨±æ‡‰ç”¨ç¨‹å¼æŽ§åˆ¶é›»è©±åŠŸèƒ½ã€‚æ“æœ‰æ¤æ¬Šé™çš„程å¼å¯è‡ªè¡Œåˆ‡æ›ç¶²è·¯ã€é–‹é—œç„¡ç·šé€šè¨ŠåŠŸèƒ½ã€‚"</string> <string name="permlab_readPhoneState">"è®€å–æ‰‹æ©Ÿç‹€æ…‹"</string> @@ -397,15 +403,15 @@ <string name="lockscreen_emergency_call">"緊急電話"</string> <string name="lockscreen_pattern_correct">"æ£ç¢ºï¼"</string> <string name="lockscreen_pattern_wrong">"抱æ‰ï¼Œè«‹å†è©¦ä¸€æ¬¡"</string> - <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> - <skip /> + <string name="lockscreen_plugged_in">"æ£åœ¨å……é›» (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> <string name="lockscreen_low_battery">"請連接充電器。"</string> <string name="lockscreen_missing_sim_message_short">"沒有 SIM å¡ã€‚"</string> <string name="lockscreen_missing_sim_message">"手機未æ’å…¥ SIM å¡ã€‚"</string> <string name="lockscreen_missing_sim_instructions">"è«‹æ’å…¥ SIM å¡ã€‚"</string> <string name="lockscreen_network_locked_message">"網路已鎖定"</string> <string name="lockscreen_sim_puk_locked_message">"SIM çš„ PUK 已鎖定。"</string> - <string name="lockscreen_sim_puk_locked_instructions">"è«‹è¯çµ¡å®¢æœä¸å¿ƒã€‚"</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM å¡å·²éŽ–å®šã€‚"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"解鎖 SIM å¡ä¸..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"畫出解鎖圖形已錯誤 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n" 請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後å†å˜—試。"</string> @@ -413,7 +419,7 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g> 秒後å†è©¦ä¸€æ¬¡ã€‚"</string> <string name="lockscreen_forgot_pattern_button_text">"忘記解鎖圖形?"</string> <string name="lockscreen_glogin_too_many_attempts">"解鎖圖形出錯次數éŽå¤šï¼"</string> - <string name="lockscreen_glogin_instructions">"è‹¥è¦è§£éŽ–ï¼Œ"\n"請以您的 Google 帳戶登入"</string> + <string name="lockscreen_glogin_instructions">"è‹¥è¦è§£é™¤éŽ–å®šï¼Œè«‹ä½¿ç”¨ Google 帳戶登入"</string> <string name="lockscreen_glogin_username_hint">"使用者å稱 (é›»å郵件)"</string> <string name="lockscreen_glogin_password_hint">"密碼"</string> <string name="lockscreen_glogin_submit_button">"登入"</string> @@ -421,16 +427,13 @@ <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> - <!-- no translation found for hour_ampm (4329881288269772723) --> - <skip /> - <!-- no translation found for hour_cap_ampm (1829009197680861107) --> - <skip /> + <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> + <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"清除通知"</string> <string name="status_bar_no_notifications_title">"沒有通知"</string> <string name="status_bar_ongoing_events_title">"進行ä¸"</string> <string name="status_bar_latest_events_title">"通知"</string> - <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> - <skip /> + <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="battery_status_charging">"å……é›»ä¸"</string> <string name="battery_low_title">"請連接充電器"</string> <string name="battery_low_subtitle">"é›»æ± é›»é‡å³å°‡ä¸è¶³ï¼š"</string> @@ -552,6 +555,7 @@ <string name="monthly">"æ¯æœˆ"</string> <string name="yearly">"æ¯å¹´"</string> <string name="VideoView_error_title">"ç„¡æ³•æ’æ”¾å½±ç‰‡"</string> + <string name="VideoView_error_text_invalid_progressive_playback">"很抱æ‰ï¼Œå½±ç‰‡æ ¼å¼ç„¡æ•ˆï¼Œè£ç½®ç„¡æ³•進行串æµè™•ç†ã€‚"</string> <string name="VideoView_error_text_unknown">"抱æ‰ï¼Œç„¡æ³•撥放æ¤å½±ç‰‡ã€‚"</string> <string name="VideoView_error_button">"確定"</string> <string name="am">"上åˆ"</string> @@ -573,18 +577,16 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"ä¸åˆ"</string> <string name="Noon">"ä¸åˆ"</string> <string name="midnight">"åˆå¤œ"</string> <string name="Midnight">"åˆå¤œ"</string> - <!-- no translation found for month_day (3693060561170538204) --> - <skip /> - <!-- no translation found for month (1976700695144952053) --> + <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>,<xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for month_year (2106203387378728384) --> - <skip /> + <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g><xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>,<xliff:g id="YEAR">%Y</xliff:g>"</string> <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> @@ -612,11 +614,9 @@ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>,<xliff:g id="YEAR1">%4$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>,<xliff:g id="YEAR2">%9$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>,<xliff:g id="YEAR1">%4$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>,<xliff:g id="YEAR2">%9$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> <string name="abbrev_month_day_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>,<xliff:g id="YEAR">%Y</xliff:g>"</string> - <!-- no translation found for abbrev_month_year (5966980891147982768) --> - <skip /> - <!-- no translation found for abbrev_month_day (3156047263406783231) --> - <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g><xliff:g id="YEAR">%Y</xliff:g>"</string> + <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g><xliff:g id="DAY">%-d</xliff:g>"</string> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"星期日"</string> <string name="day_of_week_long_monday">"星期一"</string> @@ -798,18 +798,16 @@ <string name="activity_list_empty">"找ä¸åˆ°ç¬¦åˆçš„æ´»å‹•"</string> <string name="permlab_pkgUsageStats">"更新元件使用統計資料"</string> <string name="permdesc_pkgUsageStats">"å…許修改收集到的元件使用統計資料。一般應用程å¼ä¸æœƒä½¿ç”¨æ¤åŠŸèƒ½ã€‚"</string> - <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> - <skip /> - <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> - <skip /> - <!-- no translation found for ime_action_go (8320845651737369027) --> - <skip /> - <!-- no translation found for ime_action_search (658110271822807811) --> - <skip /> - <!-- no translation found for ime_action_send (2316166556349314424) --> - <skip /> - <!-- no translation found for ime_action_next (3138843904009813834) --> + <string name="tutorial_double_tap_to_zoom_message_short">"點兩下以進行縮放控制"</string> + <string name="gadget_host_error_inflating">"擴大å°å·¥å…·æ™‚發生錯誤"</string> + <string name="ime_action_go">"é–‹å§‹"</string> + <string name="ime_action_search">"æœå°‹"</string> + <string name="ime_action_send">"傳é€"</string> + <string name="ime_action_next">"下一æ¥"</string> + <string name="ime_action_done">"完æˆ"</string> + <string name="ime_action_default">"執行"</string> + <!-- no translation found for dial_number_using (5789176425167573586) --> <skip /> - <!-- no translation found for ime_action_default (2840921885558045721) --> + <!-- no translation found for create_contact_using (4947405226788104538) --> <skip /> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 899d109..9b38d0a 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -353,8 +353,6 @@ <attr name="spinnerStyle" format="reference" /> <!-- Default Star style. --> <attr name="starStyle" format="reference" /> - <!-- Buttonless Star style. --> - <attr name="starStyleButtonless" format="reference" /> <!-- Default TabWidget style. --> <attr name="tabWidgetStyle" format="reference" /> <!-- Default TextView style. --> @@ -620,12 +618,35 @@ Corresponds to {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}. --> <flag name="actionDone" value="0x00000006" /> + <!-- Used to specify that the IME does not need + to show its extracted text UI. For input methods that may be fullscreen, + often when in landscape mode, this allows them to be smaller and let part + of the application be shown behind. Though there will likely be limited + access to the application available from the user, it can make the + experience of a (mostly) fullscreen IME less jarring. Note that when + this flag is specified the IME may <em>not</em> be set up to be able + to display text, so it should only be used in situations where this is + not needed. + <p>Corresponds to + {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_EXTRACT_UI}. --> + <flag name="flagNoExtractUi" value="0x10000000" /> + <!-- Used in conjunction with a custom action, this indicates that the + action should not be available as an accessory button when the + input method is full-screen. + Note that by setting this flag, there can be cases where the action + is simply never available to the user. Setting this generally means + that you think showing text being edited is more important than the + action you have supplied. + <p>Corresponds to + {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ACCESSORY_ACTION}. --> + <flag name="flagNoAccessoryAction" value="0x20000000" /> <!-- Used in conjunction with a custom action, - this indicates that the action should not - be available in-line as the same as a "enter" key. Typically this is + this indicates that the action should not be available in-line as + a replacement for the "enter" key. Typically this is because the action has such a significant impact or is not recoverable enough that accidentally hitting it should be avoided, such as sending - a message. + a message. Note that {@link android.widget.TextView} will + automatically set this flag for you on multi-line text views. <p>Corresponds to {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. --> <flag name="flagNoEnterAction" value="0x40000000" /> @@ -1198,7 +1219,8 @@ </declare-styleable> - <!-- Attributes that can be used with {@link android.view.ViewStub}. --> + <!-- A {@link android.view.ViewStub} lets you lazily include other XML layouts + inside your application at runtime. --> <declare-styleable name="ViewStub"> <!-- Supply an identifier for the layout resource to inflate when the ViewStub becomes visible or when forced to do so. The layout resource must be a @@ -1372,7 +1394,8 @@ </declare-styleable> <declare-styleable name="FrameLayout"> <!-- Defines the drawable to draw over the content. This can be used as an overlay. - The foreground drawable participates in the padding of the content. --> + The foreground drawable participates in the padding of the content if the gravity + is set to fill. --> <attr name="foreground" format="reference|color" /> <!-- Defines the gravity to apply to the foreground drawable. The gravity defaults to fill. --> @@ -1408,6 +1431,9 @@ edge, a right gravity will clip the left edge, and neither will clip both edges. --> <flag name="clip_horizontal" value="0x08" /> </attr> + <!-- Defines whether the foreground drawable should be drawn inside the padding. + This property is turned on by default. --> + <attr name="foregroundInsidePadding" format="boolean" /> <!-- Determines whether to measure all children or just those in the VISIBLE or INVISIBLE state when measuring. Defaults to false. --> <attr name="measureAllChildren" format="boolean" /> @@ -3024,6 +3050,22 @@ </attr> </declare-styleable> + <declare-styleable name="InputMethodService"> + <!-- Background to use for entire input method when it is being + shown in fullscreen mode with the extract view, to ensure + that it completely covers the application. This allows, + for example, the candidate view to be hidden + while in fullscreen mode without having the application show through + behind it.--> + <attr name="imeFullscreenBackground" format="reference|color" /> + <!-- Animation to use when showing the fullscreen extract UI after + it had previously been hidden. --> + <attr name="imeExtractEnterAnimation" format="reference" /> + <!-- Animation to use when hiding the fullscreen extract UI after + it had previously been shown. --> + <attr name="imeExtractExitAnimation" format="reference" /> + </declare-styleable> + <declare-styleable name="KeyboardView"> <!-- Default KeyboardView style. --> <attr name="keyboardViewStyle" format="reference" /> diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index 7e9b7ea..6ef6f52 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -61,7 +61,7 @@ <item type="id" name="copyUrl" /> <item type="id" name="switchInputMethod" /> <item type="id" name="keyboardView" /> - <item type="id" name="button_close" /> + <item type="id" name="closeButton" /> <item type="id" name="startSelectingText" /> <item type="id" name="stopSelectingText" /> <item type="id" name="addToDictionary" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 88c7b35..a7af68b 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -951,7 +951,7 @@ <public type="attr" name="reqHardKeyboard" id="0x01010229" /> <public type="attr" name="reqNavigation" id="0x0101022a" /> <public type="attr" name="windowSoftInputMode" id="0x0101022b" /> - <public type="attr" name="starStyleButtonless" id="0x0101022c" /> + <public type="attr" name="imeFullscreenBackground" id="0x0101022c" /> <public type="attr" name="noHistory" id="0x0101022d" /> <public type="attr" name="headerDividersEnabled" id="0x0101022e" /> <public type="attr" name="footerDividersEnabled" id="0x0101022f" /> @@ -1010,6 +1010,8 @@ <public type="attr" name="imeOptions" id="0x01010264" /> <public type="attr" name="imeActionLabel" id="0x01010265" /> <public type="attr" name="imeActionId" id="0x01010266" /> + <public type="attr" name="imeExtractEnterAnimation" id="0x01010268" /> + <public type="attr" name="imeExtractExitAnimation" id="0x01010269" /> <!-- The part of the UI shown by an {@link android.inputmethodservice.InputMethodService} that contains the @@ -1052,7 +1054,7 @@ an input method's input area. --> <public type="id" name="keyboardView" id="0x01020026" /> <!-- View ID of a {@link android.view.View} to close a popup keyboard --> - <public type="id" name="button_close" id="0x01020027" /> + <public type="id" name="closeButton" id="0x01020027" /> <!-- Menu ID to perform a "start selecting text" operation. --> <public type="id" name="startSelectingText" id="0x01020028" /> @@ -1066,35 +1068,19 @@ <public type="style" name="Animation.InputMethod" id="0x01030056" /> <public type="style" name="Widget.KeyboardView" id="0x01030057" /> <public type="style" name="ButtonBar" id="0x01030058" /> + <public type="style" name="Theme.Panel" id="0x01030059" /> + <public type="style" name="Theme.Light.Panel" id="0x0103005a" /> <public type="string" name="dialog_alert_title" id="0x01040014" /> <public type="string" name="VideoView_error_text_invalid_progressive_playback" id="0x01040015" /> - <public type="drawable" name="emo_im_angel" id="0x010800a4" /> - <public type="drawable" name="emo_im_cool" id="0x010800a5" /> - <public type="drawable" name="emo_im_crying" id="0x010800a6" /> - <public type="drawable" name="emo_im_embarrassed" id="0x010800a7" /> - <public type="drawable" name="emo_im_foot_in_mouth" id="0x010800a8" /> - <public type="drawable" name="emo_im_happy" id="0x010800a9" /> - <public type="drawable" name="emo_im_kissing" id="0x010800aa" /> - <public type="drawable" name="emo_im_laughing" id="0x010800ab" /> - <public type="drawable" name="emo_im_lips_are_sealed" id="0x010800ac" /> - <public type="drawable" name="emo_im_money_mouth" id="0x010800ad" /> - <public type="drawable" name="emo_im_sad" id="0x010800ae" /> - <public type="drawable" name="emo_im_surprised" id="0x010800af" /> - <public type="drawable" name="emo_im_tongue_sticking_out" id="0x010800b0" /> - <public type="drawable" name="emo_im_undecided" id="0x010800b1" /> - <public type="drawable" name="emo_im_winking" id="0x010800b2" /> - <public type="drawable" name="emo_im_wtf" id="0x010800b3" /> - <public type="drawable" name="emo_im_yelling" id="0x010800b4" /> - - <public type="drawable" name="ic_btn_speak_now" id="0x010800b5" /> + <public type="drawable" name="ic_btn_speak_now" id="0x010800a4" /> <!-- Drawable to use as a background for separators on a list with a dark background --> - <public type="drawable" name="dark_header" id="0x010800b6" /> + <public type="drawable" name="dark_header" id="0x010800a5" /> <!-- Drawable to use as a background for a taller version of the titlebar --> - <public type="drawable" name="title_bar_tall" id="0x010800b7" /> + <public type="drawable" name="title_bar_tall" id="0x010800a6" /> <public type="integer" name="config_shortAnimTime" id="0x010e0000" /> <public type="integer" name="config_mediumAnimTime" id="0x010e0001" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 340cd40..f45d2e4 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -113,6 +113,17 @@ <!-- Displayed to tell the user that they cannot change the caller ID setting. --> <string name="CLIRPermanent">The caller ID setting cannot be changed.</string> + <!-- Notification title to tell the user that restricted state is changed by access control. --> + <string name="RestrictedChangedTitle">Restricted access changed</string> + <!-- Displayed to tell the user that data service is blocked by access control. --> + <string name="RestrictedOnData">Data service is blocked.</string> + <!-- Displayed to tell the user that emergency service is blocked by access control. --> + <string name="RestrictedOnEmergency">Emergency service is blocked.</string> + <!-- Displayed to tell the user that normal service is blocked by access control. --> + <string name="RestrictedOnNormal">Voice/SMS service is blocked.</string> + <!-- Displayed to tell the user that all voice service is blocked by access control. --> + <string name="RestrictedOnAll">All voice/SMS services are blocked.</string> + <!-- Mappings between TS 27.007 +CFCC/+CLCK "service classes" and human-readable strings--> <skip /> <!-- Example: Service was enabled for: Voice, Data --> <string name="serviceClassVoice">Voice</string> @@ -1148,7 +1159,7 @@ PUK locked (Pin Unlock Kode) --> <string name="lockscreen_sim_puk_locked_message">SIM card is PUK-locked.</string> <!-- Shown in the lock screen when the SIM has become PUK locked and the user must call customer care to unlock it. --> - <string name="lockscreen_sim_puk_locked_instructions">Please contact Customer Care.</string> + <string name="lockscreen_sim_puk_locked_instructions">Please see the User Guide or contact Customer Care.</string> <!-- Shown in the lock screen to tell the user that their SIM is locked and they must unlock it. --> <string name="lockscreen_sim_locked_message">SIM card is locked.</string> @@ -2301,4 +2312,14 @@ <!-- Long label for a button on a full-screen input method for an unknown action. --> <string name="ime_action_default">Execute</string> + <!-- Strings for search suggestions. These are going here because they are referenced by both + ContactsProvider and GoogleContactsProvider --> + <skip /> + + <!-- This string appears (on two lines) when you type a number into contacts search, to let you dial the phone number you typed. The first line will be in bigger type than the second. --> + <string name="dial_number_using">Dial number\nusing <xliff:g id="number" example="555">%s</xliff:g></string> + + <!-- This string appears (on two lines) when you type a number into contacts search, to let you create a contact whose phone number is the number you typed. The first line will be in bigger type than the second. --> + <string name="create_contact_using">Create contact\nusing <xliff:g id="number" example="555">%s</xliff:g></string> + </resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index a152410..d7b654e 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -154,12 +154,11 @@ <!-- Status Bar Styles --> <style name="TextAppearance.StatusBarTitle"> - <item name="android:textSize">14sp</item> + <item name="android:textAppearance">?android:attr/textAppearanceSmall</item> <item name="android:textStyle">bold</item> - <item name="android:textColor">#ffffffff</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> </style> - <!-- Widget Styles --> <style name="Widget"> @@ -211,11 +210,6 @@ <item name="android:button">@android:drawable/btn_star</item> </style> - <style name="Widget.CompoundButton.StarButtonless"> - <item name="android:background">@android:drawable/btn_star_label_background</item> - <item name="android:button">@android:drawable/btn_star_buttonless</item> - </style> - <style name="Widget.Button.Toggle"> <item name="android:background">@android:drawable/btn_toggle_bg</item> <item name="android:textOn">@android:string/capital_on</item> @@ -317,6 +311,10 @@ <item name="android:paddingLeft">5sp</item> </style> + <style name="Widget.TextView.ListSeparator.White"> + <item name="android:textColor">?textColorSecondaryInverse</item> + </style> + <style name="Widget.EditText"> <item name="android:focusable">true</item> <item name="android:focusableInTouchMode">true</item> @@ -663,7 +661,6 @@ </style> <style name="ZoomControls"> - <item name="android:background">@android:drawable/zoom_plate</item> <item name="android:gravity">bottom</item> <item name="android:paddingLeft">15dip</item> <item name="android:paddingRight">15dip</item> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 01c46de..6b3d740 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -153,7 +153,6 @@ <item name="horizontalScrollViewStyle">@android:style/Widget.HorizontalScrollView</item> <item name="spinnerStyle">@android:style/Widget.Spinner</item> <item name="starStyle">@android:style/Widget.CompoundButton.Star</item> - <item name="starStyleButtonless">@android:style/Widget.CompoundButton.StarButtonless</item> <item name="tabWidgetStyle">@android:style/Widget.TabWidget</item> <item name="textViewStyle">@android:style/Widget.TextView</item> <item name="webViewStyle">@android:style/Widget.WebView</item> @@ -185,6 +184,7 @@ fills the entire screen --> <style name="Theme.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Theme for a light background with dark text on top. Set your activity @@ -218,6 +218,7 @@ <item name="listViewStyle">@android:style/Widget.ListView.White</item> <item name="listDivider">@drawable/divider_horizontal_bright</item> + <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item> </style> <!-- Variant of the light theme with no title bar --> @@ -229,6 +230,7 @@ fills the entire screen --> <style name="Theme.Light.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Special variation on the default theme that ensures the background is @@ -249,6 +251,7 @@ fills the entire screen --> <style name="Theme.Black.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Default theme for translucent activities, that is windows that allow you @@ -269,12 +272,14 @@ fills the entire screen --> <style name="Theme.Translucent.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Default theme for activities that don't actually display a UI; that is, they finish themselves before being resumed. --> <style name="Theme.NoDisplay"> <item name="android:windowBackground">@null</item> + <item name="android:windowContentOverlay">@null</item> <item name="android:windowIsTranslucent">false</item> <item name="android:windowAnimationStyle">@null</item> <item name="android:windowDisablePreview">true</item> @@ -291,7 +296,7 @@ <item name="android:windowTitleStyle">@android:style/DialogWindowTitle</item> <item name="android:windowBackground">@android:drawable/panel_background</item> <item name="android:windowIsFloating">true</item> - <item name="android:windowContentOverlay">@android:drawable/panel_separator</item> + <item name="android:windowContentOverlay">@null</item> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item> </style> @@ -303,30 +308,55 @@ <item name="windowBackground">@android:color/transparent</item> <item name="windowTitleStyle">@android:style/DialogWindowTitle</item> <item name="windowIsFloating">true</item> - <item name="windowContentOverlay">@drawable/panel_separator</item> + <item name="windowContentOverlay">@null</item> </style> - <!-- Default theme for dialog windows and activities, which is used by the - {@link android.app.Dialog} class. This changes the window to be - floating (not fill the entire screen), and puts a frame around its - contents. You can set this theme on an activity if you would like to - make an activity that looks like a Dialog. --> - <style name="Theme.InputMethod" parent="Theme.Light.NoTitleBar"> + <!-- Default dark theme for panel windows. This removes all extraneous + window decorations, so you basically have an empty rectangle in which + to place your content. It makes the window floating, with a transparent + background, and turns off dimming behind the window. --> + <style name="Theme.Panel"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowFrame">@null</item> + <item name="android:windowContentOverlay">@null</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimEnabled">false</item> <item name="android:windowIsTranslucent">true</item> - <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item> + <item name="android:windowNoTitle">true</item> </style> - <!-- Theme for the search input bar. --> - <style name="Theme.SearchBar" parent="Theme.Translucent.NoTitleBar"> + <!-- Default light theme for panel windows. This removes all extraneous + window decorations, so you basically have an empty rectangle in which + to place your content. It makes the window floating, with a transparent + background, and turns off dimming behind the window. --> + <style name="Theme.Light.Panel"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowFrame">@null</item> + <item name="android:windowContentOverlay">@null</item> <item name="android:windowIsFloating">true</item> + <item name="android:backgroundDimEnabled">false</item> <item name="android:windowIsTranslucent">true</item> + <item name="android:windowNoTitle">true</item> + </style> + + <!-- Default theme for input methods, which is used by the + {@link android.inputmethodservice.InputMethodService} class. + this inherits from Theme.NoTitleBar, but makes the background + transparent, the window floating and translucent, and ensures that + it does not dim the UI behind it. This also configures the window + with the standard IME animations and visuals. --> + <style name="Theme.InputMethod" parent="Theme.Panel"> + <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item> + <item name="android:imeFullscreenBackground">@android:drawable/input_method_fullscreen_background</item> + <item name="android:imeExtractEnterAnimation">@android:anim/input_method_extract_enter</item> + <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item> + </style> + + <!-- Theme for the search input bar. --> + <style name="Theme.SearchBar" parent="Theme.Panel"> + <item name="android:backgroundDimEnabled">true</item> <item name="android:windowAnimationStyle">@android:style/Animation.SearchBar</item> + <item name="windowContentOverlay">@null</item> </style> <!-- Menu Themes --> @@ -358,7 +388,7 @@ <item name="windowTitleStyle">@android:style/DialogWindowTitle</item> <item name="windowBackground">@android:color/transparent</item> <item name="windowIsFloating">true</item> - <item name="windowContentOverlay">@drawable/panel_separator</item> + <item name="windowContentOverlay">@null</item> <item name="textAppearance">@style/TextAppearance.Theme.Dialog.AppError</item> </style> </resources> diff --git a/data/fonts/DroidSansJapanese.ttf b/data/fonts/DroidSansJapanese.ttf Binary files differnew file mode 100755 index 0000000..ca79221 --- /dev/null +++ b/data/fonts/DroidSansJapanese.ttf diff --git a/data/sounds/AudioPackage2.mk b/data/sounds/AudioPackage2.mk new file mode 100644 index 0000000..5bd301d --- /dev/null +++ b/data/sounds/AudioPackage2.mk @@ -0,0 +1,92 @@ +# +# Audio Package 2 +# +# Include this file in a product makefile to include these audio files +# +# This is a larger package of sounds than the 1.0 release for devices +# that have larger internal flash. +# + +local_path:= frameworks/base/data/sounds + +PRODUCT_COPY_FILES += \ + $(local_path)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \ + $(local_path)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \ + $(local_path)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \ + $(local_path)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \ + $(local_path)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \ + $(local_path)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \ + $(local_path)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \ + $(local_path)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \ + $(local_path)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \ + $(local_path)/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \ + $(local_path)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \ + $(local_path)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \ + $(local_path)/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \ + $(local_path)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \ + $(local_path)/newwavelabs/BentleyDubs.ogg:system/media/audio/ringtones/BentleyDubs.ogg \ + $(local_path)/newwavelabs/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \ + $(local_path)/newwavelabs/CaribbeanIce.ogg:system/media/audio/ringtones/CaribbeanIce.ogg \ + $(local_path)/newwavelabs/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \ + $(local_path)/newwavelabs/EtherShake.ogg:system/media/audio/ringtones/EtherShake.ogg \ + $(local_path)/newwavelabs/FriendlyGhost.ogg:system/media/audio/ringtones/FriendlyGhost.ogg \ + $(local_path)/newwavelabs/GameOverGuitar.ogg:system/media/audio/ringtones/GameOverGuitar.ogg \ + $(local_path)/newwavelabs/Growl.ogg:system/media/audio/ringtones/Growl.ogg \ + $(local_path)/newwavelabs/InsertCoin.ogg:system/media/audio/ringtones/InsertCoin.ogg \ + $(local_path)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \ + $(local_path)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \ + $(local_path)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \ + $(local_path)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \ + $(local_path)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \ + $(local_path)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \ + $(local_path)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \ + $(local_path)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \ + $(local_path)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \ + $(local_path)/newwavelabs/RomancingTheTone.ogg:system/media/audio/ringtones/RomancingTheTone.ogg \ + $(local_path)/newwavelabs/SitarVsSitar.ogg:system/media/audio/ringtones/SitarVsSitar.ogg \ + $(local_path)/newwavelabs/SpringyJalopy.ogg:system/media/audio/ringtones/SpringyJalopy.ogg \ + $(local_path)/newwavelabs/Terminated.ogg:system/media/audio/ringtones/Terminated.ogg \ + $(local_path)/newwavelabs/TwirlAway.ogg:system/media/audio/ringtones/TwirlAway.ogg \ + $(local_path)/newwavelabs/VeryAlarmed.ogg:system/media/audio/ringtones/VeryAlarmed.ogg \ + $(local_path)/newwavelabs/World.ogg:system/media/audio/ringtones/World.ogg \ + $(local_path)/newwavelabs/CaffeineSnake.ogg:system/media/audio/notifications/CaffeineSnake.ogg \ + $(local_path)/newwavelabs/DearDeer.ogg:system/media/audio/notifications/DearDeer.ogg \ + $(local_path)/newwavelabs/DontPanic.ogg:system/media/audio/notifications/DontPanic.ogg \ + $(local_path)/newwavelabs/Highwire.ogg:system/media/audio/notifications/Highwire.ogg \ + $(local_path)/newwavelabs/KzurbSonar.ogg:system/media/audio/notifications/KzurbSonar.ogg \ + $(local_path)/newwavelabs/OnTheHunt.ogg:system/media/audio/notifications/OnTheHunt.ogg \ + $(local_path)/newwavelabs/Voila.ogg:system/media/audio/notifications/Voila.ogg \ + $(local_path)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \ + $(local_path)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \ + $(local_path)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \ + $(local_path)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \ + $(local_path)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \ + $(local_path)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \ + $(local_path)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ + $(local_path)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \ + $(local_path)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \ + $(local_path)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \ + $(local_path)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \ + $(local_path)/newwavelabs/CrazyDream.ogg:system/media/audio/ringtones/CrazyDream.ogg \ + $(local_path)/newwavelabs/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg \ + $(local_path)/newwavelabs/Big_Easy.ogg:system/media/audio/ringtones/Big_Easy.ogg \ + $(local_path)/newwavelabs/Bollywood.ogg:system/media/audio/ringtones/Bollywood.ogg \ + $(local_path)/newwavelabs/Cairo.ogg:system/media/audio/ringtones/Cairo.ogg \ + $(local_path)/newwavelabs/Calypso_Steel.ogg:system/media/audio/ringtones/Calypso_Steel.ogg \ + $(local_path)/newwavelabs/Champagne_Edition.ogg:system/media/audio/ringtones/Champagne_Edition.ogg \ + $(local_path)/newwavelabs/Club_Cubano.ogg:system/media/audio/ringtones/Club_Cubano.ogg \ + $(local_path)/newwavelabs/Eastern_Sky.ogg:system/media/audio/ringtones/Eastern_Sky.ogg \ + $(local_path)/newwavelabs/Funk_Yall.ogg:system/media/audio/ringtones/Funk_Yall.ogg \ + $(local_path)/newwavelabs/Savannah.ogg:system/media/audio/ringtones/Savannah.ogg \ + $(local_path)/newwavelabs/Gimme_Mo_Town.ogg:system/media/audio/ringtones/Gimme_Mo_Town.ogg \ + $(local_path)/newwavelabs/Glacial_Groove.ogg:system/media/audio/ringtones/Glacial_Groove.ogg \ + $(local_path)/newwavelabs/Seville.ogg:system/media/audio/ringtones/Seville.ogg \ + $(local_path)/newwavelabs/No_Limits.ogg:system/media/audio/ringtones/No_Limits.ogg \ + $(local_path)/newwavelabs/Revelation.ogg:system/media/audio/ringtones/Revelation.ogg \ + $(local_path)/newwavelabs/Paradise_Island.ogg:system/media/audio/ringtones/Paradise_Island.ogg \ + $(local_path)/newwavelabs/Road_Trip.ogg:system/media/audio/ringtones/Road_Trip.ogg \ + $(local_path)/newwavelabs/Shes_All_That.ogg:system/media/audio/ringtones/Shes_All_That.ogg \ + $(local_path)/newwavelabs/Steppin_Out.ogg:system/media/audio/ringtones/Steppin_Out.ogg \ + $(local_path)/newwavelabs/Third_Eye.ogg:system/media/audio/ringtones/Third_Eye.ogg \ + $(local_path)/newwavelabs/Thunderfoot.ogg:system/media/audio/ringtones/Thunderfoot.ogg + diff --git a/data/sounds/OriginalAudio.mk b/data/sounds/OriginalAudio.mk index 8722983..291f0b6 100644 --- a/data/sounds/OriginalAudio.mk +++ b/data/sounds/OriginalAudio.mk @@ -64,5 +64,7 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ $(LOCAL_PATH)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \ $(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \ + $(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \ + $(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \ $(LOCAL_PATH)/newwavelabs/CrazyDream.ogg:system/media/audio/ringtones/CrazyDream.ogg \ $(LOCAL_PATH)/newwavelabs/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg diff --git a/data/sounds/effects/VideoRecord.ogg b/data/sounds/effects/VideoRecord.ogg Binary files differnew file mode 100644 index 0000000..1450522 --- /dev/null +++ b/data/sounds/effects/VideoRecord.ogg diff --git a/data/sounds/effects/VideoRecord.wav b/data/sounds/effects/VideoRecord.wav Binary files differnew file mode 100644 index 0000000..5809d93 --- /dev/null +++ b/data/sounds/effects/VideoRecord.wav diff --git a/data/sounds/effects/camera_click.ogg b/data/sounds/effects/camera_click.ogg Binary files differnew file mode 100644 index 0000000..52512ac --- /dev/null +++ b/data/sounds/effects/camera_click.ogg diff --git a/data/sounds/effects/camera_click.wav b/data/sounds/effects/camera_click.wav Binary files differnew file mode 100644 index 0000000..7043bc7 --- /dev/null +++ b/data/sounds/effects/camera_click.wav diff --git a/data/sounds/newwavelabs/Big_Easy.ogg b/data/sounds/newwavelabs/Big_Easy.ogg Binary files differnew file mode 100644 index 0000000..277dd96 --- /dev/null +++ b/data/sounds/newwavelabs/Big_Easy.ogg diff --git a/data/sounds/newwavelabs/Big_Easy.wav b/data/sounds/newwavelabs/Big_Easy.wav Binary files differnew file mode 100644 index 0000000..b83926a --- /dev/null +++ b/data/sounds/newwavelabs/Big_Easy.wav diff --git a/data/sounds/newwavelabs/Bollywood.ogg b/data/sounds/newwavelabs/Bollywood.ogg Binary files differnew file mode 100644 index 0000000..b393dd4 --- /dev/null +++ b/data/sounds/newwavelabs/Bollywood.ogg diff --git a/data/sounds/newwavelabs/Bollywood.wav b/data/sounds/newwavelabs/Bollywood.wav Binary files differnew file mode 100644 index 0000000..c6234bd --- /dev/null +++ b/data/sounds/newwavelabs/Bollywood.wav diff --git a/data/sounds/newwavelabs/Cairo.ogg b/data/sounds/newwavelabs/Cairo.ogg Binary files differnew file mode 100644 index 0000000..d90d3b4 --- /dev/null +++ b/data/sounds/newwavelabs/Cairo.ogg diff --git a/data/sounds/newwavelabs/Cairo.wav b/data/sounds/newwavelabs/Cairo.wav Binary files differnew file mode 100644 index 0000000..3a853d8 --- /dev/null +++ b/data/sounds/newwavelabs/Cairo.wav diff --git a/data/sounds/newwavelabs/Calypso_Steel.ogg b/data/sounds/newwavelabs/Calypso_Steel.ogg Binary files differnew file mode 100644 index 0000000..8e07da1 --- /dev/null +++ b/data/sounds/newwavelabs/Calypso_Steel.ogg diff --git a/data/sounds/newwavelabs/Calypso_Steel.wav b/data/sounds/newwavelabs/Calypso_Steel.wav Binary files differnew file mode 100644 index 0000000..9c823d2 --- /dev/null +++ b/data/sounds/newwavelabs/Calypso_Steel.wav diff --git a/data/sounds/newwavelabs/Champagne_Edition.ogg b/data/sounds/newwavelabs/Champagne_Edition.ogg Binary files differnew file mode 100644 index 0000000..0ba8be5 --- /dev/null +++ b/data/sounds/newwavelabs/Champagne_Edition.ogg diff --git a/data/sounds/newwavelabs/Champagne_Edition.wav b/data/sounds/newwavelabs/Champagne_Edition.wav Binary files differnew file mode 100644 index 0000000..1ccada3 --- /dev/null +++ b/data/sounds/newwavelabs/Champagne_Edition.wav diff --git a/data/sounds/newwavelabs/Club_Cubano.ogg b/data/sounds/newwavelabs/Club_Cubano.ogg Binary files differnew file mode 100644 index 0000000..5d09db1 --- /dev/null +++ b/data/sounds/newwavelabs/Club_Cubano.ogg diff --git a/data/sounds/newwavelabs/Club_Cubano.wav b/data/sounds/newwavelabs/Club_Cubano.wav Binary files differnew file mode 100644 index 0000000..08557b8 --- /dev/null +++ b/data/sounds/newwavelabs/Club_Cubano.wav diff --git a/data/sounds/newwavelabs/Eastern_Sky.ogg b/data/sounds/newwavelabs/Eastern_Sky.ogg Binary files differnew file mode 100644 index 0000000..c0cf74c --- /dev/null +++ b/data/sounds/newwavelabs/Eastern_Sky.ogg diff --git a/data/sounds/newwavelabs/Eastern_Sky.wav b/data/sounds/newwavelabs/Eastern_Sky.wav Binary files differnew file mode 100644 index 0000000..c980792 --- /dev/null +++ b/data/sounds/newwavelabs/Eastern_Sky.wav diff --git a/data/sounds/newwavelabs/Funk_Yall.ogg b/data/sounds/newwavelabs/Funk_Yall.ogg Binary files differnew file mode 100644 index 0000000..5b98643 --- /dev/null +++ b/data/sounds/newwavelabs/Funk_Yall.ogg diff --git a/data/sounds/newwavelabs/Funk_Yall.wav b/data/sounds/newwavelabs/Funk_Yall.wav Binary files differnew file mode 100644 index 0000000..0f2eebf --- /dev/null +++ b/data/sounds/newwavelabs/Funk_Yall.wav diff --git a/data/sounds/newwavelabs/Gimme_Mo_Town.ogg b/data/sounds/newwavelabs/Gimme_Mo_Town.ogg Binary files differnew file mode 100644 index 0000000..a196935 --- /dev/null +++ b/data/sounds/newwavelabs/Gimme_Mo_Town.ogg diff --git a/data/sounds/newwavelabs/Gimme_Mo_Town.wav b/data/sounds/newwavelabs/Gimme_Mo_Town.wav Binary files differnew file mode 100644 index 0000000..7adaa78 --- /dev/null +++ b/data/sounds/newwavelabs/Gimme_Mo_Town.wav diff --git a/data/sounds/newwavelabs/Glacial_Groove.ogg b/data/sounds/newwavelabs/Glacial_Groove.ogg Binary files differnew file mode 100644 index 0000000..a0e83e6 --- /dev/null +++ b/data/sounds/newwavelabs/Glacial_Groove.ogg diff --git a/data/sounds/newwavelabs/Glacial_Groove.wav b/data/sounds/newwavelabs/Glacial_Groove.wav Binary files differnew file mode 100644 index 0000000..da5702f --- /dev/null +++ b/data/sounds/newwavelabs/Glacial_Groove.wav diff --git a/data/sounds/newwavelabs/No_Limits.ogg b/data/sounds/newwavelabs/No_Limits.ogg Binary files differnew file mode 100644 index 0000000..346f2fe --- /dev/null +++ b/data/sounds/newwavelabs/No_Limits.ogg diff --git a/data/sounds/newwavelabs/No_Limits.wav b/data/sounds/newwavelabs/No_Limits.wav Binary files differnew file mode 100644 index 0000000..800f390 --- /dev/null +++ b/data/sounds/newwavelabs/No_Limits.wav diff --git a/data/sounds/newwavelabs/Paradise_Island.ogg b/data/sounds/newwavelabs/Paradise_Island.ogg Binary files differnew file mode 100644 index 0000000..386bbd3 --- /dev/null +++ b/data/sounds/newwavelabs/Paradise_Island.ogg diff --git a/data/sounds/newwavelabs/Paradise_Island.wav b/data/sounds/newwavelabs/Paradise_Island.wav Binary files differnew file mode 100644 index 0000000..3a51c7c --- /dev/null +++ b/data/sounds/newwavelabs/Paradise_Island.wav diff --git a/data/sounds/newwavelabs/Revelation.ogg b/data/sounds/newwavelabs/Revelation.ogg Binary files differnew file mode 100644 index 0000000..4a240e9 --- /dev/null +++ b/data/sounds/newwavelabs/Revelation.ogg diff --git a/data/sounds/newwavelabs/Revelation.wav b/data/sounds/newwavelabs/Revelation.wav Binary files differnew file mode 100644 index 0000000..4b4f073 --- /dev/null +++ b/data/sounds/newwavelabs/Revelation.wav diff --git a/data/sounds/newwavelabs/Road_Trip.ogg b/data/sounds/newwavelabs/Road_Trip.ogg Binary files differnew file mode 100644 index 0000000..cd14ef1 --- /dev/null +++ b/data/sounds/newwavelabs/Road_Trip.ogg diff --git a/data/sounds/newwavelabs/Road_Trip.wav b/data/sounds/newwavelabs/Road_Trip.wav Binary files differnew file mode 100644 index 0000000..6f17b08 --- /dev/null +++ b/data/sounds/newwavelabs/Road_Trip.wav diff --git a/data/sounds/newwavelabs/Savannah.ogg b/data/sounds/newwavelabs/Savannah.ogg Binary files differnew file mode 100644 index 0000000..779f3dd --- /dev/null +++ b/data/sounds/newwavelabs/Savannah.ogg diff --git a/data/sounds/newwavelabs/Savannah.wav b/data/sounds/newwavelabs/Savannah.wav Binary files differnew file mode 100644 index 0000000..8d8ada2 --- /dev/null +++ b/data/sounds/newwavelabs/Savannah.wav diff --git a/data/sounds/newwavelabs/Seville.ogg b/data/sounds/newwavelabs/Seville.ogg Binary files differnew file mode 100644 index 0000000..bea926a --- /dev/null +++ b/data/sounds/newwavelabs/Seville.ogg diff --git a/data/sounds/newwavelabs/Seville.wav b/data/sounds/newwavelabs/Seville.wav Binary files differnew file mode 100644 index 0000000..c211823 --- /dev/null +++ b/data/sounds/newwavelabs/Seville.wav diff --git a/data/sounds/newwavelabs/Shes_All_That.ogg b/data/sounds/newwavelabs/Shes_All_That.ogg Binary files differnew file mode 100644 index 0000000..86afbb3 --- /dev/null +++ b/data/sounds/newwavelabs/Shes_All_That.ogg diff --git a/data/sounds/newwavelabs/Shes_All_That.wav b/data/sounds/newwavelabs/Shes_All_That.wav Binary files differnew file mode 100644 index 0000000..780936d --- /dev/null +++ b/data/sounds/newwavelabs/Shes_All_That.wav diff --git a/data/sounds/newwavelabs/Steppin_Out.ogg b/data/sounds/newwavelabs/Steppin_Out.ogg Binary files differnew file mode 100644 index 0000000..5ee5fd1 --- /dev/null +++ b/data/sounds/newwavelabs/Steppin_Out.ogg diff --git a/data/sounds/newwavelabs/Steppin_Out.wav b/data/sounds/newwavelabs/Steppin_Out.wav Binary files differnew file mode 100644 index 0000000..5fae6bc --- /dev/null +++ b/data/sounds/newwavelabs/Steppin_Out.wav diff --git a/data/sounds/newwavelabs/Third_Eye.ogg b/data/sounds/newwavelabs/Third_Eye.ogg Binary files differnew file mode 100644 index 0000000..dd5a9fd --- /dev/null +++ b/data/sounds/newwavelabs/Third_Eye.ogg diff --git a/data/sounds/newwavelabs/Third_Eye.wav b/data/sounds/newwavelabs/Third_Eye.wav Binary files differnew file mode 100644 index 0000000..cd651cc --- /dev/null +++ b/data/sounds/newwavelabs/Third_Eye.wav diff --git a/data/sounds/newwavelabs/Thunderfoot.ogg b/data/sounds/newwavelabs/Thunderfoot.ogg Binary files differnew file mode 100644 index 0000000..5f907a8 --- /dev/null +++ b/data/sounds/newwavelabs/Thunderfoot.ogg diff --git a/data/sounds/newwavelabs/Thunderfoot.wav b/data/sounds/newwavelabs/Thunderfoot.wav Binary files differnew file mode 100644 index 0000000..bd8b0a3 --- /dev/null +++ b/data/sounds/newwavelabs/Thunderfoot.wav diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd index befb018..1f62f3d 100644 --- a/docs/html/guide/topics/graphics/2d-graphics.jd +++ b/docs/html/guide/topics/graphics/2d-graphics.jd @@ -85,7 +85,10 @@ protected void onCreate(Bundle savedInstanceState) { <p>In other cases, you may want to handle your image resource as a {@link android.graphics.drawable.Drawable} object. To do so, create a Drawable from the resource like so: -<pre>Drawable myImage = Resources.getDrawable(R.drawable.my_image);</pre> +<pre> +Resources res = mContext.getResources(); +Drawable myImage = res.getDrawable(R.drawable.my_image); +</pre> <p class="caution"><strong>Caution:</strong> Each unique resource in your project can maintain only one state, no matter how many different objects you may instantiate for it. For example, if you instantiate two diff --git a/docs/html/sdk/1.5_r1/index.jd b/docs/html/sdk/1.5_r1/index.jd new file mode 100644 index 0000000..345489a --- /dev/null +++ b/docs/html/sdk/1.5_r1/index.jd @@ -0,0 +1,62 @@ +page.title=Android 1.5 SDK, Release 1 + +sdk.version=1.5_r1 +sdk.date=April 2009 + +sdk.win_download=android-sdk-windows-1.5_r1.zip +sdk.win_bytes= +sdk.win_checksum= + +sdk.mac_download=android-sdk-mac_x86-1.5_r1.zip +sdk.mac_bytes= +sdk.mac_checksum= + +sdk.linux_download=android-sdk-linux_x86-1.5_r1.zip +sdk.linux_bytes= +sdk.linux_checksum= + + +@jd:body + +<h2>SDK Contents</h2> + +<h4>Development tools</h4> + +<p>The SDK includes a variety of tools for developing and debugging application code and designing an application UI. You can read about the tools in the +<a href="{@docRoot}guide/developing/tools/index.html">Dev Guide</a> and access them in the <code><sdk>/tools/</code> directory. + +<p>The tools package included in this SDK is the same as that included in the Android 1.0, Release 2 SDK. </p> + +<h4 id="system_images">System Images</h4> + +<p>The Android system images listed below are included in this SDK. For more information about a system image — features, applications included, localizations, API changes, and so on — see its Version Notes. </p> + +<table style="margin-right:1em;" width="80%"> +<tr> +<th><nobr>System Image</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th> +</tr> + +<tr> +<td width="5%"><nobr>Android 1.5</nobr></td> +<td width="5%">3</td> +<td width="5%"><nobr><a href="{@docRoot}sdk/android-1.5.html">Version Notes</a></nobr></td> +<td>Includes com.google.android.maps external library and a set of standard development applications. </td> + +</tr> + +</table> + +<h4>Sample Code and Applications</h4> + +<p>You can look at a variety of tutorials and samples in the <a href="{@docRoot}guide/samples/index.html">Dev Guide</a> and access the sample code itself +in the <code><sdk>/samples/</code> directory of the SDK package.</p> + +<h4>Documentation</h4> + +<p>The SDK package includes a full set of local documentation. To view it, open the <code><sdk>/documentation.html</code> file in a web browser. If you are developing in an IDE such as Eclipse, you can also view the reference documentation directly in the IDE. </p> + +<p>The most current documentation is always available on the Android Developers site:</p> + +<p style="margin-left:2em;"><a href="http://developer.android.com/index.html">http://developer.android.com/</a></p> + + diff --git a/docs/html/sdk/1.5_r1/installing.jd b/docs/html/sdk/1.5_r1/installing.jd new file mode 100644 index 0000000..df9ec3a --- /dev/null +++ b/docs/html/sdk/1.5_r1/installing.jd @@ -0,0 +1,312 @@ +page.title=Installing the Android SDK +sdk.version=1.5_r1 + +@jd:body + + +<p>This page describes how to install the Android SDK and set up your +development environment. If you haven't downloaded the SDK, you can +do so from the +<a href="{@docRoot}sdk/1.5_r1/index.html">Download</a> page.</p> + +<p>If you encounter any problems during installation, see the +<a href="#installnotes">Installation Notes</a> at the bottom of +this page.</p> + +<h4 style="margin-top">Upgrading?</h4> +<p>If you have already developed applications using an earlier version +of the SDK, please skip this page and read the +<a href="{@docRoot}sdk/1.5_r1/upgrading.html"><strong>Upgrading the +SDK</strong></a></b> document instead. +</p> + + +<h2 id="setup">Preparing for Installation</h2> + +<p>Before you get started with the Android SDK, take a moment to confirm +that your development machine meets the <a +href="{@docRoot}sdk/1.5_r1/requirements.html">system requirements</a>. +</p> + +<p>If you will be developing on Eclipse with the Android Development +Tools (ADT) Plugin — the recommended path if you are new to +Android — make sure that you have a suitable version of Eclipse +installed on your computer. If you need to install Eclipse, you can +download it from this location: </p> + +<p style="margin-left:2em;"><a href= +"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a +></p> + +<p>A Java or RCP version of Eclipse is recommended. </p> + +<h2 id="installingsdk">Installing the SDK</h2> + + <p>After downloading the SDK, unpack the .zip archive to a suitable location on your machine. By default, the SDK files are unpacked into a directory named <code>android_sdk_<em><platform</em>>_<em><release></em>_<em><build></em></code>. The directory contains a link to a local copy of the documentation and the subdirectories <code>tools/</code>, <code>samples/</code>, and others. </p> + + <p>Make a note of the name and location of the unpacked SDK directory on your system — you will need to refer to the SDK directory later, when setting up the Android plugin or using SDK tools. </p> + + <p>Optionally, you can add the path to the SDK <code>tools</code> directory to your path. As mentioned above, the <code>tools/</code> directory is located in the SDK directory. </p> + <ul> + <li>On Linux, edit your ~/.bash_profile or ~/.bashrc file. Look + for a line that sets the PATH environment variable and add the + full path to the <code>tools/</code> directory to it. If you don't + see a line setting the path, you can add one:</li> + + <ul><code>export PATH=${PATH}:<em><your_sdk_dir></em>/tools</code></ul> + + <li>On a Mac, look in your home directory for .bash_profile and + proceed as for Linux. You can create the .bash_profile, if + you haven't already set one up on your machine. </li> + + <li>On Windows, right click on My Computer, and select Properties. + Under the Advanced tab, hit the Environment Variables button, and in the + dialog that comes up, double-click on Path under System Variables. Add the full path to the <code>tools/</code> directory to the path. </li> + </ul> + + <p>Adding <code>tools</code> to your path lets you run Android Debug Bridge (adb) and the other command line <a href="{@docRoot}guide/developing/tools/index.html">tools</a> without needing to supply the full path to the tools directory. Note that, if you update your SDK, you should remember to update your PATH settings to point to the new location, if different.</p> + + +<p>If you will be using the Eclipse IDE as your environment for developing Android applications, continue reading the next +section in order to install the Android Development Tools plugin and set up Eclipse. If you choose not to use Eclipse, you can +develop Android applications using other tools — read the guide to developing +<a href="{@docRoot}guide/developing/other-ide.html">in other IDEs</a>.</p> + + +<h2 id="installingplugin">Installing the ADT Plugin for Eclipse</h2> + +<p>Android offers a custom plugin for the Eclipse IDE, called Android +Development Tools (ADT), that is designed to give you a powerful, +integrated environment in which to build Android applications. It +extends the capabilites of Eclipse to let you quickly set up new Android +projects, create an application UI, add components based on the Android +Framework API, and debug using the Android SDK tools.</p> + +<p>If you are new to Android or want to develop using the Eclipse IDE, +the ADT plugin will be an essential part of your development +environment. In general, using Eclipse with ADT is a highly recommended +approach and is the fastest way to get started. This section describes +how to install ADT into your Eclipse environment. + +<p>If you prefer to work in a development environment other than Eclipse, +you do not need to install Eclipse or the ADT Plugin. Instead, you can +access the SDK tools directly to build and debug your application. </p> + +<p>Once you have Eclipse installed, as described in <a href="#setup"> +Preparing for Installation</a>, follow the steps below to +download the ADT plugin and install it in your respective Eclipse +environment. </p> + +<table style="font-size:100%"> +<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr> +<tr> +<td width="45%"> +<ol> + <li>Start Eclipse, then select <strong>Help</strong> > <strong>Software Updates</strong> > <strong>Find + and Install...</strong>. </li> + + <li>In the dialog that appears, select <strong>Search for new features to install</strong> and click <strong>Next</strong>. </li> + <li>Click <strong>New Remote Site</strong>. </li> + <li>In the resulting dialog box, enter a name for the remote site (e.g. Android Plugin) and enter this as its URL: + <pre>https://dl-ssl.google.com/android/eclipse/</pre> + <p>Alternatively, you can use http in the Location URL, if you are having + trouble with https (https is preferred for security reasons).</p> + <pre>http://dl-ssl.google.com/android/eclipse/</pre> + <p>Click <strong>OK</strong>.</p> </li> + <li>You should now see the new site added to the search list (and checked). + Click <strong>Finish</strong>. </li> + <li>In the subsequent Search Results dialog box, select the checkbox for + <strong>Android Plugin</strong> > <strong>Developer Tools</strong>. + This will check both features: "Android Developer Tools", and "Android + Editors". The Android Editors feature is optional, but recommended. If + you choose to install it, you need the WST plugin mentioned earlier in this + page. Click <strong>Next</strong>. </li> + <li>Read the license agreement and then select <strong>Accept terms of the license agreement</strong>. + Click <strong>Next</strong>. </li> + <li>Click <strong>Finish</strong>. </li> + + <li>The ADT plugin is not signed; you can accept the installation anyway + by clicking <strong>Install All</strong>. </li> + <li>Restart Eclipse. </li> +</ol> + +</td> +<td> + +<ol> + <li>Start Eclipse, then select <strong>Help</strong> > <strong>Software Updates...</strong>. + </li> + <li>In the dialog that appears, click the <strong>Available Software</strong> tab. + </li> + <li>Click <strong>Add Site...</strong> + </li> + <li>Enter this as the Location: + <pre>https://dl-ssl.google.com/android/eclipse/</pre> + <p>Alternatively, you can use http in the Location URL, if you are having + trouble with https (https is preferred for security reasons).</p> + <pre>http://dl-ssl.google.com/android/eclipse/</pre> + <p>Click <strong>OK</strong>.</p></li> + <li>Back in the Available Software view, you should see the plugin. Select the checkbox next to + <em>Developer Tools</em> and click <strong>Install...</strong> + </li> + <li>On the subsequent Install window, "Android Developer Tools", and "Android Editors" should both be checked. + The Android Editors feature is optional, but recommended. If + you choose to install it, you need the WST plugin mentioned earlier in this + page. Click <strong>Next</strong>. + </li> + <li>Accept the license agreement and click <strong>Finish</strong>.</li> + <li>Restart Eclipse. </li> +</ol> + +</td> +</tr> +</table> + +<p>Now, you just need to modify your Eclipse preferences to point to the Android SDK directory:</p> +<ol> + <li>Select <strong>Window</strong> > <strong>Preferences...</strong> to open the Preferences + panel. (Mac OS X: <strong>Eclipse</strong> > <strong>Preferences</strong>) </li> + <li>Select <strong>Android</strong> from the left panel. </li> + <li>For the SDK Location in the main panel, click <strong>Browse...</strong> and locate the SDK directory. </li> + <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li> +</ol> + +<p>Done! If you haven't encountered any problems, then you're ready to +begin developing Android applications. See the <a href="#next">After +Installation: Next Steps</a> section for suggestions on how to start. </p> + + +<h3 id="troubleshooting">Troubleshooting ADT Installation</h3> +<p> +If you are having trouble downloading the ADT plugin after following the steps above, here are some suggestions: </p> + +<ul> + <li>If Eclipse can not find the remote update site containing the ADT plugin, try changing the remote site URL to use http, rather than https. That is, set the Location for the remote site to: + <pre>http://dl-ssl.google.com/android/eclipse/</pre></li> + <li>If you are behind a firewall (such as a corporate firewall), make + sure that you have properly configured your proxy settings in Eclipse. + In Eclipse 3.3/3.4, you can configure proxy information from the main + Eclipse menu in <strong>Window</strong> (on Mac, <strong>Eclipse</strong>) > <strong>Preferences</strong> > <strong>General</strong> > <strong>Network Connections</strong>.</li> +</ul> +<p> +If you are still unable to use Eclipse to download the ADT plugin as a remote update site, you can download the ADT files to your local machine using a browser and the install the files in Eclipse from there: +</p> +<ol> +<li><a href="{@docRoot}sdk/adt_download.html">Download the ADT zip file</a> (do not unpack it). +<li>Follow steps 1 and 2 in the default install instructions (above). +<li>In Eclipse 3.3, click <strong>New Archive Site...</strong>. <br/> + In Eclipse 3.4, click <strong>Add Site...</strong>, then <strong>Archive...</strong> +<li>Browse and select the downloaded the zip file. +<li>Follow the remaining procedures, above, starting from steps 5. +</ol> +<p> +Note that to update your plugin, you will have to follow these steps again instead of the default update instructions.</p> + +<p>Note that the "Android Editors" feature of ADT requires several optional +Eclipse components (for example, WST). If you encounter an error when +installing ADT, your Eclipse installion might not include those components. +For information about how to quickly add the necessary components to your +Eclipse installation, see the troubleshooting topic +<a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui"</a>.</p> + +<h4>For Linux users</h4> +<p>If you encounter this error when installing the ADT Plugin for Eclipse: +<pre> +An error occurred during provisioning. +Cannot connect to keystore. +JKS</pre> +<p> +...then your development machine lacks a suitable Java VM. Installing Sun +Java 6 will resolve this issue and you can then reinstall the ADT +Plugin.</p> + + +<h2 id="next">After Installation: Next Steps</h2> +<p>Once you have installed the SDK and the ADT Plugin, you are ready to +begin developing applications. Here are a few ways you can get started: </p> + +<p><strong>Learn about Android</strong></p> +<ul> +<li>Take a look at the <a href="{@docRoot}guide/index.html">Dev +Guide</a> and the types of information it provides</li> +<li>Read an introduction to Android as a platform in <a +href="{@docRoot}guide/basics/what-is-android.html">What is +Android?</a></li> +<li>Learn about the Android framework and how applications run on it in +<a href="{@docRoot}guide/topics/fundamentals.html">Application +Fundamentals</a></li> +<li>Take a look at the Android framework API specification in the <a +href="{@docRoot}reference/index.html">Reference</a> tab</li> +</ul> + +<p><strong>Explore the SDK</strong></p> +<ul> +<li>Get an overview of the <a +href="{@docRoot}guide/development/tools/index.html">development +tools</a> that are available to you</li> +<li>Read the overviews of how to develop <a +href="{@docRoot}guide/developing/eclipse-adt.html">in Eclipse/ADT</a> or +<a href="{@docRoot}guide/developing/other-ide.html">in other IDEs</a> +</li> +</ul> + +<p><strong>Explore some code</strong></p> +<ul> +<li>Set up a <a href="{@docRoot}guide/tutorials/hello-world.html">Hello +World application</a></li> +<li>Follow the <a href="{@docRoot}guide/tutorials/notepad/index.html"> +Notepad Tutorial</a> to build a full Android application </li> +<li>Create a new project for one of the other sample applications +included in <code><sdk>/samples</code>, then compile and run it in +your development environment</li> +</ul> + +<p><strong>Visit the Android developer groups</strong></p> +<ul> +<li>Take a look at the <a +href="{@docRoot}community/index.html">Community</a> tab to see a list of +Android developers groups. In particular, you might want to look at the +<a href="http://groups.google.com/group/android-developers">Android +Developers</a> group to get a sense for what the Android developer +community is like.</li> +</ul> + + +<h2 id="installnotes">Installation Notes</h2> +<h4>Ubuntu Linux Notes</h4> +<ul> + <li>If you need help installing and configuring Java on your +development machine, you might find these resources helpful: + <ul> + <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/Java </a></li> + <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/JavaInstallation </a></li> + </ul> + </li> +<li>Here are the steps to install Java and Eclipse, prior to installing +the Android SDK and ADT Plugin. +<ol> + <li>If you are running a 64-bit distribution on your development +machine, you need to install the <code>ia32-libs</code> package using +<code>apt-get:</code>: + <pre>apt-get install ia32-libs</pre></li> + <li>Next, install Java: + <pre>apt-get install sun-java6-bin</pre></li> + <li>The Ubuntu package manager does not currently offer an Eclipse 3.3 + version for download, so we recommend that you download Eclipse from +eclipse.org (<a +href="http://www.eclipse.org/downloads/">http://www.eclipse.org/ +downloads/</a>). A Java or RCP version of Eclipse is recommended.</li> +<li>Follow the steps given in previous sections to install the SDK +and the ADT plugin. </li> +</ol> +</ul> +<h4>Other Linux Notes</h4> +<ul> + <li>If JDK is already installed on your development computer, please +take a moment to make sure that it meets the version requirements listed +in the <a href="{@docRoot}sdk/1.5_r1/requirements.html">System Requirements</a>. +In particular, note that some Linux distributions may include JDK 1.4 or Gnu +Compiler for Java, both of which are not supported for Android development.</li> +</ul> + + diff --git a/docs/html/sdk/1.5_r1/requirements.jd b/docs/html/sdk/1.5_r1/requirements.jd new file mode 100644 index 0000000..3f0deca --- /dev/null +++ b/docs/html/sdk/1.5_r1/requirements.jd @@ -0,0 +1,42 @@ +page.title=System Requirements + +sdk.version=1.5_r1 +sdk.date=April 2009 + +@jd:body + +<p>The sections below describe the system and software requirements for developing Android applications using the Android SDK tools included in Android 1.5 SDK, Release 1. </p> + +<h3>Supported Operating Systems</h3> +<ul> + <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li> + <li>Mac OS X 10.4.8 or later (x86 only)</li> + <li>Linux (tested on Linux Ubuntu Dapper Drake)</li> +</ul> + +<h3>Supported Development Environments</h3> +<ul> + <li>Eclipse IDE + <ul> + <li><a href="http://www.eclipse.org/downloads/">Eclipse</a> 3.3 (Europa), 3.4 (Ganymede) + <ul> + <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included in most Eclipse IDE packages) </li> + <li><a href="http://www.eclipse.org/webtools">WST</a> (optional, but needed for the Android Editors feature; included in <a href="http://www.eclipse.org/downloads/moreinfo/compare.php">most Eclipse IDE packages</a>)</li> + </ul> + </li> + <li><a href="http://java.sun.com/javase/downloads/index.jsp">JDK 5 or JDK 6</a> (JRE alone is not sufficient)</li> + <li><a href="installing.html#installingplugin">Android Development Tools plugin</a> (optional)</li> + <li><strong>Not</strong> compatible with Gnu Compiler for Java (gcj)</li> + </ul> + </li> + <li>Other development environments or IDEs + <ul> + <li><a href="http://java.sun.com/javase/downloads/index.jsp">JDK 5 or JDK 6</a> (JRE alone is not sufficient)</li> + <li><a href="http://ant.apache.org/">Apache Ant</a> 1.6.5 or later for Linux and Mac, 1.7 or later for Windows</li> + <li><strong>Not</strong> compatible with Gnu Compiler for Java (gcj)</li> + </ul> + </li> +</ul> + +<p class="note"><strong>Note:</strong> If JDK is already installed on your development computer, please take a moment to make sure that it meets the version requirements listed above. In +particular, note that some Linux distributions may include JDK 1.4 or Gnu Compiler for Java, both of which are not supported for Android development. </p>
\ No newline at end of file diff --git a/docs/html/sdk/1.5_r1/upgrading.jd b/docs/html/sdk/1.5_r1/upgrading.jd new file mode 100644 index 0000000..23cb82c --- /dev/null +++ b/docs/html/sdk/1.5_r1/upgrading.jd @@ -0,0 +1,150 @@ +page.title=Upgrading the SDK +sdk.version=1.5_r1 +@jd:body + +<!-- +<div class="sidebox-wrapper"> + <div class="sidebox-inner"> + + <h2>Useful Links</h2> + + <ul class="noindent"> + <li><a href="migrating/0.9-1.0/changes-overview.html">Overview of Changes</a> + <p>A high-level look at what's changed in Android, with + discussion of how the changes may affect your apps.</p></li> + + <li><a href="migrating/0.9-1.0/changes.html">API Diff Report</a> + <p>A detailed report that lists all the specific changes in the latest SDK.</p></li> + + <li><a href="RELEASENOTES.html">Release Notes</a> + <p>Version details, known issues, and resolved issues. </p></li> + + <li><a href="http://groups.google.com/group/android-developers">Android Developers Group</a> + <p>A forum where you can discuss migration issues and learn from other Android developers. </p></li> + + <li><a href="http://code.google.com/p/android/issues/list">Android Issue Tracker</a> + <p>If you think you may have found a bug, use the issue tracker to report it.</p></li> + </ul> + + </div> +</div> +--> + +<p>This document describes how to move your development environment and existing +Android applications from an Android 1.0 SDK to the Android 1.5, Release 1 SDK. +If you are migrating applications from an earlier SDK, please read the upgrading +document available in the Android 1.0 SDK package. +</p> + +<p>To ensure that your applications are compliant with the Android 1.5 system available +on mobile devices, you need to install the Android 1.5 SDK and port your existing Android +applications to it. The sections below will guide you through the process.</p> + +<h2 id="install-new">Installing the Latest SDK</h2> + +<p><a href="{@docRoot}sdk/1.5_r1/index.html">Download the SDK</a> and unpack it into a safe location.</p> + +<p>After unpacking the new SDK and saving it an appropriate location, you should:</p> + +<ul> + <li>Wipe your emulator data. <p>Some data formats have changed since the last + SDK release, so any previously saved data in your emulator must be removed. Open a console/terminal + and navigate to the <code>/tools</code> directory of your new SDK. Launch the + emulator with the <code>-wipe-data</code> option. + <p>Windows: <code>emulator -wipe-data</code><br/> + Mac/Linux: <code>./emulator -wipe-data</code></p> + </li> + <li>Update your PATH variable (Mac/Linux; optional). <p>If you had previously setup your + PATH variable to point to the SDK tools directory, then you'll need to update it to + point to the new SDK. For example, for a <code>.bashrc</code> or <code>.bash_profile</code> file: + <code>export PATH=$PATH:<em><your_new_sdk_dir></em>/tools</code></p> + </li> + <li>If (and only if) you are developing using Ant, you will also need to modify + your build.xml properties to point to the new SDK. + <p>Open the <code>default.properties</code> file associated with your build.xml + file (typically located in the same directory). In the default.properties + file, update the <code>sdk-folder</code> property with the full path to + the new SDK directory.</p></li> +</ul> + +<a name="Updating_the_ADT_plugin" id="Updating_the_ADT_plugin"></a> +<h2 id="update-plugin">Update your ADT Eclipse Plugin</h2> + +<p>If you develop on Eclipse and are migrating from an Android 1.0 +SDK, no update of the ADT plugin is needed — skip to <a href="#updateEclipsePrefs">Update your Eclipse SDK Preferences</a>. </p> + +<p>If you are migrating from an earlier version of the SDK, you will +need to update the ADT plugin. <p>You may also want to upgrade your +ADT plugin when a new version becomes available for your existing version +of the SDK.</p> + +<p>The steps below describe how to update the ADT plugin to the latest +version available. </p> + +<table style="font-size:100%"> +<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr> +<tr> +<td width="50%"> +<ol> + <li> Select <strong>Help</strong> > <strong>Software Updates</strong> > <strong>Find and Install...</strong>. </li> + <li> Select <strong>Search for updates of the currently installed features</strong> and click <strong>Finish</strong>. </li> + <li> If any update for ADT is available, select and install. </li> + <li> Restart Eclipse.</li> +</ol> +<p> Alternatively, </p> +<ol> + <li> Select <strong>Help</strong> > <strong>Software Updates</strong> > <strong>Manage Configuration</strong>. </li> + + <li> Navigate down the tree and select <strong>Android Development Tools <version></strong> </li> + <li> Select <strong>Scan for Updates</strong> under <strong>Available Tasks</strong>.</li> +</ol> +</td> +<td> +<ol> + <li>Select <strong>Help</strong> > <strong>Software Updates...</strong></li> + <li>Select the <strong>Installed Software</strong> tab.</li> + <li>Click <strong>Update...</strong></li> + <li>If an update for ADT is available, select it and click <strong>Finish</strong>.</li> + <li>Restart Eclipse.</li> +</ol> +</td> +</tr> +</table> + +<h2 id="updateEclipsePrefs">Update your Eclipse SDK Preferences</h2> + +<p>The last step is to update your Eclipse preferences to point to the new SDK directory:</p> + <ol> + <li>Select <strong>Window</strong> > <strong>Preferences...</strong> to open the Preferences panel. (Mac OSX: <strong>Eclipse</strong> > <strong>Preferences</strong>)</li> + <li>Select <strong>Android</strong> from the left panel.</li> + <li>For the SDK Location in the main panel, click <strong>Browse...</strong> and locate the SDK directory.</li> + <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li> + </ol> + +<h2 id="migrate">Migrate Your Applications, if Necessary</h2> + +<p>If (and only if) you have written apps in an SDK released previous to +the Android 1.0 SDK, you will need to migrate your applications. After +installing the new SDK and updating the ADT Plugin (if applicable), you +may encounter breakages in your application code, due to +framework and API changes. You'll need to update your code to match the +latest APIs.</p> + +<p>One way to start is to open your project in Eclipse and see where the ADT +identifies errors in your application. From there, you can lookup +specific API changes in the Android 1.0 APIs in the +<a href="http://code.google.com/android/migrating/changes-overview.html"> +Overview of Changes</a> and <a href="http://code.google.com/android/migrating/changes.html"> +API Diffs Report</a>.</p> + +<p>If you have additional trouble updating your code, visit the +<a href="http://groups.google.com/group/android-developers">Android Developers Group</a> +to seek help from other Android developers.</p> + +<p>If you have modified one of the ApiDemos applications and would like to migrate it +to the new SDK, note that you will need to uninstall the version of ApiDemos that comes +preinstalled in the emulator. For more information, or if you encounter an "reinstallation" +error when running or installing ApiDemos, see the troubleshooting topic +<a href="{@docRoot}guide/appendix/faq/troubleshooting.html#apidemosreinstall">I can't install ApiDemos +apps in my IDE because of a signing error</a> for information about how to solve the problem.</p> + diff --git a/docs/html/sdk/OLD_RELEASENOTES.jd b/docs/html/sdk/OLD_RELEASENOTES.jd new file mode 100644 index 0000000..7751681 --- /dev/null +++ b/docs/html/sdk/OLD_RELEASENOTES.jd @@ -0,0 +1,527 @@ +page.title=Release Notes for Older SDK Versions +@jd:body + +<div class="special"> + <p><strong>Note:</strong> These are the release notes for the "early-look" SDK versions, released + before the full Android 1.0 release in September 2008. + Release notes for the Android 1.0 and later SDK versions are provided in the main + <a href="{@docRoot}sdk/RELEASENOTES.html">Release Notes</a> document.</p> +</div> + + + +<a name="0.9_r1" id="0.9_r1"></a> +<h2>Android 0.9 SDK Beta (r1)</h2> + +<p>This beta SDK release contains a large number of bug fixes and improvements from the early-look SDKs. +The sections below describe the highlights of the release. + +<h3>New Features and Notable Changes</h3> + +<p><strong>Behavior and System Changes</strong></p> +<ul> + <li>New Home screen and many user interface updates + </li> + <li>Minor changes to Activity lifecycle and task management + </li> + <li>New window option to request OpenGL acceleration for certain kinds of View structures + </li> +</ul> +<p> + <b> + Significant API Changes</b> +</p> +<ul> + <li>onFreeze(Bundle) renamed to onSaveInstanceState(Bundle), to better reflect the fact that it does not represent an actual change in application lifecycle + </li> + <li>IntentReceivers are now known as BroadcastReceivers (but still operate on Intents.) + </li> + <li>Various parts of the API cleaned up to use Intents instead of Bundles; Intent itself improved to reduce the need for separate payload Bundles.</li> + <li>ContentProvider Cursors have had significant changes to make them easier to create and remove certain data consistency bugs. + </li> + <li>Changes to menus to make them more flexible; also added context menus (similar to "right mouse button" menus) + </li> + <li>Changes to the Sensor API to make reading sensors more convenient and reduce the need to poll + </li> + <li>Improvements to the Camera API + </li> + <li>Significant changes to the Location API to make it easier to use and better self-documenting + </li> + <li>API cleanup on MapViews + </li> + <li>Performance-related changes to the MediaPlayer, as well as support for new types of ringtones + </li> + <li>Apache HTTPClient installation upgraded to 4.x of that API; 3.x version is removed + </li> + <li>HTTPClient 4.x removes multipart methods, include HttpMime which is an extension of Mime4j (http://james.apache.org/mime4j/index.html) in your project instead + </li> + <li>Improvements to WiFi and related networking + </li> + <li>New Preferences API to easily store small amounts of data + </li> + <li>Improvements to the Telephony API, including ability to obtain source number of incoming phone calls + </li> + <li>Variety of improvements to the View API + </li> + <li>Variety of improvements to component management, such as the ability to keep components private, better control over when processes are started, and ability to "alias" an Activity to more than one entry in AndroidManifest.xml + </li> + <li>Improvements to how the Browser and WebView, such as better control over content downloads + </li> + <li>A number of enhancements to XML layouts, such as the new <merge> tag + </li> + <li>Numerous improvements to the standard widgets + </li> + <li>Network access now requires that applications obtain a permission in their AndroidManifest.xml files. + </li> +</ul> +<p> + <b> + Maps & Location</b> +</p> +<ul> + <li>The MapView will require an API key on final Android 1.0 devices. This key can be obtained at no cost from Google, and will allow access to the full MapView API. In this release, the API key must be provided but can be any dummy value. In the final 1.0-compatible SDKs, this will need to be a real key. + </li> + <li>The KML-based mock location provider supported in previous releases is no longer supported. In the current SDK, you can use the emulator console to send GPS fix updates to the emulator and applications running on it. Also, the DDMS tool provides an UI that you can use to easily upload GPX and KML files. DDMS handles playback of the KML or GPX tracks automatically. </li> +</ul> +<p> + <b>ADT Plugin for Eclipse</b></p> + <p>The ADT Plugin that accompanies this SDK includes a preview of the Graphical Layout Editor. Files located in <project>/res/layout[-qualifiers]/ will be opened with the new layout editor. This is very much a work in progress, and provided here for preview purpose. The editor feature is subject to change. +</p> +<ul> + <li>Dual page editor with a WYSIWYG page (the graphical editor) and an XML page with content assist. + </li> + <li>The interactivity in the editor itself is limited to selection at the moment. Actions on the layout elements can be done from the following standard Eclipse views: Outline (add/remove/up/down), and Properties (editing of all the element properties with a tooltip in the status bar). + </li> + <li>Top part of the editor allows you to display the layout in different configurations (language, orientation, size, etc...), and different themes. + + <ul> + <li>All referenced resources (strings, bitmaps, etc...) are resolved based on the selected configuration/theme. + </li> + <li>A green check mark next to a resource qualifier indicates that the opened file matches the value of the qualifier. A warning sign indicates that the opened file does not specifies any value for this qualifier. + </li> + <li>If a different version of the opened layout matches the new configuration selection (in a different res/layout-qualifier folder) then the editor automatically switches to that new file. + </li> + </ul> + </li> + <li>Custom Views are supported, however if they do too much in their constructor/onDraw method, it may not work (the layout library used by the editor only includes a sub-part of the Android framework). Check the android console for errors/exceptions. + </li> +</ul> + +<p>Known issues/limitations for Graphical Layout Editor include:</p> + + <ul> + <li>Font display is very close but not equals to on-device rendering since the font engine in Java slightly differs from the font engine in Android. This should not have any impact on your layouts. + </li> + <li>Creating new views in a relative layout automatically puts each new elements below each other using the <i>layout_below</i> attribute. However, until the layout file is saved, they will appear stacked on top of each other. + </li> + <li>Some XML based drawables don't draw. Fading in the scroll/list view appears as a white rectangle. Generally do not expect every single fancy drawing feature of the android framework to be supported in the layout editor (but we're working on it). + </li> + <li>Themes defined in the project are not added to the theme drop-down. + </li> + <li>No animation support! + </li> + <li>No support for WebView, MapView and SurfaceView. + </li> + <li>No UI support for <merge>, <include>, <ViewStub> elements. You can add these elements to your manifest using the xml editor only. + </li> + <li>If a layout fails to render in a way that prevents the whole editor from opening, you can: + + <ul> + <li>open that particular file in a different editor: right click the file in the package explorer and choose Open With... > XML editor + </li> + <li>completely disable the layout editor, by setting a system wide environment variable called ANDROID_DISABLE_LAYOUT to any value. + </li> + </ul> + <li>If a layout fails to render, check the android console (in the standard Eclipse Console view). Errors/Exceptions will be displayed in there. + </li> + </ul> + </li> +</ul> +<p>Other ADT features/notes include:</p> +<ul> + <li>There is a new launch option for activity. You can choose to launch the default activity (finds an activity configured to show up in the home screen), or a specific activity, or none.</li> + <li>Normal Java resources (non Java files placed in package folders) are now properly packaged in the final package, and can be accessed through normal java API such as ClassLoader.getResourceAsStream()</li> + <li>Launch configuration now has an option to wipe emulator data on launch. This always asks for confirmation.</li> + <li>Launch configuration now has an option to disable the boot animation. This will let the emulator start faster on older computers.</li> + <li>Installation of application is now more robust and will notify of installation failure. Also installation is blocking, removing issues where ADT tried to launch the activity before the app was installed.</li> + +</ul> + +<p><b>Ant Build Tools</b></p> + +<ul> + <li><span>External jar libraries are now directly supported by build.xml, just drop them in the libs directory.</li> +</ul> + +<p><b>Emulator</b></p> + +<ul> + <li>The console port number of a given emulator instance is now displayed in its window's title bar.</li> + <li>You can define the console port number used by a given emulator instance. +To do so, start the instance with the '-port <port>' option and +specify which port the emulator should bind to for the console. <port> must be an *even* integer between 5554 and 5584 inclusive. The corresponding ADB port will be <port>+1.</li> + <li>The <code>-adb-port</code> command is deprecated. Please do not use it, as it will be removed soon and you cannot use both -port and -adb-port at the same time.</li> + <li>Voice/sms are automatically forwarded to other emulator instances running on the same machine, as long as you use their console port number as the destination phone number. For example, if you have two emulators running, the first one will typically use console port 5554, and the second one will use port 5556, dialing 5556 on the first emulator will generate an incoming call on the second emulator. You can also hold/unhold calls. This also works when sending SMS messages from one emulator to the other.</li> + <li>A new <code>-scale <fraction></code> option allows you to scale the emulator window. </li> + <li>A new <code>-no-boot-anim</code> option tells the emulator to disable the boot animation. On slower systems, this can significantly reduce the time to boot the system in the emulator.</li> + +</ul> + +<p> + <b>Other Development Tools</b> +</p> + +<p>The SDK includes several new development tools, such as</p> +<ul> + <li><a href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a> is a visual tool for inspecting and debugging your user interfaces and layout. </li> + <li><a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-patch</a> allows you to easily create a NinePatch graphic using a WYSIWYG editor. </li> + <li>The <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a> generates pseudo-random system and user events, for testing your application. </li> +</ul> +<p> + <b>Application Signing</b> +</p> +<ul> + <li>Starting with this release, Android .apk files must be cryptographically signed, or the system will reject them upon installation. The purpose of this requirement is to securely and uniquely identify developers, so that the system can -- for example -- safely let multiple .apk files signed by the same developer share resources. + </li> + <li>There are no requirements on the key used to sign .apk files; locally-generated and self-signed keys are allowed. There is no PKI, and developers will not be required to purchase certificates, or similar. For developers who use the Eclipse/ADT plugin, application signing will be largely automatic. Developers who do not use Eclipse/ADT can use the standard Java jarsigner tool to sign .apk files. + </li> +</ul> +<p> + <b>Sample Code</b> +</p> +<ul> + <li>LunarLander has been converted to render into a SurfaceView via a background Thread, for better performance. + </li> + <li>New sample: the source code for the now-obsolete Home screen from M5 is included as an example of how to construct a Home screen replacement. + </li> +</ul> +<p> + <b> + Removed Functionality</b> +</p> +<ul> + <li>Due to significant API changes in the upstream open-source project and due to the timeline of getting certain Bluetooth profile implementations certified, a comprehensive Bluetooth API will not be possible or present in Android 1.0. + </li> + <li>Due to the security risks inherent in accepting arbitrary data from "outside" the device, the data messaging facility of the GTalkService will not be present in Android 1.0. The GTalkService will provide connectivity to Google's servers for Google Talk instant messaging, but the API has been removed from this release while we improve the service. Note that this will be a Google-specific service and is not part of the core of Android. + </li> + <li>We know that these changes will affect many developers who have worked with the prior early looks at the SDK, and we are very sorry for the resulting inconvenience. We look forward to the possibilty of restoring some or all of this functionality in a later version of the Android platform. + </li> +</ul> +<p> + <b> + Miscellaneous</b> +</p> +<ul> + <li>Many internal and non-public APIs have been removed from the documentation. Classes and methods that are not present in the documentation are non-public and should not be used, even though they may appear in tools such as IDEs. A future version of the SDK will ship with an android.jar file that contains only public classes, to help developers avoid accidentally using non-public APIs. + </li> + <li>A few extraneous APIs (such as unnecessary packages under java.awt) have been removed. + </li> + <li>Several additional tools are included, such as a utility for easily drawing 9-patch images. + </li> + <li>The DDMS utility has been refactored into library form. This is not of direct interest to application developers, but may be of interest to vendors interested in integrating the Android SDK into their products. Watch for more information about the ddmlib library soon. + </li> + <li>For performance and maintainability reasons, some APIs were moved into separate modules that must be explicitly included in the application via a directive in AndroidManifest.xml. Notable APIs that fall into this category are the MapView, and the java.awt.* classes, which each now reside in separate modules that must be imported. Developers who overlook this requirement will see ClassNotFoundExceptions that seem spurious. + </li> + <li>Developers who use 'adb push' to install applications must now use 'adb install', since the full package manager is now implemented. 'adb push' will no longer work to install .apk files. + </li> + <li>The emulator supports a variety of new options, and some existing options have been changed. Please consult the updated emulator documentation for details. + </li> +</ul> + +<h3> + Resolved Issues +</h3> +<p> + The list below is not comprehensive, but instead highlights the most interesting fixes since the last SDK release. +</p> +<ul> + <li>More of the standard Android user applications are now included, such as the Music and Messaging applications. + </li> + <li>Many bug fixes to the Media Player + </li> + <li>Emulator performance is improved, especially for startup + </li> + <li>More internal APIs are removed from class documentation. (However, this work is not quite yet complete.) + </li> + <li>It's now much easier to add media content to the SD card and have the ContentProvider locate and expose it to other applications. + </li> +</ul> + +<h3> + Known Issues +</h3> +<ul> + <li>The final set of Intent patterns honored by Android 1.0 has not yet been fully documented. Documentation will be provided in future releases. + </li> + <li>We regret to inform developers that Android 1.0 will not support 3.5" floppy disks. + </li> + <li>Unfortunately, the ability to play audio streams from memory (such as via an InputStream or Reader) will not be possible in Android 1.0. As a workaround, we recommend that developers save media content to SD card and use MediaPlayer to play from a file URI, or embed a small HTTP server and play from a URI on localhost (such as http://127.0.0.1:4242/something). + </li> + <li>Android now supports modules or libraries that can be optionally linked into applications; a good example is the MapView, which has been moved into such a library. However, Android 1.0 will not support the ability for third-party developers to create such libraries for sharing with other applications. + </li> + <li>We believe that we have eliminated the problem with very long emulator startups on Windows, but had some trouble reproducing the issue. We are interested in feedback from developers, if this issue persists. + </li> +</ul> + + + + +<a name="m5-rc15"></a> +<h2>Version m5-rc15</h2> + +<h3>New Features</h3> +<p>m5-rc15 does not introduce any new features.</p> + +<h3>Resolved Issues</h3> +<ul> + <li>1012640: Incorrect handling of BMP images.</li> +</ul> + +<h3>Known Issues</h3> +<p>Unless otherwise noted, Known Issues from m5-rc14 also apply to m5-rc15.</p> + + + + +<a name="m5-rc14"></a> +<h2>Version m5-rc14</h2> + +<h3>New Features</h3> + +<p>In addition to changes in the Android APIs, m5-rc14 also introduces changes to the Android Developer Tools:</p> + +<h4>emulator</h4> +<ul> + <li>The Android emulator now support SD card images up to 128 GB in size. The previous limit was 2 GB.</li> +</ul> + +<h4>DDMS</h4> +<ul> + <li>Support for managing multiple devices has been integrated into DDMS. This should make it easier to debug applications that are run on multiple device scenarios.</li> +</ul> + +<h4>ADT</h4> +<ul> + <li>ADT now attempts to connect a debugger to any application that shows up + in the wait-for-debugger state, even if this application was not launched + from Eclipse. + <br /><br /> + The connection is actually established only if there exists a project + in the Eclipse workspace that contains an <code>AndroidManifest.xml</code> + declaring a package matching the name of the process. + To force this connection from your code, use <code>Debug.waitForDebugger()</code>. Activities declaring that they require their own process through the + "process" attribute with a value like ":someProcess" will be + recognized and a debugger will be connected accordingly. + This should make it easier to debug intent receivers, services, + providers, and other activities not launched from the standard app + launcher.<br /><br /></li> + <li>ADT has launch modes for device target selection. Automatic mode will: 1) launch an emulator if no device is present, 2) automatically target the device if only one is connected, and 3) prompt the user if 2 or more are connected. Manual mode will always prompt the user.<br /><br /></li> + <li>ADT also contains the same support for multiple devices that has been introduced into DDMS.</li> +</ul> + +<h4>AIDL</h4> +<ul> + <li>AIDL files that import and reuse types is now supported by activityCreator.py and ADT.</li> +</ul> + +<h4>traceview</h4> +<ul> + <li>The <a href="{@docRoot}guide/developing/tools/traceview.html">traceview</a> tool is now included in the SDK.</li> +</ul> + +<h3>Resolved Issues</h3> + +<p>The following Known Issues from m3-rc20 have been resolved:</p> +<ul> + <li>917572: The activityCreator created incorrect IntelliJ scripts</li> + <li>917465: Unanswered incoming calls placed from the emulator console will result in an unfinished call UI if you press the call back button</li> + <li>917247: dmtracedump and traceview tools are not available in the SDK</li> + <li>912168: Extremely rapid or prolonged scrolling in the Maps application or MapsView will result in application errors</li> + <li>905852: adb emits warnings about deprecated API use on Mac OS X 10.5</li> + <li>905242: The Run dialog sometimes failed to show the Android Launcher</li> + <li>901122: The focus ring in the browser is sometimes incorrect</li> + <li>896274: On Windows, the emulator sometimes starts off-screen</li> + <li>778432: Icons for newly installed applications do not display</li> +</ul> + +<h3>Known Issues</h3> + +<p>The following are known issues in m5-rc14:</p> + +<ul> + <li>1017312: The emulator window size has been reduced slightly, to allow it to be fully visible on smaller screens. This causes a slight clipping of the HVGA emulator skin but does not affect its function.</li> + <li>1021777: Setting a power requirement in a <code>Criteria</code> object passed to <code>{@link android.location.LocationManager#getBestProvider getBestProvider()}</code> will result in a value not being returned.</li> + <li>1025850: Emulator failing to launch from the Eclipse plugin due to wrong custom command line parameters do not report the error anywhere and silently fails.</li> +</ul> + +<p>Unless otherwise noted, Known Issues from m3-rc20a also apply to m5-rc14.</p> + + + + +<a name="m3-rc37a"></a> +<h2>Version m3-rc37a</h2> + +<p>Version m3-rc37a and ADT 0.3.3 were released on December 14, 2007.</p> + +<h3>New Features</h3> + +<h4>Android Debug Bridge (ADB)</h4> +<ul> +<li>Now supports multiple emulators on one host computer. Please note that you need to use the <code>-data</code> option when starting secondary emulators, to allow those instances to save their data across sessions. Also, DDMS does not yet support debugging on multiple emulators yet. </li> +</ul> + +<h4>ADT Plugin for Eclipse</h4> +<ul> +<li>Adds editor capabilities for working with Android manifest files, such as syntax highlighting and autocompletion. The editor capabilities require the Web Tools WST plugin for Eclipse, which is included in <a href="http://www.eclipse.org/downloads/moreinfo/compare.php">most Eclipse packages</a>. Not having WST does not prevent the ADT plugin from working. If necessary, you can download and install WST from the Web Tools Project <a href="http://download.eclipse.org/webtools/downloads">downloads page</a>. To update directly from an Eclipse installation, you can add a remote update site with this URL: http://download.eclipse.org/webtools/updates . Note that installing WST on Eclipse 3.4 will require installing other packages, as detailed on the WTP downloads page</a>. +</li> +<li>Now retries to launch the app on the emulator if it fails due to timing issues when the emulator is booting.</li> +<li>Adds support for loading custom skins from the <SDK>/lib/images/skins/ directory. The Skin dropdown in the Emulator tab is now built from the content of the skins/ directory in order to support developer-made skins.</li> +<li>Adds an Emulator control panel. This is a UI on top of the emulator console that allows you to change the state of the network and gsm connection, and to initiate incoming voice call. (This is also present in standalone DDMS.)</li> +<li>Adds support for referenced projects. Android projects will add to the apk package any code from referenced projects.</li> +<li>Eclipse console now warns if an .apk that is pushed to the device declares the same package as another already installed package.</li> +<li>Java classes generated by the Eclipse plugin are now marked as derived automatically, so that Team plugins do not consider them as regular source.</li> +</ul> + +<h4>Emulator Console</h4> +<ul> +<li>Now provides support for emulating inbound SMS messages. The ADT plugin and DDMS provide integrated access to +this capability. For more information about how to emulate inbound SMS from the console, +see <a href="{@docRoot}guide/developing/tools/emulator.html#sms">SMS Emulation</a>. </li> +</ul> + +<h4>Emulator</h4> +<ul><li>The default emulator skin has been changed to HVGA-P from QVGA-L. For information +about emulator skins and how to load a specific skin when starting the emulator, see +<a href="{@docRoot}guide/developing/tools/emulator.html#skins">Using Emulator Skins</a>.</li> +</ul> + +<h3>Resolved Issues</h3> + +<h4>907947</h4> +<p><code>adb -version</code> now returns a version number.</p> + +<h4>917462</h4> +<p>Audio on Windows is fixed and is no longer 'choppy'. </p> + +<h4>Removed Manifest File Locking on Mac OS X</h4> + +<p>ADT plugin now uses a custom java editor for R.java/Manifest.java, to make those files non-editable. This is to replace the current locking mechanism which causes issues on Mac OS (preventing projects from being deleted). Note that your project must recompile at least once for the lock to be removed from the files.</p> + +<h4>The following known issues noted in m3-rc20 are now fixed:</h4> +<p> +<ul> +<li>890937: Emulator does not support non-qwerty keyboards. +<li>894618: <code>adb shell</code> may fail to connect when used the first time. +<li>896274: On Windows, the emulator window may start off-screen. +<li>899949: The emulator may fail to start with <code>-useaudio</code> on some environments. +<li>912619: Emulator console listens on non-local ports 5554-5584. +<li>917399: On Windows, running multiple emulator consoles can result in unexpected behavior when simulating incoming telephone calls. +</ul> +</p> + +<h3>Known Issues</h3> + +<p>Unless otherwise noted, Known Issues from m3-rc22a also apply to m3-rc37a.</p> + + + + +<a name="m3-rc22a"></a> +<h2>Version m3-rc22a</h2> + +<p>Version m3-rc22a and ADT 0.3.1 were released on November 16, 2007.</p> + +<h3>Resolved Issues</h3> + +<h4>920067</h4> +<p>The New Android Project wizard provided by ADT 0.3.1 now properly displays error messages when used with Eclipse 3.2 on Windows.</p> + +<h4>920045</h4> +<p>The <code>AndroidManifest.xml</code> files generated by ADT 0.3.1 now include the XML element required for displaying the associated app in the "Applications" menu. If you have applications created with ADT 0.3.0, simply ensure that your <code>AndroidManifest.xml</code> file contains the following highlighted line:</p> +<pre> +... + <intent-filter> + <action android:value="android.intent.action.MAIN" /> + <strong><category android:value="android.intent.category.LAUNCHER" /></strong> + </intent-filter> +... +</pre> + +<h4>920098</h4> +<p>ADT 0.3.1 is now compatible with Eclipse 3.4.</p> + +<h4>920282</h4> +<p>Fixes a NullPointerException that is thrown in certain situations with the DDMS perspective in Eclipse.</p> + +<h4>918637</h4> +<p>Address a keyboard lock-up issue when using <code>adb</code> on Mac OS X 10.4 and 10.5.</p> + +<h3>Known Issues</h3> + +<p>Unless otherwise noted, known issues from m3-rc20a also apply to m3-rc22a.</p> + +<a name="m3-rc20a"></a> + +<h2>Version m3-rc20a</h2> +<h3>Known Issues</h3> + +<p>The following are known issues in m3-rc20a:</p> + +<h4>778432 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>In certain circumstances, icons for newly installed applications do not display as expected.</p> + +<h4>890937 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4> +<p>The emulator currently does not support non-QWERTY keyboards.</p> + +<h4>894618 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4> +<p>The adb shell command may fail to connect when used for the first time.</p> + +<h4>896274 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>On Windows, the emulator screen will sometimes show up off-screen when it is started. The workaround for this is to right-click on the emulator taskbar entry, select Move, and move the window using keyboard arrow keys</p> + +<h4>899949 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4> +<p>The emulator may fail to start when using the <code>-useaudio</code> in some environments</p> + +<h4>901122 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>The focus ring shown in the browser may sometimes not properly wrap links.</p> + +<h4>905242 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>On Mac OS X 10.5, the Eclipse plugin's Run Dialog may sometimes fail to show the option to select the Android Launcher.</p> + +<h4>905852 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>On Mac OS X 10.5, adb will emit warnings about deprecated API use when first used.</p> + +<h4>912168 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>extremely rapid or prolonged scrolling in the Maps application or in a MapView will result in application errors.</p> + +<h4>912619 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4> +<p>The emulator console listens for connections on ports 5554-5587. Future versions will only accept connections from localhost. It is recommend that you use a firewall to block external connections to those ports on your development machine.</p> + +<h4>912849</h4> +<p>On Mac OS X 10.4, the emulator may hang if started in the background (i.e. <code>./emulator &</code>).</p> + +<h4>914692</h4> +<p>On Mac OS X 10.5, the emulator will emit warnings about deprecated API use when started from the command line.</p> + +<h4>917247 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>The dmtracedump and traceview tools are not available in the SDK.</p> + +<h4>917399 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4> +<p>On Windows, running multiple emulator consoles can result in unexpected behavior when simulating incoming telephone calls.</p> + +<h4>917465 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>Unanswered incoming calls placed from the emulator console, will result in an unfinished call UI if you press the call back button.</p> + +<h4>917572 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4> +<p>Using activityCreator with the <code>--ide intellij</code> option creates IntelliJ scripts with incorrect documentation location specified. To correct, change value for the <code><JAVADOC></code> element in the generated .ipr file from <code>file://.../docs/framework</code> to <code>file://.../docs/reference</code>.</p> + +<h4>917579</h4> +<p>On Ubuntu 7.10 (Gusty), the Eclipse package installed by the <code>apt-get install eclipse</code> command uses java-gcj by default. This configuration is not compatible with the Android Eclipse plugin (ADT) and will result in "Class not found" errors whenever you access an ADT feature.</p> + <p>The resolution for this issue is to install a Sun JDK</p> + <pre>sudo update-java-alternatives --jre java-1.5.0-sun</pre> + <p>and then configure Eclipse to use it by exporting the following environment variable:</p> + <pre>export JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun</pre> + <p>or by adding following to your <code>.eclipse/eclipserc file</code>:</p> + <pre>JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun</pre> + diff --git a/docs/html/sdk/android-1.5.jd b/docs/html/sdk/android-1.5.jd new file mode 100644 index 0000000..55fc4ba --- /dev/null +++ b/docs/html/sdk/android-1.5.jd @@ -0,0 +1,248 @@ +page.title=Android 1.5 Version Notes +sdk.version=1.5_r1 +sys.date=April 2009 +@jd:body + +<p> +<em>Date:</em> April 2009<br /> +<em>API Level:</em> <strong>3</strong></p> + + +<p>This document provides version notes for the Android 1.5 system image included in the SDK. </p> + +<ul> +<li><a href="#overview">Overview</a> +<li><a href="#overview">External Libraries</a> +<li><a href="#comp">Device Compatibility</a> +<li><a href="#apps">Built-in Applications</a> +<li><a href="#locs">UI Localizations</a> +<li><a href="#resolved-issues">Resolved Issues</a> +<li><a href="#features">New Features</a> +<li><a href="#api-changes">API Changes</a> +</ul> + +<h2 id="overview">Overview</h2> + +<p>The Android 1.5 system image delivered in the SDK is the development +counterpart to the Android 1.5 production system image, deployable to +Android-powered handsets starting in February 2009. </p> + +<p>The Android 1.5 system image delivers an updated version of the framework +API. As with previous versions, the Android 1.5 API +is assigned an integer identifier — <strong>3</strong> — that is +stored in the system itself. This identifier, called the "API Level", allows the +system to correctly determine whether an application is compatible with +the system, prior to installing the application.</p> + +<p>Applications can reference a specific API Level value in their +manifest files, to indicate the minimum version of the Android system +required to run the application. To reference a minimum API Level, applications +can add a <code>minSdkVersion</code> attribute in their manifest files. +The value of the attribute is an integer corresponding to an API Level +identifier. Prior to installing an application, the system then checks the value of +<code>minSdkVersion</code> and allows the install only +if the referenced integer is less than or equal to the API Level integer stored +in the system itself. </p> + +<p>If you use the Android 1.5 system image to build an application +compatible with Android-powered devices running the Android 1.5 +platform, please note that you <strong><span +style="color:red;">must</span></strong> set the the +<code>android:minSdkVersion</code> attribute in the application's +manifest to "3", which is the API strictly associated with Android 1.5. +</p> + +<p>Specifically, you define the <code>android:minSdkVersion</code> +attribute in a <code><uses-sdk></code> element as a child of +<code><manifest></code> in the manifest file. When set, the +attribute looks like this: </p> + +<pre><manifest> + ... + <uses-sdk minSdkVersion="3" /> + ... +</manifest></pre> + +<p>By setting <code>android:minSdkVersion</code> in this way, you ensure +that users will only be able to install your application if their +devices are running the Android 1.5 platform. In turn, this ensures that +your application will function properly on their devices, especially if +it uses <a href="#apichange">APIs introduced in Android 1.5</a>. </p> + +<p>If your application uses APIs introduced in Android 1.5 but does not +declare <code><uses-sdk minSdkVersion="3" /></code>, then it will +run properly on Android 1.5 devices but <em>not</em> on Android 1.0 +devices. In the latter case, the application will crash at runtime when +it tries to use the Android 1.5 APIs.</p> + +<p>If your application does not use any new APIs introduced in Android +1.5, you can indicate general Android 1.0 compatibility by removing +<code>minSdkVersion</code> or setting the attribute to "1". However, +before publishing your application, you must make sure to compile your +application against the Android 1.0 system image (available in the +Android SDK), to ensure that it builds and functions properly for +Android 1.0 devices. You should test the application against system +images corresponding to the API Levels that the application is designed +to be compatible with.</p> + +<p>If you are sure your application is not using Android 1.5 APIs and +has no need to use them, you might find it easier to keep working in the +Android 1.1 SDK, rather than migrating to the Android 1.5 SDK and having +to do additional testing. </p> + + +<h2 id="extlibs">External Libraries</h2> + +<p>The system image includes these external libraries, which you can +access from your application by adding a <a +href="{@docRoot}guide/topics/manifest/uses-library-element.html"> +<uses-library></a>.</p> + <ul> + <li>com.google.android.maps — gives your +application access to Google Maps data. Note that, to use Google Maps +data, a Maps API Key is required.</li> + </ul> + +<h2 id="comp">Device Compatibility</h2> + +<p>The Android 1.5 system image was tested for compatability with the +Android-powered devices listed below:</p> + <ul> + <li><a href="http://www.t-mobileg1.com">T-Mobile G1</a></li> + </ul> + +<h2 id="apps">Built-in Applications</h2> + +<p>The system image includes these built-in applications:</p> + <ul> + <li>Alarm Clock</li> + <li>API Demos</li> + <li>Browser</li> + <li>Calculator</li> + <li>Camera</li> + <li>Contacts</li> + <li>Dev Tools</li> + <li>Dialer</li> + <li>Email</li> + <li>Maps (and StreetView)</li> + <li>Messaging</li> + <li>Music</li> + <li>Pictures</li> + <li>Settings</li> + </ul> + +<h2 id="locs">UI Localizations</h2> + +<p>The system image provides localized UI strings for the languages +listed below.</p> + <ul> + <li>English, US (en_US)</li> + <li>German (de) </li> + </ul> + +<p>Localized UI strings match the locales that are displayable in +the emulator, accessible through the device Settings application.</p> + +<h2 id="resolved-issues">Resolved Issues</h2> +<ul> +<li>AlarmClock alert now plays audio/vibe directly, rather than through +AlarmManager. AlarmClock alert starts playing audio/vibe in its +IntentReceiver, rather than on activity start. These changes should +prevent alarms from being blocked by modal dialogs.</li> +<li>Fixes to device sleep. </li> +<li>Single tap no longer opens the in-call dialpad; users now need to +touch and drag it. </li> +<li>Fixes a bug causing approximately 1 in 25 outbound messages to +freeze up the IMAP connection (to a Gmail based server) when transferred +to the Sent folder.</li> +<li>Removes automatic account setup entries that were broken or not +testable. Adds minor fixes to a few of the remaining entries. Makes +improvements to warning dialogs used for a few special cases. </li> +<li>Changes default mail checking interval to every 15 minutes (instead +of defaulting to "never").</li> +<li>Fixes password-quoting bugs in IMAP, so that users can include +special characters in passwords (e.g. spaces).</li> +<li>Fixes various errors in auto and manual account setup </li> +<li>Improves reporting for various connection errors, making it easier +for the user to diagnose failed account setups.</li> +<li>Fixes new-mail notifications for POP3 accounts.</li> +<li>Ensures proper auto-checking of accounts marked as "never +check".</li> +<li>Now displays date and time using user preference (e.g. 24 hr vs. +AM/PM).</li> +<li>Now shows cc: in message view.</li> +<li>Improves recovery from POP3 connection failures.</li> +<li>POP3 parser rules loosened, so the application can work with +non-compliant email servers.</li> +</ul> + +<h2 id="features">New Features</h2> + +<ul> +<li>Maps: Adds details and reviews when a user does a search on Maps and +clicks on a business to view its details.</li> +<li>Dialer: In-call screen timeout default is now longer when using the +speakerphone.</li> +<li>Dialer: Adds a "Show dialpad" / "Hide dialpad" item to the in-call +menu, to make it easier to discover the DTMF dialpad. </li> +<li>Adds support for saving attachments from MMS</li> +<li>Adds support for marquee in layouts.</li> +</ul> + +<h2 id="api-changes">API Changes</h2> + +<h3>Overview</strong></h3> + +<ul> +<li>Adds annotations for test systems, no actual (non-test) API +changes.</li> +<li>Adds a method to allow a process to easily determine its UID. +<li>Adds support for marquee in layouts.</li> +<li>Adds new methods for determining padding in views. Useful if you are +writing your own +subclasses of {@link android.view.View View}.</li> +<li>Adds new permissions that allow an application to broadcast an SMS +or WAP Push message. </li> +<li>API cleanup: removes protected constructor from +SDK-bound system images. </li> +</ul> + +<h3>API Change Details</h3> + +<table> +<tr> +<th>Module or Feature</th><th>Change Description</th> +</tr> +<tr><td rowspan="4">Annotations for test systems</td></tr> + <tr><td>Added {@link android.test.suitebuilder.annotation.LargeTest LargeTest} annotation.</td></tr> + <tr><td>Added {@link android.test.suitebuilder.annotation.MediumTest MediumTest} annotation.</td></tr> + <tr><td>Added {@link android.test.suitebuilder.annotation.SmallTest SmallTest} annotation.</td></tr> + +<tr><td rowspan="2">Allow a process to easily know its UID.</td></tr> + <tr><td>Added public method {@link android.os.Process#myUid} to class {@link android.os.Process android.os.Process}</td></tr> + +<tr><td rowspan="6">Padding in views</td></tr> + <tr><td>Added public method {@link android.view.View#getBottomPaddingOffset} to class {@link android.view.View android.view.View}.</td></tr> + <tr><td>Added public method {@link android.view.View#getLeftPaddingOffset} to class {@link android.view.View android.view.View}.</td></tr> + <tr><td>Added public method {@link android.view.View#getRightPaddingOffset} to class {@link android.view.View android.view.View}.</td></tr> + <tr><td>Added public method {@link android.view.View#getTopPaddingOffset} to class {@link android.view.View android.view.View}.</td></tr> + <tr><td>Added public method {@link android.view.View#isPaddingOffsetRequired} to class {@link android.view.View android.view.View}.</td></tr> + +<tr><td rowspan="3">Marquee support</td></tr> + <tr><td>Added public method {@link android.widget.TextView#setMarqueeRepeatLimit} to class {@link android.widget.TextView}</td></tr> + <tr><td>Added public field {@link android.R.attr#marqueeRepeatLimit android.R.attr.marqueeRepeatLimit}</td></tr> + +<tr><td rowspan="3">New permissions</td></tr> + <tr><td>Added public field {@link android.Manifest.permission#BROADCAST_SMS android.Manifest.permission.BROADCAST_SMS}</td></tr> + <tr><td>Added public field {@link android.Manifest.permission#BROADCAST_WAP_PUSH android.Manifest.permission.BROADCAST_WAP_PUSH}</td></tr> + +<tr><td rowspan="2">API cleanup</td></tr> + <tr><td>Removed protected constructor java.net.ServerSocket.ServerSocket(java.net.SocketImpl).</td></tr> + +</table> + + + + + + diff --git a/docs/html/sdk/older_releases.jd b/docs/html/sdk/older_releases.jd new file mode 100644 index 0000000..ff57a36 --- /dev/null +++ b/docs/html/sdk/older_releases.jd @@ -0,0 +1,234 @@ +page.title=Older Releases +@jd:body + +<div class="special"> + <strong>NOTICE:</strong> + <p>The SDKs listed on this page are "early-look" versions that were released in + the year preceding the full release of Android 1.0 in September 2008. Because + these early-look SDKs were released before the Android 1.0 API specification was + finalized, they do not provide a compliant Android execution environment. + Consequently, applications that you develop in these SDKs will not be able to + run on any Android-powered devices.</p> + + <p>If you have an older application that you built in one of the early-look SDKs, + you must migrate it to the Android + 1.0 SDK (or later release) before you will be able to deploy it to + an Android-powered device. To help with this migration, each SDK package below + provides information about API changes from the previous version. You can find + the migration information in the documentation included in each SDK package.</p> + + <p>If you are just getting started developing on Android, do not use one of these early-look + SDKs. Instead, develop using the most <a href="{@docRoot}sdk/index.html">current + SDK release</a> available, to ensure that your applications will be compatible + with Android-powered devices.</p> +</div> + + + + + <h2>Android 0.9 SDK beta</h2> + <p><em>August 18, 2008 - <a href="OLD_RELEASENOTES.html#0.9_beta">Release Notes</a></em></p> + <table> + <tr> + <th>Platform</th> + <th>Package</th> + <th>Size</th> + <th>MD5 Checksum</th> + </tr> + <tr> + <td>Windows</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk-windows-0.9_beta.zip">android-sdk-windows-0.9_beta.zip</a></td> + <td>93,126,573 bytes</td> + <td>305031ad8335d1b6040bdd5a65349d6d</td> + </tr> + <tr class="alt"> + <td>Mac OS X (intel)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk-mac_x86-0.9_beta.zip">android-sdk-mac_x86-0.9_beta.zip</a></td> + <td>91,374,464 bytes</td> + <td>9a6969159091cede46302e11049fe3ca</td> + </tr> + <tr> + <td>Linux (i386)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk-linux_x86-0.9_beta.zip">android-sdk-linux_x86-0.9_beta.zip</a></td> + <td>91,821,068 bytes</td> + <td>077e5ef549dd9c5be54bd88e6a8e196c</td> + </tr> + </table> + + + + +<h2>Version m5-rc15</h2> + <p><em>March 3, 2008 - <a href="OLD_RELEASENOTES.html#m5-rc15">Release Notes</a></em></p> + <table> + <tr> + <th>Platform</th> + <th>Package</th> + <th>Size</th> + <th>MD5 Checksum</th> + </tr> + <tr> + <td>Windows</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc15_windows.zip">android-sdk_m5-rc15_windows.zip</a></td> + <td>79 MB</td> + <td>ecce40bc50201886d95ba2690cdbc5ce</td> + </tr> + <tr class="alt"> + <td>Mac OS X (intel)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc15_mac-x86.zip">android-sdk_m5-rc15_mac-x86.zip</a></td> + <td>76 MB</td> + <td>45a6385bbc1b2cb295409cfc81fb04b4</td> + </tr> + <tr> + <td>Linux (i386)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc15_linux-x86.zip">android-sdk_m5-rc15_linux-x86.zip</a></td> + <td>76 MB</td> + <td>e913f785afecdeed34c30639fd8c5862</td> + </tr> + </table> + + + + + <h2>Version m5-rc14</h2> + <p><em>February 12, 2008 - <a href="OLD_RELEASENOTES.html#m5-rc14">Release Notes</a></em></p> + <table> + <tr> + <th>Platform</th> + <th>Package</th> + <th>Size</th> + <th>MD5 Checksum</th> + </tr> + <tr> + <td>Windows</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc14_windows.zip">android-sdk_m5-rc14_windows.zip</a></td> + <td>79 MB</td> + <td>ecc75c1e69588350634ca25867ce05a0</td> + </tr> + <tr class="alt"> + <td>Mac OS X (intel)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc14_mac-x86.zip">android-sdk_m5-rc14_mac-x86.zip</a></td> + <td>76 MB</td> + <td>844c80d0adb1a326f5a9fff262c61efc</td> + </tr> + <tr> + <td>Linux (i386)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc14_linux-x86.zip">android-sdk_m5-rc14_linux-x86.zip</a></td> + <td>76 MB</td> + <td>f8b863c8a880afe9bb84124f5976aab1</td> + </tr> + </table> + + + + + <h2>Version m3-rc37a</h2> + <p><em>December 14, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc37a">Release Notes</a></em></p> + <table> + <tr> + <th>Platform</th> + <th>Package</th> + <th>Size</th> + <th>MD5 Checksum</th> + </tr> + <tr> + <td>Windows</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_windows_m3-rc37a.zip">android_sdk_windows_m3-rc37a.zip</a></td> + <td>58 MB</td> + <td>5db5aea20a2c2f010baefc4b1091a575</td> + </tr> + <tr class="alt"> + <td>Mac OS X (intel)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_darwin_m3-rc37a.zip">android_sdk_darwin_m3-rc37a.zip</a></td> + <td>54 MB</td> + <td>0b22e73fbd07b4af4009387afce3a37f</td> + </tr> + <tr> + <td>Linux (i386)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_linux_m3-rc37a.zip">android_sdk_linux_m3-rc37a.zip</a></td> + <td>54 MB</td> + <td>41285beecc4f9926e6ecf5f12610b356</td> + </tr> + </table> + + + + + <h2>Version m3-rc22a</h2> + <p><em>November 16, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc22a">Release Notes</a></em></p> + <table> + <tr> + <th>Platform</th> + <th>Package</th> + <th>Size</th> + <th>MD5 Checksum</th> + </tr> + <tr> + <td>Windows</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_windows_m3-rc22a.zip">android_sdk_windows_m3-rc22a.zip</a></td> + <td>59 MB</td> + <td>aa3dee05a9872752a3bc4efd0f93e98b</td> + </tr> + <tr class="alt"> + <td>Mac OS X (intel)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_darwin_m3-rc22a.zip">android_sdk_darwin_m3-rc22a.zip</a></td> + <td>55 MB</td> + <td>0547f45614ad94c3af22c3c0aa6f709f</td> + </tr> + <tr> + <td>Linux (i386)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_linux_m3-rc22a.zip">android_sdk_linux_m3-rc22a.zip</a></td> + <td>55 MB</td> + <td>84b3455de5cdfd841a172c13d24c382e</td> + </tr> + </table> + + + + + <h2>Version m3-rc20a</h2> + <p><em>November 12, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc20a">Release Notes</a></em></p> + <table> + <tr> + <th>Platform</th> + <th>Package</th> + <th>Size</th> + <th>MD5 Checksum</th> + </tr> + <tr> + <td>Windows</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_windows_m3-rc20a.zip">android_sdk_windows_m3-rc20a.zip</a></td> + <td>59 MB</td> + <td>a404b875708df7339ba77bdf2e08dc06</td> + </tr> + <tr class="alt"> + <td>Mac OS X (intel)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_darwin_m3-rc20a.zip">android_sdk_darwin_m3-rc20a.zip</a></td> + <td>55 MB</td> + <td>8fc29aeaa45eda84bfac854ebd02a6da</td> + </tr> + <tr> + <td>Linux (i386)</td> + <td> +<a href="{@docRoot}sdk/download.html?v=android_sdk_linux_m3-rc20a.zip">android_sdk_linux_m3-rc20a.zip</a></td> + <td>55 MB</td> + <td>9196759df9b69cd89a220b156f133364</td> + </tr> + </table> diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 76c1c84..8c7a0a7 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -2,7 +2,7 @@ <ul> <li><?cs if:android.whichdoc != "online" ?> - <h2>Android 1.1 SDK, r1</h2><?cs + <h2>Android 1.5 SDK, r1</h2><?cs else ?> <h2>Current SDK Release</h2><?cs /if ?> @@ -22,6 +22,7 @@ <li> <h2>Android System Images</h2> <ul> + <li><a href="<?cs var:toroot ?>sdk/android-1.5.html">Android 1.5 Version Notes</a></li> <li><a href="<?cs var:toroot ?>sdk/android-1.1.html">Android 1.1 Version Notes</a></li> </ul> </li> @@ -30,6 +31,7 @@ <ul> <li><a href="<?cs var:toroot ?>sdk/1.0_r2/index.html">Android 1.0 SDK, release 2</a></li> <li><a href="<?cs var:toroot ?>sdk/1.0_r1/index.html">Android 1.0 SDK, release 1</a></li> + <li><a href="<?cs var:toroot ?>sdk/older_releases.html">Older Releases</a></li> </ul> </li><?cs /if ?> diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index ff64855..7164b78 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -335,6 +335,7 @@ private: uint32_t mNotificationFrames; uint32_t mRemainingFrames; uint32_t mMarkerPosition; + bool mMarkerReached; uint32_t mNewPosition; uint32_t mUpdatePeriod; }; diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 77c90ba..3a3a714 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -38,6 +38,7 @@ public: ALARM = 4, NOTIFICATION = 5, BLUETOOTH_SCO = 6, + ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker NUM_STREAM_TYPES }; diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 659f5f8..7645978 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -409,6 +409,7 @@ private: int mLoopCount; uint32_t mRemainingFrames; uint32_t mMarkerPosition; + bool mMarkerReached; uint32_t mNewPosition; uint32_t mUpdatePeriod; }; diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 58906d1..255a67b 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -173,6 +173,7 @@ private: }; sp<IMediaPlayer> mPlayer; + thread_id_t mLockThreadId; Mutex mLock; Mutex mNotifyLock; Condition mSignal; diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 78d7621..b9ea0c6 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -104,7 +104,8 @@ enum media_recorder_error_type { // enum media_recorder_info_type { MEDIA_RECORDER_INFO_UNKNOWN = 1, - MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800 + MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800, + MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801 }; // ---------------------------------------------------------------------------- diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 1991aa7..bda969c 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -64,7 +64,8 @@ struct audio_track_cblk_t uint16_t waitTimeMs; // Cumulated wait time // Padding ensuring that data buffer starts on a cache line boundary (32 bytes). // See AudioFlinger::TrackBase constructor - int32_t Padding[3]; + int32_t Padding[1]; + // Cache line boundary audio_track_cblk_t(); uint32_t stepUser(uint32_t frameCount); diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h index f9eeb30..5c64b22 100644 --- a/include/ui/ISurfaceComposer.h +++ b/include/ui/ISurfaceComposer.h @@ -81,6 +81,11 @@ public: eOrientation270 = 3, eOrientationSwapMask = 0x01 }; + + // flags for setOrientation + enum { + eOrientationAnimationDisable = 0x00000001 + }; /* create connection with surface flinger, requires * ACCESS_SURFACE_FLINGER permission @@ -100,7 +105,7 @@ public: virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) = 0; /* Set display orientation. recquires ACCESS_SURFACE_FLINGER permission */ - virtual int setOrientation(DisplayID dpy, int orientation) = 0; + virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) = 0; /* signal that we're done booting. * recquires ACCESS_SURFACE_FLINGER permission diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h index 5d9222d..76a3b55 100644 --- a/include/ui/SurfaceComposerClient.h +++ b/include/ui/SurfaceComposerClient.h @@ -97,7 +97,7 @@ public: static status_t unfreezeDisplay(DisplayID dpy, uint32_t flags = 0); //! Set the orientation of the given display - static int setOrientation(DisplayID dpy, int orientation); + static int setOrientation(DisplayID dpy, int orientation, uint32_t flags); // Query the number of displays static ssize_t getNumberOfDisplays(); diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index 7d3fcf2..d01d83f 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -814,7 +814,7 @@ struct ResTable_config ORIENTATION_ANY = 0x0000, ORIENTATION_PORT = 0x0001, ORIENTATION_LAND = 0x0002, - ORIENTATION_SQUARE = 0x0002, + ORIENTATION_SQUARE = 0x0003, }; enum { diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 3c81a47..1069362 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -58,6 +58,9 @@ namespace android { +static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n"; +static const char* kHardwareLockedString = "Hardware lock is taken\n"; + //static const nsecs_t kStandbyTimeInNsecs = seconds(3); static const unsigned long kBufferRecoveryInUsecs = 2000; static const unsigned long kMaxBufferRecoveryInUsecs = 20000; @@ -195,7 +198,7 @@ AudioFlinger::~AudioFlinger() #ifdef WITH_A2DP // setA2dpEnabled_l() must be called with AudioFlinger::mLock held void AudioFlinger::setA2dpEnabled_l(bool enable) -{ +{ SortedVector < sp<MixerThread::Track> > tracks; SortedVector < wp<MixerThread::Track> > activeTracks; @@ -240,13 +243,8 @@ bool AudioFlinger::streamForcedToSpeaker(int streamType) // AudioSystem::routedToA2dpOutput(streamType) == false return (streamType == AudioSystem::RING || streamType == AudioSystem::ALARM || - streamType == AudioSystem::NOTIFICATION); -} - -bool AudioFlinger::streamDisablesA2dp(int streamType) -{ - return (streamType == AudioSystem::VOICE_CALL || - streamType == AudioSystem::BLUETOOTH_SCO); + streamType == AudioSystem::NOTIFICATION || + streamType == AudioSystem::ENFORCED_AUDIBLE); } status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) @@ -301,18 +299,39 @@ status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args return NO_ERROR; } +static bool tryLock(Mutex& mutex) +{ + bool locked = false; + for (int i = 0; i < kDumpLockRetries; ++i) { + if (mutex.tryLock() == NO_ERROR) { + locked = true; + break; + } + usleep(kDumpLockSleep); + } + return locked; +} + status_t AudioFlinger::dump(int fd, const Vector<String16>& args) { if (checkCallingPermission(String16("android.permission.DUMP")) == false) { dumpPermissionDenial(fd, args); } else { - bool locked = false; - for (int i = 0; i < kDumpLockRetries; ++i) { - if (mLock.tryLock() == NO_ERROR) { - locked = true; - break; - } - usleep(kDumpLockSleep); + // get state of hardware lock + bool hardwareLocked = tryLock(mHardwareLock); + if (!hardwareLocked) { + String8 result(kHardwareLockedString); + write(fd, result.string(), result.size()); + } else { + mHardwareLock.unlock(); + } + + bool locked = tryLock(mLock); + + // failed to lock - AudioFlinger is probably deadlocked + if (!locked) { + String8 result(kDeadlockedString); + write(fd, result.string(), result.size()); } dumpClients(fd, args); @@ -496,6 +515,14 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) } LOGV("setOutput done\n"); } + // setRouting() is always called at least for mode == AudioSystem::MODE_IN_CALL when + // SCO is enabled, whatever current mode is so we can safely handle A2DP disabling only + // in this case to avoid doing it several times. + if (mode == AudioSystem::MODE_IN_CALL && + (mask & AudioSystem::ROUTE_BLUETOOTH_SCO)) { + AutoMutex lock(&mLock); + handleRouteDisablesA2dp_l(routes); + } #endif // do nothing if only A2DP routing is affected @@ -619,7 +646,8 @@ status_t AudioFlinger::setStreamVolume(int stream, float value) return PERMISSION_DENIED; } - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { + if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES || + uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) { return BAD_VALUE; } @@ -663,10 +691,11 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted) return PERMISSION_DENIED; } - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { + if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES || + uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) { return BAD_VALUE; } - + #ifdef WITH_A2DP mA2dpMixerThread->setStreamMute(stream, muted); #endif @@ -681,8 +710,6 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted) mHardwareMixerThread->setStreamMute(stream, muted); } - - return NO_ERROR; } @@ -854,36 +881,29 @@ void AudioFlinger::handleForcedSpeakerRoute(int command) } #ifdef WITH_A2DP -// handleStreamDisablesA2dp_l() must be called with AudioFlinger::mLock held -void AudioFlinger::handleStreamDisablesA2dp_l(int command) -{ - switch(command) { - case ACTIVE_TRACK_ADDED: - { - if (mA2dpDisableCount++ == 0) { - if (mA2dpEnabled) { - setA2dpEnabled_l(false); - mA2dpSuppressed = true; - } +// handleRouteDisablesA2dp_l() must be called with AudioFlinger::mLock held +void AudioFlinger::handleRouteDisablesA2dp_l(int routes) +{ + if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) { + if (mA2dpDisableCount++ == 0) { + if (mA2dpEnabled) { + setA2dpEnabled_l(false); + mA2dpSuppressed = true; } - LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); } - break; - case ACTIVE_TRACK_REMOVED: - { - if (mA2dpDisableCount > 0) { - if (--mA2dpDisableCount == 0) { - if (mA2dpSuppressed) { - setA2dpEnabled_l(true); - mA2dpSuppressed = false; - } + LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); + } else { + if (mA2dpDisableCount > 0) { + if (--mA2dpDisableCount == 0) { + if (mA2dpSuppressed) { + setA2dpEnabled_l(true); + mA2dpSuppressed = false; } - LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount); - } else { - LOGE("mA2dpDisableCount is already zero"); } + LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount); + } else { + LOGE("mA2dpDisableCount is already zero"); } - break; } } #endif @@ -1517,13 +1537,6 @@ void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t) if (streamForcedToSpeaker(track->type())) { mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED); } -#ifdef WITH_A2DP - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - if (streamDisablesA2dp(track->type())) { - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED); - } -#endif } } @@ -1541,13 +1554,6 @@ void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t) if (streamForcedToSpeaker(track->type())) { mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED); } -#ifdef WITH_A2DP - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - if (streamDisablesA2dp(track->type())) { - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED); - } -#endif } } @@ -1615,8 +1621,8 @@ AudioFlinger::MixerThread::TrackBase::TrackBase( new(mCblk) audio_track_cblk_t(); // clear all buffers mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; + mCblk->sampleRate = (uint16_t)sampleRate; + mCblk->channels = (uint16_t)channelCount; if (sharedBuffer == 0) { mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); @@ -1639,8 +1645,8 @@ AudioFlinger::MixerThread::TrackBase::TrackBase( new(mCblk) audio_track_cblk_t(); // clear all buffers mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; + mCblk->sampleRate = (uint16_t)sampleRate; + mCblk->channels = (uint16_t)channelCount; mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); // Force underrun condition to avoid false underrun callback until first data is @@ -1697,7 +1703,7 @@ sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const } int AudioFlinger::MixerThread::TrackBase::sampleRate() const { - return mCblk->sampleRate; + return (int)mCblk->sampleRate; } int AudioFlinger::MixerThread::TrackBase::channelCount() const { @@ -1710,11 +1716,12 @@ void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t int16_t *bufferEnd = bufferStart + frames * cblk->channels; // Check validity of returned pointer in case the track control block would have been corrupted. - if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) { - LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ - server %d, serverBase %d, user %d, userBase %d", + if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || + cblk->channels == 2 && ((unsigned long)bufferStart & 3) ) { + LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ + server %d, serverBase %d, user %d, userBase %d, channels %d", bufferStart, bufferEnd, mBuffer, mBufferEnd, - cblk->server, cblk->serverBase, cblk->user, cblk->userBase); + cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels); return 0; } @@ -1881,12 +1888,14 @@ void AudioFlinger::MixerThread::Track::flush() // STOPPED state mState = STOPPED; + mCblk->lock.lock(); // NOTE: reset() will reset cblk->user and cblk->server with // the risk that at the same time, the AudioMixer is trying to read // data. In this case, getNextBuffer() would return a NULL pointer // as audio buffer => the AudioMixer code MUST always test that pointer // returned by getNextBuffer() is not NULL! reset(); + mCblk->lock.unlock(); } void AudioFlinger::MixerThread::Track::reset() @@ -2495,19 +2504,6 @@ status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* record mRecordTrack = recordTrack; -#ifdef WITH_A2DP - { // scope for lock2 - - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - AutoMutex lock2(&mAudioFlinger->mLock); - - // Currently there is no way to detect if we are recording over SCO, - // so we disable A2DP during any recording. - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED); - } -#endif - // signal thread to start LOGV("Signal record thread"); mWaitWorkCV.signal(); @@ -2520,18 +2516,6 @@ void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack LOGV("AudioRecordThread::stop"); AutoMutex lock(&mLock); if (mActive && (recordTrack == mRecordTrack.get())) { -#ifdef WITH_A2DP - { // scope for lock2 - - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - AutoMutex lock2(&mAudioFlinger->mLock); - - // Currently there is no way to detect if we are recording over SCO, - // so we disable A2DP during any recording. - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED); - } -#endif mActive = false; mStopped.wait(mLock); } diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index ab15947..db5cc74 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -165,7 +165,6 @@ private: void checkA2dpEnabledChange_l(); #endif static bool streamForcedToSpeaker(int streamType); - static bool streamDisablesA2dp(int streamType); // Management of forced route to speaker for certain track types. enum force_speaker_command { @@ -176,7 +175,7 @@ private: }; void handleForcedSpeakerRoute(int command); #ifdef WITH_A2DP - void handleStreamDisablesA2dp_l(int command); + void handleRouteDisablesA2dp_l(int routes); #endif // Internal dump utilites. diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp index b03467f..b02efcc 100644 --- a/libs/audioflinger/AudioMixer.cpp +++ b/libs/audioflinger/AudioMixer.cpp @@ -16,6 +16,7 @@ */ #define LOG_TAG "AudioMixer" +//#define LOG_NDEBUG 0 #include <stdint.h> #include <string.h> @@ -780,8 +781,10 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void* // in == NULL can happen if the track was flushed just after having // been enabled for mixing. - if (in == NULL) { + if (in == NULL || ((unsigned long)in & 3)) { memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t)); + LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x", + in, i, t.channelCount, t.needs); return; } size_t outFrames = b.frameCount; diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 496e271..2212436 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -16,6 +16,7 @@ LOCAL_SRC_FILES:= \ LayerBitmap.cpp \ LayerDim.cpp \ LayerOrientationAnim.cpp \ + LayerOrientationAnimRotate.cpp \ OrientationAnimation.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp index 2b30336..db40385 100644 --- a/libs/surfaceflinger/BootAnimation.cpp +++ b/libs/surfaceflinger/BootAnimation.cpp @@ -164,9 +164,7 @@ status_t BootAnimation::readyToRun() { // initialize GL glShadeModel(GL_FLAT); - glEnable(GL_DITHER); glEnable(GL_TEXTURE_2D); - glEnable(GL_SCISSOR_TEST); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); return NO_ERROR; @@ -187,44 +185,18 @@ bool BootAnimation::threadLoop() { } bool BootAnimation::android() { - initTexture(&mAndroid[0], mAssets, "images/android_320x480.png"); - initTexture(&mAndroid[1], mAssets, "images/boot_robot.png"); - initTexture(&mAndroid[2], mAssets, "images/boot_robot_glow.png"); - - // erase screen - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); + initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); + initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); // clear screen + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); - // wait ~1s - usleep(800000); - - // fade in - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - const int steps = 8; - for (int i = 1; i < steps; i++) { - float fade = i / float(steps); - glColor4f(1, 1, 1, fade * fade); - glClear(GL_COLOR_BUFFER_BIT); - glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); - eglSwapBuffers(mDisplay, mSurface); - } - - // draw last frame - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDisable(GL_BLEND); - glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); - eglSwapBuffers(mDisplay, mSurface); - - // update rect for the robot - const int x = mWidth - mAndroid[1].w - 33; - const int y = (mHeight - mAndroid[1].h) / 2 - 1; - const Rect updateRect(x, y, x + mAndroid[1].w, y + mAndroid[1].h); + const GLint xc = (mWidth - mAndroid[0].w) / 2; + const GLint yc = (mHeight - mAndroid[0].h) / 2; + const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); // draw and update only what we need mNativeWindowSurface->setSwapRectangle(updateRect.left, @@ -234,166 +206,37 @@ bool BootAnimation::android() { glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); + // Blend state + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + const nsecs_t startTime = systemTime(); do { - // glow speed and shape - nsecs_t time = systemTime() - startTime; - float t = ((4.0f / (360.0f * us2ns(16667))) * time); - t = t - floorf(t); - const float fade = 0.5f + 0.5f * sinf(t * 2 * M_PI); + nsecs_t now = systemTime(); + double time = now - startTime; + float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; + GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w; + GLint x = xc - offset; - // fade the glow in and out glDisable(GL_BLEND); - glBindTexture(GL_TEXTURE_2D, mAndroid[2].name); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glColor4f(fade, fade, fade, fade); - glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, - updateRect.width(), updateRect.height()); - - // draw the robot - glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, - updateRect.width(), updateRect.height()); + glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); + glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); - // make sure sleep a lot to not take too much CPU away from - // the boot process. With this "glow" animation there is no - // visible difference. - usleep(16667 * 4); + glEnable(GL_BLEND); + glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); + glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); eglSwapBuffers(mDisplay, mSurface); + + // 12fps: don't animate too fast to preserve CPU + const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now); + if (sleepTime > 0) + usleep(sleepTime); } while (!exitPending()); glDeleteTextures(1, &mAndroid[0].name); glDeleteTextures(1, &mAndroid[1].name); - glDeleteTextures(1, &mAndroid[2].name); - return false; -} - -bool BootAnimation::cylon() { - // initialize the textures... - initTexture(&mLeftTrail, mAssets, "images/cylon_left.png"); - initTexture(&mRightTrail, mAssets, "images/cylon_right.png"); - initTexture(&mBrightSpot, mAssets, "images/cylon_dot.png"); - - int w = mWidth; - int h = mHeight; - - const Point c(w / 2, h / 2); - const GLint amplitude = 60; - const int scx = c.x - amplitude - mBrightSpot.w / 2; - const int scy = c.y - mBrightSpot.h / 2; - const int scw = amplitude * 2 + mBrightSpot.w; - const int sch = mBrightSpot.h; - const Rect updateRect(scx, h - scy - sch, scx + scw, h - scy); - - // erase screen - glDisable(GL_SCISSOR_TEST); - glClear(GL_COLOR_BUFFER_BIT); - - eglSwapBuffers(mDisplay, mSurface); - - glClear(GL_COLOR_BUFFER_BIT); - - mNativeWindowSurface->setSwapRectangle(updateRect.left, - updateRect.top, updateRect.width(), updateRect.height()); - - glEnable(GL_SCISSOR_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - // clear the screen to white - Point p; - float t = 0; - float alpha = 1.0f; - const nsecs_t startTime = systemTime(); - nsecs_t fadeTime = 0; - - do { - // Set scissor in interesting area - glScissor(scx, scy, scw, sch); - - // erase screen - glClear(GL_COLOR_BUFFER_BIT); - - // compute wave - const float a = (t * 2 * M_PI) - M_PI / 2; - const float sn = sinf(a); - const float cs = cosf(a); - GLint x = GLint(amplitude * sn); - float derivative = cs; - - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (derivative > 0) { - // vanishing trail... - p.x = (-amplitude + c.x) - mBrightSpot.w / 2; - p.y = c.y - mLeftTrail.h / 2; - float fade = 2.0f * (0.5f - t); - //fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); - glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); - - // trail... - p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; - p.y = c.y - mRightTrail.h / 2; - fade = t < 0.25f ? t * 4.0f : 1.0f; - fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mRightTrail.name); - glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); - } else { - // vanishing trail.. - p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; - p.y = c.y - mRightTrail.h / 2; - float fade = 2.0f * (0.5f - (t - 0.5f)); - //fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mRightTrail.name); - glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); - - // trail... - p.x = (x + c.x) - mBrightSpot.w / 2; - p.y = c.y - mLeftTrail.h / 2; - fade = t < 0.5f + 0.25f ? (t - 0.5f) * 4.0f : 1.0f; - fade *= fade; - glColor4f(fade, fade, fade, fade); - glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); - glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); - } - - const Point p(x + c.x - mBrightSpot.w / 2, c.y - mBrightSpot.h / 2); - glBindTexture(GL_TEXTURE_2D, mBrightSpot.name); - glColor4f(1, 0.5, 0.5, 1); - glDrawTexiOES(p.x, p.y, 0, mBrightSpot.w, mBrightSpot.h); - - // update animation - nsecs_t time = systemTime() - startTime; - t = ((4.0f / (360.0f * us2ns(16667))) * time); - t = t - floorf(t); - - eglSwapBuffers(mDisplay, mSurface); - - if (exitPending()) { - if (fadeTime == 0) { - fadeTime = time; - } - time -= fadeTime; - alpha = 1.0f - ((float(time) * 6.0f) / float(s2ns(1))); - - session()->openTransaction(); - mFlingerSurface->setAlpha(alpha * alpha); - session()->closeTransaction(); - } - } while (alpha > 0); - - // cleanup - glFinish(); - glDeleteTextures(1, &mLeftTrail.name); - glDeleteTextures(1, &mRightTrail.name); - glDeleteTextures(1, &mBrightSpot.name); return false; } diff --git a/libs/surfaceflinger/BootAnimation.h b/libs/surfaceflinger/BootAnimation.h index b20cea0..3fb6670 100644 --- a/libs/surfaceflinger/BootAnimation.h +++ b/libs/surfaceflinger/BootAnimation.h @@ -62,16 +62,12 @@ private: status_t initTexture(Texture* texture, AssetManager& asset, const char* name); bool android(); - bool cylon(); sp<SurfaceComposerClient> mSession; AssetManager mAssets; - Texture mLeftTrail; - Texture mRightTrail; - Texture mBrightSpot; - Texture mAndroid[3]; - int mWidth; - int mHeight; + Texture mAndroid[2]; + int mWidth; + int mHeight; EGLDisplay mDisplay; EGLDisplay mContext; EGLDisplay mSurface; diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp index 2b72d7c..3e4035e 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.cpp +++ b/libs/surfaceflinger/LayerOrientationAnim.cpp @@ -22,11 +22,13 @@ #include <utils/Errors.h> #include <utils/Log.h> +#include <utils/StopWatch.h> #include <core/SkBitmap.h> #include <ui/EGLDisplaySurface.h> +#include "BlurFilter.h" #include "LayerBase.h" #include "LayerOrientationAnim.h" #include "SurfaceFlinger.h" @@ -41,22 +43,35 @@ const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim"; // --------------------------------------------------------------------------- +// Animation... +const float DURATION = ms2ns(200); +const float BOUNCES_PER_SECOND = 0.5f; +//const float BOUNCES_AMPLITUDE = 1.0f/16.0f; +const float BOUNCES_AMPLITUDE = 0; +const float DIM_TARGET = 0.40f; +//#define INTERPOLATED_TIME(_t) ((_t)*(_t)) +#define INTERPOLATED_TIME(_t) (_t) + +// --------------------------------------------------------------------------- + LayerOrientationAnim::LayerOrientationAnim( SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmap, - const LayerBitmap& bitmapIn) - : LayerBase(flinger, display), mAnim(anim), - mBitmap(bitmap), mBitmapIn(bitmapIn), + const LayerBitmap& bitmapIn, + const LayerBitmap& bitmapOut) + : LayerOrientationAnimBase(flinger, display), mAnim(anim), + mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), mTextureName(-1), mTextureNameIn(-1) { + // blur that texture. mStartTime = systemTime(); mFinishTime = 0; mOrientationCompleted = false; mFirstRedraw = false; mLastNormalizedTime = 0; - mLastScale = 0; mNeedsBlending = false; + mAlphaInLerp.set(1.0f, DIM_TARGET); + mAlphaOutLerp.set(0.5f, 1.0f); } LayerOrientationAnim::~LayerOrientationAnim() @@ -111,14 +126,8 @@ void LayerOrientationAnim::onOrientationCompleted() void LayerOrientationAnim::onDraw(const Region& clip) const { - // Animation... - const float MIN_SCALE = 0.5f; - const float DURATION = ms2ns(200); - const float BOUNCES_PER_SECOND = 1.618f; - const float BOUNCES_AMPLITUDE = 1.0f/32.0f; - const nsecs_t now = systemTime(); - float scale, alpha; + float alphaIn, alphaOut; if (mOrientationCompleted) { if (mFirstRedraw) { @@ -126,7 +135,7 @@ void LayerOrientationAnim::onDraw(const Region& clip) const // make a copy of what's on screen copybit_image_t image; - mBitmapIn.getBitmapSurface(&image); + mBitmapOut.getBitmapSurface(&image); const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.copyBackToImage(image); @@ -147,37 +156,40 @@ void LayerOrientationAnim::onDraw(const Region& clip) const const float duration = DURATION * mLastNormalizedTime; const float normalizedTime = (float(now - mFinishTime) / duration); if (normalizedTime <= 1.0f) { - const float squaredTime = normalizedTime*normalizedTime; - scale = (1.0f - mLastScale)*squaredTime + mLastScale; - alpha = (1.0f - normalizedTime); - alpha *= alpha; - alpha *= alpha; + const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); + alphaIn = mAlphaInLerp.getOut(); + alphaOut = mAlphaOutLerp(interpolatedTime); } else { mAnim->onAnimationFinished(); - scale = 1.0f; - alpha = 0.0f; + alphaIn = mAlphaInLerp.getOut(); + alphaOut = mAlphaOutLerp.getOut(); } } else { const float normalizedTime = float(now - mStartTime) / DURATION; if (normalizedTime <= 1.0f) { mLastNormalizedTime = normalizedTime; - const float squaredTime = normalizedTime*normalizedTime; - scale = (MIN_SCALE-1.0f)*squaredTime + 1.0f; - alpha = 1.0f; + const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); + alphaIn = mAlphaInLerp(interpolatedTime); + alphaOut = 0.0f; } else { mLastNormalizedTime = 1.0f; const float to_seconds = DURATION / seconds(1); - const float phi = BOUNCES_PER_SECOND * - (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); - scale = MIN_SCALE + BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); - alpha = 1.0f; + alphaIn = mAlphaInLerp.getOut(); + if (BOUNCES_AMPLITUDE > 0.0f) { + const float phi = BOUNCES_PER_SECOND * + (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); + if (alphaIn > 1.0f) alphaIn = 1.0f; + else if (alphaIn < 0.0f) alphaIn = 0.0f; + alphaIn += BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); + } + alphaOut = 0.0f; } - mLastScale = scale; + mAlphaOutLerp.setIn(alphaIn); } - drawScaled(scale, alpha); + drawScaled(1.0f, alphaIn, alphaOut); } -void LayerOrientationAnim::drawScaled(float f, float alpha) const +void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut) const { copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); @@ -188,22 +200,30 @@ void LayerOrientationAnim::drawScaled(float f, float alpha) const // TODO: with update on demand, we may be able // to not erase the screen at all during the animation if (!mOrientationCompleted) { - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); + if (scale==1.0f && (alphaIn>=1.0f || alphaOut>=1.0f)) { + // we don't need to erase the screen in that case + } else { + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + } } - const int w = dst.w*f; - const int h = dst.h*f; + copybit_image_t src; + mBitmapIn.getBitmapSurface(&src); + + copybit_image_t srcOut; + mBitmapOut.getBitmapSurface(&srcOut); + + const int w = dst.w*scale; + const int h = dst.h*scale; const int xc = uint32_t(dst.w-w)/2; const int yc = uint32_t(dst.h-h)/2; const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; - - copybit_image_t src; - mBitmap.getBitmapSurface(&src); const copybit_rect_t srect = { 0, 0, src.w, src.h }; + const Region reg(Rect( drect.l, drect.t, drect.r, drect.b )); int err = NO_ERROR; const int can_use_copybit = canUseCopybit(); @@ -211,19 +231,19 @@ void LayerOrientationAnim::drawScaled(float f, float alpha) const copybit_device_t* copybit = mFlinger->getBlitEngine(); copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - - if (alpha < 1.0f) { - copybit_image_t srcIn; - mBitmapIn.getBitmapSurface(&srcIn); - region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - err = copybit->stretch(copybit, &dst, &srcIn, &drect, &srect, &it); + + if (alphaIn > 0) { + region_iterator it(reg); + copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255)); + err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); } - if (!err && alpha > 0.0f) { - region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alpha*255)); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + if (!err && alphaOut > 0.0f) { + region_iterator it(reg); + copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255)); + err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it); } LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); } @@ -238,7 +258,7 @@ void LayerOrientationAnim::drawScaled(float f, float alpha) const t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); Transform tr; - tr.set(f,0,0,f); + tr.set(scale,0,0,scale); tr.set(xc, yc); // FIXME: we should not access mVertices and mDrawingState like that, @@ -254,9 +274,7 @@ void LayerOrientationAnim::drawScaled(float f, float alpha) const self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; } - if (alpha < 1.0f) { - copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); + if (alphaIn > 0.0f) { t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); if (UNLIKELY(mTextureNameIn == -1LU)) { mTextureNameIn = createTexture(); @@ -264,21 +282,21 @@ void LayerOrientationAnim::drawScaled(float f, float alpha) const const Region dirty(Rect(t.width, t.height)); loadTexture(dirty, mTextureNameIn, t, w, h); } - self.mDrawingState.alpha = 255; - const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); - drawWithOpenGL(clip, mTextureName, t); + self.mDrawingState.alpha = int(alphaIn*255); + drawWithOpenGL(reg, mTextureNameIn, t); } - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); + if (alphaOut > 0.0f) { + t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); + } + self.mDrawingState.alpha = int(alphaOut*255); + drawWithOpenGL(reg, mTextureName, t); } - self.mDrawingState.alpha = int(alpha*255); - const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); - drawWithOpenGL(clip, mTextureName, t); } } diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h index 73676859..365c6ae 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.h +++ b/libs/surfaceflinger/LayerOrientationAnim.h @@ -30,7 +30,19 @@ namespace android { // --------------------------------------------------------------------------- class OrientationAnimation; -class LayerOrientationAnim : public LayerBase + +class LayerOrientationAnimBase : public LayerBase +{ +public: + LayerOrientationAnimBase(SurfaceFlinger* flinger, DisplayID display) + : LayerBase(flinger, display) { + } + virtual void onOrientationCompleted() = 0; +}; + +// --------------------------------------------------------------------------- + +class LayerOrientationAnim : public LayerOrientationAnimBase { public: static const uint32_t typeInfo; @@ -40,8 +52,8 @@ public: LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& zoomOut, - const LayerBitmap& zoomIn); + const LayerBitmap& bitmapIn, + const LayerBitmap& bitmapOut); virtual ~LayerOrientationAnim(); void onOrientationCompleted(); @@ -52,20 +64,45 @@ public: virtual bool needsBlending() const; virtual bool isSecure() const { return false; } private: - void drawScaled(float scale, float alpha) const; + void drawScaled(float scale, float alphaIn, float alphaOut) const; + class Lerp { + float in; + float outMinusIn; + public: + Lerp() : in(0), outMinusIn(0) { } + Lerp(float in, float out) : in(in), outMinusIn(out-in) { } + float getIn() const { return in; }; + float getOut() const { return in + outMinusIn; } + void set(float in, float out) { + this->in = in; + this->outMinusIn = out-in; + } + void setIn(float in) { + this->in = in; + } + void setOut(float out) { + this->outMinusIn = out - this->in; + } + float operator()(float t) const { + return outMinusIn*t + in; + } + }; + OrientationAnimation* mAnim; - LayerBitmap mBitmap; LayerBitmap mBitmapIn; + LayerBitmap mBitmapOut; nsecs_t mStartTime; nsecs_t mFinishTime; bool mOrientationCompleted; mutable bool mFirstRedraw; mutable float mLastNormalizedTime; - mutable float mLastScale; mutable GLuint mTextureName; mutable GLuint mTextureNameIn; mutable bool mNeedsBlending; + + mutable Lerp mAlphaInLerp; + mutable Lerp mAlphaOutLerp; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/LayerOrientationAnimRotate.cpp new file mode 100644 index 0000000..89ffb19 --- /dev/null +++ b/libs/surfaceflinger/LayerOrientationAnimRotate.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2007 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. + */ + +#define LOG_TAG "SurfaceFlinger" + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <core/SkBitmap.h> + +#include <ui/EGLDisplaySurface.h> + +#include "LayerBase.h" +#include "LayerOrientationAnim.h" +#include "LayerOrientationAnimRotate.h" +#include "SurfaceFlinger.h" +#include "DisplayHardware/DisplayHardware.h" +#include "OrientationAnimation.h" + +namespace android { +// --------------------------------------------------------------------------- + +const uint32_t LayerOrientationAnimRotate::typeInfo = LayerBase::typeInfo | 0x100; +const char* const LayerOrientationAnimRotate::typeID = "LayerOrientationAnimRotate"; + +// --------------------------------------------------------------------------- + +const float ROTATION = M_PI * 0.5f; +const float ROTATION_FACTOR = 1.0f; // 1.0 or 2.0 +const float DURATION = ms2ns(200); +const float BOUNCES_PER_SECOND = 0.8; +const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI; + +LayerOrientationAnimRotate::LayerOrientationAnimRotate( + SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const LayerBitmap& bitmap, + const LayerBitmap& bitmapIn) + : LayerOrientationAnimBase(flinger, display), mAnim(anim), + mBitmap(bitmap), mBitmapIn(bitmapIn), + mTextureName(-1), mTextureNameIn(-1) +{ + mStartTime = systemTime(); + mFinishTime = 0; + mOrientationCompleted = false; + mFirstRedraw = false; + mLastNormalizedTime = 0; + mLastAngle = 0; + mLastScale = 0; + mNeedsBlending = false; + const GraphicPlane& plane(graphicPlane(0)); + mOriginalTargetOrientation = plane.getOrientation(); +} + +LayerOrientationAnimRotate::~LayerOrientationAnimRotate() +{ + if (mTextureName != -1U) { + LayerBase::deletedTextures.add(mTextureName); + } + if (mTextureNameIn != -1U) { + LayerBase::deletedTextures.add(mTextureNameIn); + } +} + +bool LayerOrientationAnimRotate::needsBlending() const +{ + return mNeedsBlending; +} + +Point LayerOrientationAnimRotate::getPhysicalSize() const +{ + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + return Point(hw.getWidth(), hw.getHeight()); +} + +void LayerOrientationAnimRotate::validateVisibility(const Transform&) +{ + const Layer::State& s(drawingState()); + const Transform tr(s.transform); + const Point size(getPhysicalSize()); + uint32_t w = size.x; + uint32_t h = size.y; + mTransformedBounds = tr.makeBounds(w, h); + mLeft = tr.tx(); + mTop = tr.ty(); + transparentRegionScreen.clear(); + mTransformed = true; + mCanUseCopyBit = false; +} + +void LayerOrientationAnimRotate::onOrientationCompleted() +{ + mFinishTime = systemTime(); + mOrientationCompleted = true; + mFirstRedraw = true; + mNeedsBlending = true; + mFlinger->invalidateLayerVisibility(this); +} + +void LayerOrientationAnimRotate::onDraw(const Region& clip) const +{ + // Animation... + + const nsecs_t now = systemTime(); + float angle, scale, alpha; + + if (mOrientationCompleted) { + if (mFirstRedraw) { + // make a copy of what's on screen + copybit_image_t image; + mBitmapIn.getBitmapSurface(&image); + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.copyBackToImage(image); + + // FIXME: code below is gross + mFirstRedraw = false; + mNeedsBlending = false; + LayerOrientationAnimRotate* self(const_cast<LayerOrientationAnimRotate*>(this)); + mFlinger->invalidateLayerVisibility(self); + } + + // make sure pick-up where we left off + const float duration = DURATION * mLastNormalizedTime; + const float normalizedTime = (float(now - mFinishTime) / duration); + if (normalizedTime <= 1.0f) { + const float squaredTime = normalizedTime*normalizedTime; + angle = (ROTATION*ROTATION_FACTOR - mLastAngle)*squaredTime + mLastAngle; + scale = (1.0f - mLastScale)*squaredTime + mLastScale; + alpha = normalizedTime; + } else { + mAnim->onAnimationFinished(); + angle = ROTATION; + alpha = 1.0f; + scale = 1.0f; + } + } else { + // FIXME: works only for portrait framebuffers + const Point size(getPhysicalSize()); + const float TARGET_SCALE = size.x * (1.0f / size.y); + const float normalizedTime = float(now - mStartTime) / DURATION; + if (normalizedTime <= 1.0f) { + mLastNormalizedTime = normalizedTime; + const float squaredTime = normalizedTime*normalizedTime; + angle = ROTATION * squaredTime; + scale = (TARGET_SCALE - 1.0f)*squaredTime + 1.0f; + alpha = 0; + } else { + mLastNormalizedTime = 1.0f; + angle = ROTATION; + if (BOUNCES_AMPLITUDE) { + const float to_seconds = DURATION / seconds(1); + const float phi = BOUNCES_PER_SECOND * + (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); + angle += BOUNCES_AMPLITUDE * sinf(phi); + } + scale = TARGET_SCALE; + alpha = 0; + } + mLastAngle = angle; + mLastScale = scale; + } + drawScaled(angle, scale, alpha); +} + +void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const +{ + copybit_image_t dst; + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + hw.getDisplaySurface(&dst); + + // clear screen + // TODO: with update on demand, we may be able + // to not erase the screen at all during the animation + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + + const int w = dst.w; + const int h = dst.h; + + copybit_image_t src; + mBitmap.getBitmapSurface(&src); + const copybit_rect_t srect = { 0, 0, src.w, src.h }; + + + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.w; + t.height = src.h; + t.stride = src.w; + t.vstride= src.h; + t.format = src.format; + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + + if (!mOriginalTargetOrientation) { + f = -f; + } + + Transform tr; + tr.set(f, w*0.5f, h*0.5f); + tr.scale(s, w*0.5f, h*0.5f); + + // FIXME: we should not access mVertices and mDrawingState like that, + // but since we control the animation, we know it's going to work okay. + // eventually we'd need a more formal way of doing things like this. + LayerOrientationAnimRotate& self(const_cast<LayerOrientationAnimRotate&>(*this)); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // Too slow to do this in software + self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; + } + + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); + } + self.mDrawingState.alpha = 255; //-int(alpha*255); + const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); + drawWithOpenGL(clip, mTextureName, t); + + if (alpha > 0) { + const float sign = (!mOriginalTargetOrientation) ? 1.0f : -1.0f; + tr.set(f + sign*(M_PI * 0.5f * ROTATION_FACTOR), w*0.5f, h*0.5f); + tr.scale(s, w*0.5f, h*0.5f); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + + copybit_image_t src; + mBitmapIn.getBitmapSurface(&src); + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureNameIn == -1LU)) { + mTextureNameIn = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureNameIn, t, w, h); + } + self.mDrawingState.alpha = int(alpha*255); + const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); + drawWithOpenGL(clip, mTextureNameIn, t); + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/LayerOrientationAnimRotate.h new file mode 100644 index 0000000..5fbbd42 --- /dev/null +++ b/libs/surfaceflinger/LayerOrientationAnimRotate.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007 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. + */ + +#ifndef ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H +#define ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/threads.h> +#include <utils/Parcel.h> + +#include "LayerBase.h" +#include "LayerBitmap.h" + +namespace android { + +// --------------------------------------------------------------------------- +class OrientationAnimation; + +class LayerOrientationAnimRotate : public LayerOrientationAnimBase +{ +public: + static const uint32_t typeInfo; + static const char* const typeID; + virtual char const* getTypeID() const { return typeID; } + virtual uint32_t getTypeInfo() const { return typeInfo; } + + LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const LayerBitmap& zoomOut, + const LayerBitmap& zoomIn); + virtual ~LayerOrientationAnimRotate(); + + void onOrientationCompleted(); + + virtual void onDraw(const Region& clip) const; + virtual Point getPhysicalSize() const; + virtual void validateVisibility(const Transform& globalTransform); + virtual bool needsBlending() const; + virtual bool isSecure() const { return false; } +private: + void drawScaled(float angle, float scale, float alpha) const; + + OrientationAnimation* mAnim; + LayerBitmap mBitmap; + LayerBitmap mBitmapIn; + nsecs_t mStartTime; + nsecs_t mFinishTime; + bool mOrientationCompleted; + int mOriginalTargetOrientation; + mutable bool mFirstRedraw; + mutable float mLastNormalizedTime; + mutable float mLastAngle; + mutable float mLastScale; + mutable GLuint mTextureName; + mutable GLuint mTextureNameIn; + mutable bool mNeedsBlending; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp index f6f1326..70eec8d 100644 --- a/libs/surfaceflinger/OrientationAnimation.cpp +++ b/libs/surfaceflinger/OrientationAnimation.cpp @@ -21,6 +21,7 @@ #include <limits.h> #include "LayerOrientationAnim.h" +#include "LayerOrientationAnimRotate.h" #include "OrientationAnimation.h" #include "SurfaceFlinger.h" #include "VRamHeap.h" @@ -43,10 +44,14 @@ OrientationAnimation::~OrientationAnimation() { } -void OrientationAnimation::onOrientationChanged() +void OrientationAnimation::onOrientationChanged(uint32_t type) { - if (mState == DONE) - mState = PREPARE; + if (mState == DONE) { + mType = type; + if (!(type & ISurfaceComposer::eOrientationAnimationDisable)) { + mState = PREPARE; + } + } } void OrientationAnimation::onAnimationFinished() @@ -81,14 +86,7 @@ bool OrientationAnimation::run_impl() bool OrientationAnimation::done() { - if (mFlinger->isFrozen()) { - // we are not allowed to draw, but pause a bit to make sure - // apps don't end up using the whole CPU, if they depend on - // surfaceflinger for synchronization. - usleep(8333); // 8.3ms ~ 120fps - return true; - } - return false; + return done_impl(); } bool OrientationAnimation::prepare() @@ -112,8 +110,16 @@ bool OrientationAnimation::prepare() bitmap.getBitmapSurface(&front); hw.copyFrontToImage(front); - LayerOrientationAnim* l = new LayerOrientationAnim( - mFlinger.get(), 0, this, bitmap, bitmapIn); + LayerOrientationAnimBase* l; + + if (mType & 0x80) { + l = new LayerOrientationAnimRotate( + mFlinger.get(), 0, this, bitmap, bitmapIn); + } else { + l = new LayerOrientationAnim( + mFlinger.get(), 0, this, bitmap, bitmapIn); + } + l->initStates(w, h, 0); l->setLayer(INT_MAX-1); mFlinger->addLayer(l); diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h index ba33fce..cafa38d 100644 --- a/libs/surfaceflinger/OrientationAnimation.h +++ b/libs/surfaceflinger/OrientationAnimation.h @@ -36,11 +36,11 @@ public: OrientationAnimation(const sp<SurfaceFlinger>& flinger); virtual ~OrientationAnimation(); - void onOrientationChanged(); + void onOrientationChanged(uint32_t type); void onAnimationFinished(); inline bool run() { if (LIKELY(mState == DONE)) - return false; + return done_impl(); return run_impl(); } @@ -54,7 +54,18 @@ private: }; bool run_impl(); - bool done(); + inline bool done_impl() { + if (mFlinger->isFrozen()) { + // we are not allowed to draw, but pause a bit to make sure + // apps don't end up using the whole CPU, if they depend on + // surfaceflinger for synchronization. + usleep(8333); // 8.3ms ~ 120fps + return true; + } + return false; + } + + bool done(); bool prepare(); bool phase1(); bool phase2(); @@ -62,8 +73,9 @@ private: sp<SurfaceFlinger> mFlinger; sp<MemoryDealer> mTemporaryDealer; - LayerOrientationAnim* mLayerOrientationAnim; + LayerOrientationAnimBase* mLayerOrientationAnim; int mState; + uint32_t mType; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 242d026..c2adf07 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -656,6 +656,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) const int dpy = 0; const int orientation = mCurrentState.orientation; + const uint32_t type = mCurrentState.orientationType; GraphicPlane& plane(graphicPlane(dpy)); plane.setOrientation(orientation); @@ -674,8 +675,8 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mVisibleRegionsDirty = true; mDirtyRegion.set(hw.bounds()); - - mOrientationAnimation->onOrientationChanged(); + mFreezeDisplayTime = 0; + mOrientationAnimation->onOrientationChanged(type); } if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { @@ -1202,7 +1203,8 @@ status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags) return NO_ERROR; } -int SurfaceFlinger::setOrientation(DisplayID dpy, int orientation) +int SurfaceFlinger::setOrientation(DisplayID dpy, + int orientation, uint32_t flags) { if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) return BAD_VALUE; @@ -1210,6 +1212,7 @@ int SurfaceFlinger::setOrientation(DisplayID dpy, int orientation) Mutex::Autolock _l(mStateLock); if (mCurrentState.orientation != orientation) { if (uint32_t(orientation)<=eOrientation270 || orientation==42) { + mCurrentState.orientationType = flags; mCurrentState.orientation = orientation; setTransactionFlags(eTransactionNeeded); mTransactionCV.wait(mStateLock); @@ -1805,6 +1808,7 @@ status_t GraphicPlane::setOrientation(int orientation) if (orientation == ISurfaceComposer::eOrientationDefault) { // make sure the default orientation is optimal mOrientationTransform.reset(); + mOrientation = orientation; mGlobalTransform = mTransform; return NO_ERROR; } @@ -1825,7 +1829,7 @@ status_t GraphicPlane::setOrientation(int orientation) GraphicPlane::orientationToTransfrom(orientation, w, h, &mOrientationTransform); } - + mOrientation = orientation; mGlobalTransform = mOrientationTransform * mTransform; return NO_ERROR; } diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index f7d7764..e023182 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -122,6 +122,7 @@ public: void setDisplayHardware(DisplayHardware *); void setTransform(const Transform& tr); status_t setOrientation(int orientation); + int getOrientation() const { return mOrientation; } const DisplayHardware& displayHardware() const; const Transform& transform() const; @@ -133,6 +134,7 @@ private: Transform mTransform; Transform mOrientationTransform; Transform mGlobalTransform; + int mOrientation; }; // --------------------------------------------------------------------------- @@ -165,7 +167,7 @@ public: virtual void closeGlobalTransaction(); virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags); virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); - virtual int setOrientation(DisplayID dpy, int orientation); + virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); virtual void signal() const; virtual status_t requestGPU(const sp<IGPUCallback>& callback, gpu_info_t* gpu); @@ -242,6 +244,7 @@ private: } LayerVector layersSortedByZ; uint8_t orientation; + uint8_t orientationType; uint8_t freezeDisplay; }; diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp index bec7a64..e8b0f45 100644 --- a/libs/surfaceflinger/Transform.cpp +++ b/libs/surfaceflinger/Transform.cpp @@ -103,6 +103,25 @@ void Transform::set( float xx, float xy, mType |= 0x80000000; } +void Transform::set(float radian, float x, float y) +{ + float r00 = cosf(radian); float r01 = -sinf(radian); + float r10 = sinf(radian); float r11 = cosf(radian); + mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(r00)); + mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(r01)); + mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(r10)); + mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(r11)); + mTransform.set(SkMatrix::kMTransX, SkIntToScalar(x - r00*x - r01*y)); + mTransform.set(SkMatrix::kMTransY, SkIntToScalar(y - r10*x - r11*y)); + mType |= 0x80000000 | SkMatrix::kTranslate_Mask; +} + +void Transform::scale(float s, float x, float y) +{ + mTransform.postScale(s, s, x, y); + mType |= 0x80000000; +} + void Transform::set(int tx, int ty) { if (tx | ty) { diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h index 0b4835e..4c4528e 100644 --- a/libs/surfaceflinger/Transform.h +++ b/libs/surfaceflinger/Transform.h @@ -60,7 +60,9 @@ public: void reset(); void set(float xx, float xy, float yx, float yy); void set(int tx, int ty); - + void set(float radian, float x, float y); + void scale(float s, float x, float y); + Rect makeBounds(int w, int h) const; void transform(GLfixed* point, int x, int y) const; Region transform(const Region& reg) const; diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index 3b29b09..7c2fc8e 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -245,6 +245,7 @@ EventHub::device_t* EventHub::getDevice(int32_t deviceId) const int32_t id = deviceId & ID_MASK; if (id >= mNumDevicesById || id < 0) return NULL; device_t* dev = mDevicesById[id].device; + if (dev == NULL) return NULL; if (dev->id == deviceId) { return dev; } diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp index 0fea6f9..76597e1 100644 --- a/libs/ui/ISurfaceComposer.cpp +++ b/libs/ui/ISurfaceComposer.cpp @@ -96,12 +96,13 @@ public: return reply.readInt32(); } - virtual int setOrientation(DisplayID dpy, int orientation) + virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeInt32(dpy); data.writeInt32(orientation); + data.writeInt32(flags); remote()->transact(BnSurfaceComposer::SET_ORIENTATION, data, &reply); return reply.readInt32(); } @@ -184,7 +185,8 @@ status_t BnSurfaceComposer::onTransact( case SET_ORIENTATION: { DisplayID dpy = data.readInt32(); int orientation = data.readInt32(); - reply->writeInt32( setOrientation(dpy, orientation) ); + uint32_t flags = data.readInt32(); + reply->writeInt32( setOrientation(dpy, orientation, flags) ); } break; case FREEZE_DISPLAY: { DisplayID dpy = data.readInt32(); diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp index 9354a7a..fe803ff 100644 --- a/libs/ui/SurfaceComposerClient.cpp +++ b/libs/ui/SurfaceComposerClient.cpp @@ -813,10 +813,11 @@ status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags) return sm->unfreezeDisplay(dpy, flags); } -int SurfaceComposerClient::setOrientation(DisplayID dpy, int orientation) +int SurfaceComposerClient::setOrientation(DisplayID dpy, + int orientation, uint32_t flags) { const sp<ISurfaceComposer>& sm(_get_surface_manager()); - return sm->setOrientation(dpy, orientation); + return sm->setOrientation(dpy, orientation, flags); } status_t SurfaceComposerClient::openTransaction() diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java index 6672e29..887574a 100644 --- a/location/java/com/android/internal/location/GpsLocationProvider.java +++ b/location/java/com/android/internal/location/GpsLocationProvider.java @@ -16,8 +16,10 @@ package com.android.internal.location; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.location.Criteria; import android.location.IGpsStatusListener; import android.location.Location; @@ -32,9 +34,14 @@ import android.os.SystemClock; import android.util.Config; import android.util.Log; +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.TelephonyIntents; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Properties; @@ -78,6 +85,11 @@ public class GpsLocationProvider extends LocationProviderImpl { */ public static final String EXTRA_ENABLED = "enabled"; + // these need to match GpsPositionMode enum in gps.h + private static final int GPS_POSITION_MODE_STANDALONE = 0; + private static final int GPS_POSITION_MODE_MS_BASED = 1; + private static final int GPS_POSITION_MODE_MS_ASSISTED = 2; + // these need to match GpsStatusValue defines in gps.h private static final int GPS_STATUS_NONE = 0; private static final int GPS_STATUS_SESSION_BEGIN = 1; @@ -135,6 +147,8 @@ public class GpsLocationProvider extends LocationProviderImpl { // requested frequency of fixes, in seconds private int mFixInterval = 1; + private int mPositionMode = GPS_POSITION_MODE_STANDALONE; + // true if we started navigation private boolean mStarted; @@ -156,7 +170,11 @@ public class GpsLocationProvider extends LocationProviderImpl { private GpsEventThread mEventThread; private GpsNetworkThread mNetworkThread; private Object mNetworkThreadLock = new Object(); - + + private String mSuplHost; + private int mSuplPort; + private boolean mSetSuplServer; + // how often to request NTP time, in milliseconds // current setting 4 hours private static final long NTP_INTERVAL = 4*60*60*1000; @@ -166,6 +184,27 @@ public class GpsLocationProvider extends LocationProviderImpl { private ILocationCollector mCollector; + private class TelephonyBroadcastReceiver extends BroadcastReceiver { + @Override public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { + String state = intent.getStringExtra(Phone.STATE_KEY); + String apnName = intent.getStringExtra(Phone.DATA_APN_KEY); + String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY); + + if (Config.LOGD) { + Log.d(TAG, "state: " + state + " apnName: " + apnName + " reason: " + reason); + } + if ("CONNECTED".equals(state)) { + native_set_supl_apn(apnName); + } else { + native_set_supl_apn(""); + } + } + } + } + public static boolean isSupported() { return native_is_supported(); } @@ -174,6 +213,11 @@ public class GpsLocationProvider extends LocationProviderImpl { super(LocationManager.GPS_PROVIDER); mContext = context; + TelephonyBroadcastReceiver receiver = new TelephonyBroadcastReceiver(); + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); + context.registerReceiver(receiver, intentFilter); + mProperties = new Properties(); try { File file = new File(PROPERTIES_FILE); @@ -181,6 +225,16 @@ public class GpsLocationProvider extends LocationProviderImpl { mProperties.load(stream); stream.close(); mNtpServer = mProperties.getProperty("NTP_SERVER", null); + mSuplHost = mProperties.getProperty("SUPL_HOST"); + String suplPortString = mProperties.getProperty("SUPL_PORT"); + if (mSuplHost != null && suplPortString != null) { + try { + mSuplPort = Integer.parseInt(suplPortString); + mSetSuplServer = true; + } catch (NumberFormatException e) { + Log.e(TAG, "unable to parse SUPL_PORT: " + suplPortString); + } + } } catch (IOException e) { Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE); } @@ -198,7 +252,7 @@ public class GpsLocationProvider extends LocationProviderImpl { public boolean requiresNetwork() { // We want updateNetworkState() to get called when the network state changes // for XTRA and NTP time injection support. - return (mNtpServer != null || native_supports_xtra()); + return (mNtpServer != null || native_supports_xtra() || mSuplHost != null); } public void updateNetworkState(int state) { @@ -542,7 +596,7 @@ public class GpsLocationProvider extends LocationProviderImpl { if (!mStarted) { if (Config.LOGV) Log.v(TAG, "startNavigating"); mStarted = true; - if (!native_start(false, mFixInterval)) { + if (!native_start(mPositionMode, false, mFixInterval)) { mStarted = false; Log.e(TAG, "native_start failed in startNavigating()"); } @@ -806,7 +860,7 @@ public class GpsLocationProvider extends LocationProviderImpl { } } waitTime = getWaitTime(); - } while (!mDone && ((!mXtraDownloadRequested && waitTime > 0) + } while (!mDone && ((!mXtraDownloadRequested && !mSetSuplServer && waitTime > 0) || !mNetworkAvailable)); if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop"); @@ -833,6 +887,29 @@ public class GpsLocationProvider extends LocationProviderImpl { } } + // Set the SUPL server address if we have not yet + if (mSetSuplServer) { + try { + InetAddress inetAddress = InetAddress.getByName(mSuplHost); + if (inetAddress != null) { + byte[] addrBytes = inetAddress.getAddress(); + long addr = 0; + for (int i = 0; i < addrBytes.length; i++) { + int temp = addrBytes[i]; + // signed -> unsigned + if (temp < 0) temp = 256 + temp; + addr = addr * 256 + temp; + } + // use MS-Based position mode if SUPL support is enabled + mPositionMode = GPS_POSITION_MODE_MS_BASED; + native_set_supl_server((int)addr, mSuplPort); + mSetSuplServer = false; + } + } catch (UnknownHostException e) { + Log.e(TAG, "unknown host for SUPL server " + mSuplHost); + } + } + if ((mXtraDownloadRequested || (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis())) && xtraDownloader != null) { @@ -908,7 +985,7 @@ public class GpsLocationProvider extends LocationProviderImpl { private native boolean native_init(); private native void native_disable(); private native void native_cleanup(); - private native boolean native_start(boolean singleFix, int fixInterval); + private native boolean native_start(int positionMode, boolean singleFix, int fixInterval); private native boolean native_stop(); private native void native_set_fix_frequency(int fixFrequency); private native void native_delete_aiding_data(int flags); @@ -922,4 +999,8 @@ public class GpsLocationProvider extends LocationProviderImpl { private native void native_inject_time(long time, long timeReference, int uncertainty); private native boolean native_supports_xtra(); private native void native_inject_xtra_data(byte[] data, int length); + + // SUPL Support + private native void native_set_supl_server(int addr, int port); + private native void native_set_supl_apn(String apn); } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 077d016..f509fb5 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -160,7 +160,7 @@ public class AudioManager { 16, // STREAM_MUSIC 8, // STREAM_ALARM 8, // STREAM_NOTIFICATION - 15, // STREAM_BLUETOOTH_SCO + 16, // STREAM_BLUETOOTH_SCO }; /** @hide Default volume index values for audio streams */ @@ -220,7 +220,7 @@ public class AudioManager { * By default this is on for the ring stream. If this flag is included, * this behavior will be present regardless of the stream type being * affected by the ringer mode. - * + * * @see #adjustVolume(int, int) * @see #adjustStreamVolume(int, int, int) */ @@ -954,25 +954,21 @@ public class AudioManager { /** * IME standard keypress sound * @see #playSoundEffect(int) - * @hide FIXME: Unhide before release */ public static final int FX_KEYPRESS_STANDARD = 5; /** * IME spacebar keypress sound * @see #playSoundEffect(int) - * @hide FIXME: Unhide before release */ public static final int FX_KEYPRESS_SPACEBAR = 6; /** * IME delete keypress sound * @see #playSoundEffect(int) - * @hide FIXME: Unhide before release */ public static final int FX_KEYPRESS_DELETE = 7; /** * IME return_keypress sound * @see #playSoundEffect(int) - * @hide FIXME: Unhide before release */ public static final int FX_KEYPRESS_RETURN = 8; /** @@ -988,11 +984,10 @@ public class AudioManager { * {@link #FX_FOCUS_NAVIGATION_DOWN}, * {@link #FX_FOCUS_NAVIGATION_LEFT}, * {@link #FX_FOCUS_NAVIGATION_RIGHT}, - * FIXME: include links before release - * {link #FX_KEYPRESS_STANDARD}, - * {link #FX_KEYPRESS_SPACEBAR}, - * {link #FX_KEYPRESS_DELETE}, - * {link #FX_KEYPRESS_RETURN}, + * {@link #FX_KEYPRESS_STANDARD}, + * {@link #FX_KEYPRESS_SPACEBAR}, + * {@link #FX_KEYPRESS_DELETE}, + * {@link #FX_KEYPRESS_RETURN}, * NOTE: This version uses the UI settings to determine * whether sounds are heard or not. */ @@ -1021,15 +1016,13 @@ public class AudioManager { * {@link #FX_FOCUS_NAVIGATION_DOWN}, * {@link #FX_FOCUS_NAVIGATION_LEFT}, * {@link #FX_FOCUS_NAVIGATION_RIGHT}, - * FIXME: include links before release - * {link #FX_KEYPRESS_STANDARD}, - * {link #FX_KEYPRESS_SPACEBAR}, - * {link #FX_KEYPRESS_DELETE}, - * {link #FX_KEYPRESS_RETURN}, + * {@link #FX_KEYPRESS_STANDARD}, + * {@link #FX_KEYPRESS_SPACEBAR}, + * {@link #FX_KEYPRESS_DELETE}, + * {@link #FX_KEYPRESS_RETURN}, * @param volume Sound effect volume * NOTE: This version is for applications that have their own * settings panel for enabling and controlling volume. - * @hide FIXME: Unhide before release */ public void playSoundEffect(int effectType, float volume) { if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 0ef7760..a49bd67 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -165,27 +165,24 @@ public class AudioRecord */ private Object mRecordingStateLock = new Object(); /** - * The listener the AudioRecord notifies when a previously set marker is reached. - * @see #setMarkerReachedListener(OnMarkerReachedListener) + * The listener the AudioRecord notifies when the record position reaches a marker + * or for periodic updates during the progression of the record head. + * @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener) + * @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler) */ - private OnMarkerReachedListener mMarkerListener = null; + private OnRecordPositionUpdateListener mPositionListener = null; /** - * Lock to protect marker listener updates against event notifications + * Lock to protect position listener updates against event notifications */ - private final Object mMarkerListenerLock = new Object(); + private final Object mPositionListenerLock = new Object(); /** - * The listener the AudioRecord notifies periodically during recording. - * @see #setPeriodicNotificationListener(OnPeriodicNotificationListener) + * Handler for marker events coming from the native code */ - private OnPeriodicNotificationListener mPeriodicListener = null; + private NativeEventHandler mEventHandler = null; /** - * Lock to protect periodic listener updates against event notifications + * Looper associated with the thread that creates the AudioRecord instance */ - private final Object mPeriodicListenerLock = new Object(); - /** - * Handler for events coming from the native code - */ - private NativeEventHandler mNativeEventHandler = null; + private Looper mInitializationLooper = null; /** * Size of the native audio buffer. */ @@ -217,6 +214,11 @@ public class AudioRecord throws IllegalArgumentException { mState = STATE_UNINITIALIZED; mRecordingState = RECORDSTATE_STOPPED; + + // remember which looper is associated with the AudioRecord instanciation + if ((mInitializationLooper = Looper.myLooper()) == null) { + mInitializationLooper = Looper.getMainLooper(); + } audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat); @@ -319,21 +321,6 @@ public class AudioRecord } - // Convenience method for the creation of the native event handler - // It is called only when a non-null event listener is set. - // precondition: - // mNativeEventHandler is null - private void createNativeEventHandler() { - Looper looper; - if ((looper = Looper.myLooper()) != null) { - mNativeEventHandler = new NativeEventHandler(this, looper); - } else if ((looper = Looper.getMainLooper()) != null) { - mNativeEventHandler = new NativeEventHandler(this, looper); - } else { - mNativeEventHandler = null; - } - } - /** * Releases the native AudioRecord resources. @@ -433,7 +420,6 @@ public class AudioRecord } /** - * {@hide} * Returns the minimum buffer size required for the successful creation of an AudioRecord * object. * @param sampleRateInHz the sample rate expressed in Hertz. @@ -602,36 +588,40 @@ public class AudioRecord // Initialization / configuration //-------------------- /** - * Sets the listener the AudioRecord notifies when a previously set marker is reached. + * Sets the listener the AudioRecord notifies when a previously set marker is reached or + * for each periodic record head position update. * @param listener */ - public void setMarkerReachedListener(OnMarkerReachedListener listener) { - synchronized (mMarkerListenerLock) { - mMarkerListener = listener; - } - if ((listener != null) && (mNativeEventHandler == null)) { - createNativeEventHandler(); - } + public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener) { + setRecordPositionUpdateListener(listener, null); } - - /** - * Sets the listener the AudioRecord notifies periodically during recording. - * @param listener - */ - public void setPeriodicNotificationListener(OnPeriodicNotificationListener listener) { - synchronized (mPeriodicListenerLock) { - mPeriodicListener = listener; - } - if ((listener != null) && (mNativeEventHandler == null)) { - createNativeEventHandler(); + + public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener, + Handler handler) { + synchronized (mPositionListenerLock) { + + mPositionListener = listener; + + if (listener != null) { + if (handler != null) { + mEventHandler = new NativeEventHandler(this, handler.getLooper()); + } else { + // no given handler, use the looper the AudioRecord was created in + mEventHandler = new NativeEventHandler(this, mInitializationLooper); + } + } else { + mEventHandler = null; + } } + } /** - * Sets the marker position at which the listener, if set with - * {@link #setMarkerReachedListener(OnMarkerReachedListener)}, is called. + * Sets the marker position at which the listener is called, if set with + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}. * @param markerInFrames marker position expressed in frames * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, * {@link #ERROR_INVALID_OPERATION} @@ -642,8 +632,9 @@ public class AudioRecord /** - * Sets the period at which the listener, if set with - * {@link #setPositionNotificationPeriod(int)}, is called. + * Sets the period at which the listener is called, if set with + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}. * @param periodInFrames update period expressed in frames * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION} */ @@ -659,70 +650,65 @@ public class AudioRecord * Interface definition for a callback to be invoked when an AudioRecord has * reached a notification marker set by setNotificationMarkerPosition(). */ - public interface OnMarkerReachedListener { + public interface OnRecordPositionUpdateListener { /** * Called on the listener to notify it that the previously set marker has been reached * by the recording head. */ void onMarkerReached(AudioRecord recorder); - } - - - /** - * Interface definition for a callback to be invoked for each periodic AudioRecord - * update during recording. The update interval is set by setPositionNotificationPeriod(). - */ - public interface OnPeriodicNotificationListener { + /** - * Called on the listener to periodically notify it that the recording head has reached + * Called on the listener to periodically notify it that the record head has reached * a multiple of the notification period. */ void onPeriodicNotification(AudioRecord recorder); } + + //--------------------------------------------------------- // Inner classes //-------------------- + /** - * Helper class to handle the forwarding of native events to the appropriate listeners - */ - private class NativeEventHandler extends Handler - { - private AudioRecord mAudioRecord; - - public NativeEventHandler(AudioRecord ar, Looper looper) { + * Helper class to handle the forwarding of native events to the appropriate listener + * (potentially) handled in a different thread + */ + private class NativeEventHandler extends Handler { + + private final AudioRecord mAudioRecord; + + NativeEventHandler(AudioRecord recorder, Looper looper) { super(looper); - mAudioRecord = ar; + mAudioRecord = recorder; } - + @Override public void handleMessage(Message msg) { - if (mAudioRecord == null) { - return; + OnRecordPositionUpdateListener listener = null; + synchronized (mPositionListenerLock) { + listener = mAudioRecord.mPositionListener; } + switch(msg.what) { case NATIVE_EVENT_MARKER: - synchronized (mMarkerListenerLock) { - if (mAudioRecord.mMarkerListener != null) { - mAudioRecord.mMarkerListener.onMarkerReached(mAudioRecord); - } + if (listener != null) { + listener.onMarkerReached(mAudioRecord); } break; case NATIVE_EVENT_NEW_POS: - synchronized (mPeriodicListenerLock) { - if (mAudioRecord.mPeriodicListener != null) { - mAudioRecord.mPeriodicListener.onPeriodicNotification(mAudioRecord); - } + if (listener != null) { + listener.onPeriodicNotification(mAudioRecord); } break; default: Log.e(TAG, "[ android.media.AudioRecord.NativeEventHandler ] " + "Unknown event type: " + msg.what); - break; + break; } } - } + }; //--------------------------------------------------------- @@ -737,9 +723,10 @@ public class AudioRecord return; } - if (recorder.mNativeEventHandler != null) { - Message m = recorder.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj); - recorder.mNativeEventHandler.sendMessage(m); + if (recorder.mEventHandler != null) { + Message m = + recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj); + recorder.mEventHandler.sendMessage(m); } } diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 83ede0d..2e3e460 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -21,6 +21,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.database.ContentObserver; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.os.Binder; @@ -92,7 +93,8 @@ public class AudioService extends IAudioService.Stub { private AudioHandler mAudioHandler; /** @see VolumeStreamState */ private VolumeStreamState[] mStreamStates; - + private SettingsObserver mSettingsObserver; + private boolean mMicMute; private int mMode; private int[] mRoutes = new int[AudioSystem.NUM_MODES]; @@ -157,9 +159,6 @@ public class AudioService extends IAudioService.Stub { */ private int mRingerMode; - /** @see System#MODE_RINGER_STREAMS_AFFECTED */ - private int mRingerModeAffectedStreams; - /** @see System#MUTE_STREAMS_AFFECTED */ private int mMuteAffectedStreams; @@ -181,7 +180,8 @@ public class AudioService extends IAudioService.Stub { mContext = context; mContentResolver = context.getContentResolver(); mVolumePanel = new VolumePanel(context, this); - + mSettingsObserver = new SettingsObserver(); + createAudioSystemThread(); createStreamStates(); readPersistedSettings(); @@ -275,8 +275,6 @@ public class AudioService extends IAudioService.Stub { final ContentResolver cr = mContentResolver; mRingerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); - mRingerModeAffectedStreams = System.getInt(mContentResolver, - System.MODE_RINGER_STREAMS_AFFECTED, 1 << AudioSystem.STREAM_RING); mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0); @@ -494,32 +492,36 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#setRingerMode(int) */ public void setRingerMode(int ringerMode) { if (ringerMode != mRingerMode) { - mRingerMode = ringerMode; - - // Adjust volumes via posting message - int numStreamTypes = AudioSystem.getNumStreamTypes(); - if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) { - for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { - if (!isStreamAffectedByRingerMode(streamType)) continue; - // Bring back last audible volume - setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex, - false); - } - } else { - for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { - if (!isStreamAffectedByRingerMode(streamType)) continue; - // Either silent or vibrate, either way volume is 0 - setStreamVolumeInt(streamType, 0, false); - } - } + setRingerModeInt(ringerMode); // Send sticky broadcast broadcastRingerMode(); + } + } - // Post a persist ringer mode msg - sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG, - SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); + private void setRingerModeInt(int ringerMode) { + mRingerMode = ringerMode; + + // Adjust volumes via posting message + int numStreamTypes = AudioSystem.getNumStreamTypes(); + if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) { + for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { + if (!isStreamAffectedByRingerMode(streamType)) continue; + // Bring back last audible volume + setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex, + false); + } + } else { + for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { + if (!isStreamAffectedByRingerMode(streamType)) continue; + // Either silent or vibrate, either way volume is 0 + setStreamVolumeInt(streamType, 0, false); + } } + + // Post a persist ringer mode msg + sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG, + SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); } /** @see AudioManager#shouldVibrate(int) */ @@ -565,7 +567,6 @@ public class AudioService extends IAudioService.Stub { /** * @see #setVibrateSetting(int, int) - * @hide */ public static int getValueForVibrateSetting(int existingValue, int vibrateType, int vibrateSetting) { @@ -659,7 +660,6 @@ public class AudioService extends IAudioService.Stub { } /** @see AudioManager#playSoundEffect(int, float) */ - /* @hide FIXME: unhide before release */ public void playSoundEffectVolume(int effectType, float volume) { sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SHARED_MSG, SENDMSG_NOOP, effectType, (int) (volume * 1000), null, 0); @@ -783,7 +783,9 @@ public class AudioService extends IAudioService.Stub { } public boolean isStreamAffectedByRingerMode(int streamType) { - return (mRingerModeAffectedStreams & (1 << streamType)) != 0; + int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver, + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + return (ringerModeAffectedStreams & (1 << streamType)) != 0; } public boolean isStreamAffectedByMute(int streamType) { @@ -1233,4 +1235,25 @@ public class AudioService extends IAudioService.Stub { } } + private class SettingsObserver extends ContentObserver { + + SettingsObserver() { + super(new Handler()); + mContentResolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + + /* + * Ensure all stream types that should be affected by ringer mode + * are in the proper state. + */ + setRingerModeInt(getRingerMode()); + } + + } + } diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 316fa7a..4196ef3 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -171,6 +171,10 @@ public class AudioTrack */ private NativeEventHandlerDelegate mEventHandlerDelegate = null; /** + * Looper associated with the thread that creates the AudioTrack instance + */ + private Looper mInitializationLooper = null; + /** * The audio data sampling rate in Hz. */ private int mSampleRate = 22050; @@ -248,6 +252,11 @@ public class AudioTrack int bufferSizeInBytes, int mode) throws IllegalArgumentException { mState = STATE_UNINITIALIZED; + + // remember which looper is associated with the AudioTrack instanciation + if ((mInitializationLooper = Looper.myLooper()) == null) { + mInitializationLooper = Looper.getMainLooper(); + } audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode); @@ -414,7 +423,6 @@ public class AudioTrack } /** - * @hide * Returns the current playback rate in Hz. Note that this rate may differ from one set using * {@link #setPlaybackRate(int)} as the value effectively set is implementation-dependent. */ @@ -513,7 +521,6 @@ public class AudioTrack } /** - * {@hide} * Returns the minimum buffer size required for the successful creation of an AudioTrack * object to be created in the {@link #MODE_STREAM} mode. * @param sampleRateInHz the sample rate expressed in Hertz. @@ -902,11 +909,10 @@ public class AudioTrack if (handler != null) { looper = handler.getLooper(); } else { - // no given handler, look for main looper - if ((looper = Looper.myLooper()) == null) { - looper = Looper.getMainLooper(); - } + // no given handler, use the looper the AudioTrack was created in + looper = mInitializationLooper; } + // construct the event handler with this looper if (looper != null) { // implement the event handler delegate diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java index 9de0eec..c9efac5 100644 --- a/media/java/android/media/JetPlayer.java +++ b/media/java/android/media/JetPlayer.java @@ -63,26 +63,33 @@ public class JetPlayer private static final int JET_EVENT_CHAN_SHIFT = 14; // shift to get MIDI channel to bit 0 private static final int JET_EVENT_TRACK_SHIFT = 18; // shift to get track ID to bit 0 private static final int JET_EVENT_SEG_SHIFT = 24; // shift to get segment ID to bit 0 + + // to keep in sync with values used in external/sonivox/arm-wt-22k/Android.mk + // Jet rendering audio parameters + private static final int JET_OUTPUT_RATE = 22050; // _SAMPLE_RATE_22050 in Android.mk + private static final int JET_OUTPUT_CHANNEL_CONFIG = + AudioFormat.CHANNEL_CONFIGURATION_STEREO; // NUM_OUTPUT_CHANNELS=2 in Android.mk //-------------------------------------------- // Member variables //------------------------ - private EventHandler mNativeEventHandler = null; + /** + * Handler for jet events and status updates coming from the native code + */ + private NativeEventHandler mEventHandler = null; /** - * Lock to protect status listener updates against status change notifications + * Looper associated with the thread that creates the AudioTrack instance */ - private final Object mStatusListenerLock = new Object(); + private Looper mInitializationLooper = null; /** * Lock to protect the event listener updates against event notifications */ private final Object mEventListenerLock = new Object(); - private JetStatusUpdateListener mJetStatusUpdateListener = null; - - private JetEventListener mJetEventListener = null; + private OnJetEventListener mJetEventListener = null; private static JetPlayer singletonRef; @@ -101,8 +108,9 @@ public class JetPlayer // Constructor, finalize //------------------------ public static JetPlayer getJetPlayer() { - if (singletonRef == null) + if (singletonRef == null) { singletonRef = new JetPlayer(); + } return singletonRef; } @@ -115,10 +123,24 @@ public class JetPlayer private JetPlayer() { - - native_setup(new WeakReference<JetPlayer>(this), - JetPlayer.getMaxTracks(), - 1200); //TODO parametrize this (?) + + // remember which looper is associated with the JetPlayer instanciation + if ((mInitializationLooper = Looper.myLooper()) == null) { + mInitializationLooper = Looper.getMainLooper(); + } + + int buffSizeInBytes = AudioTrack.getMinBufferSize(JET_OUTPUT_RATE, + JET_OUTPUT_CHANNEL_CONFIG, AudioFormat.ENCODING_PCM_16BIT); + + if ((buffSizeInBytes != AudioTrack.ERROR) + && (buffSizeInBytes != AudioTrack.ERROR_BAD_VALUE)) { + + native_setup(new WeakReference<JetPlayer>(this), + JetPlayer.getMaxTracks(), + // bytes to frame conversion: sample format is ENCODING_PCM_16BIT, 2 channels + // 1200 == minimum buffer size in frames on generation 1 hardware + Math.max(1200, buffSizeInBytes / 4)); + } } @@ -132,18 +154,6 @@ public class JetPlayer } - private void createNativeEventHandler() { - Looper looper; - if ((looper = Looper.myLooper()) != null) { - mNativeEventHandler = new EventHandler(this, looper); - } else if ((looper = Looper.getMainLooper()) != null) { - mNativeEventHandler = new EventHandler(this, looper); - } else { - mNativeEventHandler = null; - } - } - - //-------------------------------------------- // Getters //------------------------ @@ -235,24 +245,27 @@ public class JetPlayer //--------------------------------------------------------- // Internal class to handle events posted from native code //------------------------ - private class EventHandler extends Handler + private class NativeEventHandler extends Handler { private JetPlayer mJet; - public EventHandler(JetPlayer jet, Looper looper) { + public NativeEventHandler(JetPlayer jet, Looper looper) { super(looper); mJet = jet; } @Override public void handleMessage(Message msg) { + OnJetEventListener listener = null; + synchronized (mEventListenerLock) { + listener = mJet.mJetEventListener; + } switch(msg.what) { case JET_EVENT: - synchronized (mEventListenerLock) { - if (mJetEventListener != null) { - // call the appropriate listener after decoding the event parameters - // encoded in msg.arg1 - mJetEventListener.onJetEvent( + if (listener != null) { + // call the appropriate listener after decoding the event parameters + // encoded in msg.arg1 + mJetEventListener.onJetEvent( mJet, (short)((msg.arg1 & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT), (byte) ((msg.arg1 & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT), @@ -261,28 +274,21 @@ public class JetPlayer (byte)(((msg.arg1 & JET_EVENT_CHAN_MASK) >> JET_EVENT_CHAN_SHIFT) + 1), (byte) ((msg.arg1 & JET_EVENT_CTRL_MASK) >> JET_EVENT_CTRL_SHIFT), (byte) (msg.arg1 & JET_EVENT_VAL_MASK) ); - } } return; case JET_USERID_UPDATE: - synchronized (mStatusListenerLock) { - if (mJetStatusUpdateListener != null) { - mJetStatusUpdateListener.onJetUserIdUpdate(mJet, msg.arg1, msg.arg2); - } + if (listener != null) { + listener.onJetUserIdUpdate(mJet, msg.arg1, msg.arg2); } return; case JET_NUMQUEUEDSEGMENT_UPDATE: - synchronized (mStatusListenerLock) { - if (mJetStatusUpdateListener != null) { - mJetStatusUpdateListener.onJetNumQueuedSegmentUpdate(mJet, msg.arg1); - } + if (listener != null) { + listener.onJetNumQueuedSegmentUpdate(mJet, msg.arg1); } return; case JET_PAUSE_UPDATE: - synchronized (mStatusListenerLock) { - if (mJetStatusUpdateListener != null) - mJetStatusUpdateListener.onJetPauseUpdate(mJet, msg.arg1); - } + if (listener != null) + listener.onJetPauseUpdate(mJet, msg.arg1); return; default: @@ -294,22 +300,48 @@ public class JetPlayer //-------------------------------------------- - // Jet status update listener + // Jet event listener //------------------------ - public void setStatusUpdateListener(JetStatusUpdateListener listener) { - synchronized(mStatusListenerLock) { - mJetStatusUpdateListener = listener; - } - - if ((listener != null) && (mNativeEventHandler == null)) { - createNativeEventHandler(); + public void setEventListener(OnJetEventListener listener) { + setEventListener(listener, null); + } + + public void setEventListener(OnJetEventListener listener, Handler handler) { + synchronized(mEventListenerLock) { + + mJetEventListener = listener; + + if (listener != null) { + if (handler != null) { + mEventHandler = new NativeEventHandler(this, handler.getLooper()); + } else { + // no given handler, use the looper the AudioTrack was created in + mEventHandler = new NativeEventHandler(this, mInitializationLooper); + } + } else { + mEventHandler = null; + } + } } + /** - * Handles the notification when the JET status is updated. + * Handles the notification when the JET engine generates an event. */ - public interface JetStatusUpdateListener { + public interface OnJetEventListener { + /** + * Callback for when the JET engine generates a new event. + * + * @param player the JET player the event is coming from + * @param segment 8 bit unsigned value + * @param track 6 bit unsigned value + * @param channel 4 bit unsigned value + * @param controller 7 bit unsigned value + * @param value 7 bit unsigned value + */ + void onJetEvent(JetPlayer player, + short segment, byte track, byte channel, byte controller, byte value); /** * Callback for when JET's currently playing segment userID is updated. * @@ -338,38 +370,6 @@ public class JetPlayer //-------------------------------------------- - // Jet event listener - //------------------------ - public void setEventListener(JetEventListener listener) { - synchronized(mEventListenerLock) { - mJetEventListener = listener; - } - - if ((listener != null) && (mNativeEventHandler == null)) { - createNativeEventHandler(); - } - } - - /** - * Handles the notification when the JET engine generates an event. - */ - public interface JetEventListener { - /** - * Callback for when the JET engine generates a new event. - * - * @param player the JET player the event is coming from - * @param segment 8 bit unsigned value - * @param track 6 bit unsigned value - * @param channel 4 bit unsigned value - * @param controller 7 bit unsigned value - * @param value 7 bit unsigned value - */ - void onJetEvent(JetPlayer player, - short segment, byte track, byte channel, byte controller, byte value); - } - - - //-------------------------------------------- // Native methods //------------------------ private native final boolean native_setup(Object Jet_this, @@ -397,13 +397,15 @@ public class JetPlayer @SuppressWarnings("unused") private static void postEventFromNative(Object jetplayer_ref, int what, int arg1, int arg2) { - + //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2); JetPlayer jet = (JetPlayer)((WeakReference)jetplayer_ref).get(); - if( (jet!=null) && (jet.mNativeEventHandler!=null) ){ - Message m = jet.mNativeEventHandler.obtainMessage(what, arg1, arg2, null); - jet.mNativeEventHandler.sendMessage(m); + if ((jet != null) && (jet.mEventHandler != null)) { + Message m = + jet.mEventHandler.obtainMessage(what, arg1, arg2, null); + jet.mEventHandler.sendMessage(m); } + } diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 202d0ae..19ab0ad 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -1036,11 +1036,11 @@ public class MediaPlayer * Register a callback to be invoked when the media source is ready * for playback. * - * @param l the callback that will be run + * @param listener the callback that will be run */ - public void setOnPreparedListener(OnPreparedListener l) + public void setOnPreparedListener(OnPreparedListener listener) { - mOnPreparedListener = l; + mOnPreparedListener = listener; } private OnPreparedListener mOnPreparedListener; @@ -1063,11 +1063,11 @@ public class MediaPlayer * Register a callback to be invoked when the end of a media source * has been reached during playback. * - * @param l the callback that will be run + * @param listener the callback that will be run */ - public void setOnCompletionListener(OnCompletionListener l) + public void setOnCompletionListener(OnCompletionListener listener) { - mOnCompletionListener = l; + mOnCompletionListener = listener; } private OnCompletionListener mOnCompletionListener; @@ -1092,11 +1092,11 @@ public class MediaPlayer * Register a callback to be invoked when the status of a network * stream's buffer has changed. * - * @param l the callback that will be run + * @param listener the callback that will be run. */ - public void setOnBufferingUpdateListener(OnBufferingUpdateListener l) + public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) { - mOnBufferingUpdateListener = l; + mOnBufferingUpdateListener = listener; } private OnBufferingUpdateListener mOnBufferingUpdateListener; @@ -1119,11 +1119,11 @@ public class MediaPlayer * Register a callback to be invoked when a seek operation has been * completed. * - * @param l the callback that will be run + * @param listener the callback that will be run */ - public void setOnSeekCompleteListener(OnSeekCompleteListener l) + public void setOnSeekCompleteListener(OnSeekCompleteListener listener) { - mOnSeekCompleteListener = l; + mOnSeekCompleteListener = listener; } private OnSeekCompleteListener mOnSeekCompleteListener; @@ -1131,8 +1131,6 @@ public class MediaPlayer /** * Interface definition of a callback to be invoked when the * video size is first known or updated - * FIXME: Unhide this API after approval - * @hide */ public interface OnVideoSizeChangedListener { @@ -1142,7 +1140,6 @@ public class MediaPlayer * @param mp the MediaPlayer associated with this callback * @param width the width of the video * @param height the height of the video - * @hide */ public void onVideoSizeChanged(MediaPlayer mp, int width, int height); } @@ -1151,12 +1148,11 @@ public class MediaPlayer * Register a callback to be invoked when the video size is * known or updated. * - * @param l the callback that will be run - * @hide + * @param listener the callback that will be run */ - public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener l) + public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) { - mOnVideoSizeChangedListener = l; + mOnVideoSizeChangedListener = listener; } private OnVideoSizeChangedListener mOnVideoSizeChangedListener; @@ -1178,7 +1174,7 @@ public class MediaPlayer /** The video is streamed and its container is not valid for progressive * playback i.e the video's index (e.g moov atom) is not at the start of the * file. - * @hide pending API council approval. Replace with @see tag after. + * @see android.media.MediaPlayer.OnErrorListener */ public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; @@ -1226,14 +1222,12 @@ public class MediaPlayer */ /** Unspecified media player info. * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_UNKNOWN = 1; /** The video is too complex for the decoder: it can't decode frames fast * enough. Possibly only the audio plays fine at this stage. * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; @@ -1241,20 +1235,17 @@ public class MediaPlayer * not interleaved at all, e.g has all the video samples first then all the * audio ones. Video is playing but a lot of disk seeks may be happening. * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; /** The media cannot be seeked (e.g live stream) * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_NOT_SEEKABLE = 801; /** * Interface definition of a callback to be invoked to communicate some * info and/or warning about the media or its playback. - * @hide pending API council approval. */ public interface OnInfoListener { @@ -1282,7 +1273,6 @@ public class MediaPlayer * Register a callback to be invoked when an info/warning is available. * * @param listener the callback that will be run - * @hide pending API council approval. */ public void setOnInfoListener(OnInfoListener listener) { diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 1c08cba..676f241 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -259,6 +259,12 @@ public class MediaRecorder /** * Sets the maximum duration (in ms) of the recording session. * Call this after setOutFormat() but before prepare(). + * After recording reaches the specified duration, a notification + * will be sent to the {@link android.media.MediaRecorder.OnInfoListener} + * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED} + * and recording will be stopped. Stopping happens asynchronously, there + * is no guarantee that the recorder will have stopped by the time the + * listener is notified. * * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit) * @@ -266,6 +272,21 @@ public class MediaRecorder public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException; /** + * Sets the maximum filesize (in bytes) of the recording session. + * Call this after setOutFormat() but before prepare(). + * After recording reaches the specified filesize, a notification + * will be sent to the {@link android.media.MediaRecorder.OnInfoListener} + * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED} + * and recording will be stopped. Stopping happens asynchronously, there + * is no guarantee that the recorder will have stopped by the time the + * listener is notified. + * + * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit) + * + */ + public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException; + + /** * Sets the audio encoder to be used for recording. If this method is not * called, the output file will not contain an audio track. Call this after * setOutputFormat() but before prepare(). @@ -441,6 +462,10 @@ public class MediaRecorder * @see android.media.MediaRecorder.OnInfoListener */ public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; + /** A maximum filesize had been setup and has now been reached. + * @see android.media.MediaRecorder.OnInfoListener + */ + public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; /** * Interface definition for a callback to be invoked when an error @@ -455,6 +480,8 @@ public class MediaRecorder * @param what the type of error that has occurred: * <ul> * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN} + * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED} + * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED} * </ul> * @param extra an extra code, specific to the error type */ diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 1e508d2..209b09f 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -268,6 +268,19 @@ android_media_MediaRecorder_setMaxDuration(JNIEnv *env, jobject thiz, jint max_d } static void +android_media_MediaRecorder_setMaxFileSize( + JNIEnv *env, jobject thiz, jlong max_filesize_bytes) +{ + LOGV("setMaxFileSize(%lld)", max_filesize_bytes); + sp<MediaRecorder> mr = getMediaRecorder(env, thiz); + + char params[64]; + sprintf(params, "max-filesize=%lld", max_filesize_bytes); + + process_media_recorder_call(env, mr->setParameters(String8(params)), "java/lang/RuntimeException", "setMaxFileSize failed."); +} + +static void android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz) { LOGV("prepare"); @@ -370,6 +383,7 @@ static JNINativeMethod gMethods[] = { {"setVideoSize", "(II)V", (void *)android_media_MediaRecorder_setVideoSize}, {"setVideoFrameRate", "(I)V", (void *)android_media_MediaRecorder_setVideoFrameRate}, {"setMaxDuration", "(I)V", (void *)android_media_MediaRecorder_setMaxDuration}, + {"setMaxFileSize", "(J)V", (void *)android_media_MediaRecorder_setMaxFileSize}, {"_prepare", "()V", (void *)android_media_MediaRecorder_prepare}, {"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude}, {"start", "()V", (void *)android_media_MediaRecorder_start}, diff --git a/media/jni/soundpool/NOTICE b/media/jni/soundpool/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/media/jni/soundpool/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 7594ff0..986f88e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -200,6 +200,7 @@ status_t AudioRecord::set( // TODO: add audio hardware input latency here mLatency = (1000*mFrameCount) / mSampleRate; mMarkerPosition = 0; + mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; @@ -293,6 +294,9 @@ status_t AudioRecord::stop() if (android_atomic_and(~1, &mActive) == 1) { mAudioRecord->stop(); + // the record head position will reset to 0, so if a marker is set, we need + // to activate it again + mMarkerReached = false; if (t != 0) { t->requestExit(); } else { @@ -317,6 +321,7 @@ status_t AudioRecord::setMarkerPosition(uint32_t marker) if (mCbf == 0) return INVALID_OPERATION; mMarkerPosition = marker; + mMarkerReached = false; return NO_ERROR; } @@ -492,10 +497,10 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) size_t readSize; // Manage marker callback - if (mMarkerPosition > 0) { + if (!mMarkerReached && (mMarkerPosition > 0)) { if (mCblk->user >= mMarkerPosition) { mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); - mMarkerPosition = 0; + mMarkerReached = true; } } @@ -527,7 +532,14 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) readSize = audioBuffer.size; // Sanity check on returned size - if (ssize_t(readSize) <= 0) break; + if (ssize_t(readSize) <= 0) { + // The callback is done filling buffers + // Keep this thread going to handle timed events and + // still try to get more data in intervals of WAIT_PERIOD_MS + // but don't just loop and block the CPU, so wait + usleep(WAIT_PERIOD_MS*1000); + break; + } if (readSize > reqSize) readSize = reqSize; audioBuffer.size = readSize; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d26b0c5..24f7281 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -259,6 +259,7 @@ status_t AudioTrack::set( mLatency = afLatency + (1000*mFrameCount) / mSampleRate; mLoopCount = 0; mMarkerPosition = 0; + mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; @@ -360,6 +361,9 @@ void AudioTrack::stop() // Cancel loops (If we are in the middle of a loop, playback // would not stop until loopCount reaches 0). setLoop(0, 0, 0); + // the playback head position will reset to 0, so if a marker is set, we need + // to activate it again + mMarkerReached = false; // Force flush if a shared buffer is used otherwise audioflinger // will not stop before end of buffer is reached. if (mSharedBuffer != 0) { @@ -385,14 +389,18 @@ bool AudioTrack::stopped() const void AudioTrack::flush() { LOGV("flush"); + + // clear playback marker and periodic update counter + mMarkerPosition = 0; + mMarkerReached = false; + mUpdatePeriod = 0; + if (!mActive) { - mCblk->lock.lock(); mAudioTrack->flush(); // Release AudioTrack callback thread in case it was waiting for new buffers // in AudioTrack::obtainBuffer() mCblk->cv.signal(); - mCblk->lock.unlock(); } } @@ -443,7 +451,7 @@ void AudioTrack::setSampleRate(int rate) if (rate > afSamplingRate*2) rate = afSamplingRate*2; if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE; - mCblk->sampleRate = rate; + mCblk->sampleRate = (uint16_t)rate; } uint32_t AudioTrack::getSampleRate() @@ -510,6 +518,7 @@ status_t AudioTrack::setMarkerPosition(uint32_t marker) if (mCbf == 0) return INVALID_OPERATION; mMarkerPosition = marker; + mMarkerReached = false; return NO_ERROR; } @@ -757,10 +766,10 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) } // Manage marker callback - if(mMarkerPosition > 0) { + if (!mMarkerReached && (mMarkerPosition > 0)) { if (mCblk->server >= mMarkerPosition) { mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); - mMarkerPosition = 0; + mMarkerReached = true; } } diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp index 2c62104..586aacb 100644 --- a/media/libmedia/JetPlayer.cpp +++ b/media/libmedia/JetPlayer.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_NDEBUG 0 +//#define LOG_NDEBUG 0 #define LOG_TAG "JetPlayer-C" #include <utils/Log.h> @@ -194,8 +194,15 @@ int JetPlayer::render() { } while (1) { + mMutex.lock(); // [[[[[[[[ LOCK --------------------------------------- + if (mEasData == NULL) { + mMutex.unlock(); + LOGV("JetPlayer::render(): NULL EAS data, exiting render."); + goto threadExit; + } + // nothing to render, wait for client thread to wake us up while (!mRender) { @@ -255,7 +262,10 @@ int JetPlayer::render() { }//while (1) threadExit: - mAudioTrack->flush(); + if (mAudioTrack) { + mAudioTrack->stop(); + mAudioTrack->flush(); + } if (mAudioBuffer) { delete [] mAudioBuffer; mAudioBuffer = NULL; diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 6b40412..809316a 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -91,6 +91,7 @@ MediaPlayer::MediaPlayer() mLoop = false; mLeftVolume = mRightVolume = 1.0; mVideoWidth = mVideoHeight = 0; + mLockThreadId = 0; } void MediaPlayer::onFirstRef() @@ -223,16 +224,24 @@ status_t MediaPlayer::prepare() { LOGV("prepare"); Mutex::Autolock _l(mLock); - if (mPrepareSync) return -EALREADY; + mLockThreadId = getThreadId(); + if (mPrepareSync) { + mLockThreadId = 0; + return -EALREADY; + } mPrepareSync = true; status_t ret = prepareAsync_l(); - if (ret != NO_ERROR) return ret; + if (ret != NO_ERROR) { + mLockThreadId = 0; + return ret; + } if (mPrepareSync) { mSignal.wait(mLock); // wait for prepare done mPrepareSync = false; } LOGV("prepare complete - status=%d", mPrepareStatus); + mLockThreadId = 0; return mPrepareStatus; } @@ -407,8 +416,12 @@ status_t MediaPlayer::seekTo_l(int msec) status_t MediaPlayer::seekTo(int msec) { + mLockThreadId = getThreadId(); Mutex::Autolock _l(mLock); - return seekTo_l(msec); + status_t result = seekTo_l(msec); + mLockThreadId = 0; + + return result; } status_t MediaPlayer::reset() @@ -485,14 +498,24 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) { LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); bool send = true; + bool locked = false; // TODO: In the future, we might be on the same thread if the app is // running in the same process as the media server. In that case, // this will deadlock. - mLock.lock(); + // + // The threadId hack below works around this for the care of prepare + // and seekTo within the same process. + // FIXME: Remember, this is a hack, it's not even a hack that is applied + // consistently for all use-cases, this needs to be revisited. + if (mLockThreadId != getThreadId()) { + mLock.lock(); + locked = true; + } + if (mPlayer == 0) { LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); - mLock.unlock(); // release the lock when done. + if (locked) mLock.unlock(); // release the lock when done. return; } @@ -561,7 +584,7 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) } sp<MediaPlayerListener> listener = mListener; - mLock.unlock(); + if (locked) mLock.unlock(); // this prevents re-entrant calls into client code if ((listener != 0) && send) { diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 23b3b9d..6b26faf 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -367,8 +367,9 @@ status_t MediaRecorder::setParameters(const String8& params) { status_t ret = mMediaRecorder->setParameters(params); if (OK != ret) { LOGE("setParameters(%s) failed: %d", params.string(), ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return ret; + // Do not change our current state to MEDIA_RECORDER_ERROR, failures + // of the only currently supported parameters, "max-duration" and + // "max-filesize" are _not_ fatal. } return ret; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 95001c6..8ef0dc6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -460,6 +460,7 @@ void MediaPlayerService::Client::disconnect() Mutex::Autolock l(mLock); p = mPlayer; } + mClient.clear(); mPlayer.clear(); // clear the notification to prevent callbacks to dead client diff --git a/media/sdutils/Android.mk b/media/sdutils/Android.mk index 2009b3c..dafb8a6 100644 --- a/media/sdutils/Android.mk +++ b/media/sdutils/Android.mk @@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := libhardware_legacy libcutils libutils libc LOCAL_MODULE:= sdutil +LOCAL_MODULE_TAGS := debug include $(BUILD_EXECUTABLE) diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java index 3c449c9..6edc2cc 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java @@ -16,12 +16,13 @@ package com.android.mediaframeworktest; -import com.android.mediaframeworktest.functional.MediaPlayerApiTest; -import com.android.mediaframeworktest.functional.SimTonesTest; -import com.android.mediaframeworktest.functional.MediaMetadataTest; import com.android.mediaframeworktest.functional.CameraTest; -import com.android.mediaframeworktest.functional.MediaRecorderTest; import com.android.mediaframeworktest.functional.MediaAudioTrackTest; +import com.android.mediaframeworktest.functional.MediaMetadataTest; +import com.android.mediaframeworktest.functional.MediaMimeTest; +import com.android.mediaframeworktest.functional.MediaPlayerApiTest; +import com.android.mediaframeworktest.functional.MediaRecorderTest; +import com.android.mediaframeworktest.functional.SimTonesTest; import junit.framework.TestSuite; @@ -50,6 +51,7 @@ public class MediaFrameworkTestRunner extends InstrumentationTestRunner { suite.addTestSuite(CameraTest.class); suite.addTestSuite(MediaRecorderTest.class); suite.addTestSuite(MediaAudioTrackTest.class); + suite.addTestSuite(MediaMimeTest.class); return suite; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java new file mode 100644 index 0000000..d2809c1 --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2009 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.mediaframeworktest.functional; + +import java.io.File; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; +import com.android.mediaframeworktest.MediaFrameworkTest; + +/* + * System tests for the handling of mime type in the media framework. + * + * To run this test suite: + make frameworks/base/media/tests/MediaFrameworkTest + make mediaframeworktest + + adb install -r out/target/product/dream/data/app/mediaframeworktest.apk + + adb shell am instrument -e class \ + com.android.mediaframeworktest.functional.MediaMimeTest \ + -w com.android.mediaframeworktest/.MediaFrameworkTestRunner + * + */ +public class MediaMimeTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { + private final String TAG = "MediaMimeTest"; + private Context mContext; + private final String MP3_FILE = "/sdcard/media_api/music/SHORTMP3.mp3"; + private final String MEDIA_PLAYBACK_NAME = "com.android.music.MediaPlaybackActivity"; + + public MediaMimeTest() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mContext = getActivity(); + // Checks you have all the test files on your SDCARD. + assertTrue(new File(MP3_FILE).exists()); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + // ---------------------------------------------------------------------- + // AUDIO mime type resolution tests. + + @MediumTest + // Checks the MediaPlaybackActivity handles audio/mp3. + public void testCheckMediaPlaybackHandlesAudioMp3() throws Exception { + assertMediaPlaybackActivityHandles("audio/mp3"); + } + + @MediumTest + // Checks the MediaPlaybackActivity handles audio/*. + public void testCheckMediaPlaybackHandlesAudio() throws Exception { + assertMediaPlaybackActivityHandles("audio/*"); + } + + @MediumTest + // Checks the MediaPlaybackActivity handles application/itunes. Some servers + // set the Content-type header to application/iTunes (with capital T, but + // the download manager downcasts it) for their MP3 podcasts. This is non + // standard but we try to support it anyway. + // See bug 1401491 + public void testCheckMediaPlaybackHandlesApplicationItunes() throws Exception { + assertMediaPlaybackActivityHandles("application/itunes"); + } + + @MediumTest + // Checks the activity resolver handling of mime types is case sensitive. + // See bug 1710534 + public void testCheckActivityResolverMimeHandlingIsCaseSensitive() throws Exception { + assertNoActivityHandles("AUDIO/MP3"); // <--- look uppercase + } + + @MediumTest + // Checks the activity resolver does not trims leading whitespaces when + // resolving mime types. Trailing whitespaces seems to be non + // significant. + // See bug 1710534 + public void testCheckWhiteSpacesInMimeTypeHandling() throws Exception { + assertNoActivityHandles(" audio/mp3"); + assertNoActivityHandles(" audio/mp3 "); + assertMediaPlaybackActivityHandles("audio/mp3 "); + } + + // @return a ResolveInfo instance for the mime type or null if the type is + // not handled by any activity. + private ResolveInfo resolveMime(String mime) { + Intent viewIntent = new Intent(Intent.ACTION_VIEW); + Uri uri = Uri.fromParts("file", MP3_FILE, null); + + viewIntent.setDataAndType(uri, mime); + return mContext.getPackageManager().resolveActivity( + viewIntent, PackageManager.MATCH_DEFAULT_ONLY); + } + + // Helper method to check the media playback activity handles the given mime type. + // @param mime type to test for + private void assertMediaPlaybackActivityHandles(String mime) throws Exception { + ResolveInfo ri = resolveMime(mime); + + assertNotNull(ri); + assertEquals(MEDIA_PLAYBACK_NAME, ri.activityInfo.name.toString()); + } + + // Helper method to check that NO activity handles the given mime type. + // @param mime type to test for + private void assertNoActivityHandles(String mime) throws Exception { + assertNull(resolveMime(mime)); + } +} diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java index 4fa6735..61a8a29 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java @@ -22,8 +22,7 @@ import android.graphics.Bitmap; import java.io.FileOutputStream; import android.test.AndroidTestCase; import com.android.mediaframeworktest.MediaNames; -import android.test.suitebuilder.annotation.LargeTest; -import android.test.suitebuilder.annotation.Suppress; +import android.test.suitebuilder.annotation.*; /** * WARNING: @@ -35,7 +34,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { private static final String TAG = "MediaMetadataRetrieverTest"; // Test album art extraction. - @LargeTest + @MediumTest public static void testAlbumArt() throws Exception { Log.v(TAG, "testAlbumArt starts."); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); @@ -109,7 +108,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // If the specified call order and valid media file is used, no exception // should be thrown. - @LargeTest + @MediumTest public static void testBasicNormalMethodCallSequence() throws Exception { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); @@ -136,7 +135,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // If setDataSource() has not been called, both captureFrame() and extractMetadata() must // return null. - @LargeTest + @MediumTest public static void testBasicAbnormalMethodCallSequence() { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); @@ -145,7 +144,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { } // Test setDataSource() - @LargeTest + @MediumTest public static void testSetDataSource() { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); @@ -190,7 +189,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // Due to the lack of permission to access hardware decoder, any calls // attempting to capture a frame will fail. These are commented out for now // until we find a solution to this access permission problem. - @LargeTest + @MediumTest public static void testIntendedUsage() { // By default, capture frame and retrieve metadata MediaMetadataRetriever retriever = new MediaMetadataRetriever(); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java index bde000b..134144d 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; import java.io.IOException; @@ -59,7 +59,7 @@ public class MediaRecorderPrepareStateUnitTest extends AndroidTestCase implement } } - @LargeTest + @MediumTest public void testPrepare() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java index 80532c3..cae9e31 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderResetStateUnitTest extends AndroidTestCase implements recorder.reset(); } - @LargeTest + @MediumTest public void testReset() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java index e387a77..4b5a818 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderSetAudioEncoderStateUnitTest extends AndroidTestCase i recorder.setAudioEncoder(MediaRecorderStateUnitTestTemplate.AUDIO_ENCODER); } - @LargeTest + @MediumTest public void testSetAudioEncoder() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java index 60af54c..f8ab48cf 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderSetAudioSourceStateUnitTest extends AndroidTestCase im recorder.setAudioSource(MediaRecorderStateUnitTestTemplate.AUDIO_SOURCE); } - @LargeTest + @MediumTest public void testSetAudioSource() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java index 37d97e9..712a758 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -51,7 +51,7 @@ public class MediaRecorderSetOutputFileStateUnitTest extends AndroidTestCase imp recorder.setOutputFile(MediaRecorderStateUnitTestTemplate.RECORD_OUTPUT_PATH); } - @LargeTest + @MediumTest public void testSetOutputFile() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java index a7ee2d4..cacdd87 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderSetOutputFormatStateUnitTest extends AndroidTestCase i recorder.setOutputFormat(MediaRecorderStateUnitTestTemplate.OUTPUT_FORMAT); } - @LargeTest + @MediumTest public void testSetOutputFormat() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java index 4af5967..d1232fc 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderStartStateUnitTest extends AndroidTestCase implements recorder.start(); } - @LargeTest + @MediumTest public void testStart() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java index 5475900..8737595 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderStopStateUnitTest extends AndroidTestCase implements M recorder.stop(); } - @LargeTest + @MediumTest public void testStop() { mTestTemplate.runTestOnMethod(this); } diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 42c53f9..7fb8585 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -107,13 +107,67 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback */ public void setRenderer(Renderer renderer) { if (mGLThread != null) { - throw new IllegalStateException("setRenderer has already been called for this instance."); + throw new IllegalStateException( + "setRenderer has already been called for this instance."); + } + if (mEGLConfigChooser == null) { + mEGLConfigChooser = new SimpleEGLConfigChooser(true); } mGLThread = new GLThread(renderer); mGLThread.start(); } /** + * Set the EGLConfigChooser associated with this view. If this method is + * called at all, it must be called before {@link #setRenderer(Renderer)} + * is called. + * <p> + * The supplied configChooser will be used to choose a configuration. + * @param configChooser + */ + public void setEGLConfigChooser(EGLConfigChooser configChooser) { + if (mGLThread != null) { + throw new IllegalStateException( + "setRenderer has already been called for this instance."); + } + mEGLConfigChooser = configChooser; + } + + /** + * Set the EGLConfigChooser associated with this view. If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + * <p> + * This method installs a config chooser which will choose a config + * as close to 16-bit RGB as possible, with or without an optional depth + * buffer as close to 16-bits as possible. + * <p> + * If no setEGLConfigChooser method is called, then by default the + * view will choose a config as close to 16-bit RGB as possible, with + * a depth buffer as close to 16-bits as possible. + * + * @param needDepth + */ + public void setEGLConfigChooser(boolean needDepth) { + setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); + } + + /** + * Set the EGLConfigChooser associated with this view. If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + * <p> + * This method installs a config chooser which will choose a config + * with at least the specified component sizes, and as close + * to the specified component sizes as possible. + * + */ + public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, + int alphaSize, int depthSize, int stencilSize) { + setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, + blueSize, alphaSize, depthSize, stencilSize)); + } + /** * Set the rendering mode. When the renderMode is * RENDERMODE_CONTINUOUSLY, the renderer is called * repeatedly to re-render the scene. When the rendermode @@ -200,11 +254,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback */ public interface Renderer { /** - * @return the EGL configuration specification desired by the renderer. - */ - int[] getConfigSpec(); - - /** * Surface created. * Called when the surface is created. Called when the application * starts, and whenever the GPU is reinitialized. This will @@ -235,6 +284,140 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } /** + * An interface for choosing a configuration from a list of + * potential configurations. + * + */ + public interface EGLConfigChooser { + /** + * Choose a configuration from the list. Implementors typically + * implement this method by calling + * {@link EGL10#eglChooseConfig} and iterating through the results. + * @param egl the EGL10 for the current display. + * @param display the current display. + * @return the chosen configuration. + */ + EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); + } + + private static abstract class BaseConfigChooser + implements EGLConfigChooser { + public BaseConfigChooser(int[] configSpec) { + mConfigSpec = configSpec; + } + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + int[] num_config = new int[1]; + egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); + + int numConfigs = num_config[0]; + + if (numConfigs <= 0) { + throw new IllegalArgumentException( + "No configs match configSpec"); + } + + EGLConfig[] configs = new EGLConfig[numConfigs]; + egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, + num_config); + EGLConfig config = chooseConfig(egl, display, configs); + if (config == null) { + throw new IllegalArgumentException("No config chosen"); + } + return config; + } + + abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs); + + protected int[] mConfigSpec; + } + + private static class ComponentSizeChooser extends BaseConfigChooser { + public ComponentSizeChooser(int redSize, int greenSize, int blueSize, + int alphaSize, int depthSize, int stencilSize) { + super(new int[] { + EGL10.EGL_RED_SIZE, redSize, + EGL10.EGL_GREEN_SIZE, greenSize, + EGL10.EGL_BLUE_SIZE, blueSize, + EGL10.EGL_ALPHA_SIZE, alphaSize, + EGL10.EGL_DEPTH_SIZE, depthSize, + EGL10.EGL_STENCIL_SIZE, stencilSize, + EGL10.EGL_NONE}); + mValue = new int[1]; + mRedSize = redSize; + mGreenSize = greenSize; + mBlueSize = blueSize; + mAlphaSize = alphaSize; + mDepthSize = depthSize; + mStencilSize = stencilSize; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs) { + EGLConfig closestConfig = null; + int closestDistance = 1000; + for(EGLConfig config : configs) { + int r = findConfigAttrib(egl, display, config, + EGL10.EGL_RED_SIZE, 0); + int g = findConfigAttrib(egl, display, config, + EGL10.EGL_GREEN_SIZE, 0); + int b = findConfigAttrib(egl, display, config, + EGL10.EGL_BLUE_SIZE, 0); + int a = findConfigAttrib(egl, display, config, + EGL10.EGL_ALPHA_SIZE, 0); + int d = findConfigAttrib(egl, display, config, + EGL10.EGL_DEPTH_SIZE, 0); + int s = findConfigAttrib(egl, display, config, + EGL10.EGL_STENCIL_SIZE, 0); + int distance = Math.abs(r - mRedSize) + + Math.abs(g - mGreenSize) + + Math.abs(b - mBlueSize) + Math.abs(a - mAlphaSize) + + Math.abs(d - mDepthSize) + Math.abs(s - mStencilSize); + if (distance < closestDistance) { + closestDistance = distance; + closestConfig = config; + } + } + return closestConfig; + } + + private int findConfigAttrib(EGL10 egl, EGLDisplay display, + EGLConfig config, int attribute, int defaultValue) { + + if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { + return mValue[0]; + } + return defaultValue; + } + + private int[] mValue; + // Subclasses can adjust these values: + protected int mRedSize; + protected int mGreenSize; + protected int mBlueSize; + protected int mAlphaSize; + protected int mDepthSize; + protected int mStencilSize; + } + + /** + * This class will choose a supported surface as close to + * RGB565 as possible, with or without a depth buffer. + * + */ + private static class SimpleEGLConfigChooser extends ComponentSizeChooser { + public SimpleEGLConfigChooser(boolean withDepthBuffer) { + super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0); + // Adjust target values. This way we'll accept a 4444 or + // 555 buffer if there's no 565 buffer available. + mRedSize = 5; + mGreenSize = 6; + mBlueSize = 5; + } + } + + /** * An EGL helper class. */ @@ -247,7 +430,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * Initialize EGL for a given configuration spec. * @param configSpec */ - public void start(int[] configSpec){ + public void start(){ /* * Get an EGL instance */ @@ -263,12 +446,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback */ int[] version = new int[2]; mEgl.eglInitialize(mEglDisplay, version); - - EGLConfig[] configs = new EGLConfig[1]; - int[] num_config = new int[1]; - mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, - num_config); - mEglConfig = configs[0]; + mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); /* * Create an OpenGL ES context. This must be done only once, an @@ -418,12 +596,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private void guardedRun() throws InterruptedException { mEglHelper = new EglHelper(); - /* - * Specify a configuration for our opengl session - * and grab the first configuration that matches is - */ - int[] configSpec = mRenderer.getConfigSpec(); - mEglHelper.start(configSpec); + mEglHelper.start(); GL10 gl = null; boolean tellRendererSurfaceCreated = true; @@ -463,7 +636,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback mRequestRender = false; } if (needStart) { - mEglHelper.start(configSpec); + mEglHelper.start(); tellRendererSurfaceCreated = true; changed = true; } @@ -656,6 +829,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private boolean mSizeChanged = true; private GLThread mGLThread; + private EGLConfigChooser mEGLConfigChooser; private GLWrapper mGLWrapper; private int mDebugFlags; } diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java index df6c557..e150c19 100644 --- a/opengl/java/android/opengl/GLUtils.java +++ b/opengl/java/android/opengl/GLUtils.java @@ -40,7 +40,6 @@ public final class GLUtils { /** * return the internal format as defined by OpenGL ES of the supplied bitmap. - * * @param bitmap * @return the internal format of the bitmap. */ @@ -48,40 +47,30 @@ public final class GLUtils { if (bitmap == null) { throw new NullPointerException("getInternalFormat can't be used with a null Bitmap"); } - switch (bitmap.getConfig()) { - case ALPHA_8: - return GL10.GL_ALPHA; - case ARGB_4444: - case ARGB_8888: - return GL10.GL_RGBA; - case RGB_565: - return GL10.GL_RGB; + int result = native_getInternalFormat(bitmap); + if (result < 0) { + throw new IllegalArgumentException("Unknown internalformat"); } - throw new IllegalArgumentException("Unknown internalformat"); + return result; } /** - * Return the type as defined by OpenGL ES of the supplied bitmap. + * Return the type as defined by OpenGL ES of the supplied bitmap, if there + * is one. If the bitmap is stored in a compressed format, it may not have + * a valid OpenGL ES type. + * @throws IllegalArgumentException if the bitmap does not have a type. + * @param bitmap + * @return the OpenGL ES type of the bitmap. */ public static int getType(Bitmap bitmap) { if (bitmap == null) { throw new NullPointerException("getType can't be used with a null Bitmap"); } - int type; - switch(bitmap.getConfig()) { - case ARGB_4444: - type = GL10.GL_UNSIGNED_SHORT_4_4_4_4; - break; - case RGB_565: - type = GL10.GL_UNSIGNED_SHORT_5_6_5; - break; - case ALPHA_8: - case ARGB_8888: - default: - type = GL10.GL_UNSIGNED_BYTE; - break; + int result = native_getType(bitmap); + if (result < 0) { + throw new IllegalArgumentException("Unknown type"); } - return type; + return result; } /** @@ -111,15 +100,16 @@ public final class GLUtils { if (bitmap == null) { throw new NullPointerException("texImage2D can't be used with a null Bitmap"); } - int type = getType(bitmap); - if (native_texImage2D(target, level, internalformat, bitmap, type, border)!=0) { + if (native_texImage2D(target, level, internalformat, bitmap, -1, border)!=0) { throw new IllegalArgumentException("invalid Bitmap format"); } } /** * A version of texImage2D() that takes an explicit type parameter - * as defined by the OpenGL ES specification. + * as defined by the OpenGL ES specification. The actual type and + * internalformat of the bitmap must be compatible with the specified + * type and internalformat parameters. * * @param target * @param level @@ -139,7 +129,8 @@ public final class GLUtils { } /** - * A version of texImage2D that determines the internalFormat automatically. + * A version of texImage2D that determines the internalFormat and type + * automatically. * * @param target * @param level @@ -151,8 +142,7 @@ public final class GLUtils { if (bitmap == null) { throw new NullPointerException("texImage2D can't be used with a null Bitmap"); } - int type = getType(bitmap); - if (native_texImage2D(target, level, -1, bitmap, type, border)!=0) { + if (native_texImage2D(target, level, -1, bitmap, -1, border)!=0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -213,6 +203,8 @@ public final class GLUtils { native private static void nativeClassInit(); + native private static int native_getInternalFormat(Bitmap bitmap); + native private static int native_getType(Bitmap bitmap); native private static int native_texImage2D(int target, int level, int internalformat, Bitmap bitmap, int type, int border); native private static int native_texSubImage2D(int target, int level, int xoffset, int yoffset, diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 5b90bf0..3b4c041 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -1055,8 +1055,12 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, { if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + if (ggl_unlikely(num_config==0)) { + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + } - if (ggl_unlikely(configs==0 || attrib_list==0)) { + if (ggl_unlikely(attrib_list==0)) { *num_config = 0; return EGL_TRUE; } @@ -1102,11 +1106,19 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, // return the configurations found int n=0; if (possibleMatch) { - for (int i=0 ; config_size && i<numConfigs ; i++) { - if (possibleMatch & (1<<i)) { - *configs++ = (EGLConfig)i; - config_size--; - n++; + if (configs) { + for (int i=0 ; config_size && i<numConfigs ; i++) { + if (possibleMatch & (1<<i)) { + *configs++ = (EGLConfig)i; + config_size--; + n++; + } + } + } else { + for (int i=0 ; i<numConfigs ; i++) { + if (possibleMatch & (1<<i)) { + n++; + } } } } diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 687c8bc..0b4bcce 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -725,9 +725,8 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, egl_display_t const * const dp = get_display(dpy); if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (configs == 0) { - *num_config = 0; - return EGL_TRUE; + if (num_config==0) { + return setError(EGL_BAD_PARAMETER, EGL_FALSE); } EGLint n; @@ -784,7 +783,9 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, if (res && n>0) { // n has to be 0 or 1, by construction, and we already know // which config it will return (since there can be only one). - configs[0] = MAKE_CONFIG(i, index); + if (configs) { + configs[0] = MAKE_CONFIG(i, index); + } *num_config = 1; } } @@ -798,19 +799,23 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, if (cnx->dso) { if (cnx->hooks->egl.eglChooseConfig( dp->dpys[i], attrib_list, configs, config_size, &n)) { - // now we need to convert these client EGLConfig to our - // internal EGLConfig format. This is done in O(n log n). - for (int j=0 ; j<n ; j++) { - int index = binarySearch<EGLConfig>( - dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]); - if (index >= 0) { - configs[j] = MAKE_CONFIG(i, index); - } else { - return setError(EGL_BAD_CONFIG, EGL_FALSE); + if (configs) { + // now we need to convert these client EGLConfig to our + // internal EGLConfig format. This is done in O(n log n). + for (int j=0 ; j<n ; j++) { + int index = binarySearch<EGLConfig>( + dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]); + if (index >= 0) { + if (configs) { + configs[j] = MAKE_CONFIG(i, index); + } + } else { + return setError(EGL_BAD_CONFIG, EGL_FALSE); + } } + configs += n; + config_size -= n; } - configs += n; - config_size -= n; *num_config += n; res = EGL_TRUE; } diff --git a/packages/SettingsProvider/etc/Android.mk b/packages/SettingsProvider/etc/Android.mk index d73175f..81ca4b1 100644 --- a/packages/SettingsProvider/etc/Android.mk +++ b/packages/SettingsProvider/etc/Android.mk @@ -31,17 +31,3 @@ LOCAL_SRC_FILES := $(LOCAL_MODULE) include $(BUILD_PREBUILT) -######################## -include $(CLEAR_VARS) - -LOCAL_MODULE := favorites.xml - -LOCAL_MODULE_TAGS := user - -# This will install the file in /system/etc -# -LOCAL_MODULE_CLASS := ETC - -LOCAL_SRC_FILES := $(LOCAL_MODULE) - -include $(BUILD_PREBUILT) diff --git a/packages/SettingsProvider/etc/favorites.xml b/packages/SettingsProvider/etc/favorites.xml deleted file mode 100644 index ae74b8e..0000000 --- a/packages/SettingsProvider/etc/favorites.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2009 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. ---> - -<favorites> - <favorite package="com.android.contacts" class="com.android.contacts.DialtactsActivity" screen="1" x="0" y="3"/> - <favorite package="com.android.contacts" class="com.android.contacts.DialtactsContactsEntryActivity" screen="1" x="1" y="3" /> - <favorite package="com.android.browser" class="com.android.browser.BrowserActivity" screen="1" x="2" y="3" /> - <favorite package="com.google.android.apps.maps" class="com.google.android.maps.MapsActivity" screen="1" x="3" y="3" /> - <favorite package="com.android.vending" class="com.android.vending.AssetBrowserActivity" screen="1" x="0" y="2" /> -</favorites> diff --git a/preloaded-classes b/preloaded-classes index ed476d6..bd2fa68 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -22,6 +22,7 @@ android.app.ActivityThread$PackageInfo$ServiceDispatcher android.app.ActivityThread$PackageInfo$ServiceDispatcher$InnerConnection android.app.ActivityThread$ProviderRecord android.app.ActivityThread$ProviderRefCount +android.app.AlertDialog android.app.Application android.app.ApplicationContext android.app.ApplicationContext$ApplicationContentResolver @@ -35,28 +36,38 @@ android.app.Dialog android.app.ExpandableListActivity android.app.IActivityManager android.app.IActivityManager$ContentProviderHolder$1 +android.app.IAlarmManager$Stub android.app.IAlarmManager$Stub$Proxy +android.app.IApplicationThread android.app.INotificationManager$Stub android.app.INotificationManager$Stub$Proxy +android.app.ISearchManager +android.app.ISearchManager$Stub android.app.ISearchManager$Stub$Proxy android.app.Instrumentation android.app.IntentReceiverLeaked android.app.ListActivity android.app.ListActivity$1 android.app.ListActivity$2 +android.app.LocalActivityManager android.app.Notification android.app.NotificationManager android.app.PendingIntent android.app.PendingIntent$1 +android.app.ProgressDialog android.app.ReceiverRestrictedContext android.app.ResultInfo android.app.ResultInfo$1 +android.app.SearchDialog +android.app.SearchDialog$SearchAutoComplete +android.app.Service android.app.ServiceConnectionLeaked android.app.TabActivity -android.bluetooth.BluetoothAudioGateway -android.bluetooth.BluetoothDevice -android.bluetooth.IBluetoothDevice$Stub$Proxy +android.content.AbstractSyncableContentProvider +android.content.AbstractTableMerger android.content.AsyncQueryHandler$WorkerHandler +android.content.BroadcastReceiver +android.content.ComponentCallbacks android.content.ComponentName android.content.ComponentName$1 android.content.ContentProvider$Transport @@ -70,23 +81,36 @@ android.content.ContentServiceProxy android.content.ContentValues android.content.Context android.content.ContextWrapper +android.content.DialogInterface +android.content.DialogInterface$OnCancelListener +android.content.DialogInterface$OnDismissListener android.content.IContentProvider android.content.Intent +android.content.Intent$1 android.content.IntentFilter +android.content.SearchRecentSuggestionsProvider +android.content.ServiceConnection +android.content.SharedPreferences android.content.SyncResult android.content.SyncResult$1 android.content.SyncStats android.content.SyncStats$1 +android.content.SyncableContentProvider android.content.UriMatcher android.content.pm.ActivityInfo android.content.pm.ActivityInfo$1 android.content.pm.ApplicationInfo +android.content.pm.ApplicationInfo$1 android.content.pm.ComponentInfo android.content.pm.IPackageManager android.content.pm.IPackageManager$Stub android.content.pm.IPackageManager$Stub$Proxy +android.content.pm.InstrumentationInfo +android.content.pm.InstrumentationInfo$1 android.content.pm.PackageItemInfo android.content.pm.PackageManager +android.content.pm.PackageManager$NameNotFoundException +android.content.pm.PermissionInfo android.content.pm.ProviderInfo android.content.pm.ProviderInfo$1 android.content.pm.ResolveInfo$1 @@ -104,10 +128,13 @@ android.content.res.XmlBlock android.content.res.XmlBlock$Parser android.database.AbstractCursor android.database.AbstractCursor$SelfContentObserver +android.database.AbstractWindowedCursor +android.database.BulkCursorNative android.database.BulkCursorProxy android.database.BulkCursorToCursorAdaptor android.database.ContentObservable android.database.ContentObserver$Transport +android.database.Cursor android.database.CursorToBulkCursorAdaptor android.database.CursorToBulkCursorAdaptor$ContentObserverProxy android.database.CursorWindow @@ -117,12 +144,15 @@ android.database.IContentObserver$Stub$Proxy android.database.MergeCursor android.database.sqlite.SQLiteCursor android.database.sqlite.SQLiteDatabase +android.database.sqlite.SQLiteDatabase$CursorFactory android.database.sqlite.SQLiteDirectCursorDriver android.database.sqlite.SQLiteQuery android.database.sqlite.SQLiteStatement android.ddm.DdmHandleAppName +android.ddm.DdmHandleExit android.ddm.DdmHandleHeap android.ddm.DdmHandleHello +android.ddm.DdmHandleNativeHeap android.ddm.DdmHandleThread android.ddm.DdmRegister android.graphics.Bitmap @@ -151,6 +181,7 @@ android.graphics.Shader android.graphics.Shader$TileMode android.graphics.Typeface android.graphics.Xfermode +android.graphics.drawable.AnimationDrawable android.graphics.drawable.BitmapDrawable android.graphics.drawable.BitmapDrawable$BitmapState android.graphics.drawable.ColorDrawable @@ -159,8 +190,8 @@ android.graphics.drawable.Drawable android.graphics.drawable.DrawableContainer android.graphics.drawable.GradientDrawable android.graphics.drawable.LayerDrawable -android.graphics.drawable.LayerDrawable$LayerState android.graphics.drawable.LayerDrawable$ChildDrawable +android.graphics.drawable.LayerDrawable$LayerState android.graphics.drawable.NinePatchDrawable android.graphics.drawable.NinePatchDrawable$NinePatchState android.graphics.drawable.PaintDrawable @@ -175,7 +206,10 @@ android.graphics.drawable.StateListDrawable$StateListState android.graphics.drawable.TransitionDrawable android.graphics.drawable.TransitionDrawable$TransitionState android.graphics.drawable.shapes.RoundRectShape +android.hardware.SensorManager +android.inputmethodservice.KeyboardView android.location.ILocationManager$Stub +android.location.Location android.media.AudioManager android.net.LocalSocket android.net.LocalSocketAddress @@ -185,10 +219,16 @@ android.net.LocalSocketImpl$SocketInputStream android.net.LocalSocketImpl$SocketOutputStream android.net.NetworkConnectivityListener$State android.net.NetworkInfo +android.net.NetworkInfo$DetailedState +android.net.SSLCertificateSocketFactory android.net.Uri +android.net.Uri$1 +android.net.Uri$AbstractHierarchicalUri +android.net.Uri$AbstractPart android.net.Uri$HierarchicalUri android.net.Uri$OpaqueUri android.net.Uri$Part +android.net.Uri$Part$EmptyPart android.net.Uri$PathPart android.net.Uri$PathSegments android.net.Uri$StringUri @@ -197,14 +237,22 @@ android.net.http.AndroidHttpClient android.net.http.AndroidHttpClient$1 android.net.http.AndroidHttpClient$2 android.net.http.AndroidHttpClient$CurlLogger +android.net.http.DomainNameChecker +android.net.http.CertificateChainValidator android.net.http.EventHandler android.net.http.HttpsConnection android.net.http.RequestQueue +android.net.http.SslError +android.net.wifi.IWifiManager$Stub +android.net.wifi.SupplicantState +android.net.wifi.WifiConfiguration +android.net.wifi.WifiInfo android.opengl.Material android.os.Binder android.os.BinderProxy android.os.Build android.os.Bundle +android.os.Bundle$1 android.os.Environment android.os.FileUtils android.os.Handler @@ -212,7 +260,9 @@ android.os.HandlerThread android.os.IBinder android.os.IHardwareService$Stub android.os.IHardwareService$Stub$Proxy +android.os.IPowerManager$Stub android.os.IPowerManager$Stub$Proxy +android.os.IServiceManager android.os.Looper android.os.Message android.os.Message$1 @@ -229,40 +279,24 @@ android.os.ServiceManager android.os.ServiceManagerNative android.os.ServiceManagerProxy android.os.Vibrator -android.text.format.DateUtils -android.text.format.Time +android.preference.CheckBoxPreference android.preference.DialogPreference +android.preference.EditTextPreference android.preference.ListPreference android.preference.Preference android.preference.PreferenceActivity android.preference.PreferenceGroup android.preference.PreferenceGroupAdapter +android.preference.PreferenceManager android.preference.PreferenceScreen -android.provider.Browser -android.provider.Calendar$CalendarAlerts -android.provider.Calendar$Instances -android.provider.Checkin$Events$Tag -android.provider.Checkin$Stats$Tag -android.provider.Gmail -android.provider.Gmail$CursorStatus -android.provider.Gmail$LabelMap -android.provider.Gmail$LabelMap$1 -android.provider.Gmail$MessageCursor -android.provider.Gmail$PersonalLevel -android.provider.MediaStore$Audio$Artists -android.provider.MediaStore$Audio$Media -android.provider.MediaStore$Images$Media -android.provider.Settings$Gservices -android.provider.Settings$NameValueCache -android.provider.Settings$Secure -android.provider.Settings$System -android.provider.Sync$Settings$QueryMap -android.provider.Telephony$MmsSms$PendingMessages -android.provider.Telephony$Threads +android.preference.RingtonePreference +android.sax.RootElement android.server.search.SearchableInfo android.server.search.SearchableInfo$1 android.telephony.PhoneNumberUtils +android.telephony.PhoneStateListener android.telephony.ServiceState +android.telephony.TelephonyManager android.telephony.gsm.SmsManager android.telephony.gsm.SmsMessage android.text.AutoText @@ -270,25 +304,48 @@ android.text.BoringLayout android.text.BoringLayout$Metrics android.text.DynamicLayout android.text.DynamicLayout$ChangeWatcher +android.text.Editable android.text.Editable$Factory +android.text.GetChars +android.text.GraphicsOperations android.text.Html$HtmlParser +android.text.InputFilter android.text.Layout +android.text.Layout$Alignment +android.text.Layout$Directions android.text.Layout$Ellipsizer +android.text.NoCopySpan +android.text.NoCopySpan$Concrete android.text.PackedIntVector android.text.PackedObjectVector +android.text.ParcelableSpan android.text.Selection +android.text.Selection$END +android.text.Selection$START +android.text.SpanWatcher +android.text.Spannable android.text.Spannable$Factory android.text.SpannableString android.text.SpannableStringBuilder +android.text.SpannableStringInternal +android.text.Spanned android.text.SpannedString android.text.StaticLayout android.text.Styled android.text.TextPaint android.text.TextUtils +android.text.TextUtils$1 +android.text.TextUtils$EllipsizeCallback +android.text.TextUtils$SimpleStringSplitter android.text.TextUtils$TruncateAt +android.text.TextWatcher +android.text.format.DateUtils +android.text.format.Time android.text.method.ArrowKeyMovementMethod android.text.method.BaseKeyListener +android.text.method.KeyListener android.text.method.MetaKeyKeyListener +android.text.method.MovementMethod android.text.method.QwertyKeyListener android.text.method.ReplacementTransformationMethod android.text.method.ReplacementTransformationMethod$SpannedReplacementCharSequence @@ -298,29 +355,43 @@ android.text.method.TextKeyListener$Capitalize android.text.method.TextKeyListener$SettingsObserver android.text.method.TransformationMethod android.text.style.AlignmentSpan +android.text.style.CharacterStyle android.text.style.ForegroundColorSpan android.text.style.LeadingMarginSpan android.text.style.LineBackgroundSpan android.text.style.LineHeightSpan +android.text.style.MetricAffectingSpan android.text.style.ParagraphStyle android.text.style.ReplacementSpan android.text.style.StyleSpan +android.text.style.URLSpan +android.text.style.UpdateAppearance +android.text.style.UpdateLayout android.text.style.WrapTogetherSpan android.text.util.Linkify +android.text.util.Regex android.util.AndroidRuntimeException android.util.AttributeSet android.util.DisplayMetrics android.util.FloatMath android.util.SparseArray android.util.TypedValue +android.util.Xml$XmlSerializerFactory android.view.AbsSavedState +android.view.ContextMenu +android.view.ContextMenu$ContextMenuInfo android.view.ContextThemeWrapper android.view.Display android.view.FocusFinder android.view.FocusFinder$1 +android.view.GestureDetector$SimpleOnGestureListener +android.view.Gravity +android.view.IWindow android.view.IWindow$Stub +android.view.IWindowManager android.view.IWindowManager$Stub android.view.IWindowManager$Stub$Proxy +android.view.IWindowSession android.view.IWindowSession$Stub android.view.IWindowSession$Stub$Proxy android.view.KeyCharacterMap @@ -328,8 +399,12 @@ android.view.KeyEvent android.view.KeyEvent$1 android.view.KeyEvent$Callback android.view.LayoutInflater +android.view.LayoutInflater$Factory +android.view.Menu android.view.MenuInflater +android.view.MenuItem android.view.MotionEvent +android.view.MotionEvent$1 android.view.Surface android.view.SurfaceHolder android.view.SurfaceView @@ -338,21 +413,33 @@ android.view.VelocityTracker android.view.View android.view.View$AttachInfo android.view.View$AttachInfo$Callbacks +android.view.View$BaseSavedState android.view.View$BaseSavedState$1 android.view.View$MeasureSpec +android.view.View$OnCreateContextMenuListener android.view.View$ScrollabilityCache +android.view.ViewConfiguration android.view.ViewGroup +android.view.ViewGroup$LayoutParams android.view.ViewGroup$MarginLayoutParams +android.view.ViewManager android.view.ViewRoot android.view.ViewRoot$1 +android.view.ViewRoot$InputMethodCallback +android.view.ViewRoot$RunQueue android.view.ViewRoot$TrackballAxis android.view.ViewRoot$W android.view.ViewStub android.view.ViewTreeObserver +android.view.ViewTreeObserver$InternalInsetsInfo +android.view.ViewTreeObserver$OnPreDrawListener android.view.Window +android.view.Window$Callback android.view.Window$LocalWindowManager android.view.WindowLeaked +android.view.WindowManager android.view.WindowManager$LayoutParams +android.view.WindowManager$LayoutParams$1 android.view.WindowManagerImpl android.view.animation.AccelerateDecelerateInterpolator android.view.animation.AlphaAnimation @@ -361,41 +448,45 @@ android.view.animation.AnimationSet android.view.animation.LinearInterpolator android.view.animation.Transformation android.view.inputmethod.BaseInputConnection -android.view.inputmethod.CompletionInfo$1 android.view.inputmethod.CompletionInfo -android.view.inputmethod.EditorInfo$1 +android.view.inputmethod.CompletionInfo$1 android.view.inputmethod.EditorInfo -android.view.inputmethod.ExtractedText$1 +android.view.inputmethod.EditorInfo$1 android.view.inputmethod.ExtractedText -android.view.inputmethod.ExtractedTextRequest$1 +android.view.inputmethod.ExtractedText$1 android.view.inputmethod.ExtractedTextRequest -android.view.inputmethod.InputBinding$1 +android.view.inputmethod.ExtractedTextRequest$1 android.view.inputmethod.InputBinding +android.view.inputmethod.InputBinding$1 android.view.inputmethod.InputConnection -android.view.inputmethod.InputMethod$SessionCallback android.view.inputmethod.InputMethod -android.view.inputmethod.InputMethodInfo$1 +android.view.inputmethod.InputMethod$SessionCallback android.view.inputmethod.InputMethodInfo +android.view.inputmethod.InputMethodInfo$1 +android.view.inputmethod.InputMethodManager android.view.inputmethod.InputMethodManager$1 android.view.inputmethod.InputMethodManager$2 android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper -android.view.inputmethod.InputMethodManager -android.view.inputmethod.InputMethodSession$EventCallback +android.view.inputmethod.InputMethodManager$H android.view.inputmethod.InputMethodSession +android.view.inputmethod.InputMethodSession$EventCallback android.webkit.BrowserFrame android.webkit.CacheManager android.webkit.CallbackProxy android.webkit.CookieManager android.webkit.CookieSyncManager +android.webkit.HttpDateTime android.webkit.JWebCoreJavaBridge android.webkit.LoadListener android.webkit.MimeTypeMap android.webkit.TextDialog +android.webkit.URLUtil android.webkit.WebBackForwardList android.webkit.WebHistoryItem android.webkit.WebIconDatabase android.webkit.WebIconDatabase$EventHandler android.webkit.WebIconDatabase$EventHandler$1 +android.webkit.WebIconDatabase$EventHandler$IconResult android.webkit.WebSettings android.webkit.WebSettings$EventHandler android.webkit.WebSettings$EventHandler$1 @@ -405,6 +496,7 @@ android.webkit.WebSettings$TextSize android.webkit.WebSyncManager android.webkit.WebSyncManager$SyncHandler android.webkit.WebView +android.webkit.WebView$ExtendedZoomControls android.webkit.WebView$FocusNode android.webkit.WebView$PrivateHandler android.webkit.WebViewCore @@ -428,6 +520,7 @@ android.widget.AbsoluteLayout android.widget.AbsoluteLayout$LayoutParams android.widget.AdapterView android.widget.AdapterView$AdapterDataSetObserver +android.widget.ArrayAdapter android.widget.AutoCompleteTextView android.widget.AutoCompleteTextView$DropDownItemClickListener android.widget.AutoCompleteTextView$DropDownListView @@ -446,7 +539,6 @@ android.widget.ExpandableListView android.widget.FrameLayout android.widget.FrameLayout$LayoutParams android.widget.Gallery -android.widget.GridView android.widget.HeaderViewListAdapter android.widget.ImageView android.widget.ImageView$ScaleType @@ -456,10 +548,10 @@ android.widget.ListView android.widget.ListView$ArrowScrollFocusResult android.widget.ListView$SavedState android.widget.ListView$SavedState$1 -android.widget.MediaController android.widget.PopupWindow android.widget.ProgressBar android.widget.RadioGroup +android.widget.RatingBar android.widget.RelativeLayout android.widget.RelativeLayout$LayoutParams android.widget.RemoteViews @@ -467,7 +559,10 @@ android.widget.ScrollBarDrawable android.widget.ScrollView android.widget.Scroller android.widget.SeekBar +android.widget.SimpleCursorAdapter +android.widget.SlidingDrawer android.widget.Spinner +android.widget.Spinner$DropDownAdapter android.widget.TabHost android.widget.TabWidget android.widget.TableLayout @@ -483,15 +578,22 @@ android.widget.TextView$InputContentType android.widget.TextView$InputMethodState android.widget.TextView$Marquee android.widget.TextView$MenuHandler -android.widget.TextView$SavedState$1 android.widget.TextView$SavedState +android.widget.TextView$SavedState$1 android.widget.ToggleButton android.widget.TwoLineListItem -android.widget.VideoView android.widget.ViewAnimator android.widget.ViewSwitcher android.widget.ZoomButton android.widget.ZoomControls +com.android.internal.database.ArrayListCursor +com.android.internal.database.SortCursor +com.android.internal.appwidget.IAppWidgetService$Stub +com.android.internal.http.multipart.FilePart +com.android.internal.http.multipart.MultipartEntity +com.android.internal.http.multipart.Part +com.android.internal.http.multipart.PartSource +com.android.internal.http.multipart.StringPart com.android.internal.logging.AndroidConfig com.android.internal.logging.AndroidHandler com.android.internal.os.AndroidPrintStream @@ -499,55 +601,92 @@ com.android.internal.os.BinderInternal$GcWatcher com.android.internal.os.LoggingPrintStream com.android.internal.os.LoggingPrintStream$1 com.android.internal.os.RuntimeInit +com.android.internal.os.RuntimeInit$1 com.android.internal.os.RuntimeInit$UncaughtHandler com.android.internal.os.ZygoteInit$MethodAndArgsCaller +com.android.internal.policy.IPolicy com.android.internal.policy.PolicyManager +com.android.internal.policy.impl.PhoneLayoutInflater +com.android.internal.policy.impl.PhoneWindow +com.android.internal.policy.impl.PhoneWindow$1 +com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback +com.android.internal.policy.impl.PhoneWindow$DecorView +com.android.internal.policy.impl.PhoneWindow$PanelFeatureState +com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState +com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState$1 +com.android.internal.policy.impl.Policy +com.android.internal.telephony.Connection$DisconnectCause +com.android.internal.telephony.Connection$PostDialState +com.android.internal.telephony.IPhoneStateListener$Stub +com.android.internal.telephony.ITelephony$Stub com.android.internal.telephony.Phone com.android.internal.telephony.Phone$DataActivityState com.android.internal.telephony.Phone$DataState com.android.internal.telephony.Phone$State +com.android.internal.telephony.Phone$SuppService com.android.internal.telephony.PhoneBase com.android.internal.telephony.PhoneStateIntentReceiver com.android.internal.telephony.SimCard$State com.android.internal.telephony.gsm.BaseCommands +com.android.internal.telephony.gsm.CallForwardInfo com.android.internal.telephony.gsm.CommandsInterface +com.android.internal.telephony.gsm.DriverCall +com.android.internal.telephony.gsm.DriverCall$State +com.android.internal.telephony.gsm.GSMConnection com.android.internal.telephony.gsm.GSMPhone com.android.internal.telephony.gsm.GsmAlphabet +com.android.internal.telephony.gsm.GsmMmiCode com.android.internal.telephony.gsm.GsmSimCard com.android.internal.telephony.gsm.ISms$Stub com.android.internal.telephony.gsm.PdpConnection$PdpFailCause com.android.internal.telephony.gsm.RIL com.android.internal.telephony.gsm.ServiceStateTracker -com.android.internal.view.menu.MenuDialogHelper +com.android.internal.telephony.gsm.stk.ComprehensionTlvTag +com.android.internal.telephony.gsm.stk.ResultCode +com.android.internal.util.FastXmlSerializer +com.android.internal.view.IInputConnectionWrapper com.android.internal.view.IInputConnectionWrapper$MyHandler com.android.internal.view.IInputConnectionWrapper$SomeArgs -com.android.internal.view.IInputConnectionWrapper -com.android.internal.view.IInputContext$Stub$Proxy -com.android.internal.view.IInputContext$Stub com.android.internal.view.IInputContext -com.android.internal.view.IInputContextCallback$Stub$Proxy -com.android.internal.view.IInputContextCallback$Stub +com.android.internal.view.IInputContext$Stub +com.android.internal.view.IInputContext$Stub$Proxy com.android.internal.view.IInputContextCallback -com.android.internal.view.IInputMethod$Stub$Proxy -com.android.internal.view.IInputMethod$Stub +com.android.internal.view.IInputContextCallback$Stub +com.android.internal.view.IInputContextCallback$Stub$Proxy com.android.internal.view.IInputMethod -com.android.internal.view.IInputMethodCallback$Stub$Proxy -com.android.internal.view.IInputMethodCallback$Stub +com.android.internal.view.IInputMethod$Stub +com.android.internal.view.IInputMethod$Stub$Proxy com.android.internal.view.IInputMethodCallback -com.android.internal.view.IInputMethodClient$Stub$Proxy -com.android.internal.view.IInputMethodClient$Stub +com.android.internal.view.IInputMethodCallback$Stub +com.android.internal.view.IInputMethodCallback$Stub$Proxy com.android.internal.view.IInputMethodClient -com.android.internal.view.IInputMethodManager$Stub$Proxy -com.android.internal.view.IInputMethodManager$Stub +com.android.internal.view.IInputMethodClient$Stub +com.android.internal.view.IInputMethodClient$Stub$Proxy com.android.internal.view.IInputMethodManager -com.android.internal.view.IInputMethodSession$Stub$Proxy -com.android.internal.view.IInputMethodSession$Stub +com.android.internal.view.IInputMethodManager$Stub +com.android.internal.view.IInputMethodManager$Stub$Proxy com.android.internal.view.IInputMethodSession -com.android.internal.view.InputBindResult$1 +com.android.internal.view.IInputMethodSession$Stub +com.android.internal.view.IInputMethodSession$Stub$Proxy com.android.internal.view.InputBindResult -com.android.internal.view.InputConnectionWrapper$InputContextCallback +com.android.internal.view.InputBindResult$1 com.android.internal.view.InputConnectionWrapper +com.android.internal.view.InputConnectionWrapper$InputContextCallback +com.android.internal.view.menu.ExpandedMenuView +com.android.internal.view.menu.IconMenuItemView +com.android.internal.view.menu.IconMenuView +com.android.internal.view.menu.ListMenuItemView +com.android.internal.view.menu.MenuBuilder +com.android.internal.view.menu.MenuBuilder$Callback +com.android.internal.view.menu.MenuDialogHelper +com.android.internal.view.menu.MenuItemImpl +com.android.internal.view.menu.SubMenuBuilder +com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient com.android.internal.widget.LockPatternView +com.android.internal.widget.NumberPicker +com.android.internal.widget.NumberPickerButton +com.google.android.gdata.client.AndroidGDataClient +com.google.android.gdata.client.AndroidGDataClient$PostRequestCreator com.google.android.gles_jni.EGLImpl com.google.android.gles_jni.GLImpl com.google.android.mms.ContentType @@ -557,9 +696,15 @@ com.google.android.mms.pdu.PduPersister com.google.android.net.GoogleHttpClient com.google.android.net.UrlRules com.google.android.net.UrlRules$Rule +com.google.android.util.SimplePullParser +com.google.common.Config +com.google.common.io.protocol.ProtoBuf +com.google.common.io.protocol.ProtoBufType +com.google.common.util.text.TextUtil com.ibm.icu4jni.charset.CharsetDecoderICU com.ibm.icu4jni.charset.CharsetEncoderICU com.ibm.icu4jni.charset.CharsetICU +com.ibm.icu4jni.text.CollationAttribute com.ibm.icu4jni.text.DecimalFormat com.ibm.icu4jni.text.DecimalFormatSymbols com.ibm.icu4jni.text.NativeDecimalFormat$UNumberFormatAttribute @@ -567,6 +712,9 @@ com.ibm.icu4jni.text.NativeDecimalFormat$UNumberFormatSymbol com.ibm.icu4jni.text.RuleBasedCollator dalvik.system.DexFile dalvik.system.PathClassLoader +java.beans.PropertyChangeEvent +java.beans.PropertyChangeListener +java.beans.PropertyChangeSupport java.io.BufferedInputStream java.io.ByteArrayInputStream java.io.ByteArrayOutputStream @@ -575,24 +723,36 @@ java.io.FileDescriptor java.io.FileInputStream java.io.FileInputStream$RepositioningLock java.io.FileNotFoundException +java.io.FilterInputStream +java.io.IOException +java.io.ObjectStreamClass java.io.PrintWriter java.io.RandomAccessFile java.io.RandomAccessFile$RepositionLock java.io.StringWriter +java.io.Writer java.lang.Character$valueOfCache java.lang.Class java.lang.ClassCache +java.lang.ClassNotFoundException +java.lang.IllegalArgumentException java.lang.IllegalStateException java.lang.Integer java.lang.Integer$valueOfCache +java.lang.LinkageError java.lang.Long java.lang.Long$valueOfCache +java.lang.NoClassDefFoundError +java.lang.NumberFormatException java.lang.Object java.lang.Runtime +java.lang.RuntimeException +java.lang.Short$valueOfCache java.lang.String java.lang.StringBuffer java.lang.StringBuilder java.lang.Thread +java.lang.ThreadLocal java.lang.ThreadLocal$Values java.lang.Throwable java.lang.VMThread @@ -606,12 +766,16 @@ java.math.BigDecimal java.math.BigInt java.math.BigInteger java.math.Multiplication +java.net.ContentHandler java.net.InetAddress java.net.InetAddress$CacheElement java.net.InetAddress$WaitReachable java.net.JarURLConnection java.net.NegativeCache +java.net.NetPermission +java.net.ProxySelectorImpl java.net.Socket$ConnectLock +java.net.URI java.net.URL java.net.URLConnection java.net.URLConnection$DefaultContentHandler @@ -622,17 +786,23 @@ java.nio.DirectByteBuffer java.nio.ReadWriteDirectByteBuffer java.nio.ReadWriteIntArrayBuffer java.nio.ReadWriteShortArrayBuffer +java.nio.ShortBuffer java.nio.ShortToByteBufferAdapter java.nio.charset.CharsetEncoder java.security.AccessControlContext +java.security.GeneralSecurityException java.security.KeyStore +java.security.MessageDigest java.security.ProtectionDomain +java.security.Provider java.security.SecureRandom java.security.Security java.security.cert.CertPathValidator java.security.cert.CertificateFactory java.security.cert.PKIXParameters java.security.cert.TrustAnchor +java.security.cert.X509CertSelector +java.security.cert.X509Certificate java.text.Collator java.text.DateFormat java.text.DateFormat$Field @@ -649,18 +819,30 @@ java.util.Arrays java.util.Arrays$ArrayList java.util.Calendar java.util.Collections$SynchronizedCollection +java.util.Collections$UnmodifiableList java.util.Collections$UnmodifiableMap +java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$1 java.util.Date +java.util.EnumMap +java.util.EventListener +java.util.EventObject java.util.Formatter java.util.GregorianCalendar java.util.HashMap java.util.HashMap$1 java.util.HashMap$2 +java.util.HashMap$2$1 java.util.HashMap$Entry +java.util.HashMap$HashMapEntrySet +java.util.HashMap$HashMapEntrySet$1 java.util.HashSet java.util.Hashtable +java.util.Hashtable$4 +java.util.Hashtable$4$1 java.util.Hashtable$Entry +java.util.Hashtable$HashEnumerator java.util.Hashtable$HashIterator +java.util.IdentityHashMap java.util.LinkedHashMap java.util.LinkedHashMap$LinkedHashMapEntry java.util.LinkedList @@ -668,6 +850,7 @@ java.util.LinkedList$Link java.util.List java.util.Locale java.util.Properties +java.util.Random java.util.ResourceBundle java.util.SimpleTimeZone java.util.TimeZone @@ -677,45 +860,91 @@ java.util.TreeSet java.util.Vector java.util.WeakHashMap java.util.WeakHashMap$Entry +java.util.concurrent.ConcurrentHashMap +java.util.concurrent.ConcurrentLinkedQueue +java.util.concurrent.DelayQueue +java.util.concurrent.LinkedBlockingQueue +java.util.concurrent.ScheduledThreadPoolExecutor +java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue java.util.concurrent.TimeUnit java.util.concurrent.atomic.AtomicBoolean java.util.concurrent.atomic.AtomicInteger +java.util.concurrent.atomic.UnsafeAccess java.util.concurrent.locks.AbstractQueuedSynchronizer java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject java.util.concurrent.locks.AbstractQueuedSynchronizer$Node +java.util.concurrent.locks.Lock java.util.concurrent.locks.LockSupport java.util.concurrent.locks.ReentrantLock java.util.concurrent.locks.ReentrantLock$FairSync java.util.concurrent.locks.ReentrantLock$NonfairSync java.util.concurrent.locks.ReentrantLock$Sync +java.util.concurrent.locks.ReentrantReadWriteLock +java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync +java.util.concurrent.locks.UnsafeAccess java.util.jar.Attributes java.util.jar.Attributes$Name +java.util.jar.InitManifest +java.util.jar.JarEntry java.util.jar.JarFile +java.util.jar.JarFile$1JarFileEnumerator +java.util.jar.JarFile$JarFileInputStream +java.util.jar.JarVerifier java.util.jar.Manifest java.util.logging.ErrorManager +java.util.logging.Formatter +java.util.logging.Handler java.util.logging.Level java.util.logging.LogManager +java.util.logging.LogManager$1 +java.util.logging.LogManager$2 +java.util.logging.LogManager$2$1 +java.util.logging.LogManager$3 java.util.logging.LogRecord java.util.logging.Logger java.util.logging.LoggingPermission java.util.logging.SimpleFormatter java.util.regex.Matcher java.util.regex.Pattern +java.util.zip.DeflaterOutputStream +java.util.zip.Inflater +java.util.zip.InflaterInputStream +java.util.zip.ZipConstants java.util.zip.ZipEntry +java.util.zip.ZipEntry$LittleEndianReader java.util.zip.ZipFile +java.util.zip.ZipFile$2 +java.util.zip.ZipFile$RAFStream javax.microedition.khronos.egl.EGLContext javax.net.ssl.HttpsURLConnection +javax.net.ssl.SSLHandshakeException javax.security.auth.x500.X500Principal +javax.security.cert.X509Certificate javax.security.cert.X509Certificate$2 junit.framework.Assert +org.apache.commons.codec.binary.Base64 +org.apache.commons.codec.binary.Hex +org.apache.commons.logging.LogFactory org.apache.commons.logging.impl.Jdk14Logger +org.apache.harmony.archive.util.Util org.apache.harmony.dalvik.ddmc.Chunk org.apache.harmony.dalvik.ddmc.ChunkHandler org.apache.harmony.dalvik.ddmc.DdmServer +org.apache.harmony.dalvik.ddmc.DdmVmInternal +org.apache.harmony.luni.internal.net.www.protocol.file.FileURLConnection +org.apache.harmony.luni.internal.net.www.protocol.file.Handler +org.apache.harmony.luni.internal.net.www.protocol.http.Handler +org.apache.harmony.luni.internal.net.www.protocol.https.Handler org.apache.harmony.luni.internal.net.www.protocol.jar.Handler org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection +org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$1 +org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$CacheEntry +org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$JarURLConnectionInputStream +org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$LRUComparator +org.apache.harmony.luni.internal.util.TimezoneGetter org.apache.harmony.luni.internal.util.ZoneInfo org.apache.harmony.luni.internal.util.ZoneInfoDB +org.apache.harmony.luni.net.PlainSocketImpl org.apache.harmony.luni.net.PlainSocketImpl2 org.apache.harmony.luni.platform.PlatformAddress org.apache.harmony.luni.util.TwoKeyHashMap @@ -732,6 +961,7 @@ org.apache.harmony.security.asn1.ASN1Implicit org.apache.harmony.security.asn1.ASN1Integer org.apache.harmony.security.asn1.ASN1OctetString org.apache.harmony.security.asn1.ASN1SetOf +org.apache.harmony.security.asn1.ASN1StringType org.apache.harmony.security.asn1.ASN1StringType$1 org.apache.harmony.security.asn1.ASN1StringType$2 org.apache.harmony.security.asn1.ASN1StringType$3 @@ -742,14 +972,18 @@ org.apache.harmony.security.asn1.ASN1StringType$7 org.apache.harmony.security.asn1.ASN1UTCTime org.apache.harmony.security.asn1.BitString org.apache.harmony.security.fortress.Engine +org.apache.harmony.security.fortress.SecurityUtils org.apache.harmony.security.fortress.Services +org.apache.harmony.security.pkcs7.ContentInfo org.apache.harmony.security.provider.cert.X509CertFactoryImpl org.apache.harmony.security.provider.cert.X509CertImpl org.apache.harmony.security.provider.cert.X509CertPathImpl +org.apache.harmony.security.provider.crypto.RandomBitsSupplier org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl org.apache.harmony.security.utils.AlgNameMapper org.apache.harmony.security.x501.AttributeTypeAndValue org.apache.harmony.security.x501.AttributeValue +org.apache.harmony.security.x501.DirectoryString org.apache.harmony.security.x501.DirectoryString$1 org.apache.harmony.security.x501.Name org.apache.harmony.security.x501.Name$1 @@ -764,36 +998,45 @@ org.apache.harmony.security.x509.Extension$1 org.apache.harmony.security.x509.Extension$2 org.apache.harmony.security.x509.Extensions org.apache.harmony.security.x509.Extensions$1 +org.apache.harmony.security.x509.GeneralName +org.apache.harmony.security.x509.GeneralNames org.apache.harmony.security.x509.KeyUsage +org.apache.harmony.security.x509.ORAddress org.apache.harmony.security.x509.SubjectPublicKeyInfo org.apache.harmony.security.x509.SubjectPublicKeyInfo$1 org.apache.harmony.security.x509.TBSCertificate org.apache.harmony.security.x509.TBSCertificate$1 +org.apache.harmony.security.x509.Time org.apache.harmony.security.x509.Time$1 org.apache.harmony.security.x509.Validity org.apache.harmony.security.x509.Validity$1 org.apache.harmony.xml.ExpatParser org.apache.harmony.xml.ExpatPullParser org.apache.harmony.xml.ExpatReader +org.apache.harmony.xnet.provider.jsse.ClientSessionContext org.apache.harmony.xnet.provider.jsse.OpenSSLSessionImpl org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl +org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$Finalizer org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream +org.apache.harmony.xnet.provider.jsse.SSLContextImpl org.apache.harmony.xnet.provider.jsse.SSLParameters -org.apache.harmony.xnet.provider.jsse.ClientSessionContext org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl org.apache.harmony.xnet.provider.jsse.TrustManagerImpl org.apache.http.HttpHost +org.apache.http.HttpRequestInterceptor org.apache.http.HttpVersion org.apache.http.auth.AuthSchemeRegistry org.apache.http.client.HttpClient org.apache.http.client.RequestDirector +org.apache.http.client.methods.HttpRequestBase org.apache.http.client.protocol.RequestAddCookies org.apache.http.client.protocol.RequestDefaultHeaders org.apache.http.client.protocol.RequestProxyAuthentication org.apache.http.client.protocol.RequestTargetAuthentication org.apache.http.client.protocol.ResponseProcessCookies org.apache.http.conn.params.ConnManagerParams$1 +org.apache.http.conn.params.ConnRouteParams org.apache.http.conn.routing.HttpRoute org.apache.http.conn.routing.RouteInfo$LayerType org.apache.http.conn.routing.RouteInfo$TunnelType @@ -805,11 +1048,13 @@ org.apache.http.conn.ssl.AllowAllHostnameVerifier org.apache.http.conn.ssl.BrowserCompatHostnameVerifier org.apache.http.conn.ssl.SSLSocketFactory org.apache.http.conn.ssl.StrictHostnameVerifier +org.apache.http.conn.util.InetAddressUtils org.apache.http.cookie.CookieSpecRegistry org.apache.http.impl.DefaultConnectionReuseStrategy org.apache.http.impl.DefaultHttpResponseFactory org.apache.http.impl.EnglishReasonPhraseCatalog org.apache.http.impl.HttpConnectionMetricsImpl +org.apache.http.impl.SocketHttpClientConnection org.apache.http.impl.auth.BasicSchemeFactory org.apache.http.impl.auth.DigestSchemeFactory org.apache.http.impl.client.AbstractAuthenticationHandler @@ -821,6 +1066,8 @@ org.apache.http.impl.client.DefaultProxyAuthenticationHandler org.apache.http.impl.client.DefaultRedirectHandler org.apache.http.impl.client.DefaultTargetAuthenticationHandler org.apache.http.impl.client.DefaultUserTokenHandler +org.apache.http.impl.client.EntityEnclosingRequestWrapper +org.apache.http.impl.conn.AbstractClientConnAdapter org.apache.http.impl.conn.DefaultClientConnection org.apache.http.impl.conn.DefaultClientConnectionOperator org.apache.http.impl.conn.DefaultHttpRoutePlanner @@ -832,8 +1079,10 @@ org.apache.http.impl.conn.tsccm.ConnPoolByRoute org.apache.http.impl.conn.tsccm.RefQueueWorker org.apache.http.impl.conn.tsccm.RouteSpecificPool org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager +org.apache.http.impl.cookie.BasicClientCookie org.apache.http.impl.cookie.BestMatchSpecFactory org.apache.http.impl.cookie.BrowserCompatSpecFactory +org.apache.http.impl.cookie.DateUtils org.apache.http.impl.cookie.NetscapeDraftSpecFactory org.apache.http.impl.cookie.RFC2109SpecFactory org.apache.http.impl.cookie.RFC2965SpecFactory @@ -846,10 +1095,13 @@ org.apache.http.impl.io.HttpTransportMetricsImpl org.apache.http.impl.io.SocketInputBuffer org.apache.http.impl.io.SocketOutputBuffer org.apache.http.message.BasicHeaderValueParser +org.apache.http.message.BasicHttpEntityEnclosingRequest +org.apache.http.message.BasicHttpResponse org.apache.http.message.BasicLineFormatter org.apache.http.message.BasicLineParser org.apache.http.params.BasicHttpParams org.apache.http.protocol.BasicHttpProcessor +org.apache.http.protocol.HTTP org.apache.http.protocol.HttpRequestExecutor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList @@ -860,9 +1112,12 @@ org.apache.http.protocol.RequestTargetHost org.apache.http.protocol.RequestUserAgent org.apache.http.util.ByteArrayBuffer org.apache.http.util.CharArrayBuffer +org.apache.http.util.EntityUtils +org.apache.http.util.VersionInfo org.bouncycastle.asn1.DERBitString org.bouncycastle.asn1.DERIA5String org.bouncycastle.asn1.DERInteger +org.bouncycastle.asn1.DERObject org.bouncycastle.asn1.DERObjectIdentifier org.bouncycastle.asn1.DEROctetString org.bouncycastle.asn1.DERPrintableString @@ -872,8 +1127,10 @@ org.bouncycastle.asn1.DERTaggedObject org.bouncycastle.asn1.DERUTCTime org.bouncycastle.asn1.DERUTF8String org.bouncycastle.asn1.OrderedTable +org.bouncycastle.asn1.nist.NISTObjectIdentifiers org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers org.bouncycastle.asn1.x509.AlgorithmIdentifier +org.bouncycastle.asn1.x509.RSAPublicKeyStructure org.bouncycastle.asn1.x509.SubjectPublicKeyInfo org.bouncycastle.asn1.x509.TBSCertificateStructure org.bouncycastle.asn1.x509.Time @@ -883,15 +1140,25 @@ org.bouncycastle.asn1.x509.X509Extensions org.bouncycastle.asn1.x509.X509Name org.bouncycastle.asn1.x509.X509NameElementList org.bouncycastle.asn1.x9.X9ObjectIdentifiers +org.bouncycastle.crypto.engines.AESFastEngine +org.bouncycastle.jce.provider.CertPathValidatorUtilities +org.bouncycastle.jce.provider.JCEBlockCipher$AES org.bouncycastle.jce.provider.JCERSAPublicKey org.bouncycastle.jce.provider.JDKKeyFactory$RSA org.bouncycastle.jce.provider.JDKKeyStore org.bouncycastle.jce.provider.JDKKeyStore$StoreEntry org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi +org.bouncycastle.jce.provider.RSAUtil org.bouncycastle.jce.provider.X509CertificateObject org.ccil.cowan.tagsoup.HTMLScanner org.ccil.cowan.tagsoup.Parser +org.json.JSONArray +org.json.JSONObject +org.json.JSONStringer org.kxml2.io.KXmlParser +org.kxml2.io.KXmlSerializer org.xml.sax.helpers.DefaultHandler org.xml.sax.helpers.NewInstance +org.xmlpull.v1.XmlPullParserFactory org.xmlpull.v1.sax2.Driver +sun.misc.Unsafe diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index 618b317..4188005 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -176,6 +176,9 @@ class BatteryService extends Binder { private synchronized final void update() { native_update(); + boolean logOutlier = false; + long dischargeDuration = 0; + mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL; if (mAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; @@ -199,13 +202,12 @@ class BatteryService extends Binder { // There's no value in this data unless we've discharged at least once and the // battery level has changed; so don't log until it does. if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryLevel) { - long duration = SystemClock.elapsedRealtime() - mDischargeStartTime; - EventLog.writeEvent(LOG_BATTERY_DISCHARGE_STATUS, duration, + dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; + logOutlier = true; + EventLog.writeEvent(LOG_BATTERY_DISCHARGE_STATUS, dischargeDuration, mDischargeStartLevel, mBatteryLevel); // make sure we see a discharge event before logging again mDischargeStartTime = 0; - - logOutlier(duration); } } else if (mPlugType == BATTERY_PLUGGED_NONE) { // charging -> discharging or we just powered up @@ -231,7 +233,8 @@ class BatteryService extends Binder { mPlugType == BATTERY_PLUGGED_NONE) { // We want to make sure we log discharge cycle outliers // if the battery is about to die. - logOutlier(SystemClock.elapsedRealtime() - mDischargeStartTime); + dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; + logOutlier = true; } // Separate broadcast is sent for power connected / not connected @@ -254,6 +257,11 @@ class BatteryService extends Binder { mLastBatteryLevelCritical = mBatteryLevelCritical; sendIntent(); + + // This needs to be done after sendIntent() so that we get the lastest battery stats. + if (logOutlier && dischargeDuration != 0) { + logOutlier(dischargeDuration); + } } } @@ -262,7 +270,7 @@ class BatteryService extends Binder { Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); try { - mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE); + mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE, mBatteryLevel); } catch (RemoteException e) { // Should never happen. } diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java index 2131ffd..42367ef 100755 --- a/services/java/com/android/server/HardwareService.java +++ b/services/java/com/android/server/HardwareService.java @@ -21,8 +21,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.os.Handler; import android.os.Hardware; import android.os.IHardwareService; +import android.os.Message; import android.os.Power; import android.os.PowerManager; import android.os.Process; @@ -35,11 +37,26 @@ import android.util.Log; public class HardwareService extends IHardwareService.Stub { private static final String TAG = "HardwareService"; + static final int LIGHT_ID_BACKLIGHT = 0; + static final int LIGHT_ID_KEYBOARD = 1; + static final int LIGHT_ID_BUTTONS = 2; + static final int LIGHT_ID_BATTERY = 3; + static final int LIGHT_ID_NOTIFICATIONS = 4; + static final int LIGHT_ID_ATTENTION = 5; + + static final int LIGHT_FLASH_NONE = 0; + static final int LIGHT_FLASH_TIMED = 1; + + private boolean mAttentionLightOn; + private boolean mPulsing; + HardwareService(Context context) { // Reset the hardware to a default state, in case this is a runtime // restart instead of a fresh boot. vibratorOff(); + mNativePointer = init_native(); + mContext = context; PowerManager pm = (PowerManager)context.getSystemService( Context.POWER_SERVICE); @@ -51,9 +68,18 @@ public class HardwareService extends IHardwareService.Stub { context.registerReceiver(mIntentReceiver, filter); } + protected void finalize() throws Throwable { + finalize_native(mNativePointer); + super.finalize(); + } + public void vibrate(long milliseconds) { - vibratePattern(new long[] { 0, milliseconds }, -1, - new Binder()); + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires VIBRATE permission"); + } + doCancelVibrate(); + vibratorOn(milliseconds); } private boolean isAll0(long[] pattern) { @@ -164,40 +190,80 @@ public class HardwareService extends IHardwareService.Stub { Hardware.enableCameraFlash(milliseconds); } - public void setScreenBacklight(int brightness) { + public void setBacklights(int brightness) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires HARDWARE_TEST permission"); } // Don't let applications turn the screen all the way off brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); - Hardware.setScreenBacklight(brightness); + setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness); + setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness); + setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness); } - public void setKeyboardBacklight(boolean on) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires HARDWARE_TEST permission"); - } - Hardware.setKeyboardBacklight(on); + void setLightOff_UNCHECKED(int light) { + setLight_native(mNativePointer, light, 0, LIGHT_FLASH_NONE, 0, 0); } - public void setButtonBacklight(boolean on) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires HARDWARE_TEST permission"); + void setLightBrightness_UNCHECKED(int light, int brightness) { + int b = brightness & 0x000000ff; + b = 0xff000000 | (b << 16) | (b << 8) | b; + setLight_native(mNativePointer, light, b, LIGHT_FLASH_NONE, 0, 0); + } + + void setLightColor_UNCHECKED(int light, int color) { + setLight_native(mNativePointer, light, color, LIGHT_FLASH_NONE, 0, 0); + } + + void setLightFlashing_UNCHECKED(int light, int color, int mode, int onMS, int offMS) { + setLight_native(mNativePointer, light, color, mode, onMS, offMS); + } + + public void setAttentionLight(boolean on) { + // Not worthy of a permission. We shouldn't have a flashlight permission. + synchronized (this) { + mAttentionLightOn = on; + mPulsing = false; + setLight_native(mNativePointer, LIGHT_ID_ATTENTION, on ? 0xffffffff : 0, + LIGHT_FLASH_NONE, 0, 0); } - Hardware.setButtonBacklight(on); } - public void setLedState(int colorARGB, int onMS, int offMS) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires HARDWARE_TEST permission"); + public void pulseBreathingLight() { + synchronized (this) { + // HACK: Added at the last minute of cupcake -- design this better; + // Don't reuse the attention light -- make another one. + if (false) { + Log.d(TAG, "pulseBreathingLight mAttentionLightOn=" + mAttentionLightOn + + " mPulsing=" + mPulsing); + } + if (!mAttentionLightOn && !mPulsing) { + mPulsing = true; + setLight_native(mNativePointer, LIGHT_ID_ATTENTION, 0xff101010, + LIGHT_FLASH_NONE, 0, 0); + mH.sendMessageDelayed(Message.obtain(mH, 1), 3000); + } } - Hardware.setLedState(colorARGB, onMS, offMS); } + private Handler mH = new Handler() { + @Override + public void handleMessage(Message msg) { + synchronized (this) { + if (false) { + Log.d(TAG, "pulse cleanup handler firing mPulsing=" + mPulsing); + } + if (mPulsing) { + mPulsing = false; + setLight_native(mNativePointer, LIGHT_ID_ATTENTION, + mAttentionLightOn ? 0xffffffff : 0, + LIGHT_FLASH_NONE, 0, 0); + } + } + } + }; + private void doCancelVibrate() { synchronized (this) { if (mThread != null) { @@ -206,8 +272,8 @@ public class HardwareService extends IHardwareService.Stub { mThread.notify(); } mThread = null; - vibratorOff(); } + vibratorOff(); } } @@ -315,6 +381,12 @@ public class HardwareService extends IHardwareService.Stub { } } }; + + private static native int init_native(); + private static native void finalize_native(int ptr); + + private static native void setLight_native(int ptr, int light, int color, int mode, + int onMS, int offMS); private Context mContext; private PowerManager.WakeLock mWakeLock; @@ -323,6 +395,8 @@ public class HardwareService extends IHardwareService.Stub { volatile Death mDeath; volatile IBinder mToken; + private int mNativePointer; + native static void vibratorOn(long milliseconds); native static void vibratorOff(); } diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java index 855734d..c9066be 100644 --- a/services/java/com/android/server/HeadsetObserver.java +++ b/services/java/com/android/server/HeadsetObserver.java @@ -98,12 +98,12 @@ class HeadsetObserver extends UEventObserver { sendIntent(isUnplug); if (isUnplug) { - // It often takes >200ms to flush the audio pipeline after apps - // pause audio playback, but audio route changes are immediate, - // so delay the route change by 400ms. + // It can take hundreds of ms flush the audio pipeline after + // apps pause audio playback, but audio route changes are + // immediate, so delay the route change by 1000ms. // This could be improved once the audio sub-system provides an // interface to clear the audio pipeline. - mHandler.sendEmptyMessageDelayed(0, 400); + mHandler.sendEmptyMessageDelayed(0, 1000); } else { updateAudioRoute(); } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 9948322..4198154 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -308,6 +308,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mScreenOn = true; } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { mScreenOn = false; + } else if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) { + hideInputMethodMenu(); + return; } else { Log.w(TAG, "Unexpected intent " + intent); } @@ -436,6 +439,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub IntentFilter screenOnOffFilt = new IntentFilter(); screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON); screenOnOffFilt.addAction(Intent.ACTION_SCREEN_OFF); + screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt); buildInputMethodListLocked(mMethodList, mMethodMap); @@ -585,6 +589,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + mCurClient.pid + " uid " + mCurClient.uid); } mCurClient = null; + + hideInputMethodMenuLocked(); } } @@ -820,6 +826,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurToken = null; } + mCurId = null; clearCurMethodLocked(); if (reportToClient && mCurClient != null) { @@ -896,10 +903,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub setInputMethodLocked(id); } catch (IllegalArgumentException e) { Log.w(TAG, "Unknown input method from prefs: " + id, e); + mCurMethodId = null; unbindCurrentMethodLocked(true); } } else { // There is no longer an input method set, so stop any current one. + mCurMethodId = null; unbindCurrentMethodLocked(true); } } @@ -1436,18 +1445,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } void hideInputMethodMenu() { + synchronized (mMethodMap) { + hideInputMethodMenuLocked(); + } + } + + void hideInputMethodMenuLocked() { if (DEBUG) Log.v(TAG, "Hide switching menu"); - synchronized (mMethodMap) { - if (mSwitchingDialog != null) { - mSwitchingDialog.dismiss(); - mSwitchingDialog = null; - } - - mDialogBuilder = null; - mItems = null; - mIms = null; + if (mSwitchingDialog != null) { + mSwitchingDialog.dismiss(); + mSwitchingDialog = null; } + + mDialogBuilder = null; + mItems = null; + mIms = null; } // ---------------------------------------------------------------------- @@ -1584,7 +1597,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } p.println(" mInputMethodIcon=" + mInputMethodIcon); p.println(" mInputMethodData=" + mInputMethodData); - p.println(" mCurrentMethod=" + mCurMethodId); + p.println(" mCurMethodId=" + mCurMethodId); client = mCurClient; p.println(" mCurClient=" + client + " mCurSeq=" + mCurSeq); p.println(" mCurFocusedWindow=" + mCurFocusedWindow); diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java index 63b486c..411cd6b 100644 --- a/services/java/com/android/server/KeyInputQueue.java +++ b/services/java/com/android/server/KeyInputQueue.java @@ -176,7 +176,7 @@ public abstract class KeyInputQueue { keycode, repeatCount, device != null ? device.mMetaKeysState : 0, device != null ? device.id : -1, scancode, - flags); + flags | KeyEvent.FLAG_FROM_SYSTEM); } Thread mThread = new Thread("InputDeviceReader") { diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index e48e047..5abf249 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -86,6 +86,7 @@ import com.android.server.am.BatteryStatsService; public class LocationManagerService extends ILocationManager.Stub implements INetworkLocationManager { private static final String TAG = "LocationManagerService"; + private static final boolean LOCAL_LOGV = false; // Minimum time interval between last known location writes, in milliseconds. private static final long MIN_LAST_KNOWN_LOCATION_TIME = 60L * 1000L; @@ -338,8 +339,8 @@ public class LocationManagerService extends ILocationManager.Stub } public void binderDied() { - if (Config.LOGD) { - Log.d(TAG, "Location listener died"); + if (LOCAL_LOGV) { + Log.v(TAG, "Location listener died"); } synchronized (mLocationListeners) { removeUpdatesLocked(this); @@ -486,9 +487,9 @@ public class LocationManagerService extends ILocationManager.Stub String name = subdirs[i].getName(); - if (Config.LOGD) { - Log.d(TAG, "Found dir " + subdirs[i].getAbsolutePath()); - Log.d(TAG, "name = " + name); + if (LOCAL_LOGV) { + Log.v(TAG, "Found dir " + subdirs[i].getAbsolutePath()); + Log.v(TAG, "name = " + name); } // Don't create a fake provider if a real provider exists @@ -551,8 +552,8 @@ public class LocationManagerService extends ILocationManager.Stub mContext = context; mLocationHandler = new LocationWorkerHandler(); - if (Config.LOGD) { - Log.d(TAG, "Constructed LocationManager Service"); + if (LOCAL_LOGV) { + Log.v(TAG, "Constructed LocationManager Service"); } // Alarm manager, needs to be done before calling loadProviders() below @@ -731,8 +732,8 @@ public class LocationManagerService extends ILocationManager.Stub } private List<String> _getAllProvidersLocked() { - if (Config.LOGD) { - Log.d(TAG, "getAllProviders"); + if (LOCAL_LOGV) { + Log.v(TAG, "getAllProviders"); } List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); ArrayList<String> out = new ArrayList<String>(providers.size()); @@ -751,14 +752,14 @@ public class LocationManagerService extends ILocationManager.Stub } catch (SecurityException se) { throw se; } catch (Exception e) { - Log.e(TAG, "getProviders gotString exception:", e); + Log.e(TAG, "getProviders got exception:", e); return null; } } private List<String> _getProvidersLocked(boolean enabledOnly) { - if (Config.LOGD) { - Log.d(TAG, "getProviders"); + if (LOCAL_LOGV) { + Log.v(TAG, "getProviders"); } List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); ArrayList<String> out = new ArrayList<String>(); @@ -990,8 +991,8 @@ public class LocationManagerService extends ILocationManager.Stub private void requestLocationUpdatesLocked(String provider, long minTime, float minDistance, Receiver receiver) { - if (Config.LOGD) { - Log.d(TAG, "_requestLocationUpdates: listener = " + receiver); + if (LOCAL_LOGV) { + Log.v(TAG, "_requestLocationUpdates: listener = " + receiver); } LocationProviderImpl impl = LocationProviderImpl.getProvider(provider); @@ -1088,8 +1089,8 @@ public class LocationManagerService extends ILocationManager.Stub } private void removeUpdatesLocked(Receiver receiver) { - if (Config.LOGD) { - Log.d(TAG, "_removeUpdates: listener = " + receiver); + if (LOCAL_LOGV) { + Log.v(TAG, "_removeUpdates: listener = " + receiver); } // so wakelock calls will succeed @@ -1292,8 +1293,8 @@ public class LocationManagerService extends ILocationManager.Stub boolean inProximity = alert.isInProximity(latitude, longitude); if (!entered && inProximity) { - if (Config.LOGD) { - Log.i(TAG, "Entered alert"); + if (LOCAL_LOGV) { + Log.v(TAG, "Entered alert"); } mProximitiesEntered.add(alert); Intent enteredIntent = new Intent(); @@ -1301,8 +1302,8 @@ public class LocationManagerService extends ILocationManager.Stub try { intent.send(mContext, 0, enteredIntent, null, null); } catch (PendingIntent.CanceledException e) { - if (Config.LOGD) { - Log.i(TAG, "Canceled proximity alert: " + alert, e); + if (LOCAL_LOGV) { + Log.v(TAG, "Canceled proximity alert: " + alert, e); } if (intentsToRemove == null) { intentsToRemove = new ArrayList<PendingIntent>(); @@ -1310,8 +1311,8 @@ public class LocationManagerService extends ILocationManager.Stub intentsToRemove.add(intent); } } else if (entered && !inProximity) { - if (Config.LOGD) { - Log.i(TAG, "Exited alert"); + if (LOCAL_LOGV) { + Log.v(TAG, "Exited alert"); } mProximitiesEntered.remove(alert); Intent exitedIntent = new Intent(); @@ -1319,8 +1320,8 @@ public class LocationManagerService extends ILocationManager.Stub try { intent.send(mContext, 0, exitedIntent, null, null); } catch (PendingIntent.CanceledException e) { - if (Config.LOGD) { - Log.i(TAG, "Canceled proximity alert: " + alert, e); + if (LOCAL_LOGV) { + Log.v(TAG, "Canceled proximity alert: " + alert, e); } if (intentsToRemove == null) { intentsToRemove = new ArrayList<PendingIntent>(); @@ -1330,8 +1331,8 @@ public class LocationManagerService extends ILocationManager.Stub } } else { // Mark alert for expiration - if (Config.LOGD) { - Log.i(TAG, "Expiring proximity alert: " + alert); + if (LOCAL_LOGV) { + Log.v(TAG, "Expiring proximity alert: " + alert); } if (intentsToRemove == null) { intentsToRemove = new ArrayList<PendingIntent>(); @@ -1387,8 +1388,8 @@ public class LocationManagerService extends ILocationManager.Stub private void addProximityAlertLocked(double latitude, double longitude, float radius, long expiration, PendingIntent intent) { - if (Config.LOGD) { - Log.d(TAG, "addProximityAlert: latitude = " + latitude + + if (LOCAL_LOGV) { + Log.v(TAG, "addProximityAlert: latitude = " + latitude + ", longitude = " + longitude + ", expiration = " + expiration + ", intent = " + intent); @@ -1439,8 +1440,8 @@ public class LocationManagerService extends ILocationManager.Stub } private void removeProximityAlertLocked(PendingIntent intent) { - if (Config.LOGD) { - Log.d(TAG, "removeProximityAlert: intent = " + intent); + if (LOCAL_LOGV) { + Log.v(TAG, "removeProximityAlert: intent = " + intent); } mProximityAlerts.remove(intent); diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index bc4b169..6ed8b4c 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -38,7 +38,6 @@ import android.os.BatteryManager; import android.os.Binder; import android.os.RemoteException; import android.os.Handler; -import android.os.Hardware; import android.os.IBinder; import android.os.Message; import android.os.Power; @@ -80,6 +79,7 @@ class NotificationManagerService extends INotificationManager.Stub private WorkerHandler mHandler; private StatusBarService mStatusBarService; + private HardwareService mHardware; private NotificationRecord mSoundNotification; private AsyncPlayer mSound; @@ -99,25 +99,11 @@ class NotificationManagerService extends INotificationManager.Stub private boolean mBatteryFull; private NotificationRecord mLedNotification; - // Low battery - red, blinking on 0.125s every 3 seconds - private static final int BATTERY_LOW_ARGB = 0xFFFF0000; - private static final int BATTERY_LOW_ON = 125; - private static final int BATTERY_LOW_OFF = 2875; - - // Charging Low - red solid on - private static final int CHARGING_LOW_ARGB = 0xFFFF0000; - private static final int CHARGING_LOW_ON = 0; - private static final int CHARGING_LOW_OFF = 0; - - // Charging - orange solid on - private static final int CHARGING_ARGB = 0xFFFFFF00; - private static final int CHARGING_ON = 0; - private static final int CHARGING_OFF = 0; - - // Charging Full - green solid on - private static final int CHARGING_FULL_ARGB = 0xFF00FF00; - private static final int CHARGING_FULL_ON = 0; - private static final int CHARGING_FULL_OFF = 0; + private static final int BATTERY_LOW_ARGB = 0xFFFF0000; // Charging Low - red solid on + private static final int BATTERY_MEDIUM_ARGB = 0xFFFFFF00; // Charging - orange solid on + private static final int BATTERY_FULL_ARGB = 0xFF00FF00; // Charging Full - green solid on + private static final int BATTERY_BLINK_ON = 125; + private static final int BATTERY_BLINK_OFF = 2875; // Tag IDs for EventLog. private static final int EVENT_LOG_ENQUEUE = 2750; @@ -326,10 +312,12 @@ class NotificationManagerService extends INotificationManager.Stub } }; - NotificationManagerService(Context context, StatusBarService statusBar) + NotificationManagerService(Context context, StatusBarService statusBar, + HardwareService hardware) { super(); mContext = context; + mHardware = hardware; mAm = ActivityManagerNative.getDefault(); mSound = new AsyncPlayer(TAG); mSound.setUsesWakeLock(context); @@ -600,6 +588,7 @@ class NotificationManagerService extends INotificationManager.Stub long identity = Binder.clearCallingIdentity(); try { r.statusBarKey = mStatusBarService.addIcon(icon, n); + mHardware.pulseBreathingLight(); } finally { Binder.restoreCallingIdentity(identity); @@ -830,35 +819,40 @@ class NotificationManagerService extends INotificationManager.Stub // lock on mNotificationList private void updateLightsLocked() { - // battery low has highest priority, then charging - if (mBatteryLow && !mBatteryCharging) { - Hardware.setLedState(BATTERY_LOW_ARGB, BATTERY_LOW_ON, BATTERY_LOW_OFF); + // Battery low always shows, other states only show if charging. + if (mBatteryLow) { + mHardware.setLightFlashing_UNCHECKED(HardwareService.LIGHT_ID_BATTERY, BATTERY_LOW_ARGB, + HardwareService.LIGHT_FLASH_TIMED, BATTERY_BLINK_ON, BATTERY_BLINK_OFF); } else if (mBatteryCharging) { - if (mBatteryLow) { - Hardware.setLedState(CHARGING_LOW_ARGB, CHARGING_LOW_ON, CHARGING_LOW_OFF); - } else if (mBatteryFull) { - Hardware.setLedState(CHARGING_FULL_ARGB, CHARGING_FULL_ON, CHARGING_FULL_OFF); + if (mBatteryFull) { + mHardware.setLightColor_UNCHECKED(HardwareService.LIGHT_ID_BATTERY, + BATTERY_FULL_ARGB); } else { - Hardware.setLedState(CHARGING_ARGB, CHARGING_ON, CHARGING_OFF); + mHardware.setLightColor_UNCHECKED(HardwareService.LIGHT_ID_BATTERY, + BATTERY_MEDIUM_ARGB); } } else { - // handle notification lights - if (mLedNotification == null) { - // get next notification, if any - int n = mLights.size(); - if (n > 0) { - mLedNotification = mLights.get(n-1); - } - } + mHardware.setLightOff_UNCHECKED(HardwareService.LIGHT_ID_BATTERY); + } - if (mLedNotification == null) { - Hardware.setLedState(0, 0, 0); - } else { - Hardware.setLedState(mLedNotification.notification.ledARGB, - mLedNotification.notification.ledOnMS, - mLedNotification.notification.ledOffMS); + // handle notification lights + if (mLedNotification == null) { + // get next notification, if any + int n = mLights.size(); + if (n > 0) { + mLedNotification = mLights.get(n-1); } } + if (mLedNotification == null) { + mHardware.setLightOff_UNCHECKED(HardwareService.LIGHT_ID_NOTIFICATIONS); + } else { + mHardware.setLightFlashing_UNCHECKED( + HardwareService.LIGHT_ID_NOTIFICATIONS, + mLedNotification.notification.ledARGB, + HardwareService.LIGHT_FLASH_TIMED, + mLedNotification.notification.ledOnMS, + mLedNotification.notification.ledOffMS); + } } // lock on mNotificationList diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 9f428e9..9e062f4 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -57,7 +57,6 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; -import android.content.pm.PackageParser.Package; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -129,6 +128,7 @@ class PackageManagerService extends IPackageManager.Stub { static final int SCAN_FORCE_DEX = 1<<2; static final int SCAN_UPDATE_SIGNATURE = 1<<3; static final int SCAN_FORWARD_LOCKED = 1<<4; + static final int SCAN_NEW_INSTALL = 1<<5; static final int LOG_BOOT_PROGRESS_PMS_START = 3060; static final int LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START = 3070; @@ -1948,7 +1948,7 @@ class PackageManagerService extends IPackageManager.Stub { } // The signature has changed, but this package is in the system // image... let's recover! - pkg.mSignatures = pkgSetting.signatures.mSignatures; + pkgSetting.signatures.mSignatures = pkg.mSignatures; // However... if this package is part of a shared user, but it // doesn't match the signature of the shared user, let's fail. // What this means is that you can't change the signatures @@ -1963,6 +1963,31 @@ class PackageManagerService extends IPackageManager.Stub { } removeExisting = true; } + + // Verify that this new package doesn't have any content providers + // that conflict with existing packages. Only do this if the + // package isn't already installed, since we don't want to break + // things that are installed. + if ((scanMode&SCAN_NEW_INSTALL) != 0) { + int N = pkg.providers.size(); + int i; + for (i=0; i<N; i++) { + PackageParser.Provider p = pkg.providers.get(i); + String names[] = p.info.authority.split(";"); + for (int j = 0; j < names.length; j++) { + if (mProviders.containsKey(names[j])) { + PackageParser.Provider other = mProviders.get(names[j]); + Log.w(TAG, "Can't install because provider name " + names[j] + + " (in package " + pkg.applicationInfo.packageName + + ") is already used by " + + ((other != null && other.component != null) + ? other.component.getPackageName() : "?")); + mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER; + return null; + } + } + } + } } if (removeExisting) { @@ -2181,9 +2206,12 @@ class PackageManagerService extends IPackageManager.Stub { ", className = " + p.info.name + ", isSyncable = " + p.info.isSyncable); } else { + PackageParser.Provider other = mProviders.get(names[j]); Log.w(TAG, "Skipping provider name " + names[j] + " (in package " + pkg.applicationInfo.packageName + - "): name already used"); + "): name already used by " + + ((other != null && other.component != null) + ? other.component.getPackageName() : "?")); } } if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { @@ -3205,7 +3233,7 @@ class PackageManagerService extends IPackageManager.Stub { mHandler.removeCallbacks(this); PackageInstalledInfo res; synchronized (mInstallLock) { - res = installPackageLI(packageURI, flags); + res = installPackageLI(packageURI, flags, true); } if (observer != null) { try { @@ -3220,12 +3248,18 @@ class PackageManagerService extends IPackageManager.Stub { res.removedInfo.sendBroadcast(false, true); Bundle extras = new Bundle(1); extras.putInt(Intent.EXTRA_UID, res.uid); - if (res.removedInfo.removedPackage != null) { + final boolean update = res.removedInfo.removedPackage != null; + if (update) { extras.putBoolean(Intent.EXTRA_REPLACING, true); } sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, res.pkg.applicationInfo.packageName, extras); + if (update) { + sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, + res.pkg.applicationInfo.packageName, + extras); + } } Runtime.getRuntime().gc(); } @@ -3246,7 +3280,7 @@ class PackageManagerService extends IPackageManager.Stub { private void installNewPackageLI(String pkgName, File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, - PackageParser.Package pkg, boolean forwardLocked, + PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, PackageInstalledInfo res) { // Remember this for later, in case we need to rollback this install boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists(); @@ -3270,7 +3304,8 @@ class PackageManagerService extends IPackageManager.Stub { destResourceFile, pkg, 0, SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE - | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)); + | (forwardLocked ? SCAN_FORWARD_LOCKED : 0) + | (newInstall ? SCAN_NEW_INSTALL : 0)); if (newPackage == null) { Log.w(TAG, "Package couldn't be installed in " + destPackageFile); if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) { @@ -3302,7 +3337,7 @@ class PackageManagerService extends IPackageManager.Stub { private void replacePackageLI(String pkgName, File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, - PackageParser.Package pkg, boolean forwardLocked, + PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, PackageInstalledInfo res) { PackageParser.Package deletedPackage; // First find the old package info and check signatures @@ -3317,17 +3352,19 @@ class PackageManagerService extends IPackageManager.Stub { if(sysPkg) { replaceSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath, - destPackageFile, destResourceFile, pkg, forwardLocked, res); + destPackageFile, destResourceFile, pkg, forwardLocked, + newInstall, res); } else { replaceNonSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath, - destPackageFile, destResourceFile, pkg, forwardLocked, res); + destPackageFile, destResourceFile, pkg, forwardLocked, + newInstall, res); } } private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage, File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, - PackageParser.Package pkg, boolean forwardLocked, + PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, PackageInstalledInfo res) { PackageParser.Package newPackage = null; String pkgName = deletedPackage.packageName; @@ -3347,7 +3384,8 @@ class PackageManagerService extends IPackageManager.Stub { destResourceFile, pkg, parseFlags, SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE - | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)); + | (forwardLocked ? SCAN_FORWARD_LOCKED : 0) + | (newInstall ? SCAN_NEW_INSTALL : 0)); if (newPackage == null) { Log.w(TAG, "Package couldn't be installed in " + destPackageFile); if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) { @@ -3404,7 +3442,7 @@ class PackageManagerService extends IPackageManager.Stub { Uri.fromFile(new File(deletedPackage.mPath)), isForwardLocked(deletedPackage) ? PackageManager.FORWARD_LOCK_PACKAGE - : 0); + : 0, false); } } } @@ -3412,7 +3450,7 @@ class PackageManagerService extends IPackageManager.Stub { private void replaceSystemPackageLI(PackageParser.Package deletedPackage, File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, - PackageParser.Package pkg, boolean forwardLocked, + PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, PackageInstalledInfo res) { PackageParser.Package newPackage = null; boolean updatedSettings = false; @@ -3450,7 +3488,8 @@ class PackageManagerService extends IPackageManager.Stub { destResourceFile, pkg, parseFlags, SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE - | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)); + | (forwardLocked ? SCAN_FORWARD_LOCKED : 0) + | (newInstall ? SCAN_NEW_INSTALL : 0)); if (newPackage == null) { Log.w(TAG, "Package couldn't be installed in " + destPackageFile); if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) { @@ -3484,8 +3523,7 @@ class PackageManagerService extends IPackageManager.Stub { oldPkgSetting.resourcePath, oldPkg, parseFlags, SCAN_MONITOR - | SCAN_UPDATE_SIGNATURE - | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)); + | SCAN_UPDATE_SIGNATURE); // Restore the old system information in Settings synchronized(mPackages) { if(updatedSettings) { @@ -3556,7 +3594,8 @@ class PackageManagerService extends IPackageManager.Stub { } } - private PackageInstalledInfo installPackageLI(Uri pPackageURI, int pFlags) { + private PackageInstalledInfo installPackageLI(Uri pPackageURI, + int pFlags, boolean newInstall) { File tmpPackageFile = null; String pkgName = null; boolean forwardLocked = false; @@ -3669,21 +3708,21 @@ class PackageManagerService extends IPackageManager.Stub { replacePackageLI(pkgName, tmpPackageFile, destFilePath, destPackageFile, destResourceFile, - pkg, forwardLocked, + pkg, forwardLocked, newInstall, res); } else { installNewPackageLI(pkgName, tmpPackageFile, destFilePath, destPackageFile, destResourceFile, - pkg, forwardLocked, + pkg, forwardLocked, newInstall, res); } } finally { if (tmpPackageFile != null && tmpPackageFile.exists()) { tmpPackageFile.delete(); } - return res; } + return res; } private int setPermissionsLI(String pkgName, @@ -3861,14 +3900,26 @@ class PackageManagerService extends IPackageManager.Stub { private boolean deletePackageX(String packageName, boolean sendBroadCast, boolean deleteCodeAndResources, int flags) { PackageRemovedInfo info = new PackageRemovedInfo(); - boolean res = false; + boolean res; synchronized (mInstallLock) { res = deletePackageLI(packageName, deleteCodeAndResources, flags, info); } if(res && sendBroadCast) { - info.sendBroadcast(deleteCodeAndResources, false); + boolean systemUpdate = info.isRemovedPackageSystemUpdate; + info.sendBroadcast(deleteCodeAndResources, systemUpdate); + + // If the removed package was a system update, the old system packaged + // was re-enabled; we need to broadcast this information + if (systemUpdate) { + Bundle extras = new Bundle(1); + extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid); + extras.putBoolean(Intent.EXTRA_REPLACING, true); + + sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras); + sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras); + } } return res; } @@ -3877,7 +3928,8 @@ class PackageManagerService extends IPackageManager.Stub { String removedPackage; int uid = -1; int removedUid = -1; - + boolean isRemovedPackageSystemUpdate = false; + void sendBroadcast(boolean fullRemove, boolean replacing) { Bundle extras = new Bundle(1); extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid); @@ -3963,6 +4015,7 @@ class PackageManagerService extends IPackageManager.Stub { Log.i(TAG, "Deleting system pkg from data partition"); } // Delete the updated package + outInfo.isRemovedPackageSystemUpdate = true; boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo); if (!ret) { return false; diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index ad30ffc..bbca401 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -135,8 +135,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private boolean mDoneBooting = false; private int mStayOnConditions = 0; - private int mNotificationQueue = -1; - private int mNotificationWhy; + private int[] mBroadcastQueue = new int[] { -1, -1, -1 }; + private int[] mBroadcastWhy = new int[3]; private int mPartialCount = 0; private int mPowerState; private boolean mOffBecauseOfUser; @@ -154,6 +154,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private final LockList mLocks = new LockList(); private Intent mScreenOffIntent; private Intent mScreenOnIntent; + private HardwareService mHardware; private Context mContext; private UnsynchronizedWakeLock mBroadcastWakeLock; private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock; @@ -164,11 +165,12 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private TimeoutTask mTimeoutTask = new TimeoutTask(); private LightAnimator mLightAnimator = new LightAnimator(); private final BrightnessState mScreenBrightness - = new BrightnessState(Power.SCREEN_LIGHT); + = new BrightnessState(SCREEN_BRIGHT_BIT); private final BrightnessState mKeyboardBrightness - = new BrightnessState(Power.KEYBOARD_LIGHT); + = new BrightnessState(KEYBOARD_BRIGHT_BIT); private final BrightnessState mButtonBrightness - = new BrightnessState(Power.BUTTON_LIGHT); + = new BrightnessState(BUTTON_BRIGHT_BIT); + private boolean mStillNeedSleepNotification; private boolean mIsPowered = false; private IActivityManager mActivityService; private IBatteryStats mBatteryStats; @@ -357,7 +359,9 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private ContentQueryMap mSettings; - void init(Context context, IActivityManager activity, BatteryService battery) { + void init(Context context, HardwareService hardware, IActivityManager activity, + BatteryService battery) { + mHardware = hardware; mContext = context; mActivityService = activity; mBatteryStats = BatteryStatsService.getService(); @@ -387,7 +391,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage mHandler = new Handler(); mBroadcastWakeLock = new UnsynchronizedWakeLock( - PowerManager.PARTIAL_WAKE_LOCK, "sleep_notification", true); + PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true); mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock( PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false); mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock( @@ -795,8 +799,10 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage + " mStayOnConditions=" + mStayOnConditions); pw.println(" mOffBecauseOfUser=" + mOffBecauseOfUser + " mUserState=" + mUserState); - pw.println(" mNotificationQueue=" + mNotificationQueue - + " mNotificationWhy=" + mNotificationWhy); + pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1] + + ',' + mBroadcastQueue[2] + "}"); + pw.println(" mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1] + + ',' + mBroadcastWhy[2] + "}"); pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet); pw.println(" mKeyboardVisible=" + mKeyboardVisible + " mUserActivityAllowed=" + mUserActivityAllowed); @@ -837,6 +843,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage pw.println(" poke lock '" + p.tag + "':" + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0 ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "") + + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0 + ? " POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS" : "") + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0 ? " POKE_LOCK_SHORT_TIMEOUT" : "") + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0 @@ -921,29 +929,56 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private void sendNotificationLocked(boolean on, int why) { - if (!on) { - mNotificationWhy = why; + mStillNeedSleepNotification = false; + } + + // Add to the queue. + int index = 0; + while (mBroadcastQueue[index] != -1) { + index++; + } + mBroadcastQueue[index] = on ? 1 : 0; + mBroadcastWhy[index] = why; + + // If we added it position 2, then there is a pair that can be stripped. + // If we added it position 1 and we're turning the screen off, we can strip + // the pair and do nothing, because the screen is already off, and therefore + // keyguard has already been enabled. + // However, if we added it at position 1 and we're turning it on, then position + // 0 was to turn it off, and we can't strip that, because keyguard needs to come + // on, so have to run the queue then. + if (index == 2) { + // Also, while we're collapsing them, if it's going to be an "off," and one + // is off because of user, then use that, regardless of whether it's the first + // or second one. + if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) { + mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER; + } + mBroadcastQueue[0] = on ? 1 : 0; + mBroadcastQueue[1] = -1; + mBroadcastQueue[2] = -1; + index = 0; + } + if (index == 1 && !on) { + mBroadcastQueue[0] = -1; + mBroadcastQueue[1] = -1; + index = -1; + // The wake lock was being held, but we're not actually going to do any + // broadcasts, so release the wake lock. + EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount); + mBroadcastWakeLock.release(); } - int value = on ? 1 : 0; - if (mNotificationQueue == -1) { - // empty + // Now send the message. + if (index >= 0) { // Acquire the broadcast wake lock before changing the power // state. It will be release after the broadcast is sent. + // We always increment the ref count for each notification in the queue + // and always decrement when that notification is handled. mBroadcastWakeLock.acquire(); EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount); - mNotificationQueue = value; mHandler.post(mNotificationTask); - } else if (mNotificationQueue != value) { - // it's a pair, so cancel it - mNotificationQueue = -1; - mHandler.removeCallbacks(mNotificationTask); - EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount); - mBroadcastWakeLock.release(); - } else { - // else, same so do nothing -- maybe we should warn? - Log.w(TAG, "Duplicate notification: on=" + on + " why=" + why); } } @@ -951,64 +986,69 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage { public void run() { - int value; - int why; - WindowManagerPolicy policy; - synchronized (mLocks) { - policy = getPolicyLocked(); - value = mNotificationQueue; - why = mNotificationWhy; - mNotificationQueue = -1; - } - if (value == 1) { - mScreenOnStart = SystemClock.uptimeMillis(); - - policy.screenTurnedOn(); - try { - ActivityManagerNative.getDefault().wakingUp(); - } catch (RemoteException e) { - // ignore it + while (true) { + int value; + int why; + WindowManagerPolicy policy; + synchronized (mLocks) { + value = mBroadcastQueue[0]; + why = mBroadcastWhy[0]; + for (int i=0; i<2; i++) { + mBroadcastQueue[i] = mBroadcastQueue[i+1]; + mBroadcastWhy[i] = mBroadcastWhy[i+1]; + } + policy = getPolicyLocked(); } + if (value == 1) { + mScreenOnStart = SystemClock.uptimeMillis(); + + policy.screenTurnedOn(); + try { + ActivityManagerNative.getDefault().wakingUp(); + } catch (RemoteException e) { + // ignore it + } - if (mSpew) { - Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock); - } - if (mContext != null && ActivityManagerNative.isSystemReady()) { - mContext.sendOrderedBroadcast(mScreenOnIntent, null, - mScreenOnBroadcastDone, mHandler, 0, null, null); - } else { - synchronized (mLocks) { - EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2, - mBroadcastWakeLock.mCount); - mBroadcastWakeLock.release(); + if (mSpew) { + Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock); + } + if (mContext != null && ActivityManagerNative.isSystemReady()) { + mContext.sendOrderedBroadcast(mScreenOnIntent, null, + mScreenOnBroadcastDone, mHandler, 0, null, null); + } else { + synchronized (mLocks) { + EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2, + mBroadcastWakeLock.mCount); + mBroadcastWakeLock.release(); + } } } - } - else if (value == 0) { - mScreenOffStart = SystemClock.uptimeMillis(); - - policy.screenTurnedOff(why); - try { - ActivityManagerNative.getDefault().goingToSleep(); - } catch (RemoteException e) { - // ignore it. - } + else if (value == 0) { + mScreenOffStart = SystemClock.uptimeMillis(); + + policy.screenTurnedOff(why); + try { + ActivityManagerNative.getDefault().goingToSleep(); + } catch (RemoteException e) { + // ignore it. + } - if (mContext != null && ActivityManagerNative.isSystemReady()) { - mContext.sendOrderedBroadcast(mScreenOffIntent, null, - mScreenOffBroadcastDone, mHandler, 0, null, null); - } else { - synchronized (mLocks) { - EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3, - mBroadcastWakeLock.mCount); - mBroadcastWakeLock.release(); + if (mContext != null && ActivityManagerNative.isSystemReady()) { + mContext.sendOrderedBroadcast(mScreenOffIntent, null, + mScreenOffBroadcastDone, mHandler, 0, null, null); + } else { + synchronized (mLocks) { + EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3, + mBroadcastWakeLock.mCount); + mBroadcastWakeLock.release(); + } } } - } - else { - // If we're in this case, then this handler is running for a previous - // paired transaction. mBroadcastWakeLock will already have been released - // in sendNotificationLocked. + else { + // If we're in this case, then this handler is running for a previous + // paired transaction. mBroadcastWakeLock will already have been released. + break; + } } } }; @@ -1226,15 +1266,20 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } if (mPowerState != newState) { - err = updateLightsLocked(newState, 0); - if (err != 0) { - return; - } + updateLightsLocked(newState, 0); mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK); } if (oldScreenOn != newScreenOn) { if (newScreenOn) { + // When the user presses the power button, we need to always send out the + // notification that it's going to sleep so the keyguard goes on. But + // we can't do that until the screen fades out, so we don't show the keyguard + // too early. + if (mStillNeedSleepNotification) { + sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER); + } + // Turn on the screen UNLESS there was a prior // preventScreenOn(true) request. (Note that the lifetime // of a single preventScreenOn() request is limited to 5 @@ -1290,7 +1335,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } mPowerState &= ~SCREEN_ON_BIT; if (!mScreenBrightness.animating) { - err = screenOffFinishedAnimating(becauseOfUser); + err = screenOffFinishedAnimatingLocked(becauseOfUser); } else { mOffBecauseOfUser = becauseOfUser; err = 0; @@ -1301,7 +1346,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } } - private int screenOffFinishedAnimating(boolean becauseOfUser) { + private int screenOffFinishedAnimatingLocked(boolean becauseOfUser) { // I don't think we need to check the current state here because all of these // Power.setScreenState and sendNotificationLocked can both handle being // called multiple times in the same state. -joeo @@ -1327,11 +1372,12 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD); } - private int updateLightsLocked(int newState, int forceState) { - int oldState = mPowerState; - int difference = (newState ^ oldState) | forceState; + private void updateLightsLocked(int newState, int forceState) { + final int oldState = mPowerState; + final int realDifference = (newState ^ oldState); + final int difference = realDifference | forceState; if (difference == 0) { - return 0; + return; } int offMask = 0; @@ -1345,17 +1391,19 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage if (ANIMATE_KEYBOARD_LIGHTS) { if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS); + ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, + preferredBrightness); } else { mKeyboardBrightness.setTargetLocked(preferredBrightness, - ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS); + ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, + Power.BRIGHTNESS_OFF); } startAnimation = true; } else { if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { - offMask |= Power.KEYBOARD_LIGHT; + offMask |= KEYBOARD_BRIGHT_BIT; } else { - onMask |= Power.KEYBOARD_LIGHT; + onMask |= KEYBOARD_BRIGHT_BIT; } } } @@ -1364,23 +1412,49 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage if (ANIMATE_BUTTON_LIGHTS) { if ((newState & BUTTON_BRIGHT_BIT) == 0) { mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS); + ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, + preferredBrightness); } else { mButtonBrightness.setTargetLocked(preferredBrightness, - ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS); + ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, + Power.BRIGHTNESS_OFF); } startAnimation = true; } else { if ((newState & BUTTON_BRIGHT_BIT) == 0) { - offMask |= Power.BUTTON_LIGHT; + offMask |= BUTTON_BRIGHT_BIT; } else { - onMask |= Power.BUTTON_LIGHT; + onMask |= BUTTON_BRIGHT_BIT; } } } if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { if (ANIMATE_SCREEN_LIGHTS) { + int nominalCurrentValue = -1; + // If there was an actual difference in the light state, then + // figure out the "ideal" current value based on the previous + // state. Otherwise, this is a change due to the brightness + // override, so we want to animate from whatever the current + // value is. + if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { + switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) { + case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT: + nominalCurrentValue = preferredBrightness; + break; + case SCREEN_ON_BIT: + nominalCurrentValue = Power.BRIGHTNESS_DIM; + break; + case 0: + nominalCurrentValue = Power.BRIGHTNESS_OFF; + break; + case SCREEN_BRIGHT_BIT: + default: + // not possible + nominalCurrentValue = (int)mScreenBrightness.curValue; + break; + } + } if ((newState & SCREEN_BRIGHT_BIT) == 0) { // dim or turn off backlight, depending on if the screen is on // the scale is because the brightness ramp isn't linear and this biases @@ -1398,7 +1472,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage steps = (int)(ANIM_STEPS*ratio*scale); } mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - steps, INITIAL_SCREEN_BRIGHTNESS); + steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); } else { int steps; if ((oldState & SCREEN_ON_BIT) != 0) { @@ -1417,23 +1491,23 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage mScreenOffTime = SystemClock.elapsedRealtime(); } mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_DIM, - steps, INITIAL_SCREEN_BRIGHTNESS); + steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); } } else { mScreenBrightness.setTargetLocked(preferredBrightness, - ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS); + ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); } startAnimation = true; } else { if ((newState & SCREEN_BRIGHT_BIT) == 0) { // dim or turn off backlight, depending on if the screen is on if ((newState & SCREEN_ON_BIT) == 0) { - offMask |= Power.SCREEN_LIGHT; + offMask |= SCREEN_BRIGHT_BIT; } else { - dimMask |= Power.SCREEN_LIGHT; + dimMask |= SCREEN_BRIGHT_BIT; } } else { - onMask |= Power.SCREEN_LIGHT; + onMask |= SCREEN_BRIGHT_BIT; } } } @@ -1446,10 +1520,9 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage mHandler.post(mLightAnimator); } - int err = 0; if (offMask != 0) { //Log.i(TAG, "Setting brightess off: " + offMask); - err |= Power.setLightBrightness(offMask, Power.BRIGHTNESS_OFF); + setLightBrightness(offMask, Power.BRIGHTNESS_OFF); } if (dimMask != 0) { int brightness = Power.BRIGHTNESS_DIM; @@ -1458,7 +1531,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage brightness = Power.BRIGHTNESS_LOW_BATTERY; } //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask); - err |= Power.setLightBrightness(dimMask, brightness); + setLightBrightness(dimMask, brightness); } if (onMask != 0) { int brightness = getPreferredBrightness(); @@ -1467,10 +1540,20 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage brightness = Power.BRIGHTNESS_LOW_BATTERY; } //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask); - err |= Power.setLightBrightness(onMask, brightness); + setLightBrightness(onMask, brightness); } + } - return err; + private void setLightBrightness(int mask, int value) { + if ((mask & SCREEN_BRIGHT_BIT) != 0) { + mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, value); + } + if ((mask & BUTTON_BRIGHT_BIT) != 0) { + mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, value); + } + if ((mask & KEYBOARD_BRIGHT_BIT) != 0) { + mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, value); + } } class BrightnessState { @@ -1493,16 +1576,22 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage + " delta=" + delta); } - void setTargetLocked(int target, int stepsToTarget, int initialValue) { + void setTargetLocked(int target, int stepsToTarget, int initialValue, + int nominalCurrentValue) { if (!initialized) { initialized = true; curValue = (float)initialValue; } targetValue = target; - delta = (targetValue-curValue) / stepsToTarget; + delta = (targetValue - + (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue)) + / stepsToTarget; if (mSpew) { + String noticeMe = nominalCurrentValue == curValue ? "" : " ******************"; Log.i(TAG, "Setting target " + mask + ": cur=" + curValue - + " target=" + targetValue + " delta=" + delta); + + " target=" + targetValue + " delta=" + delta + + " nominalCurrentValue=" + nominalCurrentValue + + noticeMe); } animating = true; } @@ -1517,6 +1606,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage int curIntValue = (int)curValue; boolean more = true; if (delta == 0) { + curValue = curIntValue = targetValue; more = false; } else if (delta > 0) { if (curIntValue >= targetValue) { @@ -1530,11 +1620,11 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } } //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask); - Power.setLightBrightness(mask, curIntValue); + setLightBrightness(mask, curIntValue); animating = more; if (!more) { - if (mask == Power.SCREEN_LIGHT && curIntValue == Power.BRIGHTNESS_OFF) { - screenOffFinishedAnimating(mOffBecauseOfUser); + if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) { + screenOffFinishedAnimatingLocked(mOffBecauseOfUser); } } return more; @@ -1602,13 +1692,23 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0) - && !((eventType == OTHER_EVENT) || (eventType == BUTTON_EVENT))) { + && (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) { if (false) { - Log.d(TAG, "dropping mPokey=0x" + Integer.toHexString(mPokey)); + Log.d(TAG, "dropping cheek or short event mPokey=0x" + Integer.toHexString(mPokey)); } return; } + if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0) + && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT + || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) { + if (false) { + Log.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey)); + } + return; + } + + if (false) { if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) { Log.d(TAG, "userActivity !!!");//, new RuntimeException()); @@ -1686,6 +1786,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } } EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared); + mStillNeedSleepNotification = true; mUserState = SCREEN_OFF; setPowerState(SCREEN_OFF, false, true); cancelTimerLocked(); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a629ec6..1f508a6 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -86,6 +86,7 @@ class ServerThread extends Thread { int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF : Integer.parseInt(factoryTestStr); + HardwareService hardware = null; PowerManagerService power = null; IPackageManager pm = null; Context context = null; @@ -127,9 +128,13 @@ class ServerThread extends Thread { BatteryService battery = new BatteryService(context); ServiceManager.addService("battery", battery); + Log.i(TAG, "Starting Hardware Service."); + hardware = new HardwareService(context); + ServiceManager.addService("hardware", hardware); + // only initialize the power service after we have started the - // content providers and the batter service. - power.init(context, ActivityManagerService.getDefault(), battery); + // hardware service, content providers and the battery service. + power.init(context, hardware, ActivityManagerService.getDefault(), battery); Log.i(TAG, "Starting Alarm Manager."); AlarmManagerService alarm = new AlarmManagerService(context); @@ -171,7 +176,7 @@ class ServerThread extends Thread { int bluetoothOn = Settings.Secure.getInt(mContentResolver, Settings.Secure.BLUETOOTH_ON, 0); if (bluetoothOn > 0) { - bluetooth.enable(null); + bluetooth.enable(); } } @@ -208,13 +213,6 @@ class ServerThread extends Thread { } try { - Log.i(TAG, "Starting Hardware Service."); - ServiceManager.addService("hardware", new HardwareService(context)); - } catch (Throwable e) { - Log.e(TAG, "Failure starting Hardware Service", e); - } - - try { Log.i(TAG, "Starting NetStat Service."); ServiceManager.addService("netstat", new NetStatService(context)); } catch (Throwable e) { @@ -232,7 +230,7 @@ class ServerThread extends Thread { try { Log.i(TAG, "Starting Notification Manager."); ServiceManager.addService(Context.NOTIFICATION_SERVICE, - new NotificationManagerService(context, statusBar)); + new NotificationManagerService(context, statusBar, hardware)); } catch (Throwable e) { Log.e(TAG, "Failure starting Notification Manager", e); } diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index a74915c..fa54421 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -440,6 +440,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } private void broadcastSignalStrengthChanged(int asu) { + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.notePhoneSignalStrength(asu); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED); intent.putExtra(PhoneStateIntentReceiver.INTENT_KEY_ASU, asu); mContext.sendStickyBroadcast(intent); @@ -469,6 +477,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private void broadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible, String reason, String apn, String interfaceName) { + // Note: not reporting to the battery stats service here, because the + // status bar takes care of that after taking into account all of the + // required info. Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString()); if (!isDataConnectivityPossible) { diff --git a/services/java/com/android/server/ViewServer.java b/services/java/com/android/server/ViewServer.java index 4201b39..07826a6 100644 --- a/services/java/com/android/server/ViewServer.java +++ b/services/java/com/android/server/ViewServer.java @@ -24,6 +24,9 @@ import java.net.InetAddress; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; /** * The ViewServer is local socket server that can be used to communicate with the @@ -41,7 +44,14 @@ class ViewServer implements Runnable { // Debug facility private static final String LOG_TAG = "ViewServer"; + private static final String VALUE_PROTOCOL_VERSION = "2"; + private static final String VALUE_SERVER_VERSION = "2"; + // Protocol commands + // Returns the protocol version + private static final String COMMAND_PROTOCOL_VERSION = "PROTOCOL"; + // Returns the server version + private static final String COMMAND_SERVER_VERSION = "SERVER"; // Lists all of the available windows in the system private static final String COMMAND_WINDOW_MANAGER_LIST = "LIST"; @@ -169,7 +179,11 @@ class ViewServer implements Runnable { } boolean result; - if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) { + if (COMMAND_PROTOCOL_VERSION.equalsIgnoreCase(command)) { + result = writeValue(client, VALUE_PROTOCOL_VERSION); + } else if (COMMAND_SERVER_VERSION.equalsIgnoreCase(command)) { + result = writeValue(client, VALUE_SERVER_VERSION); + } else if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) { result = mWindowManager.viewServerListWindows(client); } else { result = mWindowManager.viewServerWindowCommand(client, @@ -197,4 +211,28 @@ class ViewServer implements Runnable { } } } + + private static boolean writeValue(Socket client, String value) { + boolean result; + BufferedWriter out = null; + try { + OutputStream clientStream = client.getOutputStream(); + out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); + out.write(value); + out.write("\n"); + out.flush(); + result = true; + } catch (Exception e) { + result = false; + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + result = false; + } + } + } + return result; + } } diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index e298f49..6323e2f 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -62,6 +62,9 @@ import java.util.regex.Pattern; import java.io.FileDescriptor; import java.io.PrintWriter; +import com.android.internal.app.IBatteryStats; +import com.android.server.am.BatteryStatsService; + /** * WifiService handles remote WiFi operation requests by implementing * the IWifiManager interface. It also creates a WifiMonitor to listen @@ -86,6 +89,9 @@ public class WifiService extends IWifiManager.Stub { private int mPluggedType; private final LockList mLocks = new LockList(); + + private final IBatteryStats mBatteryStats; + /** * See {@link Settings.Gservices#WIFI_IDLE_MS}. This is the default value if a * Settings.Gservices value is not present. This timeout value is chosen as @@ -168,7 +174,8 @@ public class WifiService extends IWifiManager.Stub { WifiService(Context context, WifiStateTracker tracker) { mContext = context; mWifiStateTracker = tracker; - + mBatteryStats = BatteryStatsService.getService(); + /* * Initialize the hidden-networks state */ @@ -532,6 +539,18 @@ public class WifiService extends IWifiManager.Stub { private void setWifiEnabledState(int wifiState) { final int previousWifiState = mWifiState; + long ident = Binder.clearCallingIdentity(); + try { + if (wifiState == WIFI_STATE_ENABLED) { + mBatteryStats.noteWifiOn(); + } else if (wifiState == WIFI_STATE_DISABLED) { + mBatteryStats.noteWifiOff(); + } + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + // Update state mWifiState = wifiState; @@ -1828,6 +1847,19 @@ public class WifiService extends IWifiManager.Stub { private boolean acquireWifiLockLocked(WifiLock wifiLock) { mLocks.addLock(wifiLock); + + int uid = Binder.getCallingUid(); + long ident = Binder.clearCallingIdentity(); + try { + switch(wifiLock.mLockMode) { + case (WifiManager.WIFI_MODE_FULL): mBatteryStats.noteFullWifiLockAcquired(uid); + case (WifiManager.WIFI_MODE_SCAN_ONLY): mBatteryStats.noteScanWifiLockAcquired(uid); + } + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + updateWifiState(); return true; } @@ -1840,9 +1872,26 @@ public class WifiService extends IWifiManager.Stub { } private boolean releaseWifiLockLocked(IBinder lock) { - boolean result; - result = (mLocks.removeLock(lock) != null); + boolean hadLock; + + WifiLock wifiLock = mLocks.removeLock(lock); + hadLock = (wifiLock != null); + + if (hadLock) { + int uid = Binder.getCallingUid(); + long ident = Binder.clearCallingIdentity(); + try { + switch(wifiLock.mLockMode) { + case (WifiManager.WIFI_MODE_FULL): mBatteryStats.noteFullWifiLockReleased(uid); + case (WifiManager.WIFI_MODE_SCAN_ONLY): mBatteryStats.noteScanWifiLockReleased(uid); + } + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + } + updateWifiState(); - return result; + return hadLock; } } diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index e4bd3c3..2e16157 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -19,6 +19,8 @@ package com.android.server; import static android.os.LocalPowerManager.CHEEK_EVENT; import static android.os.LocalPowerManager.OTHER_EVENT; import static android.os.LocalPowerManager.TOUCH_EVENT; +import static android.os.LocalPowerManager.LONG_TOUCH_EVENT; +import static android.os.LocalPowerManager.TOUCH_UP_EVENT; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND; @@ -317,6 +319,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo int mRotation = 0; int mRequestedRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + int mLastRotationFlags; ArrayList<IRotationWatcher> mRotationWatchers = new ArrayList<IRotationWatcher>(); @@ -388,6 +391,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo final Rect mTempRect = new Rect(); + final Configuration mTempConfiguration = new Configuration(); + public static WindowManagerService main(Context context, PowerManagerService pm, boolean haveInputMethods) { WMThread thr = new WMThread(context, pm, haveInputMethods); @@ -1294,7 +1299,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // Update Orientation after adding a window, only if the window needs to be // displayed right away if (win.isVisibleOrAdding()) { - if (updateOrientationFromAppTokens(null) != null) { + if (updateOrientationFromAppTokens(null, null) != null) { sendNewConfiguration(); } } @@ -1663,7 +1668,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (assignLayers) { assignLayersLocked(); } - newConfig = updateOrientationFromAppTokensLocked(null); + newConfig = updateOrientationFromAppTokensLocked(null, null); performLayoutAndPlaceSurfacesLocked(); if (win.mAppToken != null) { win.mAppToken.updateReportedVisibilityLocked(); @@ -2079,6 +2084,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo while (pos >= 0) { AppWindowToken wtoken = mAppTokens.get(pos); pos--; + // if we're about to tear down this window, don't use it for orientation + if (!wtoken.hidden && wtoken.hiddenRequested) { + continue; + } + if (!haveGroup) { // We ignore any hidden applications on the top. if (wtoken.hiddenRequested || wtoken.willBeHidden) { @@ -2119,11 +2129,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } public Configuration updateOrientationFromAppTokens( - IBinder freezeThisOneIfNeeded) { + Configuration currentConfig, IBinder freezeThisOneIfNeeded) { Configuration config; long ident = Binder.clearCallingIdentity(); synchronized(mWindowMap) { - config = updateOrientationFromAppTokensLocked(freezeThisOneIfNeeded); + config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded); } if (config != null) { mLayoutNeeded = true; @@ -2141,7 +2151,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo * android.os.IBinder) */ Configuration updateOrientationFromAppTokensLocked( - IBinder freezeThisOneIfNeeded) { + Configuration appConfig, IBinder freezeThisOneIfNeeded) { boolean changed = false; long ident = Binder.clearCallingIdentity(); try { @@ -2157,7 +2167,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (changed) { changed = setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION); + WindowManagerPolicy.USE_LAST_ROTATION, + mLastRotationFlags & (~Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)); if (changed) { if (freezeThisOneIfNeeded != null) { AppWindowToken wtoken = findAppWindowToken( @@ -2167,7 +2178,19 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo ActivityInfo.CONFIG_ORIENTATION); } } - return computeNewConfiguration(); + return computeNewConfigurationLocked(); + } + } + + // No obvious action we need to take, but if our current + // state mismatches the activity maanager's, update it + if (appConfig != null) { + mTempConfiguration.setToDefaults(); + if (computeNewConfigurationLocked(mTempConfiguration)) { + if (appConfig.diff(mTempConfiguration) != 0) { + Log.i(TAG, "Config changed: " + mTempConfiguration); + return new Configuration(mTempConfiguration); + } } } } finally { @@ -2349,6 +2372,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo ttoken.startingWindow = null; ttoken.startingMoved = true; startingWindow.mToken = wtoken; + startingWindow.mRootToken = wtoken; startingWindow.mAppToken = wtoken; mWindows.remove(startingWindow); ttoken.windows.remove(startingWindow); @@ -3236,7 +3260,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo mPolicy.enableScreenAfterBoot(); // Make sure the last requested orientation has been applied. - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false); + setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, + mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); } public void setInTouchMode(boolean mode) { @@ -3246,23 +3271,24 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } public void setRotation(int rotation, - boolean alwaysSendConfiguration) { + boolean alwaysSendConfiguration, int animFlags) { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setOrientation()")) { + "setRotation()")) { return; } - setRotationUnchecked(rotation, alwaysSendConfiguration); + setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags); } - public void setRotationUnchecked(int rotation, boolean alwaysSendConfiguration) { + public void setRotationUnchecked(int rotation, + boolean alwaysSendConfiguration, int animFlags) { if(DEBUG_ORIENTATION) Log.v(TAG, "alwaysSendConfiguration set to "+alwaysSendConfiguration); long origId = Binder.clearCallingIdentity(); boolean changed; synchronized(mWindowMap) { - changed = setRotationUncheckedLocked(rotation); + changed = setRotationUncheckedLocked(rotation, animFlags); } if (changed) { @@ -3279,12 +3305,13 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo Binder.restoreCallingIdentity(origId); } - public boolean setRotationUncheckedLocked(int rotation) { + public boolean setRotationUncheckedLocked(int rotation, int animFlags) { boolean changed; if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) { rotation = mRequestedRotation; } else { mRequestedRotation = rotation; + mLastRotationFlags = animFlags; } if (DEBUG_ORIENTATION) Log.v(TAG, "Overwriting rotation value from " + rotation); rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, @@ -3304,9 +3331,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000); startFreezingDisplayLocked(); + Log.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); mQueue.setOrientation(rotation); if (mDisplayEnabled) { - Surface.setOrientation(0, rotation); + Surface.setOrientation(0, rotation, animFlags); } for (int i=mWindows.size()-1; i>=0; i--) { WindowState w = (WindowState)mWindows.get(i); @@ -3611,38 +3639,49 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo public Configuration computeNewConfiguration() { synchronized (mWindowMap) { - if (mDisplay == null) { - return null; - } - Configuration config = new Configuration(); - mQueue.getInputConfiguration(config); - final int dw = mDisplay.getWidth(); - final int dh = mDisplay.getHeight(); - int orientation = Configuration.ORIENTATION_SQUARE; - if (dw < dh) { - orientation = Configuration.ORIENTATION_PORTRAIT; - } else if (dw > dh) { - orientation = Configuration.ORIENTATION_LANDSCAPE; - } - config.orientation = orientation; - config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; - config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; - mPolicy.adjustConfigurationLw(config); - Log.i(TAG, "Input configuration changed: " + config); - long now = SystemClock.uptimeMillis(); - //Log.i(TAG, "Config changing, gc pending: " + mFreezeGcPending + ", now " + now); - if (mFreezeGcPending != 0) { - if (now > (mFreezeGcPending+1000)) { - //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000)); - mH.removeMessages(H.FORCE_GC); - Runtime.getRuntime().gc(); - mFreezeGcPending = now; - } - } else { + return computeNewConfigurationLocked(); + } + } + + Configuration computeNewConfigurationLocked() { + Configuration config = new Configuration(); + if (!computeNewConfigurationLocked(config)) { + return null; + } + Log.i(TAG, "Config changed: " + config); + long now = SystemClock.uptimeMillis(); + //Log.i(TAG, "Config changing, gc pending: " + mFreezeGcPending + ", now " + now); + if (mFreezeGcPending != 0) { + if (now > (mFreezeGcPending+1000)) { + //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000)); + mH.removeMessages(H.FORCE_GC); + Runtime.getRuntime().gc(); mFreezeGcPending = now; } - return config; + } else { + mFreezeGcPending = now; + } + return config; + } + + boolean computeNewConfigurationLocked(Configuration config) { + if (mDisplay == null) { + return false; } + mQueue.getInputConfiguration(config); + final int dw = mDisplay.getWidth(); + final int dh = mDisplay.getHeight(); + int orientation = Configuration.ORIENTATION_SQUARE; + if (dw < dh) { + orientation = Configuration.ORIENTATION_PORTRAIT; + } else if (dw > dh) { + orientation = Configuration.ORIENTATION_LANDSCAPE; + } + config.orientation = orientation; + config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; + config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; + mPolicy.adjustConfigurationLw(config); + return true; } // ------------------------------------------------------------- @@ -3664,6 +3703,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo private static final float CHEEK_THRESHOLD = 0.6f; private int mEventState = EVENT_NONE; private float mEventSize; + private int eventType(MotionEvent ev) { float size = ev.getSize(); switch (ev.getAction()) { @@ -3672,7 +3712,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT; case MotionEvent.ACTION_UP: if (size > mEventSize) mEventSize = size; - return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : OTHER_EVENT; + return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT; case MotionEvent.ACTION_MOVE: final int N = ev.getHistorySize(); if (size > mEventSize) mEventSize = size; @@ -3685,7 +3725,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) { return TOUCH_EVENT; } else { - return OTHER_EVENT; + return LONG_TOUCH_EVENT; } default: // not good @@ -4053,7 +4093,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (downTime == 0) downTime = eventTime; KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, - deviceId, scancode); + deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM); boolean result = dispatchKey(newEvent, Binder.getCallingPid(), Binder.getCallingUid()); if (sync) { @@ -5107,7 +5147,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (DEBUG_INPUT) Log.v( TAG, "Key repeat: count=" + keyRepeatCount + ", next @ " + nextKeyTime); - dispatchKey(new KeyEvent(lastKey, curTime, keyRepeatCount), 0, 0); + dispatchKey(KeyEvent.changeTimeRepeat(lastKey, curTime, keyRepeatCount), 0, 0); } else { curTime = SystemClock.uptimeMillis(); @@ -5361,6 +5401,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo final Session mSession; final IWindow mClient; WindowToken mToken; + WindowToken mRootToken; AppWindowToken mAppToken; AppWindowToken mTargetAppToken; final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); @@ -5573,6 +5614,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } appToken = parent; } + mRootToken = appToken; mAppToken = appToken.appWindowToken; mSurface = null; @@ -6231,7 +6273,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo */ boolean isVisibleNow() { return mSurface != null && mPolicyVisibility && !mAttachedHidden - && !mToken.hidden && !mExiting && !mDestroying; + && !mRootToken.hidden && !mExiting && !mDestroying; } /** @@ -6272,7 +6314,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo final AppWindowToken atoken = mAppToken; final boolean animating = atoken != null ? atoken.animating : false; return mSurface != null && mPolicyVisibility && !mDestroying - && ((!mAttachedHidden && !mToken.hidden) + && ((!mAttachedHidden && !mRootToken.hidden) || mAnimating || animating); } @@ -6431,6 +6473,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo + " mLastLayer=" + mLastLayer); pw.println(prefix + "mSurface=" + mSurface); pw.println(prefix + "mToken=" + mToken); + pw.println(prefix + "mRootToken=" + mRootToken); pw.println(prefix + "mAppToken=" + mAppToken); pw.println(prefix + "mTargetAppToken=" + mTargetAppToken); pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility) @@ -6939,7 +6982,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo public static final int REMOVE_STARTING = 6; public static final int FINISHED_STARTING = 7; public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; - public static final int UPDATE_ORIENTATION = 10; public static final int WINDOW_FREEZE_TIMEOUT = 11; public static final int HOLD_SCREEN_CHANGED = 12; public static final int APP_TRANSITION_TIMEOUT = 13; @@ -7167,11 +7209,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } } break; - case UPDATE_ORIENTATION: { - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false); - break; - } - case WINDOW_FREEZE_TIMEOUT: { synchronized (mWindowMap) { Log.w(TAG, "Window freeze timeout expired."); @@ -7279,7 +7316,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } case COMPUTE_AND_SEND_NEW_CONFIGURATION: { - if (updateOrientationFromAppTokens(null) != null) { + if (updateOrientationFromAppTokens(null, null) != null) { sendNewConfiguration(); } break; @@ -7458,7 +7495,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo boolean gone = win.mViewVisibility == View.GONE || !win.mRelayoutCalled - || win.mToken.hidden; + || win.mRootToken.hidden; // If this view is GONE, then skip it -- keep the current // frame, and let the caller know so they can ignore it @@ -7762,6 +7799,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo boolean blurring = false; boolean dimming = false; boolean covered = false; + boolean syswin = false; for (i=N-1; i>=0; i--) { WindowState w = (WindowState)mWindows.get(i); @@ -8021,9 +8059,15 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { holdScreen = w.mSession; } - if (w.mAttrs.screenBrightness >= 0 && screenBrightness < 0) { + if (!syswin && w.mAttrs.screenBrightness >= 0 + && screenBrightness < 0) { screenBrightness = w.mAttrs.screenBrightness; } + if (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG + || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD + || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR) { + syswin = true; + } } if (w.isFullscreenOpaque(dw, dh)) { // This window completely covers everything behind it, @@ -8507,6 +8551,15 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo private void startFreezingDisplayLocked() { if (mDisplayFrozen) { + // Freezing the display also suspends key event delivery, to + // keep events from going astray while the display is reconfigured. + // If someone has changed orientation again while the screen is + // still frozen, the events will continue to be blocked while the + // successive orientation change is processed. To prevent spurious + // ANRs, we reset the event dispatch timeout in this case. + synchronized (mKeyWaiter) { + mKeyWaiter.mWasFrozen = true; + } return; } @@ -8550,10 +8603,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } Surface.unfreezeDisplay(0); - // Freezing the display also suspends key event delivery, to - // keep events from going astray while the display is reconfigured. - // Now that we're back, notify the key waiter that we're alive - // again and it should restart its timeouts. + // Reset the key delivery timeout on unfreeze, too. We force a wakeup here + // too because regular key delivery processing should resume immediately. synchronized (mKeyWaiter) { mKeyWaiter.mWasFrozen = true; mKeyWaiter.notifyAll(); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 9d720d1..d676c00 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -121,6 +121,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen static final boolean DEBUG_VISBILITY = localLOGV || false; static final boolean DEBUG_PROCESSES = localLOGV || false; static final boolean DEBUG_USER_LEAVING = localLOGV || false; + static final boolean DEBUG_RESULTS = localLOGV || false; static final boolean VALIDATE_TOKENS = false; static final boolean SHOW_ACTIVITY_START_TIME = true; @@ -1536,6 +1537,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // just restarting it anyway. if (checkConfig) { Configuration config = mWindowManager.updateOrientationFromAppTokens( + mConfiguration, r.mayFreezeScreenLocked(app) ? r : null); updateConfigurationLocked(config, r); } @@ -2336,6 +2338,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. Configuration config = mWindowManager.updateOrientationFromAppTokens( + mConfiguration, next.mayFreezeScreenLocked(next.app) ? next : null); if (config != null) { next.frozenBeforeDestroy = true; @@ -2364,7 +2367,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (a != null) { final int N = a.size(); if (!next.finishing && N > 0) { - if (localLOGV) Log.v( + if (DEBUG_RESULTS) Log.v( TAG, "Delivering results to " + next + ": " + a); next.app.thread.scheduleSendResult(next, a); @@ -2701,7 +2704,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen HistoryRecord resultRecord = null; if (resultTo != null) { int index = indexOfTokenLocked(resultTo, false); - if (localLOGV) Log.v( + if (DEBUG_RESULTS) Log.v( TAG, "Sending result to " + resultTo + " (index " + index + ")"); if (index >= 0) { sourceRecord = (HistoryRecord)mHistory.get(index); @@ -3358,6 +3361,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen final long origId = Binder.clearCallingIdentity(); mWindowManager.setAppOrientation(r, requestedOrientation); Configuration config = mWindowManager.updateOrientationFromAppTokens( + mConfiguration, r.mayFreezeScreenLocked(r.app) ? r : null); if (config != null) { r.frozenBeforeDestroy = true; @@ -3423,7 +3427,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen */ private final boolean requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason) { - if (localLOGV) Log.v( + if (DEBUG_RESULTS) Log.v( TAG, "Finishing activity: token=" + token + ", result=" + resultCode + ", data=" + resultData); @@ -3486,7 +3490,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // send the result HistoryRecord resultTo = r.resultTo; if (resultTo != null) { - if (localLOGV) Log.v(TAG, "Adding result to " + resultTo); + if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo + + " who=" + r.resultWho + " req=" + r.requestCode + + " res=" + resultCode + " data=" + resultData); if (r.info.applicationInfo.uid > 0) { grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, r.packageName, resultData, r); @@ -3495,6 +3501,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen resultData); r.resultTo = null; } + else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r); // Make sure this HistoryRecord is not holding on to other resources, // because clients have remote IPC references to this object so we @@ -3652,6 +3659,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen data, r); } + if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r + + " : who=" + resultWho + " req=" + requestCode + + " res=" + resultCode + " data=" + data); if (mResumedActivity == r && r.app != null && r.app.thread != null) { try { ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); @@ -5982,7 +5992,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen final boolean clearWhenTaskReset = (target.intent.getFlags() &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0; - if (!finishOnTaskLaunch && target.resultTo != null) { + if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) { // If this activity is sending a reply to a previous // activity, we can't do anything with it now until // we reach the start of the reply chain. @@ -5992,7 +6002,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (replyChainEnd < 0) { replyChainEnd = targetI; } - } else if (!finishOnTaskLaunch && allowTaskReparenting + } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting && target.taskAffinity != null && !target.taskAffinity.equals(task.affinity)) { // If this activity has an affinity for another @@ -9013,7 +9023,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } r.app = app; - r.restartTime = SystemClock.uptimeMillis(); + r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); app.services.add(r); bumpServiceExecutingLocked(r); @@ -10133,8 +10143,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // installed. Maybe in the future we want to have a special install // broadcast or such for apps, but we'd like to deliberately make // this decision. - String skipPackage = (intent.ACTION_PACKAGE_ADDED.equals( - intent.getAction()) && intent.getData() != null) + boolean skip = false; + if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) { + skip = true; + } else if (intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) { + skip = true; + } else if (intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) { + skip = true; + } + String skipPackage = (skip && intent.getData() != null) ? intent.getData().getSchemeSpecificPart() : null; if (skipPackage != null && receivers != null) { @@ -11306,6 +11323,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // XXX should compute this based on the max of // all connected clients. ConnectionRecord cr = kt.next(); + if (cr.binding.client == app) { + // Binding to ourself is not interesting. + continue; + } if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) { ProcessRecord client = cr.binding.client; int myHiddenAdj = hiddenAdj; @@ -11352,6 +11373,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen Iterator<ProcessRecord> kt = cpr.clients.iterator(); while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) { ProcessRecord client = kt.next(); + if (client == app) { + // Being our own client is not interesting. + continue; + } int myHiddenAdj = hiddenAdj; if (myHiddenAdj > client.hiddenAdj) { if (client.hiddenAdj > FOREGROUND_APP_ADJ) { diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 27d0401..2192e06 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -25,6 +25,7 @@ import android.os.IBinder; import android.os.Parcel; import android.os.Process; import android.os.ServiceManager; +import android.telephony.TelephonyManager; import android.util.PrintWriterPrinter; import java.io.FileDescriptor; @@ -148,14 +149,98 @@ public final class BatteryStatsService extends IBatteryStats.Stub { mStats.notePhoneOffLocked(); } } + + public void notePhoneSignalStrength(int asu) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.notePhoneSignalStrengthLocked(asu); + } + } + + public void notePhoneDataConnectionState(int dataType, boolean hasData) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.notePhoneDataConnectionStateLocked(dataType, hasData); + } + } + + public void noteWifiOn() { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiOnLocked(); + } + } + + public void noteWifiOff() { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiOffLocked(); + } + } + + public void noteWifiRunning() { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiRunningLocked(); + } + } + + public void noteWifiStopped() { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiStoppedLocked(); + } + } + + public void noteBluetoothOn() { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteBluetoothOnLocked(); + } + } + + public void noteBluetoothOff() { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteBluetoothOffLocked(); + } + } + + public void noteFullWifiLockAcquired(int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteFullWifiLockAcquiredLocked(uid); + } + } + + public void noteFullWifiLockReleased(int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteFullWifiLockReleasedLocked(uid); + } + } + + public void noteScanWifiLockAcquired(int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteScanWifiLockAcquiredLocked(uid); + } + } + + public void noteScanWifiLockReleased(int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteScanWifiLockReleasedLocked(uid); + } + } public boolean isOnBattery() { return mStats.isOnBattery(); } - public void setOnBattery(boolean onBattery) { + public void setOnBattery(boolean onBattery, int level) { enforceCallingPermission(); - mStats.setOnBattery(onBattery); + mStats.setOnBattery(onBattery, level); } public long getAwakeTimeBattery() { diff --git a/services/java/com/android/server/status/DateView.java b/services/java/com/android/server/status/DateView.java index 7c44d67..78bfd5e 100644 --- a/services/java/com/android/server/status/DateView.java +++ b/services/java/com/android/server/status/DateView.java @@ -4,12 +4,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.Log; import android.widget.TextView; import android.view.MotionEvent; +import java.text.DateFormat; import java.util.Date; public final class DateView extends TextView { @@ -51,7 +51,7 @@ public final class DateView extends TextView { private final void updateClock() { Date now = new Date(); - setText(DateFormat.getLongDateFormat(getContext()).format(now)); + setText(DateFormat.getDateInstance(DateFormat.LONG).format(now)); } void setUpdates(boolean update) { diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java index 8433227..713cd13 100644 --- a/services/java/com/android/server/status/StatusBarPolicy.java +++ b/services/java/com/android/server/status/StatusBarPolicy.java @@ -17,13 +17,16 @@ package com.android.server.status; import com.android.internal.R; +import com.android.internal.app.IBatteryStats; import com.android.internal.location.GpsLocationProvider; import com.android.internal.telephony.SimCard; import com.android.internal.telephony.TelephonyIntents; +import com.android.server.am.BatteryStatsService; import android.app.AlertDialog; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothError; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothIntent; import android.content.BroadcastReceiver; @@ -37,9 +40,11 @@ import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.net.NetworkInfo; import android.net.wifi.WifiManager; +import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.RemoteException; import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -77,9 +82,10 @@ public class StatusBarPolicy { private static final int BATTERY_THRESHOLD_WARNING = 1; private static final int BATTERY_THRESHOLD_EMPTY = 2; - private Context mContext; - private StatusBarService mService; - private Handler mHandler = new StatusBarHandler(); + private final Context mContext; + private final StatusBarService mService; + private final Handler mHandler = new StatusBarHandler(); + private final IBatteryStats mBatteryStats; // clock private Calendar mCalendar; @@ -143,6 +149,7 @@ public class StatusBarPolicy { SimCard.State mSimState = SimCard.State.READY; int mPhoneState = TelephonyManager.CALL_STATE_IDLE; int mDataState = TelephonyManager.DATA_DISCONNECTED; + int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; ServiceState mServiceState; int mSignalAsu = -1; @@ -222,8 +229,7 @@ public class StatusBarPolicy { else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { updateBattery(intent); } - else if (action.equals(BluetoothIntent.ENABLED_ACTION) || - action.equals(BluetoothIntent.DISABLED_ACTION) || + else if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION) || action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION) || action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) { updateBluetooth(intent); @@ -250,6 +256,7 @@ public class StatusBarPolicy { private StatusBarPolicy(Context context, StatusBarService service) { mContext = context; mService = service; + mBatteryStats = BatteryStatsService.getService(); // clock mCalendar = Calendar.getInstance(TimeZone.getDefault()); @@ -345,8 +352,7 @@ public class StatusBarPolicy { filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); - filter.addAction(BluetoothIntent.ENABLED_ACTION); - filter.addAction(BluetoothIntent.DISABLED_ACTION); + filter.addAction(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION); filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION); filter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); @@ -712,8 +718,8 @@ public class StatusBarPolicy { } private final void updateDataNetType() { - int net = mPhone.getNetworkType(); - switch (net) { + mDataNetType = mPhone.getNetworkType(); + switch (mDataNetType) { case TelephonyManager.NETWORK_TYPE_EDGE: mDataIconList = sDataNetType_e; break; @@ -767,6 +773,13 @@ public class StatusBarPolicy { mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim; mService.updateIcon(mDataIcon, mDataData, null); } + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.notePhoneDataConnectionState(mDataNetType, visible); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } if (mDataIconVisible != visible) { mService.setIconVisibility(mDataIcon, visible); mDataIconVisible = visible; @@ -796,10 +809,10 @@ public class StatusBarPolicy { int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth; String action = intent.getAction(); - if (action.equals(BluetoothIntent.DISABLED_ACTION)) { - mBluetoothEnabled = false; - } else if (action.equals(BluetoothIntent.ENABLED_ACTION)) { - mBluetoothEnabled = true; + if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) { + int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE, + BluetoothError.ERROR); + mBluetoothEnabled = state == BluetoothDevice.BLUETOOTH_STATE_ON; } else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) { mBluetoothHeadsetState = intent.getIntExtra(BluetoothIntent.HEADSET_STATE, BluetoothHeadset.STATE_ERROR); diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java index 5442e1d..5336e27 100644 --- a/services/java/com/android/server/status/StatusBarService.java +++ b/services/java/com/android/server/status/StatusBarService.java @@ -57,6 +57,8 @@ import android.widget.LinearLayout; import android.widget.RemoteViews; import android.widget.ScrollView; import android.widget.TextView; +import android.widget.FrameLayout; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -1476,9 +1478,11 @@ public class StatusBarService extends IStatusBar.Stub /// ---------- Expanded View -------------- pixelFormat = PixelFormat.TRANSLUCENT; - bg = mExpandedView.getBackground(); - if (bg != null) { - pixelFormat = bg.getOpacity(); + if (false) { + bg = mExpandedView.getBackground(); + if (bg != null) { + pixelFormat = bg.getOpacity(); + } } lp = mExpandedDialog.getWindow().getAttributes(); @@ -1490,11 +1494,13 @@ public class StatusBarService extends IStatusBar.Stub lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM + | WindowManager.LayoutParams.FLAG_DITHER; lp.format = pixelFormat; lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL; lp.setTitle("StatusBarExpanded"); mExpandedDialog.getWindow().setAttributes(lp); + mExpandedDialog.getWindow().setFormat(pixelFormat); mExpandedParams = lp; mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); @@ -1503,7 +1509,8 @@ public class StatusBarService extends IStatusBar.Stub ViewGroup.LayoutParams.WRAP_CONTENT)); mExpandedDialog.show(); mExpandedDialog.hide(); - View hack = (View)mExpandedView.getParent(); + FrameLayout hack = (FrameLayout)mExpandedView.getParent(); + hack.setForeground(null); } void setDateViewVisibility(boolean visible, int anim) { diff --git a/services/java/com/android/server/status/TrackingPatternView.java b/services/java/com/android/server/status/TrackingPatternView.java new file mode 100644 index 0000000..0ae9984 --- /dev/null +++ b/services/java/com/android/server/status/TrackingPatternView.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 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. + */ + +package com.android.server.status; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.graphics.BitmapFactory; +import android.graphics.Bitmap; +import android.graphics.Paint; +import android.graphics.Canvas; + +public class TrackingPatternView extends View { + private Bitmap mTexture; + private Paint mPaint; + private int mTextureWidth; + private int mTextureHeight; + + public TrackingPatternView(Context context, AttributeSet attrs) { + super(context, attrs); + + mTexture = BitmapFactory.decodeResource(getResources(), + com.android.internal.R.drawable.status_bar_background); + mTextureWidth = mTexture.getWidth(); + mTextureHeight = mTexture.getHeight(); + + mPaint = new Paint(); + mPaint.setDither(false); + } + + @Override + public void onDraw(Canvas canvas) { + final Bitmap texture = mTexture; + final Paint paint = mPaint; + + final int width = getWidth(); + final int height = getHeight(); + + final int textureWidth = mTextureWidth; + final int textureHeight = mTextureHeight; + + Log.d("TrackingPatternView", "width=" + width + " textureWidth=" + textureWidth); + + int x = 0; + int y; + + while (x < width) { + y = 0; + while (y < height) { + canvas.drawBitmap(texture, x, y, paint); + y += textureHeight; + } + x += textureWidth; + } + } +} diff --git a/services/jni/com_android_server_HardwareService.cpp b/services/jni/com_android_server_HardwareService.cpp index ac36348..b0aab59 100644 --- a/services/jni/com_android_server_HardwareService.cpp +++ b/services/jni/com_android_server_HardwareService.cpp @@ -15,19 +15,110 @@ ** limitations under the License. */ -#define LOG_TAG "Vibrator" +#define LOG_TAG "HardwareService" #include "jni.h" #include "JNIHelp.h" -#include <stdio.h> #include "android_runtime/AndroidRuntime.h" + #include <utils/misc.h> #include <utils/Log.h> #include <hardware_legacy/vibrator.h> +#include <hardware/hardware.h> +#include <hardware/lights.h> + +#include <stdio.h> +//#include <string.h> namespace android { +// These values must correspond with the LIGHT_ID constants in +// HardwareService.java +enum { + LIGHT_INDEX_BACKLIGHT = 0, + LIGHT_INDEX_KEYBOARD = 1, + LIGHT_INDEX_BUTTONS = 2, + LIGHT_INDEX_BATTERY = 3, + LIGHT_INDEX_NOTIFICATIONS = 4, + LIGHT_INDEX_ATTENTION = 5, + LIGHT_COUNT +}; + +struct Devices { + light_device_t* lights[LIGHT_COUNT]; +}; + +static light_device_t* get_device(hw_module_t* module, char const* name) +{ + int err; + hw_device_t* device; + err = module->methods->open(module, name, &device); + if (err == 0) { + return (light_device_t*)device; + } else { + return NULL; + } +} + +static jint init_native(JNIEnv *env, jobject clazz) +{ + int err; + hw_module_t* module; + Devices* devices; + + devices = (Devices*)malloc(sizeof(Devices)); + + err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); + if (err == 0) { + devices->lights[LIGHT_INDEX_BACKLIGHT] + = get_device(module, LIGHT_ID_BACKLIGHT); + devices->lights[LIGHT_INDEX_KEYBOARD] + = get_device(module, LIGHT_ID_KEYBOARD); + devices->lights[LIGHT_INDEX_BUTTONS] + = get_device(module, LIGHT_ID_BUTTONS); + devices->lights[LIGHT_INDEX_BATTERY] + = get_device(module, LIGHT_ID_BATTERY); + devices->lights[LIGHT_INDEX_NOTIFICATIONS] + = get_device(module, LIGHT_ID_NOTIFICATIONS); + devices->lights[LIGHT_INDEX_ATTENTION] + = get_device(module, LIGHT_ID_ATTENTION); + } else { + memset(devices, 0, sizeof(Devices)); + } + + return (jint)devices; +} + +static void finalize_native(JNIEnv *env, jobject clazz, int ptr) +{ + Devices* devices = (Devices*)ptr; + if (devices == NULL) { + return; + } + + free(devices); +} + +static void setLight_native(JNIEnv *env, jobject clazz, int ptr, + int light, int colorARGB, int flashMode, int onMS, int offMS) +{ + Devices* devices = (Devices*)ptr; + light_state_t state; + + if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) { + return ; + } + + memset(&state, 0, sizeof(light_state_t)); + state.color = colorARGB; + state.flashMode = flashMode; + state.flashOnMS = onMS; + state.flashOffMS = offMS; + + devices->lights[light]->set_light(devices->lights[light], &state); +} + static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms) { // LOGI("vibratorOn\n"); @@ -41,11 +132,14 @@ static void vibratorOff(JNIEnv *env, jobject clazz) } static JNINativeMethod method_table[] = { + { "init_native", "()I", (void*)init_native }, + { "finalize_native", "(I)V", (void*)init_native }, + { "setLight_native", "(IIIIII)V", (void*)setLight_native }, { "vibratorOn", "(J)V", (void*)vibratorOn }, { "vibratorOff", "()V", (void*)vibratorOff } }; -int register_android_os_Vibrator(JNIEnv *env) +int register_android_server_HardwareService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/HardwareService", method_table, NELEM(method_table)); diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp index 3d68cfb..26200d3 100644 --- a/services/jni/onload.cpp +++ b/services/jni/onload.cpp @@ -7,7 +7,7 @@ namespace android { int register_android_server_AlarmManagerService(JNIEnv* env); int register_android_server_BatteryService(JNIEnv* env); int register_android_server_KeyInputQueue(JNIEnv* env); -int register_android_os_Vibrator(JNIEnv* env); +int register_android_server_HardwareService(JNIEnv* env); int register_android_server_SensorService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); }; @@ -26,7 +26,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) LOG_ASSERT(env, "Could not retrieve the env!"); register_android_server_KeyInputQueue(env); - register_android_os_Vibrator(env); + register_android_server_HardwareService(env); register_android_server_AlarmManagerService(env); register_android_server_BatteryService(env); register_android_server_SensorService(env); diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 13b6e5c..da53e15 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -39,6 +39,7 @@ public class CallerInfo { public static final String UNKNOWN_NUMBER = "-1"; public static final String PRIVATE_NUMBER = "-2"; + public static final String PAYPHONE_NUMBER = "-3"; /** * Please note that, any one of these member variables can be null, diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java index d833810..ead49bf 100644 --- a/telephony/java/com/android/internal/telephony/Connection.java +++ b/telephony/java/com/android/internal/telephony/Connection.java @@ -21,6 +21,13 @@ package com.android.internal.telephony; */ public abstract class Connection { + // Number presentation type for caller id display + public static int PRESENTATION_ALLOWED = 1; // normal + public static int PRESENTATION_RESTRICTED = 2; // block by user + public static int PRESENTATION_UNKNOWN = 3; // no specified or unknown by network + public static int PRESENTATION_PAYPHONE = 4; // show pay phone info + + public enum DisconnectCause { NOT_DISCONNECTED, /* has not yet disconnected */ INCOMING_MISSED, /* an incoming call that was missed and never answered */ @@ -218,7 +225,12 @@ public abstract class Connection /** * Cancel any post */ - public abstract void cancelPostDial(); + public abstract void cancelPostDial(); + + /** + * Returns the caller id presentation type for incoming and waiting calls + * @return one of PRESENTATION_* + */ + public abstract int getNumberPresentation(); - } diff --git a/telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl b/telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl new file mode 100644 index 0000000..6c1f4bb --- /dev/null +++ b/telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl @@ -0,0 +1,31 @@ +package com.android.internal.telephony; + +/** + * Interface used to interact with extended MMI/USSD network service. + */ +interface IExtendedNetworkService { + /** + * Set a MMI/USSD command to ExtendedNetworkService for further process. + * This should be called when a MMI command is placed from panel. + * @param number the dialed MMI/USSD number. + */ + void setMmiString(String number); + + /** + * return the specific string which is used to prompt MMI/USSD is running + */ + CharSequence getMmiRunningText(); + + /** + * Get specific message which should be displayed on pop-up dialog. + * @param text original MMI/USSD message response from framework + * @return specific user message correspond to text. null stands for no pop-up dialog need to show. + */ + CharSequence getUserMessage(CharSequence text); + + /** + * Clear pre-set MMI/USSD command. + * This should be called when user cancel a pre-dialed MMI command. + */ + void clearMmiString(); +} diff --git a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java b/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java index 2f91411..3ca39de 100644 --- a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java +++ b/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java @@ -32,11 +32,15 @@ public class ApnSetting { String user; String password; String[] types; + int id; + String numeric; - ApnSetting(String carrier, String apn, String proxy, String port, + ApnSetting(int id, String numeric, String carrier, String apn, String proxy, String port, String mmsc, String mmsProxy, String mmsPort, String user, String password, String[] types) { + this.id = id; + this.numeric = numeric; this.carrier = carrier; this.apn = apn; this.proxy = proxy; @@ -52,6 +56,8 @@ public class ApnSetting { public String toString() { StringBuilder sb = new StringBuilder(); sb.append(carrier) + .append(", ").append(id) + .append(", ").append(numeric) .append(", ").append(apn) .append(", ").append(proxy) .append(", ").append(mmsc) diff --git a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java index 30b1be8..02a6841 100644 --- a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java @@ -20,6 +20,7 @@ import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -28,6 +29,7 @@ import android.database.ContentObserver; import android.database.Cursor; import android.net.NetworkInfo; import android.net.wifi.WifiManager; +import android.net.Uri; import android.os.AsyncResult; import android.os.Handler; import android.os.INetStatService; @@ -149,6 +151,8 @@ final class DataConnectionTracker extends Handler */ private ArrayList<ApnSetting> waitingApns = null; + private ApnSetting preferredApn = null; + /** * pdpList holds all the PDP connection, i.e. IP Link in GPRS */ @@ -255,6 +259,10 @@ final class DataConnectionTracker extends Handler static final int EVENT_PS_RESTRICT_ENABLED = 30; static final int EVENT_PS_RESTRICT_DISABLED = 31; + static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn"); + static final String APN_ID = "apn_id"; + private boolean canSetPreferApn = false; + BroadcastReceiver mIntentReceiver = new BroadcastReceiver () { @Override @@ -787,6 +795,8 @@ final class DataConnectionTracker extends Handler String[] types = parseTypes( cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE))); ApnSetting apn = new ApnSetting( + cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)), + cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)), cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)), cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)), cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)), @@ -1459,6 +1469,11 @@ final class DataConnectionTracker extends Handler } if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { SystemProperties.set("gsm.defaultpdpcontext.active", "true"); + if (canSetPreferApn && preferredApn == null) { + Log.d(LOG_TAG, "PREFERED APN is null"); + preferredApn = mActiveApn; + setPreferredApn(preferredApn.id); + } } else { SystemProperties.set("gsm.defaultpdpcontext.active", "false"); } @@ -1678,7 +1693,15 @@ final class DataConnectionTracker extends Handler if (allApns.isEmpty()) { if (DBG) log("No APN found for carrier: " + operator); + preferredApn = null; notifyNoData(PdpConnection.PdpFailCause.BAD_APN); + } else { + preferredApn = getPreferredApn(); + Log.d(LOG_TAG, "Get PreferredAPN"); + if (preferredApn != null && !preferredApn.numeric.equals(operator)) { + preferredApn = null; + setPreferredApn(-1); + } } } @@ -1699,6 +1722,22 @@ final class DataConnectionTracker extends Handler */ private ArrayList<ApnSetting> buildWaitingApns() { ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>(); + String operator = phone.mSIMRecords.getSIMOperatorNumeric(); + + if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { + if (canSetPreferApn && preferredApn != null) { + Log.i(LOG_TAG, "Preferred APN:" + operator + ":" + + preferredApn.numeric + ":" + preferredApn); + if (preferredApn.numeric.equals(operator)) { + Log.i(LOG_TAG, "Waiting APN set to preferred APN"); + apnList.add(preferredApn); + return apnList; + } else { + setPreferredApn(-1); + preferredApn = null; + } + } + } if (allApns != null) { for (ApnSetting apn : allApns) { @@ -1745,4 +1784,53 @@ final class DataConnectionTracker extends Handler reconnectAfterFail(cause, reason); } } + + private void setPreferredApn(int pos) { + if (!canSetPreferApn) { + return; + } + + ContentResolver resolver = phone.getContext().getContentResolver(); + resolver.delete(PREFERAPN_URI, null, null); + + if (pos >= 0) { + ContentValues values = new ContentValues(); + values.put(APN_ID, pos); + resolver.insert(PREFERAPN_URI, values); + } + } + + private ApnSetting getPreferredApn() { + if (allApns.isEmpty()) { + return null; + } + + Cursor cursor = phone.getContext().getContentResolver().query( + PREFERAPN_URI, new String[] { "_id", "name", "apn" }, + null, null, Telephony.Carriers.DEFAULT_SORT_ORDER); + + if (cursor != null) { + canSetPreferApn = true; + } else { + canSetPreferApn = false; + } + + if (canSetPreferApn && cursor.getCount() > 0) { + int pos; + cursor.moveToFirst(); + pos = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)); + for(ApnSetting p:allApns) { + if (p.id == pos && p.canHandleType(mRequestedApnType)) { + cursor.close(); + return p; + } + } + } + + if (cursor != null) { + cursor.close(); + } + + return null; + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java b/telephony/java/com/android/internal/telephony/gsm/DriverCall.java index 178e661..aab885a 100644 --- a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java +++ b/telephony/java/com/android/internal/telephony/gsm/DriverCall.java @@ -16,6 +16,7 @@ package com.android.internal.telephony.gsm; import com.android.internal.telephony.*; + import android.util.Log; import java.lang.Comparable; import android.telephony.PhoneNumberUtils; @@ -36,7 +37,7 @@ public class DriverCall implements Comparable WAITING; // MT call only // If you add a state, make sure to look for the switch() // statements that use this enum - }; + } public int index; public boolean isMT; @@ -46,6 +47,7 @@ public class DriverCall implements Comparable public int TOA; public boolean isVoice; public int als; + public int numberPresentation; /** returns null on error */ static DriverCall @@ -64,7 +66,10 @@ public class DriverCall implements Comparable ret.isVoice = (0 == p.nextInt()); ret.isMpty = p.nextBoolean(); - + + // use ALLOWED as default presentation while parsing CLCC + ret.numberPresentation = Connection.PRESENTATION_ALLOWED; + if (p.hasMore()) { // Some lame implementations return strings // like "NOT AVAILABLE" in the CLCC line @@ -105,7 +110,7 @@ public class DriverCall implements Comparable + state + "," + (isVoice ? "voice" : "no_voc") + "," + (isMpty ? "conf" : "norm") + "," - + TOA + "," + als; + + TOA + "," + als + ",cli " + numberPresentation; } public static State @@ -122,6 +127,19 @@ public class DriverCall implements Comparable throw new ATParseEx("illegal call state " + state); } } + + public static int + presentationFromCLIP(int cli) throws ATParseEx + { + switch(cli) { + case 0: return Connection.PRESENTATION_ALLOWED; + case 1: return Connection.PRESENTATION_RESTRICTED; + case 2: return Connection.PRESENTATION_UNKNOWN; + case 3: return Connection.PRESENTATION_PAYPHONE; + default: + throw new ATParseEx("illegal presentation " + cli); + } + } //***** Comparable Implementation diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java b/telephony/java/com/android/internal/telephony/gsm/GSMCall.java index 7179bb7..4feaf21 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMCall.java @@ -37,7 +37,7 @@ class GSMCall extends Call { switch (dcState) { case ACTIVE: return State.ACTIVE; - case HOLDING: return State.HOLDING; + case HOLDING: return State.HOLDING; case DIALING: return State.DIALING; case ALERTING: return State.ALERTING; case INCOMING: return State.INCOMING; diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java b/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java index 70e9f62..4777892 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java @@ -16,6 +16,7 @@ package com.android.internal.telephony.gsm; import com.android.internal.telephony.*; + import android.content.Context; import android.os.Handler; import android.os.PowerManager; @@ -71,6 +72,7 @@ public class GSMConnection extends Connection { DisconnectCause cause = DisconnectCause.NOT_DISCONNECTED; PostDialState postDialState = PostDialState.NOT_STARTED; + int numberPresentation = Connection.PRESENTATION_ALLOWED; Handler h; @@ -124,6 +126,7 @@ public class GSMConnection extends Connection { isIncoming = dc.isMT; createTime = System.currentTimeMillis(); + numberPresentation = dc.numberPresentation; this.index = index; @@ -756,4 +759,9 @@ public class GSMConnection extends Connection { private void log(String msg) { Log.d(LOG_TAG, "[GSMConn] " + msg); } + + @Override + public int getNumberPresentation() { + return numberPresentation; + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java index ce6c186..04f8332 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java @@ -1212,9 +1212,11 @@ public final class GsmMmiCode extends Handler implements MmiCode } else if (sc.equals(SC_WAIT)) { // Call Waiting includes additional data in the response. sb.append(createQueryCallWaitingResultMessage(ints[1])); - } else if (isServiceCodeCallBarring(sc) || (ints[0] == 1)) { + } else if (isServiceCodeCallBarring(sc)) { // ints[0] for Call Barring is a bit vector of services - // for all other services, treat it as a boolean + sb.append(createQueryCallBarringResultMessage(ints[0])); + } else if (ints[0] == 1) { + // for all other services, treat it as a boolean sb.append(context.getText(com.android.internal.R.string.serviceEnabled)); } else { sb.append(context.getText(com.android.internal.R.string.mmiError)); @@ -1245,7 +1247,23 @@ public final class GsmMmiCode extends Handler implements MmiCode } return sb; } - + private CharSequence + createQueryCallBarringResultMessage(int serviceClass) + { + StringBuilder sb = new StringBuilder(context.getText(com.android.internal.R.string.serviceEnabledFor)); + + for (int classMask = 1 + ; classMask <= SERVICE_CLASS_MAX + ; classMask <<= 1 + ) { + if ((classMask & serviceClass) != 0) { + sb.append("\n"); + sb.append(serviceClassToCFString(classMask & serviceClass)); + } + } + return sb; + } + /*** * TODO: It would be nice to have a method here that can take in a dialstring and * figure out if there is an MMI code embedded within it. This code would replace diff --git a/telephony/java/com/android/internal/telephony/gsm/RIL.java b/telephony/java/com/android/internal/telephony/gsm/RIL.java index 8b10ed2..2221eed 100644 --- a/telephony/java/com/android/internal/telephony/gsm/RIL.java +++ b/telephony/java/com/android/internal/telephony/gsm/RIL.java @@ -201,7 +201,7 @@ public final class RIL extends BaseCommands implements CommandsInterface private Context mContext; WakeLock mWakeLock; int mRequestMessagesPending; - + // Is this the first radio state change? private boolean mInitialRadioStateChange = true; @@ -2329,7 +2329,9 @@ public final class RIL extends BaseCommands implements CommandsInterface case RIL_SIM_NETWORK_PERSONALIZATION: return SimStatus.SIM_NETWORK_PERSONALIZATION; default: - throw new RuntimeException ("Invalid RIL_REQUEST_GET_SIM_STATUS result: " + status); + // Unrecognized SIM status. Treat it like a missing SIM. + Log.e(LOG_TAG, "Unrecognized RIL_REQUEST_GET_SIM_STATUS result: " + status); + return SimStatus.SIM_ABSENT; } } @@ -2355,7 +2357,8 @@ public final class RIL extends BaseCommands implements CommandsInterface dc.als = p.readInt(); dc.isVoice = (0 == p.readInt()) ? false : true; dc.number = p.readString(); - + dc.numberPresentation = DriverCall.presentationFromCLIP(p.readInt()); + // Make sure there's a leading + on addresses with a TOA // of 145 diff --git a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java index 89ce506..e336d7d 100644 --- a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java @@ -24,6 +24,7 @@ import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERAT import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC; +import com.android.internal.telephony.SimCard; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.Phone; import com.android.internal.telephony.gsm.DataConnectionTracker.State; @@ -175,16 +176,17 @@ final class ServiceStateTracker extends Handler // waiting period before recheck gprs and voice registration static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000; - // notification type + // restricted state type static final int PS_ENABLED = 1001; // Access Control blocks data service static final int PS_DISABLED = 1002; // Access Control enables data service static final int CS_ENABLED = 1003; // Access Control blocks all voice/sms service static final int CS_DISABLED = 1004; // Access Control enables all voice/sms service static final int CS_NORMAL_ENABLED = 1005; // Access Control blocks normal voice/sms service - static final int CS_NORMAL_DISABLED = 1006; // Access Control enables normal voice/sms service - static final int CS_EMERGENCY_ENABLED = 1007; // Access Control blocks emergency call service - static final int CS_EMERGENCY_DISABLED = 1008; // Access Control enables emergency call service + static final int CS_EMERGENCY_ENABLED = 1006; // Access Control blocks emergency call service + // notification id + static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted + static final int CS_NOTIFICATION = 999; //id to update and cancel CS restricted //***** Events static final int EVENT_RADIO_STATE_CHANGED = 1; @@ -1181,7 +1183,8 @@ final class ServiceStateTracker extends Handler /** * Set restricted state based on the OnRestrictedStateChanged notification * If any voice or packet restricted state changes, trigger a UI - * notification and notify registrants. + * notification and notify registrants when sim is ready. + * * @param ar an int value of RIL_RESTRICTED_STATE_* */ private void onRestrictedStateChanged(AsyncResult ar) @@ -1198,38 +1201,78 @@ final class ServiceStateTracker extends Handler newRs.setCsEmergencyRestricted( ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) || ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); - newRs.setCsNormalRestricted( - ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) || - ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); - newRs.setPsRestricted( - (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0); + + + //ignore the normal call and data restricted state before SIM READY + if (phone.getSimCard().getState() == SimCard.State.READY){ + newRs.setCsNormalRestricted( + ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) || + ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); + newRs.setPsRestricted( + (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0); + } Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs); if (!rs.isPsRestricted() && newRs.isPsRestricted()) { psRestrictEnabledRegistrants.notifyRegistrants(); - setNotification(PS_ENABLED, false); + setNotification(PS_ENABLED); } else if (rs.isPsRestricted() && !newRs.isPsRestricted()) { psRestrictDisabledRegistrants.notifyRegistrants(); - setNotification(PS_DISABLED, false); + setNotification(PS_DISABLED); } - if (!rs.isCsRestricted() && newRs.isCsRestricted()) { - setNotification(CS_ENABLED, false); - } else if (rs.isCsRestricted() && !newRs.isCsRestricted()) { - setNotification(CS_DISABLED, false); - } else { - if (!rs.isCsEmergencyRestricted() && newRs.isCsEmergencyRestricted()) { - setNotification(CS_EMERGENCY_ENABLED, false); - } else if (rs.isCsEmergencyRestricted() && !newRs.isCsEmergencyRestricted()) { - setNotification(CS_EMERGENCY_DISABLED, false); + /** + * There are two kind of cs restriction, normal and emergency. So + * there are 4 x 4 combinations in current and new restricted states + * and we only need to notify when state is changed. + */ + if (rs.isCsRestricted()) { + if (!newRs.isCsRestricted()) { + // remove all restriction + setNotification(CS_DISABLED); + } else if (!newRs.isCsNormalRestricted()) { + // remove normal restriction + setNotification(CS_EMERGENCY_ENABLED); + } else if (!newRs.isCsEmergencyRestricted()) { + // remove emergency restriction + setNotification(CS_NORMAL_ENABLED); + } + } else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) { + if (!newRs.isCsRestricted()) { + // remove all restriction + setNotification(CS_DISABLED); + } else if (newRs.isCsRestricted()) { + // enable all restriction + setNotification(CS_ENABLED); + } else if (newRs.isCsNormalRestricted()) { + // remove emergency restriction and enable normal restriction + setNotification(CS_NORMAL_ENABLED); } - if (!rs.isCsNormalRestricted() && newRs.isCsNormalRestricted()) { - setNotification(CS_NORMAL_ENABLED, false); - } else if (rs.isCsEmergencyRestricted() && !newRs.isCsEmergencyRestricted()) { - setNotification(CS_NORMAL_DISABLED, false); + } else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) { + if (!newRs.isCsRestricted()) { + // remove all restriction + setNotification(CS_DISABLED); + } else if (newRs.isCsRestricted()) { + // enable all restriction + setNotification(CS_ENABLED); + } else if (newRs.isCsEmergencyRestricted()) { + // remove normal restriction and enable emergency restriction + setNotification(CS_EMERGENCY_ENABLED); + } + } else { + if (newRs.isCsRestricted()) { + // enable all restriction + setNotification(CS_ENABLED); + } else if (newRs.isCsEmergencyRestricted()) { + // enable emergency restriction + setNotification(CS_EMERGENCY_ENABLED); + } else if (newRs.isCsNormalRestricted()) { + // enable normal restriction + setNotification(CS_NORMAL_ENABLED); } } + rs = newRs; } Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs); @@ -1593,67 +1636,61 @@ final class ServiceStateTracker extends Handler * Post a notification to NotificationManager for restricted state * * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE - * @param isCancel true to cancel the previous posted notification - * (current is not implemented yet) */ - private void setNotification(int notifyType, boolean isCancel) { + private void setNotification(int notifyType) { Log.d(LOG_TAG, "[DSAC DEB] " + "create notification " + notifyType); + + Context context = phone.getContext(); + mNotification = new Notification(); mNotification.when = System.currentTimeMillis(); mNotification.flags = Notification.FLAG_AUTO_CANCEL; - mNotification.icon = com.android.internal.R.drawable.icon_highlight_square; + mNotification.icon = com.android.internal.R.drawable.stat_sys_warning; Intent intent = new Intent(); mNotification.contentIntent = PendingIntent - .getActivity(phone.getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + .getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); - // TODO - // should use getResources().getText(com.android.internal.R.) - CharSequence title = "Restricted State Changed"; CharSequence details = ""; + CharSequence title = context.getText(com.android.internal.R.string.RestrictedChangedTitle); + int notificationId = CS_NOTIFICATION; + switch (notifyType) { case PS_ENABLED: - details = "Access Control blocks data service."; + notificationId = PS_NOTIFICATION; + details = context.getText(com.android.internal.R.string.RestrictedOnData);; break; case PS_DISABLED: - details = "Access Control enables data service."; + notificationId = PS_NOTIFICATION; break; case CS_ENABLED: - details = "Access Control blocks all voice/sms service."; + details = context.getText(com.android.internal.R.string.RestrictedOnAll);; break; - case CS_DISABLED: - details = "Access Control enables all voice/sms service."; - break; case CS_NORMAL_ENABLED: - details = "Access Control blocks normal voice/sms service."; + details = context.getText(com.android.internal.R.string.RestrictedOnNormal);; break; - case CS_NORMAL_DISABLED: - details = "Access Control enables normal voice/sms service."; - break; case CS_EMERGENCY_ENABLED: - details = "Access Control blocks emergency call service."; + details = context.getText(com.android.internal.R.string.RestrictedOnEmergency);; break; - case CS_EMERGENCY_DISABLED: - details = "Access Control enables emergency call service."; + case CS_DISABLED: + // do nothing and cancel the notification later break; } Log.d(LOG_TAG, "[DSAC DEB] " + "put notification " + title + " / " +details); mNotification.tickerText = title; - mNotification.setLatestEventInfo(phone.getContext(), title, details, + mNotification.setLatestEventInfo(context, title, details, mNotification.contentIntent); NotificationManager notificationManager = (NotificationManager) - phone.getContext().getSystemService(Context.NOTIFICATION_SERVICE); - - if (isCancel) { - // TODO - //if we go the notification route, probably want to only put up a single - //notification if both CS+PS is restricted, instead of one for each.nnnnn - //Anyway, need UX team input on UI. - //notificationManager.cancel(notifyType); + context.getSystemService(Context.NOTIFICATION_SERVICE); + + if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) { + // cancel previous post notification + notificationManager.cancel(notificationId); + } else { + // update restricted state notification + notificationManager.notify(notificationId, mNotification); } - notificationManager.notify(notifyType, mNotification); } - } diff --git a/tests/AndroidTests/res/raw/v21_backslash.vcf b/tests/AndroidTests/res/raw/v21_backslash.vcf new file mode 100644 index 0000000..bd3002b --- /dev/null +++ b/tests/AndroidTests/res/raw/v21_backslash.vcf @@ -0,0 +1,5 @@ +BEGIN:VCARD
+VERSION:2.1
+N:;A\;B\\;C\\\;;D;\:E;\\\\;
+FN:A;B\C\;D:E\\
+END:VCARD
diff --git a/tests/AndroidTests/res/raw/v21_complicated.vcf b/tests/AndroidTests/res/raw/v21_complicated.vcf new file mode 100644 index 0000000..de34e16 --- /dev/null +++ b/tests/AndroidTests/res/raw/v21_complicated.vcf @@ -0,0 +1,106 @@ +BEGIN:VCARD
+VERSION:2.1
+N:Gump;Forrest;Hoge;Pos;Tao
+FN:Joe Due
+ORG:Gump Shrimp Co.;Sales Dept.\;Manager;Fish keeper
+ROLE:Fish Cake Keeper!
+X-CLASS:PUBLIC
+TITLE:Shrimp Man
+TEL;WORK;VOICE:(111) 555-1212
+TEL;HOME;VOICE:(404) 555-1212
+TEL;CELL:0311111111
+TEL;VIDEO:0322222222
+TEL;VOICE:0333333333
+ADR;WORK:;;100 Waters Edge;Baytown;LA;30314;United States of America
+LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, LA 30314=0D=0AUnited States of America
+ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
+LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0A=
+Baytown, LA 30314=0D=0A=
+United States of America
+EMAIL;PREF;INTERNET:forrestgump@walladalla.com
+EMAIL;CELL:cell@example.com
+NOTE:The following note is the example from RFC 2045.
+NOTE;ENCODING=QUOTED-PRINTABLE:Now's the time =
+for all folk to come=
+ to the aid of their country.
+
+PHOTO;ENCODING=BASE64;TYPE=JPEG:
+ /9j/4QoPRXhpZgAATU0AKgAAAAgADQEOAAIAAAAPAAAAqgEPAAIAAAAHAAAAugEQAAIAAAAG
+ AAAAwgESAAMAAAABAAEAAAEaAAUAAAABAAAAyAEbAAUAAAABAAAA0AEoAAMAAAABAAIAAAEx
+ AAIAAAAOAAAA2AEyAAIAAAAUAAAA5gITAAMAAAABAAEAAIKYAAIAAAAOAAAA+odpAAQAAAAB
+ AAABhMSlAAcAAAB8AAABCAAABB4yMDA4MTAyOTEzNTUzMQAARG9Db01vAABEOTA1aQAAAABI
+ AAAAAQAAAEgAAAABRDkwNWkgVmVyMS4wMAAyMDA4OjEwOjI5IDEzOjU1OjQ3ACAgICAgICAg
+ ICAgICAAUHJpbnRJTQAwMzAwAAAABgABABQAFAACAQAAAAADAAAANAEABQAAAAEBAQAAAAEQ
+ gAAAAAAAEQkAACcQAAAPCwAAJxAAAAWXAAAnEAAACLAAACcQAAAcAQAAJxAAAAJeAAAnEAAA
+ AIsAACcQAAADywAAJxAAABvlAAAnEAAogpoABQAAAAEAAANqgp0ABQAAAAEAAANyiCIAAwAA
+ AAEAAgAAkAAABwAAAAQwMjIwkAMAAgAAABQAAAN6kAQAAgAAABQAAAOOkQEABwAAAAQBAgMA
+ kQIABQAAAAEAAAOikgEACgAAAAEAAAOqkgIABQAAAAEAAAOykgQACgAAAAEAAAO6kgUABQAA
+ AAEAAAPCkgcAAwAAAAEAAgAAkggAAwAAAAEAAAAAkgkAAwAAAAEAAAAAkgoABQAAAAEAAAPK
+ knwABwAAAAEAAAAAkoYABwAAABYAAAPSoAAABwAAAAQwMTAwoAEAAwAAAAEAAQAAoAIAAwAA
+ AAEAYAAAoAMAAwAAAAEASAAAoAUABAAAAAEAAAQAog4ABQAAAAEAAAPoog8ABQAAAAEAAAPw
+ ohAAAwAAAAEAAgAAohcAAwAAAAEAAgAAowAABwAAAAEDAAAAowEABwAAAAEBAAAApAEAAwAA
+ AAEAAAAApAIAAwAAAAEAAAAApAMAAwAAAAEAAAAApAQABQAAAAEAAAP4pAUAAwAAAAEAHQAA
+ pAYAAwAAAAEAAAAApAcAAwAAAAEAAAAApAgAAwAAAAEAAAAApAkAAwAAAAEAAAAApAoAAwAA
+ AAEAAAAApAwAAwAAAAEAAgAAAAAAAAAAAFMAACcQAAABXgAAAGQyMDA4OjEwOjI5IDEzOjU1
+ OjMxADIwMDg6MTA6MjkgMTM6NTU6NDcAAAApiAAAGwAAAAKyAAAAZAAAAV4AAABkAAAAAAAA
+ AGQAAAAlAAAACgAADpIAAAPoAAAAAAAAAAAyMDA4MTAyOTEzNTUzMQAAICoAAAAKAAAq4gAA
+ AAoAAAAAAAAAAQACAAEAAgAAAARSOTgAAAIABwAAAAQwMTAwAAAAAAAGAQMAAwAAAAEABgAA
+ ARoABQAAAAEAAARsARsABQAAAAEAAAR0ASgAAwAAAAEAAgAAAgEABAAAAAEAAAR8AgIABAAA
+ AAEAAAWLAAAAAAAAAEgAAAABAAAASAAAAAH/2P/bAIQAIBYYHBgUIBwaHCQiICYwUDQwLCww
+ YkZKOlB0Znp4cmZwboCQuJyAiK6KbnCg2qKuvsTO0M58muLy4MjwuMrOxgEiJCQwKjBeNDRe
+ xoRwhMbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbG
+ /8AAEQgAeACgAwEhAAIRAQMRAf/EAaIAAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKCxAA
+ AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK
+ FhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWG
+ h4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl
+ 5ufo6erx8vP09fb3+Pn6AQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgsRAAIBAgQEAwQH
+ BQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBka
+ JicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT
+ lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz
+ 9PX29/j5+v/aAAwDAQACEQMRAD8AFFSqKkZIoqRVpgSKKeBTEOApwFADsUYpgIRSEUANIppF
+ ICNhUTCgCMio2FICJhULCgC0oqVaAJFFSqKBkgFOApiHCnCgB2KMUCENJQA0imEUDGMKiYUA
+ RtUbUgIWqJhQBZSpFoAlWpVoGPFPFMQ7tSK2ODQA4yKO9HmKe9FxAzDHFIOlAAaYaAGNUTUD
+ ImqNqQETVE1AE6VKKAJFNSqaAHg08GmANIFFQM5Y5qJMBuT60ZNQIcrkVYSQMKuLGKaaasQx
+ qiagZE1RtSAjaomoAkQ1KpoAlU1IpoAkU07OBTArO+5qkV12Y71lfUBmaKkCRSuznrTFba2a
+ oCwGyM0E1qIjY1GxoGRNUZNICNqiagByGplNAEimpFNMB4YDvSucpxSYEIU04KazsAu1qArU
+ WELtPpTSposBNETt5pxNaoCNjUbGgCNjUZoGRtUTUgFU1KpoAkBqQHigCFnO7rUqOdlZp6gA
+ c+tODn1pXAXzD60eYfWncQvmNSGQ07gOMhCVEJGz1ptgS5yKYxqwGE1GxoAiamGkMapqVTQB
+ Kpp+eKAICfmqWM/Kaz6gANOBqQFzRmmAuaTNACsfkqMHmm9wJs8U0mtRDGNRsaAI2phpDI1N
+ SqaAJFNSA8UCISfmqSM/Kaz6jAHmnA1ICg0uaAFzSZpgKx+SmDrTe4E2eKaTWoiMmmMaAIzT
+ DSGRKakU0ASKaeDTERseakjPyms+oxAacDUgOBpc0gFzSZpgOY/KKYv3qrqIlpprQBjGoyaA
+ GGmmkMgU1IppgPBqQGgQu0Gn4wvFKwEQpwNZDHZpc0ALmigRKBleaQKBWtgA001QDGqM0gGm
+ mGkMrqakBoAepp4NMRIDTwaAE2A008GokgHxjd1pzKFpW0uAg5NSBBTirgOpDWgDTTTQAw0w
+ 0gGGmmgZWBp4pASKaeDTEOBp4NADwajbrUyBEkXWnSUdAGr1qeiAMSkNWAhphoAaaYaQDDTT
+ SGVRTwaYDxTwaBDwaeDQA4GlK5oauIeo20pGaLaAKqgU6hKwBSGmAhphoAaaYaQxhpppDKgN
+ PFMB4p4oEPFOBpgPBp4NAhwpwoAWloAKSgBDTTQMYaYaQDTTTSGA/9n/2wCEAAoHBwgHBgoI
+ CAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9
+ PjsBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7
+ Ozs7Ozs7Ozs7Ozs7O//AABEIAEgAYAMBIQACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAA
+ AQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNC
+ scEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hp
+ anN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS
+ 09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcI
+ CQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVi
+ ctEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4
+ eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY
+ 2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AJ7SLgcVr20I4rNFGvbQAAHFaEUX
+ SrQi5HCMdKk8oY6VSJYx4hjpVaWMelAFC4iGDxWPdR8mkxmRdxjBrEvI+tZjN20xtHNbNqAc
+ UIDXg6Cr0WKtCY8XKQOyzOB3FKNWsyceZ+lS6sY6NkjvPSdwImBHUmmy4q076oCjOODWPdgc
+ 0MpGPdAYNYl4o5rNjNKzkyorZtXxihAa1vIDip7m9Frb7/4jwKcnyxbEzN3ieJppZsyZ4U1H
+ urzZau4mWVlNrGk0UuWPVa1YroXEIkHfrXZh5W90RWncAHmsi6bJNdQ0ZNw3BrGuiMGs2Mks
+ puBzWzbzdOaEBeOpR2oUtkk9hTru7iuo4m8wgemKyqTi04sBsfkEf68j8KlUQZz9o/SuZRj3
+ JYriAji4/Sp7W6htbV2aXcu70ramoxle4gN7HcIXjbis+4k5NdaaauhmVcv1rHuW61DGiG1m
+ 6c1s20/TmgAv5vmj57VKk3+ixnPc1xVV70h9CVJuOtSrL71hFgxzScUkkn+iY/2q1i9xDrGT
+ 9y31pJ5Otd1L+GhMy7mTrWXO2SapjRn28vTmta3nxjmgGOvJd2w1Kkv+ipz/ABGuOoveYdCe
+ ObjrU6y5rlsA8ycUksn+ij/eNaw6iJLNsW59zTJn6816FP4EJmbO+Saz5m602UjIgk4HNadv
+ LwKaBl+MpIMOMipp490SCJeF7CoqQvF2JuRqWQ4YEGrSiQJuKnHrXByMpki73GFBNXIoh9n2
+ SrnnOK6MPTbd3sSwIVF2qMCqkzHmuy1lYRnTHrVGWpZaMKB+BWlbycYoQM0IZDxzV+GU8c1a
+ IYy5Y+dnHatAsfsAHfArmS1mPoh1gT8x9qtk1rQX7tCe5DIapzGtGBQm71SlqGWjnIH6Vowt
+ zmhAy/E3vV6F6tEMuxlWIyAfrVxCCAO1VZEEyYA4AApxNGwyJ+lVJRUsaKMw61SlFQzRAP/Z
+
+X-ATTRIBUTE:Some String
+BDAY:19800101
+GEO:35.6563854,139.6994233
+URL:http://www.example.com/
+REV:20080424T195243Z
+END:VCARD
\ No newline at end of file diff --git a/tests/AndroidTests/res/raw/v21_japanese_1.vcf b/tests/AndroidTests/res/raw/v21_japanese_1.vcf new file mode 100644 index 0000000..d05e2ff --- /dev/null +++ b/tests/AndroidTests/res/raw/v21_japanese_1.vcf @@ -0,0 +1,6 @@ +BEGIN:VCARD
+VERSION:2.1
+N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh;;;;
+SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ;;;;
+TEL;PREF;VOICE:0300000000
+END:VCARD
diff --git a/tests/AndroidTests/res/raw/v21_japanese_2.vcf b/tests/AndroidTests/res/raw/v21_japanese_2.vcf new file mode 100644 index 0000000..fa54acb --- /dev/null +++ b/tests/AndroidTests/res/raw/v21_japanese_2.vcf @@ -0,0 +1,10 @@ +BEGIN:VCARD
+VERSION:2.1
+FN;CHARSET=SHIFT_JIS:ˆÀ“¡ ƒƒCƒh 1
+N;CHARSET=SHIFT_JIS:ˆÀ“¡;ƒƒCƒh1;;;
+SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³;Û²ÄÞ1;;;
+ADR;HOME;CHARSET=SHIFT_JIS;ENCODING=QUOTED-PRINTABLE:;=93=8C=8B=9E=93=73=
+=8F=61=92=4A=8B=E6=8D=F7=8B=75=92=AC26-1=83=5A=83=8B=83=8A=83=41=83=93=
+=83=5E=83=8F=81=5B6=8A=4B;;;;150-8512;
+NOTE;CHARSET=SHIFT_JIS;ENCODING=QUOTED-PRINTABLE:=83=81=83=82
+END:VCARD
diff --git a/tests/AndroidTests/res/raw/v21_multiple_entry.vcf b/tests/AndroidTests/res/raw/v21_multiple_entry.vcf new file mode 100644 index 0000000..ebbb19a --- /dev/null +++ b/tests/AndroidTests/res/raw/v21_multiple_entry.vcf @@ -0,0 +1,33 @@ +BEGIN:VCARD
+VERSION:2.1
+N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh3;;;;
+SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ3;;;;
+TEL;X-NEC-SECRET:9
+TEL;X-NEC-HOTEL:10
+TEL;X-NEC-SCHOOL:11
+TEL;HOME;FAX:12
+END:VCARD
+
+
+BEGIN:VCARD
+VERSION:2.1
+N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh4;;;;
+SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ4;;;;
+TEL;MODEM:13
+TEL;PAGER:14
+TEL;X-NEC-FAMILY:15
+TEL;X-NEC-GIRL:16
+END:VCARD
+
+
+BEGIN:VCARD
+VERSION:2.1
+N;CHARSET=SHIFT_JIS:ˆÀ“¡ƒƒCƒh5;;;;
+SOUND;X-IRMC-N;CHARSET=SHIFT_JIS:±ÝÄÞ³Û²ÄÞ5;;;;
+TEL;X-NEC-BOY:17
+TEL;X-NEC-FRIEND:18
+TEL;X-NEC-PHS:19
+TEL;X-NEC-RESTAURANT:20
+END:VCARD
+
+
diff --git a/tests/AndroidTests/res/raw/v21_simple.vcf b/tests/AndroidTests/res/raw/v21_simple.vcf new file mode 100644 index 0000000..beddabb --- /dev/null +++ b/tests/AndroidTests/res/raw/v21_simple.vcf @@ -0,0 +1,4 @@ +BEGIN:VCARD
+N:Ando;Roid;
+FN:Ando Roid
+END:VCARD
diff --git a/tests/AndroidTests/res/raw/v30_simple.vcf b/tests/AndroidTests/res/raw/v30_simple.vcf new file mode 100644 index 0000000..418661f --- /dev/null +++ b/tests/AndroidTests/res/raw/v30_simple.vcf @@ -0,0 +1,13 @@ +BEGIN:VCARD
+VERSION:3.0
+FN:And Roid
+N:And;Roid;;;
+ORG:Open;Handset; Alliance
+SORT-STRING:android
+TEL;TYPE=PREF;TYPE=VOICE:0300000000
+CLASS:PUBLIC
+X-GNO:0
+X-GN:group0
+X-REDUCTION:0
+REV:20081031T065854Z
+END:VCARD
diff --git a/core/res/res/color/widget_paneltabwidget.xml b/tests/AndroidTests/res/values-12key-63x57/configVarying.xml index fcec9c0..50b3765 100644 --- a/core/res/res/color/widget_paneltabwidget.xml +++ b/tests/AndroidTests/res/values-12key-63x57/configVarying.xml @@ -14,7 +14,9 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_enabled="true" android:color="#ffffffff"/> - <item android:color="#ff000000"/> <!-- disabled --> -</selector> +<resources> + <item type="configVarying" name="simple">simple 12key 63x57</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 12key 63x57</item> + </bag> +</resources> diff --git a/core/res/res/color/theme_panel_text.xml b/tests/AndroidTests/res/values-12key-dpad/configVarying.xml index 1268a89..83eb080 100644 --- a/core/res/res/color/theme_panel_text.xml +++ b/tests/AndroidTests/res/values-12key-dpad/configVarying.xml @@ -14,7 +14,9 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_enabled="true" android:color="#FF000000"/> - <item android:color="#80888888"/> <!-- disabled --> -</selector> +<resources> + <item type="configVarying" name="simple">simple 12key dpad</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 12key dpad</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-12key/configVarying.xml b/tests/AndroidTests/res/values-12key/configVarying.xml index 14ce1a7..e11340c 100644 --- a/tests/AndroidTests/res/values-12key/configVarying.xml +++ b/tests/AndroidTests/res/values-12key/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag 12key</item> </bag> - <item type="configVarying" name="simple_12key">only simple 12key</item> - <bag type="configVarying" name="bag_12key"> - <item name="testString">only bag 12key</item> - </bag> </resources> diff --git a/core/res/res/color/widget_autocompletetextview_dark.xml b/tests/AndroidTests/res/values-240dpi/configVarying.xml index 802f6c6..9f32f8d 100644 --- a/core/res/res/color/widget_autocompletetextview_dark.xml +++ b/tests/AndroidTests/res/values-240dpi/configVarying.xml @@ -14,7 +14,9 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_focused="true" android:color="#ff000000"/> - <item android:color="#ffffffff"/> <!-- unfocused --> -</selector> +<resources> + <item type="configVarying" name="simple">simple 240dpi</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 240dpi</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-320x200/configVarying.xml b/tests/AndroidTests/res/values-320x200/configVarying.xml index 035e55e..ca2a286 100644 --- a/tests/AndroidTests/res/values-320x200/configVarying.xml +++ b/tests/AndroidTests/res/values-320x200/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag 320x200</item> </bag> - <item type="configVarying" name="simple_320x200">only simple 320x200</item> - <bag type="configVarying" name="bag_320x200"> - <item name="testString">only bag 320x200</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-32dpi-keysexposed/configVarying.xml b/tests/AndroidTests/res/values-32dpi-keysexposed/configVarying.xml new file mode 100644 index 0000000..cd7f8da --- /dev/null +++ b/tests/AndroidTests/res/values-32dpi-keysexposed/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple 32dpi keysexposed</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 32dpi keysexposed</item> + </bag> +</resources> diff --git a/core/res/res/color/widget_textview_bigspinneritem_dark.xml b/tests/AndroidTests/res/values-32dpi-stylus/configVarying.xml index d98fa46..63fcdc8 100644 --- a/core/res/res/color/widget_textview_bigspinneritem_dark.xml +++ b/tests/AndroidTests/res/values-32dpi-stylus/configVarying.xml @@ -14,7 +14,9 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_selected="true" android:color="#ff000000"/> - <item android:color="#ffffffff"/> <!-- unselected --> -</selector> +<resources> + <item type="configVarying" name="simple">simple 32dpi stylus</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 32dpi stylus</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-480x320/configVarying.xml b/tests/AndroidTests/res/values-480x320/configVarying.xml index 8b28d89..d4305fc 100644 --- a/tests/AndroidTests/res/values-480x320/configVarying.xml +++ b/tests/AndroidTests/res/values-480x320/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag 480x320</item> </bag> - <item type="configVarying" name="simple_480x320">only simple 480x320</item> - <bag type="configVarying" name="bag_480x320"> - <item name="testString">only bag 480x320</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-dpad-63x57/configVarying.xml b/tests/AndroidTests/res/values-dpad-63x57/configVarying.xml new file mode 100644 index 0000000..8383e9e --- /dev/null +++ b/tests/AndroidTests/res/values-dpad-63x57/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple dpad 63x57</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag dpad 63x57</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-finger/configVarying.xml index efe4758..674787e 100644 --- a/tests/AndroidTests/res/values-finger/configVarying.xml +++ b/tests/AndroidTests/res/values-finger/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag finger</item> </bag> - <item type="configVarying" name="simple_finger">only simple finger</item> - <bag type="configVarying" name="bag_finger"> - <item name="testString">only bag finger</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-keysexposed-12key/configVarying.xml b/tests/AndroidTests/res/values-keysexposed-12key/configVarying.xml new file mode 100644 index 0000000..2a2b8d9 --- /dev/null +++ b/tests/AndroidTests/res/values-keysexposed-12key/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple keysexposed 12key</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag keysexposed 12key</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-keysexposed-dpad/configVarying.xml b/tests/AndroidTests/res/values-keysexposed-dpad/configVarying.xml new file mode 100644 index 0000000..f279eb0 --- /dev/null +++ b/tests/AndroidTests/res/values-keysexposed-dpad/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple keysexposed dpad</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag keysexposed dpad</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-land/configVarying.xml b/tests/AndroidTests/res/values-land/configVarying.xml new file mode 100644 index 0000000..7d3d7e8 --- /dev/null +++ b/tests/AndroidTests/res/values-land/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple landscape</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag landscape</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mcc111-mnc222/configVarying.xml b/tests/AndroidTests/res/values-mcc111-mnc222/configVarying.xml new file mode 100644 index 0000000..84c31c6 --- /dev/null +++ b/tests/AndroidTests/res/values-mcc111-mnc222/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple mcc111 mnc222</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mcc111 mnc222</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mcc111-xx-rYY/configVarying.xml b/tests/AndroidTests/res/values-mcc111-xx-rYY/configVarying.xml new file mode 100644 index 0000000..3aa1ba0 --- /dev/null +++ b/tests/AndroidTests/res/values-mcc111-xx-rYY/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple mcc111 xx-rYY</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mcc111 xx-rYY</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mcc111-xx/configVarying.xml b/tests/AndroidTests/res/values-mcc111-xx/configVarying.xml new file mode 100644 index 0000000..09bd817 --- /dev/null +++ b/tests/AndroidTests/res/values-mcc111-xx/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple mcc111 xx</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mcc111 xx</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mcc111/configVarying.xml b/tests/AndroidTests/res/values-mcc111/configVarying.xml index 16b13a5..b516194 100644 --- a/tests/AndroidTests/res/values-mcc111/configVarying.xml +++ b/tests/AndroidTests/res/values-mcc111/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag mcc111</item> </bag> - <item type="configVarying" name="simple_mcc111">only simple mcc111</item> - <bag type="configVarying" name="bag_mcc111"> - <item name="testString">only bag mcc111</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-mnc222-square/configVarying.xml b/tests/AndroidTests/res/values-mnc222-square/configVarying.xml new file mode 100644 index 0000000..952c595 --- /dev/null +++ b/tests/AndroidTests/res/values-mnc222-square/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple mnc222 square</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mnc222 square</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mnc222-xx/configVarying.xml b/tests/AndroidTests/res/values-mnc222-xx/configVarying.xml new file mode 100644 index 0000000..c1cafbc --- /dev/null +++ b/tests/AndroidTests/res/values-mnc222-xx/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple mnc222 xx</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mnc222 xx</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mnc222/configVarying.xml b/tests/AndroidTests/res/values-mnc222/configVarying.xml index 7f68729..a37b7ef 100644 --- a/tests/AndroidTests/res/values-mnc222/configVarying.xml +++ b/tests/AndroidTests/res/values-mnc222/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag mnc222</item> </bag> - <item type="configVarying" name="simple_mnc222">only simple mnc222</item> - <bag type="configVarying" name="bag_mnc222"> - <item name="testString">only bag mnc222</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-notouch/configVarying.xml b/tests/AndroidTests/res/values-notouch/configVarying.xml index 8a71de4..f919f87 100644 --- a/tests/AndroidTests/res/values-notouch/configVarying.xml +++ b/tests/AndroidTests/res/values-notouch/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag notouch</item> </bag> - <item type="configVarying" name="simple_notouch">only simple notouch</item> - <bag type="configVarying" name="bag_notouch"> - <item name="testString">only bag notouch</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-port/configVarying.xml b/tests/AndroidTests/res/values-port/configVarying.xml new file mode 100644 index 0000000..0e1f247 --- /dev/null +++ b/tests/AndroidTests/res/values-port/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple portrait</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag portrait</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-square-32dpi/configVarying.xml b/tests/AndroidTests/res/values-square-32dpi/configVarying.xml new file mode 100644 index 0000000..41a69cd --- /dev/null +++ b/tests/AndroidTests/res/values-square-32dpi/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple square 32dpi</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag square 32dpi</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-square-stylus/configVarying.xml b/tests/AndroidTests/res/values-square-stylus/configVarying.xml new file mode 100644 index 0000000..de7892e --- /dev/null +++ b/tests/AndroidTests/res/values-square-stylus/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple square stylus</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag square stylus</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-square/configVarying.xml b/tests/AndroidTests/res/values-square/configVarying.xml new file mode 100644 index 0000000..ba3a036 --- /dev/null +++ b/tests/AndroidTests/res/values-square/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple square</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag square</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-stylus-12key/configVarying.xml b/tests/AndroidTests/res/values-stylus-12key/configVarying.xml new file mode 100644 index 0000000..d79f079 --- /dev/null +++ b/tests/AndroidTests/res/values-stylus-12key/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple stylus 12key</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag stylus 12key</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-stylus-keysexposed/configVarying.xml b/tests/AndroidTests/res/values-stylus-keysexposed/configVarying.xml new file mode 100644 index 0000000..ff4e766 --- /dev/null +++ b/tests/AndroidTests/res/values-stylus-keysexposed/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple stylus keysexposed</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag stylus keysexposed</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-stylus/configVarying.xml b/tests/AndroidTests/res/values-stylus/configVarying.xml index 87df119..83936a7 100644 --- a/tests/AndroidTests/res/values-stylus/configVarying.xml +++ b/tests/AndroidTests/res/values-stylus/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag stylus</item> </bag> - <item type="configVarying" name="simple_stylus">only simple stylus</item> - <bag type="configVarying" name="bag_stylus"> - <item name="testString">only bag stylus</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-xx-32dpi/configVarying.xml b/tests/AndroidTests/res/values-xx-32dpi/configVarying.xml new file mode 100644 index 0000000..4cc162c --- /dev/null +++ b/tests/AndroidTests/res/values-xx-32dpi/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple xx 32dpi</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag xx 32dpi</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-xx-rYY/configVarying.xml b/tests/AndroidTests/res/values-xx-rYY/configVarying.xml index 4e52db9..2d2a9a1 100644 --- a/tests/AndroidTests/res/values-xx-rYY/configVarying.xml +++ b/tests/AndroidTests/res/values-xx-rYY/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag xx-rYY</item> </bag> - <item type="configVarying" name="simple_xx_rYY">only simple xx_rYY</item> - <bag type="configVarying" name="bag_xx_rYY"> - <item name="testString">only bag xx_rYY</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values-xx-square/configVarying.xml b/tests/AndroidTests/res/values-xx-square/configVarying.xml new file mode 100644 index 0000000..807feec --- /dev/null +++ b/tests/AndroidTests/res/values-xx-square/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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> + <item type="configVarying" name="simple">simple xx square</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag xx square</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-xx/configVarying.xml b/tests/AndroidTests/res/values-xx/configVarying.xml index e50649d..fef2737 100644 --- a/tests/AndroidTests/res/values-xx/configVarying.xml +++ b/tests/AndroidTests/res/values-xx/configVarying.xml @@ -19,8 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag xx</item> </bag> - <item type="configVarying" name="simple_xx">only simple xx</item> - <bag type="configVarying" name="bag_xx"> - <item name="testString">only bag xx</item> - </bag> </resources> diff --git a/tests/AndroidTests/res/values/configVarying.xml b/tests/AndroidTests/res/values/configVarying.xml index c4a20ad..3b3e4a4 100644 --- a/tests/AndroidTests/res/values/configVarying.xml +++ b/tests/AndroidTests/res/values/configVarying.xml @@ -19,9 +19,4 @@ <bag type="configVarying" name="bag"> <item name="testString">bag default</item> </bag> - - <item type="configVarying" name="simple_default">only simple default</item> - <bag type="configVarying" name="bag_default"> - <item name="testString">only bag default</item> - </bag> </resources> diff --git a/tests/AndroidTests/src/com/android/unit_tests/VCardTests.java b/tests/AndroidTests/src/com/android/unit_tests/VCardTests.java new file mode 100644 index 0000000..b7f562d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/VCardTests.java @@ -0,0 +1,773 @@ +/* + * Copyright (C) 2009 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.unit_tests; + +import android.content.ContentValues; +import android.syncml.pim.PropertyNode; +import android.syncml.pim.VDataBuilder; +import android.syncml.pim.VNode; +import android.syncml.pim.vcard.VCardException; +import android.syncml.pim.vcard.VCardParser_V21; +import android.syncml.pim.vcard.VCardParser_V30; +import android.test.AndroidTestCase; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Vector; + +public class VCardTests extends AndroidTestCase { + + private class PropertyNodesVerifier { + private HashMap<String, Vector<PropertyNode>> mPropertyNodeMap; + public PropertyNodesVerifier(PropertyNode... nodes) { + mPropertyNodeMap = new HashMap<String, Vector<PropertyNode>>(); + for (PropertyNode propertyNode : nodes) { + String propName = propertyNode.propName; + Vector<PropertyNode> expectedNodes = + mPropertyNodeMap.get(propName); + if (expectedNodes == null) { + expectedNodes = new Vector<PropertyNode>(); + mPropertyNodeMap.put(propName, expectedNodes); + } + expectedNodes.add(propertyNode); + } + } + + public void verify(VNode vnode) { + for (PropertyNode propertyNode : vnode.propList) { + String propName = propertyNode.propName; + Vector<PropertyNode> nodes = mPropertyNodeMap.get(propName); + if (nodes == null) { + fail("Unexpected propName \"" + propName + "\" exists."); + } + boolean successful = false; + int size = nodes.size(); + for (int i = 0; i < size; i++) { + PropertyNode expectedNode = nodes.get(i); + if (expectedNode.propName.equals(propName)) { + if (expectedNode.equals(propertyNode)) { + successful = true; + nodes.remove(i); + if (nodes.size() == 0) { + mPropertyNodeMap.remove(propName); + } + break; + } else { + fail("Property \"" + propName + "\" has wrong value.\n" + + "expected: " + expectedNode.toString() + + "\n actual: " + propertyNode.toString()); + } + } + } + if (!successful) { + fail("Unexpected property \"" + propName + "\" exists."); + } + } + if (mPropertyNodeMap.size() != 0) { + Vector<String> expectedProps = new Vector<String>(); + for (Vector<PropertyNode> nodes : mPropertyNodeMap.values()) { + for (PropertyNode node : nodes) { + expectedProps.add(node.propName); + } + } + fail("expected props " + Arrays.toString(expectedProps.toArray()) + + " was not found"); + } + } + } + + public void testV21SimpleCase() throws IOException, VCardException { + VCardParser_V21 parser = new VCardParser_V21(); + VDataBuilder builder = new VDataBuilder(); + InputStream is = getContext().getResources().openRawResource(R.raw.v21_simple); + assertEquals(true, parser.parse(is,"ISO-8859-1", builder)); + is.close(); + assertEquals(1, builder.vNodeList.size()); + PropertyNodesVerifier verifier = new PropertyNodesVerifier( + new PropertyNode("N", "Ando;Roid;", + Arrays.asList("Ando", "Roid", ""), + null, null, null, null), + new PropertyNode("FN", "Ando Roid", + null, null, null, null, null)); + verifier.verify(builder.vNodeList.get(0)); + } + + public void testV21BackslashCase() throws IOException, VCardException { + VCardParser_V21 parser = new VCardParser_V21(); + VDataBuilder builder = new VDataBuilder(); + InputStream is = getContext().getResources().openRawResource(R.raw.v21_backslash); + assertEquals(true, parser.parse(is,"ISO-8859-1", builder)); + is.close(); + assertEquals(1, builder.vNodeList.size()); + PropertyNodesVerifier verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "2.1", + null, null, null, null, null), + new PropertyNode("N", ";A;B\\;C\\;;D;:E;\\\\;", + Arrays.asList("", "A;B\\", "C\\;", "D", ":E", "\\\\", ""), + null, null, null, null), + new PropertyNode("FN", "A;B\\C\\;D:E\\\\", + null, null, null, null, null)); + verifier.verify(builder.vNodeList.get(0)); + } + + public void testV21ComplicatedCase() throws IOException, VCardException { + VCardParser_V21 parser = new VCardParser_V21(); + VDataBuilder builder = new VDataBuilder(); + InputStream is = getContext().getResources().openRawResource(R.raw.v21_complicated); + assertEquals(true, parser.parse(is,"ISO-8859-1", builder)); + is.close(); + assertEquals(1, builder.vNodeList.size()); + ContentValues contentValuesForQP = new ContentValues(); + contentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE"); + ContentValues contentValuesForPhoto = new ContentValues(); + contentValuesForPhoto.put("ENCODING", "BASE64"); + // Push data into int array at first since values like 0x80 are + // interpreted as int by the compiler and casting all of them is + // cumbersome... + int[] photoIntArray = { + 0xff, 0xd8, 0xff, 0xe1, 0x0a, 0x0f, 0x45, 0x78, 0x69, 0x66, 0x00, + 0x00, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, + 0x01, 0x0e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0xaa, 0x01, 0x0f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x00, 0xba, 0x01, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0xc2, 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x1b, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0xd0, 0x01, 0x28, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x31, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x32, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xe6, 0x02, 0x13, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x82, + 0x98, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xfa, + 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x84, 0xc4, 0xa5, 0x00, 0x07, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, + 0x01, 0x08, 0x00, 0x00, 0x04, 0x1e, 0x32, 0x30, 0x30, 0x38, 0x31, + 0x30, 0x32, 0x39, 0x31, 0x33, 0x35, 0x35, 0x33, 0x31, 0x00, 0x00, + 0x44, 0x6f, 0x43, 0x6f, 0x4d, 0x6f, 0x00, 0x00, 0x44, 0x39, 0x30, + 0x35, 0x69, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x44, 0x39, 0x30, + 0x35, 0x69, 0x20, 0x56, 0x65, 0x72, 0x31, 0x2e, 0x30, 0x30, 0x00, + 0x32, 0x30, 0x30, 0x38, 0x3a, 0x31, 0x30, 0x3a, 0x32, 0x39, 0x20, + 0x31, 0x33, 0x3a, 0x35, 0x35, 0x3a, 0x34, 0x37, 0x00, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x49, 0x4d, 0x00, 0x30, 0x33, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x34, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x09, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x0f, 0x0b, 0x00, + 0x00, 0x27, 0x10, 0x00, 0x00, 0x05, 0x97, 0x00, 0x00, 0x27, 0x10, + 0x00, 0x00, 0x08, 0xb0, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x1c, + 0x01, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x02, 0x5e, 0x00, 0x00, + 0x27, 0x10, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x27, 0x10, 0x00, + 0x00, 0x03, 0xcb, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x1b, 0xe5, + 0x00, 0x00, 0x27, 0x10, 0x00, 0x28, 0x82, 0x9a, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x6a, 0x82, 0x9d, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x72, 0x88, 0x22, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x90, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x30, 0x32, 0x32, 0x30, 0x90, + 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x03, 0x7a, + 0x90, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x03, + 0x8e, 0x91, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, + 0x03, 0x00, 0x91, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x03, 0xa2, 0x92, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x03, 0xaa, 0x92, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x03, 0xb2, 0x92, 0x04, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x03, 0xba, 0x92, 0x05, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xc2, 0x92, 0x07, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x92, 0x08, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x92, 0x09, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x92, + 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xca, + 0x92, 0x7c, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x92, 0x86, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x03, 0xd2, 0xa0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x30, + 0x31, 0x30, 0x30, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x60, 0x00, 0x00, 0xa0, 0x03, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0xa0, 0x05, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x0e, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xe8, 0xa2, 0x0f, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xf0, 0xa2, 0x10, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa2, + 0x17, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, + 0xa3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, + 0x00, 0xa3, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0xa4, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0xa4, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xa4, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x04, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x03, 0xf8, 0xa4, 0x05, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0xa4, 0x06, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x07, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x08, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, + 0x09, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xa4, 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xa4, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, + 0x00, 0x27, 0x10, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x00, 0x64, + 0x32, 0x30, 0x30, 0x38, 0x3a, 0x31, 0x30, 0x3a, 0x32, 0x39, 0x20, + 0x31, 0x33, 0x3a, 0x35, 0x35, 0x3a, 0x33, 0x31, 0x00, 0x32, 0x30, + 0x30, 0x38, 0x3a, 0x31, 0x30, 0x3a, 0x32, 0x39, 0x20, 0x31, 0x33, + 0x3a, 0x35, 0x35, 0x3a, 0x34, 0x37, 0x00, 0x00, 0x00, 0x29, 0x88, + 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x02, 0xb2, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x25, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0e, 0x92, 0x00, 0x00, 0x03, 0xe8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x30, 0x30, + 0x38, 0x31, 0x30, 0x32, 0x39, 0x31, 0x33, 0x35, 0x35, 0x33, 0x31, + 0x00, 0x00, 0x20, 0x2a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x2a, + 0xe2, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x04, 0x52, 0x39, 0x38, 0x00, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x04, 0x30, 0x31, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x00, 0x01, 0x1a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x04, 0x6c, 0x01, 0x1b, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x04, 0x74, 0x01, 0x28, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x04, 0x7c, 0x02, 0x02, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x8b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, + 0x00, 0x20, 0x16, 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c, + 0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30, 0x2c, 0x2c, 0x30, + 0x62, 0x46, 0x4a, 0x3a, 0x50, 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, + 0x70, 0x6e, 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a, 0x6e, + 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4, 0xce, 0xd0, 0xce, 0x7c, + 0x9a, 0xe2, 0xf2, 0xe0, 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0x01, + 0x22, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, + 0x84, 0x70, 0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xff, 0xc0, + 0x00, 0x11, 0x08, 0x00, 0x78, 0x00, 0xa0, 0x03, 0x01, 0x21, 0x00, + 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x01, 0xa2, 0x00, + 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, + 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, + 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, + 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, + 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, + 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, + 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01, 0x00, + 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, + 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, + 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, + 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, + 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, + 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, + 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, + 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, + 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, + 0x14, 0x54, 0xaa, 0x2a, 0x46, 0x48, 0xa2, 0xa4, 0x55, 0xa6, 0x04, + 0x8a, 0x29, 0xe0, 0x53, 0x10, 0xe0, 0x29, 0xc0, 0x50, 0x03, 0xb1, + 0x46, 0x29, 0x80, 0x84, 0x52, 0x11, 0x40, 0x0d, 0x22, 0x9a, 0x45, + 0x20, 0x23, 0x61, 0x51, 0x30, 0xa0, 0x08, 0xc8, 0xa8, 0xd8, 0x52, + 0x02, 0x26, 0x15, 0x0b, 0x0a, 0x00, 0xb4, 0xa2, 0xa5, 0x5a, 0x00, + 0x91, 0x45, 0x4a, 0xa2, 0x81, 0x92, 0x01, 0x4e, 0x02, 0x98, 0x87, + 0x0a, 0x70, 0xa0, 0x07, 0x62, 0x8c, 0x50, 0x21, 0x0d, 0x25, 0x00, + 0x34, 0x8a, 0x61, 0x14, 0x0c, 0x63, 0x0a, 0x89, 0x85, 0x00, 0x46, + 0xd5, 0x1b, 0x52, 0x02, 0x16, 0xa8, 0x98, 0x50, 0x05, 0x94, 0xa9, + 0x16, 0x80, 0x25, 0x5a, 0x95, 0x68, 0x18, 0xf1, 0x4f, 0x14, 0xc4, + 0x3b, 0xb5, 0x22, 0xb6, 0x38, 0x34, 0x00, 0xe3, 0x22, 0x8e, 0xf4, + 0x79, 0x8a, 0x7b, 0xd1, 0x71, 0x03, 0x30, 0xc7, 0x14, 0x83, 0xa5, + 0x00, 0x06, 0x98, 0x68, 0x01, 0x8d, 0x51, 0x35, 0x03, 0x22, 0x6a, + 0x8d, 0xa9, 0x01, 0x13, 0x54, 0x4d, 0x40, 0x13, 0xa5, 0x4a, 0x28, + 0x02, 0x45, 0x35, 0x2a, 0x9a, 0x00, 0x78, 0x34, 0xf0, 0x69, 0x80, + 0x34, 0x81, 0x45, 0x40, 0xce, 0x58, 0xe6, 0xa2, 0x4c, 0x06, 0xe4, + 0xfa, 0xd1, 0x93, 0x50, 0x21, 0xca, 0xe4, 0x55, 0x84, 0x90, 0x30, + 0xab, 0x8b, 0x18, 0xa6, 0x9a, 0x6a, 0xc4, 0x31, 0xaa, 0x26, 0xa0, + 0x64, 0x4d, 0x51, 0xb5, 0x20, 0x23, 0x6a, 0x89, 0xa8, 0x02, 0x44, + 0x35, 0x2a, 0x9a, 0x00, 0x95, 0x4d, 0x48, 0xa6, 0x80, 0x24, 0x53, + 0x4e, 0xce, 0x05, 0x30, 0x2b, 0x3b, 0xee, 0x6a, 0x91, 0x5d, 0x76, + 0x63, 0xbd, 0x65, 0x7d, 0x40, 0x66, 0x68, 0xa9, 0x02, 0x45, 0x2b, + 0xb3, 0x9e, 0xb4, 0xc5, 0x6d, 0xad, 0x9a, 0xa0, 0x2c, 0x06, 0xc8, + 0xcd, 0x04, 0xd6, 0xa2, 0x23, 0x63, 0x51, 0xb1, 0xa0, 0x64, 0x4d, + 0x51, 0x93, 0x48, 0x08, 0xda, 0xa2, 0x6a, 0x00, 0x72, 0x1a, 0x99, + 0x4d, 0x00, 0x48, 0xa6, 0xa4, 0x53, 0x4c, 0x07, 0x86, 0x03, 0xbd, + 0x2b, 0x9c, 0xa7, 0x14, 0x98, 0x10, 0x85, 0x34, 0xe0, 0xa6, 0xb3, + 0xb0, 0x0b, 0xb5, 0xa8, 0x0a, 0xd4, 0x58, 0x42, 0xed, 0x3e, 0x94, + 0xd2, 0xa6, 0x8b, 0x01, 0x34, 0x44, 0xed, 0xe6, 0x9c, 0x4d, 0x6a, + 0x80, 0x8d, 0x8d, 0x46, 0xc6, 0x80, 0x23, 0x63, 0x51, 0x9a, 0x06, + 0x46, 0xd5, 0x13, 0x52, 0x01, 0x54, 0xd4, 0xaa, 0x68, 0x02, 0x40, + 0x6a, 0x40, 0x78, 0xa0, 0x08, 0x59, 0xce, 0xee, 0xb5, 0x2a, 0x39, + 0xd9, 0x59, 0xa7, 0xa8, 0x00, 0x73, 0xeb, 0x4e, 0x0e, 0x7d, 0x69, + 0x5c, 0x05, 0xf3, 0x0f, 0xad, 0x1e, 0x61, 0xf5, 0xa7, 0x71, 0x0b, + 0xe6, 0x35, 0x21, 0x90, 0xd3, 0xb8, 0x0e, 0x32, 0x10, 0x95, 0x10, + 0x91, 0xb3, 0xd6, 0x9b, 0x60, 0x4b, 0x9c, 0x8a, 0x63, 0x1a, 0xb0, + 0x18, 0x4d, 0x46, 0xc6, 0x80, 0x22, 0x6a, 0x61, 0xa4, 0x31, 0xaa, + 0x6a, 0x55, 0x34, 0x01, 0x2a, 0x9a, 0x7e, 0x78, 0xa0, 0x08, 0x09, + 0xf9, 0xaa, 0x58, 0xcf, 0xca, 0x6b, 0x3e, 0xa0, 0x00, 0xd3, 0x81, + 0xa9, 0x01, 0x73, 0x46, 0x69, 0x80, 0xb9, 0xa4, 0xcd, 0x00, 0x2b, + 0x1f, 0x92, 0xa3, 0x07, 0x9a, 0x6f, 0x70, 0x26, 0xcf, 0x14, 0xd2, + 0x6b, 0x51, 0x0c, 0x63, 0x51, 0xb1, 0xa0, 0x08, 0xda, 0x98, 0x69, + 0x0c, 0x8d, 0x4d, 0x4a, 0xa6, 0x80, 0x24, 0x53, 0x52, 0x03, 0xc5, + 0x02, 0x21, 0x27, 0xe6, 0xa9, 0x23, 0x3f, 0x29, 0xac, 0xfa, 0x8c, + 0x01, 0xe6, 0x9c, 0x0d, 0x48, 0x0a, 0x0d, 0x2e, 0x68, 0x01, 0x73, + 0x49, 0x9a, 0x60, 0x2b, 0x1f, 0x92, 0x98, 0x3a, 0xd3, 0x7b, 0x81, + 0x36, 0x78, 0xa6, 0x93, 0x5a, 0x88, 0x8c, 0x9a, 0x63, 0x1a, 0x00, + 0x8c, 0xd3, 0x0d, 0x21, 0x91, 0x29, 0xa9, 0x14, 0xd0, 0x04, 0x8a, + 0x69, 0xe0, 0xd3, 0x11, 0x1b, 0x1e, 0x6a, 0x48, 0xcf, 0xca, 0x6b, + 0x3e, 0xa3, 0x10, 0x1a, 0x70, 0x35, 0x20, 0x38, 0x1a, 0x5c, 0xd2, + 0x01, 0x73, 0x49, 0x9a, 0x60, 0x39, 0x8f, 0xca, 0x29, 0x8b, 0xf7, + 0xaa, 0xba, 0x88, 0x96, 0x9a, 0x6b, 0x40, 0x18, 0xc6, 0xa3, 0x26, + 0x80, 0x18, 0x69, 0xa6, 0x90, 0xc8, 0x14, 0xd4, 0x8a, 0x69, 0x80, + 0xf0, 0x6a, 0x40, 0x68, 0x10, 0xbb, 0x41, 0xa7, 0xe3, 0x0b, 0xc5, + 0x2b, 0x01, 0x10, 0xa7, 0x03, 0x59, 0x0c, 0x76, 0x69, 0x73, 0x40, + 0x0b, 0x9a, 0x28, 0x11, 0x28, 0x19, 0x5e, 0x69, 0x02, 0x81, 0x5a, + 0xd8, 0x00, 0xd3, 0x4d, 0x50, 0x0c, 0x6a, 0x8c, 0xd2, 0x01, 0xa6, + 0x98, 0x69, 0x0c, 0xae, 0xa6, 0xa4, 0x06, 0x80, 0x1e, 0xa6, 0x9e, + 0x0d, 0x31, 0x12, 0x03, 0x4f, 0x06, 0x80, 0x13, 0x60, 0x34, 0xd3, + 0xc1, 0xa8, 0x92, 0x01, 0xf1, 0x8d, 0xdd, 0x69, 0xcc, 0xa1, 0x69, + 0x5b, 0x4b, 0x80, 0x83, 0x93, 0x52, 0x04, 0x14, 0xe2, 0xae, 0x03, + 0xa9, 0x0d, 0x68, 0x03, 0x4d, 0x34, 0xd0, 0x03, 0x0d, 0x30, 0xd2, + 0x01, 0x86, 0x9a, 0x68, 0x19, 0x58, 0x1a, 0x78, 0xa4, 0x04, 0x8a, + 0x69, 0xe0, 0xd3, 0x10, 0xe0, 0x69, 0xe0, 0xd0, 0x03, 0xc1, 0xa8, + 0xdb, 0xad, 0x4c, 0x81, 0x12, 0x45, 0xd6, 0x9d, 0x25, 0x1d, 0x00, + 0x6a, 0xf5, 0xa9, 0xe8, 0x80, 0x31, 0x29, 0x0d, 0x58, 0x08, 0x69, + 0x86, 0x80, 0x1a, 0x69, 0x86, 0x90, 0x0c, 0x34, 0xd3, 0x48, 0x65, + 0x51, 0x4f, 0x06, 0x98, 0x0f, 0x14, 0xf0, 0x68, 0x10, 0xf0, 0x69, + 0xe0, 0xd0, 0x03, 0x81, 0xa5, 0x2b, 0x9a, 0x1a, 0xb8, 0x87, 0xa8, + 0xdb, 0x4a, 0x46, 0x68, 0xb6, 0x80, 0x2a, 0xa8, 0x14, 0xea, 0x12, + 0xb0, 0x05, 0x21, 0xa6, 0x02, 0x1a, 0x61, 0xa0, 0x06, 0x9a, 0x61, + 0xa4, 0x31, 0x86, 0x9a, 0x69, 0x0c, 0xa8, 0x0d, 0x3c, 0x53, 0x01, + 0xe2, 0x9e, 0x28, 0x10, 0xf1, 0x4e, 0x06, 0x98, 0x0f, 0x06, 0x9e, + 0x0d, 0x02, 0x1c, 0x29, 0xc2, 0x80, 0x16, 0x96, 0x80, 0x0a, 0x4a, + 0x00, 0x43, 0x4d, 0x34, 0x0c, 0x61, 0xa6, 0x1a, 0x40, 0x34, 0xd3, + 0x4d, 0x21, 0x80, 0xff, 0xd9, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0a, + 0x07, 0x07, 0x08, 0x07, 0x06, 0x0a, 0x08, 0x08, 0x08, 0x0b, 0x0a, + 0x0a, 0x0b, 0x0e, 0x18, 0x10, 0x0e, 0x0d, 0x0d, 0x0e, 0x1d, 0x15, + 0x16, 0x11, 0x18, 0x23, 0x1f, 0x25, 0x24, 0x22, 0x1f, 0x22, 0x21, + 0x26, 0x2b, 0x37, 0x2f, 0x26, 0x29, 0x34, 0x29, 0x21, 0x22, 0x30, + 0x41, 0x31, 0x34, 0x39, 0x3b, 0x3e, 0x3e, 0x3e, 0x25, 0x2e, 0x44, + 0x49, 0x43, 0x3c, 0x48, 0x37, 0x3d, 0x3e, 0x3b, 0x01, 0x0a, 0x0b, + 0x0b, 0x0e, 0x0d, 0x0e, 0x1c, 0x10, 0x10, 0x1c, 0x3b, 0x28, 0x22, + 0x28, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x48, 0x00, 0x60, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, + 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, + 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, + 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, + 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, + 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, + 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, + 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, + 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, + 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, + 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, + 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, + 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, + 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, + 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, + 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, + 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, + 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x9e, 0xd2, + 0x2e, 0x07, 0x15, 0xaf, 0x6d, 0x08, 0xe2, 0xb3, 0x45, 0x1a, 0xf6, + 0xd0, 0x00, 0x01, 0xc5, 0x68, 0x45, 0x17, 0x4a, 0xb4, 0x22, 0xe4, + 0x70, 0x8c, 0x74, 0xa9, 0x3c, 0xa1, 0x8e, 0x95, 0x48, 0x96, 0x31, + 0xe2, 0x18, 0xe9, 0x55, 0xa5, 0x8c, 0x7a, 0x50, 0x05, 0x0b, 0x88, + 0x86, 0x0f, 0x15, 0x8f, 0x75, 0x1f, 0x26, 0x93, 0x19, 0x91, 0x77, + 0x18, 0xc1, 0xac, 0x4b, 0xc8, 0xfa, 0xd6, 0x63, 0x37, 0x6d, 0x31, + 0xb4, 0x73, 0x5b, 0x36, 0xa0, 0x1c, 0x50, 0x80, 0xd7, 0x83, 0xa0, + 0xab, 0xd1, 0x62, 0xad, 0x09, 0x8f, 0x17, 0x29, 0x03, 0xb2, 0xcc, + 0xe0, 0x77, 0x14, 0xa3, 0x56, 0xb3, 0x27, 0x1e, 0x67, 0xe9, 0x52, + 0xea, 0xc6, 0x3a, 0x36, 0x48, 0xef, 0x3d, 0x27, 0x70, 0x22, 0x60, + 0x47, 0x52, 0x69, 0xb2, 0xe2, 0xad, 0x3b, 0xea, 0x80, 0xa3, 0x38, + 0xe0, 0xd6, 0x3d, 0xd8, 0x1c, 0xd0, 0xca, 0x46, 0x3d, 0xd0, 0x18, + 0x35, 0x89, 0x78, 0xa3, 0x9a, 0xcd, 0x8c, 0xd2, 0xb3, 0x93, 0x2a, + 0x2b, 0x66, 0xd5, 0xf1, 0x8a, 0x10, 0x1a, 0xd6, 0xf2, 0x03, 0x8a, + 0x9e, 0xe6, 0xf4, 0x5a, 0xdb, 0xef, 0xfe, 0x23, 0xc0, 0xa7, 0x27, + 0xcb, 0x16, 0xc4, 0xcc, 0xdd, 0xe2, 0x78, 0x9a, 0x69, 0x66, 0xcc, + 0x99, 0xe1, 0x4d, 0x47, 0xba, 0xbc, 0xd9, 0x6a, 0xee, 0x26, 0x59, + 0x59, 0x4d, 0xac, 0x69, 0x34, 0x52, 0xe5, 0x8f, 0x55, 0xad, 0x58, + 0xae, 0x85, 0xc4, 0x22, 0x41, 0xdf, 0xad, 0x76, 0x61, 0xe5, 0x6f, + 0x74, 0x45, 0x69, 0xdc, 0x00, 0x79, 0xac, 0x8b, 0xa6, 0xc9, 0x35, + 0xd4, 0x34, 0x64, 0xdc, 0x37, 0x06, 0xb1, 0xae, 0x88, 0xc1, 0xac, + 0xd8, 0xc9, 0x2c, 0xa6, 0xe0, 0x73, 0x5b, 0x36, 0xf3, 0x74, 0xe6, + 0x84, 0x05, 0xe3, 0xa9, 0x47, 0x6a, 0x14, 0xb6, 0x49, 0x3d, 0x85, + 0x3a, 0xee, 0xee, 0x2b, 0xa8, 0xe2, 0x6f, 0x30, 0x81, 0xe9, 0x8a, + 0xca, 0xa4, 0xe2, 0xd3, 0x8b, 0x01, 0xb1, 0xf9, 0x04, 0x7f, 0xaf, + 0x23, 0xf0, 0xa9, 0x54, 0x41, 0x9c, 0xfd, 0xa3, 0xf4, 0xae, 0x65, + 0x18, 0xf7, 0x25, 0x8a, 0xe2, 0x02, 0x38, 0xb8, 0xfd, 0x2a, 0x7b, + 0x5b, 0xa8, 0x6d, 0x6d, 0x5d, 0x9a, 0x5d, 0xcb, 0xbb, 0xd2, 0xb6, + 0xa6, 0xa3, 0x19, 0x5e, 0xe2, 0x03, 0x7b, 0x1d, 0xc2, 0x17, 0x8d, + 0xb8, 0xac, 0xfb, 0x89, 0x39, 0x35, 0xd6, 0x9a, 0x6a, 0xe8, 0x66, + 0x55, 0xcb, 0xf5, 0xac, 0x7b, 0x96, 0xeb, 0x50, 0xc6, 0x88, 0x6d, + 0x66, 0xe9, 0xcd, 0x6c, 0xdb, 0x4f, 0xd3, 0x9a, 0x00, 0x2f, 0xe6, + 0xf9, 0xa3, 0xe7, 0xb5, 0x4a, 0x93, 0x7f, 0xa2, 0xc6, 0x73, 0xdc, + 0xd7, 0x15, 0x55, 0xef, 0x48, 0x7d, 0x09, 0x52, 0x6e, 0x3a, 0xd4, + 0xab, 0x2f, 0xbd, 0x61, 0x16, 0x0c, 0x73, 0x49, 0xc5, 0x24, 0x92, + 0x7f, 0xa2, 0x63, 0xfd, 0xaa, 0xd6, 0x2f, 0x71, 0x0e, 0xb1, 0x93, + 0xf7, 0x2d, 0xf5, 0xa4, 0x9e, 0x4e, 0xb5, 0xdd, 0x4b, 0xf8, 0x68, + 0x4c, 0xcb, 0xb9, 0x93, 0xad, 0x65, 0xce, 0xd9, 0x26, 0xa9, 0x8d, + 0x19, 0xf6, 0xf2, 0xf4, 0xe6, 0xb5, 0xad, 0xe7, 0xc6, 0x39, 0xa0, + 0x18, 0xeb, 0xc9, 0x77, 0x6c, 0x35, 0x2a, 0x4b, 0xfe, 0x8a, 0x9c, + 0xff, 0x00, 0x11, 0xae, 0x3a, 0x8b, 0xde, 0x61, 0xd0, 0x9e, 0x39, + 0xb8, 0xeb, 0x53, 0xac, 0xb9, 0xae, 0x5b, 0x00, 0xf3, 0x27, 0x14, + 0x92, 0xc9, 0xfe, 0x8a, 0x3f, 0xde, 0x35, 0xac, 0x3a, 0x88, 0x92, + 0xcd, 0xb1, 0x6e, 0x7d, 0xcd, 0x32, 0x67, 0xeb, 0xcd, 0x7a, 0x14, + 0xfe, 0x04, 0x26, 0x66, 0xce, 0xf9, 0x26, 0xb3, 0xe6, 0x6e, 0xb4, + 0xd9, 0x48, 0xc8, 0x82, 0x4e, 0x07, 0x35, 0xa7, 0x6f, 0x2f, 0x02, + 0x9a, 0x06, 0x5f, 0x8c, 0xa4, 0x83, 0x0e, 0x32, 0x2a, 0x69, 0xe3, + 0xdd, 0x12, 0x08, 0x97, 0x85, 0xec, 0x2a, 0x2a, 0x42, 0xf1, 0x76, + 0x26, 0xe4, 0x6a, 0x59, 0x0e, 0x18, 0x10, 0x6a, 0xd2, 0x89, 0x02, + 0x6e, 0x2a, 0x71, 0xeb, 0x5c, 0x1c, 0x8c, 0xa6, 0x48, 0xbb, 0xdc, + 0x61, 0x41, 0x35, 0x72, 0x28, 0x87, 0xd9, 0xf6, 0x4a, 0xb9, 0xe7, + 0x38, 0xae, 0x8c, 0x3d, 0x36, 0xdd, 0xde, 0xc4, 0xb0, 0x21, 0x51, + 0x76, 0xa8, 0xc0, 0xaa, 0x93, 0x31, 0xe6, 0xbb, 0x2d, 0x65, 0x61, + 0x19, 0xd3, 0x1e, 0xb5, 0x46, 0x5a, 0x96, 0x5a, 0x30, 0xa0, 0x7e, + 0x05, 0x69, 0x5b, 0xc9, 0xc6, 0x28, 0x40, 0xcd, 0x08, 0x64, 0x3c, + 0x73, 0x57, 0xe1, 0x94, 0xf1, 0xcd, 0x5a, 0x21, 0x8c, 0xb9, 0x63, + 0xe7, 0x67, 0x1d, 0xab, 0x40, 0xb1, 0xfb, 0x00, 0x1d, 0xf0, 0x2b, + 0x99, 0x2d, 0x66, 0x3e, 0x88, 0x75, 0x81, 0x3f, 0x31, 0xf6, 0xab, + 0x64, 0xd6, 0xb4, 0x17, 0xee, 0xd0, 0x9e, 0xe4, 0x32, 0x1a, 0xa7, + 0x31, 0xad, 0x18, 0x14, 0x26, 0xef, 0x54, 0xa5, 0xa8, 0x65, 0xa3, + 0x9c, 0x81, 0xfa, 0x56, 0x8c, 0x2d, 0xce, 0x68, 0x40, 0xcb, 0xf1, + 0x37, 0xbd, 0x5e, 0x85, 0xea, 0xd1, 0x0c, 0xbb, 0x19, 0x56, 0x23, + 0x20, 0x1f, 0xad, 0x5c, 0x42, 0x08, 0x03, 0xb5, 0x55, 0x91, 0x04, + 0xc9, 0x80, 0x38, 0x00, 0x0a, 0x71, 0x34, 0x6c, 0x32, 0x27, 0xe9, + 0x55, 0x25, 0x15, 0x2c, 0x68, 0xa3, 0x30, 0xeb, 0x54, 0xa5, 0x15, + 0x0c, 0xd1, 0x00, 0xff, 0xd9}; + int length = photoIntArray.length; + byte[] photoByteArray = new byte[length]; + for (int i = 0; i < length; i++) { + photoByteArray[i] = (byte)photoIntArray[i]; + } + PropertyNodesVerifier verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "2.1", + null, null, null, null, null), + new PropertyNode("N", "Gump;Forrest;Hoge;Pos;Tao", + Arrays.asList("Gump", "Forrest", + "Hoge", "Pos", "Tao"), + null, null, null, null), + new PropertyNode("FN", "Joe Due", + null, null, null, null, null), + new PropertyNode("ORG", + "Gump Shrimp Co.;Sales Dept.;Manager;Fish keeper", + Arrays.asList("Gump Shrimp Co.", + "Sales Dept.;Manager", + "Fish keeper"), + null, null, null, null), + new PropertyNode("ROLE", "Fish Cake Keeper!", + null, null, null, null, null), + new PropertyNode("TITLE", "Shrimp Man", + null, null, null, null, null), + new PropertyNode("X-CLASS", "PUBLIC", + null, null, null, null, null), + new PropertyNode("TEL", "(111) 555-1212", + null, null, null, + new HashSet<String>(Arrays.asList("WORK", "VOICE")), null), + new PropertyNode("TEL", "(404) 555-1212", + null, null, null, + new HashSet<String>(Arrays.asList("HOME", "VOICE")), null), + new PropertyNode("TEL", "0311111111", + null, null, null, + new HashSet<String>(Arrays.asList("CELL")), null), + new PropertyNode("TEL", "0322222222", + null, null, null, + new HashSet<String>(Arrays.asList("VIDEO")), null), + new PropertyNode("TEL", "0333333333", + null, null, null, + new HashSet<String>(Arrays.asList("VOICE")), null), + new PropertyNode("ADR", + ";;100 Waters Edge;Baytown;LA;30314;United States of America", + Arrays.asList("", "", "100 Waters Edge", "Baytown", + "LA", "30314", "United States of America"), + null, null, + new HashSet<String>(Arrays.asList("WORK")), null), + new PropertyNode("LABEL", + "100 Waters Edge\r\nBaytown, LA 30314\r\nUnited States of America", + null, null, contentValuesForQP, + new HashSet<String>(Arrays.asList("WORK")), null), + new PropertyNode("ADR", + ";;42 Plantation St.;Baytown;LA;30314;United States of America", + Arrays.asList("", "", "42 Plantation St.", "Baytown", + "LA", "30314", "United States of America"), null, null, + new HashSet<String>(Arrays.asList("HOME")), null), + new PropertyNode("LABEL", + "42 Plantation St.\r\nBaytown, LA 30314\r\nUnited States of America", + null, null, contentValuesForQP, + new HashSet<String>(Arrays.asList("HOME")), null), + new PropertyNode("EMAIL", "forrestgump@walladalla.com", + null, null, null, + new HashSet<String>(Arrays.asList("PREF", "INTERNET")), null), + new PropertyNode("EMAIL", "cell@example.com", + null, null, null, + new HashSet<String>(Arrays.asList("CELL")), null), + new PropertyNode("NOTE", "The following note is the example from RFC 2045.", + null, null, null, null, null), + new PropertyNode("NOTE", + "Now's the time for all folk to come to the aid of their country.", + null, null, contentValuesForQP, null, null), + new PropertyNode("PHOTO", null, + null, photoByteArray, contentValuesForPhoto, + new HashSet<String>(Arrays.asList("JPEG")), null), + new PropertyNode("X-ATTRIBUTE", "Some String", + null, null, null, null, null), + new PropertyNode("BDAY", "19800101", + null, null, null, null, null), + new PropertyNode("GEO", "35.6563854,139.6994233", + null, null, null, null, null), + new PropertyNode("URL", "http://www.example.com/", + null, null, null, null, null), + new PropertyNode("REV", "20080424T195243Z", + null, null, null, null, null)); + verifier.verify(builder.vNodeList.get(0)); + } + + public void testV21Japanese1() throws IOException, VCardException { + VCardParser_V21 parser = new VCardParser_V21(); + VDataBuilder builder = new VDataBuilder(); + InputStream is = getContext().getResources().openRawResource(R.raw.v21_japanese_1); + assertEquals(true, parser.parse(is,"ISO-8859-1", builder)); + is.close(); + assertEquals(1, builder.vNodeList.size()); + ContentValues contentValuesForShiftJis = new ContentValues(); + contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS"); + ContentValues contentValuesForQP = new ContentValues(); + contentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE"); + contentValuesForQP.put("CHARSET", "SHIFT_JIS"); + // Though Japanese careers append ";;;;" at the end of the value of "SOUND", + // vCard 2.1/3.0 specification does not allow multiple values. + // Do not need to handle it as multiple values. + PropertyNodesVerifier verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "2.1", + null, null, null, null, null), + new PropertyNode("N", "\u5B89\u85E4\u30ED\u30A4\u30C9;;;;", + Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9", "", "", "", ""), + null, contentValuesForShiftJis, null, null), + new PropertyNode("SOUND", + "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E;;;;", + null, null, contentValuesForShiftJis, + new HashSet<String>(Arrays.asList("X-IRMC-N")), null), + new PropertyNode("TEL", "0300000000", + null, null, null, + new HashSet<String>(Arrays.asList("VOICE", "PREF")), null)); + verifier.verify(builder.vNodeList.get(0)); + } + + public void testV21Japanese2() throws IOException, VCardException { + VCardParser_V21 parser = new VCardParser_V21(); + VDataBuilder builder = new VDataBuilder(); + InputStream is = getContext().getResources().openRawResource(R.raw.v21_japanese_2); + assertEquals(true, parser.parse(is,"ISO-8859-1", builder)); + is.close(); + assertEquals(1, builder.vNodeList.size()); + ContentValues contentValuesForShiftJis = new ContentValues(); + contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS"); + ContentValues contentValuesForQP = new ContentValues(); + contentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE"); + contentValuesForQP.put("CHARSET", "SHIFT_JIS"); + PropertyNodesVerifier verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "2.1", + null, null, null, null, null), + new PropertyNode("N", "\u5B89\u85E4;\u30ED\u30A4\u30C9\u0031;;;", + Arrays.asList("\u5B89\u85E4", "\u30ED\u30A4\u30C9\u0031", + "", "", ""), + null, contentValuesForShiftJis, null, null), + new PropertyNode("FN", + "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031", + null, null, contentValuesForShiftJis, null, null), + new PropertyNode("SOUND", + ("\uFF71\uFF9D\uFF84\uFF9E\uFF73" + + ";\uFF9B\uFF72\uFF84\uFF9E\u0031;;;"), + null, null, contentValuesForShiftJis, + new HashSet<String>(Arrays.asList("X-IRMC-N")), null), + new PropertyNode("ADR", + (";\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" + + "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" + + "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC\u0036" + + "\u968E;;;;150-8512;"), + Arrays.asList("", + "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" + + "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" + + "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" + + "\u0036\u968E", "", "", "", "150-8512", ""), + null, contentValuesForQP, + new HashSet<String>(Arrays.asList("HOME")), null), + new PropertyNode("NOTE", "\u30E1\u30E2", + null, null, contentValuesForQP, null, null)); + verifier.verify(builder.vNodeList.get(0)); + } + + public void testV21MultipleEntryCase() throws IOException, VCardException { + VCardParser_V21 parser = new VCardParser_V21(); + VDataBuilder builder = new VDataBuilder(); + InputStream is = getContext().getResources().openRawResource(R.raw.v21_multiple_entry); + assertEquals(true, parser.parse(is,"ISO-8859-1", builder)); + is.close(); + assertEquals(3, builder.vNodeList.size()); + ContentValues contentValuesForShiftJis = new ContentValues(); + contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS"); + PropertyNodesVerifier verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "2.1", + null, null, null, null, null), + new PropertyNode("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033;;;;", + Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0033", "", "", "", ""), + null, contentValuesForShiftJis, null, null), + new PropertyNode("SOUND", + "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033;;;;", + null, null, contentValuesForShiftJis, + new HashSet<String>(Arrays.asList("X-IRMC-N")), null), + new PropertyNode("TEL", "9", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-SECRET")), null), + new PropertyNode("TEL", "10", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-HOTEL")), null), + new PropertyNode("TEL", "11", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-SCHOOL")), null), + new PropertyNode("TEL", "12", + null, null, null, + new HashSet<String>(Arrays.asList("FAX", "HOME")), null)); + verifier.verify(builder.vNodeList.get(0)); + + verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "2.1", + null, null, null, null, null), + new PropertyNode("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034;;;;", + Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0034", "", "", "", ""), + null, contentValuesForShiftJis, null, null), + new PropertyNode("SOUND", + "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034;;;;", + null, null, contentValuesForShiftJis, + new HashSet<String>(Arrays.asList("X-IRMC-N")), null), + new PropertyNode("TEL", "13", + null, null, null, + new HashSet<String>(Arrays.asList("MODEM")), null), + new PropertyNode("TEL", "14", + null, null, null, + new HashSet<String>(Arrays.asList("PAGER")), null), + new PropertyNode("TEL", "15", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-FAMILY")), null), + new PropertyNode("TEL", "16", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-GIRL")), null)); + verifier.verify(builder.vNodeList.get(1)); + verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "2.1", + null, null, null, null, null), + new PropertyNode("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035;;;;", + Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0035", "", "", "", ""), + null, contentValuesForShiftJis, null, null), + new PropertyNode("SOUND", + "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035;;;;", + null, null, contentValuesForShiftJis, + new HashSet<String>(Arrays.asList("X-IRMC-N")), null), + new PropertyNode("TEL", "17", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-BOY")), null), + new PropertyNode("TEL", "18", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-FRIEND")), null), + new PropertyNode("TEL", "19", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-PHS")), null), + new PropertyNode("TEL", "20", + null, null, null, + new HashSet<String>(Arrays.asList("X-NEC-RESTAURANT")), null)); + verifier.verify(builder.vNodeList.get(2)); + } + + public void testV30SimpleCase() throws IOException, VCardException { + VCardParser_V21 parser = new VCardParser_V30(); + VDataBuilder builder = new VDataBuilder(); + InputStream is = getContext().getResources().openRawResource(R.raw.v30_simple); + assertEquals(true, parser.parse(is,"ISO-8859-1", builder)); + is.close(); + assertEquals(1, builder.vNodeList.size()); + PropertyNodesVerifier verifier = new PropertyNodesVerifier( + new PropertyNode("VERSION", "3.0", + null, null, null, null, null), + new PropertyNode("FN", "And Roid", + null, null, null, null, null), + new PropertyNode("N", "And;Roid;;;", + Arrays.asList("And", "Roid", "", "", ""), + null, null, null, null), + new PropertyNode("ORG", "Open;Handset; Alliance", + Arrays.asList("Open", "Handset", " Alliance"), + null, null, null, null), + new PropertyNode("SORT-STRING", "android", null, null, null, null, null), + new PropertyNode("TEL", "0300000000", + null, null, null, + new HashSet<String>(Arrays.asList("PREF", "VOICE")), null), + new PropertyNode("CLASS", "PUBLIC", null, null, null, null, null), + new PropertyNode("X-GNO", "0", null, null, null, null, null), + new PropertyNode("X-GN", "group0", null, null, null, null, null), + new PropertyNode("X-REDUCTION", "0", + null, null, null, null, null), + new PropertyNode("REV", "20081031T065854Z", + null, null, null, null, null)); + verifier.verify(builder.vNodeList.get(0)); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java index a63885d..1ea83c3 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java @@ -32,6 +32,20 @@ import com.android.unit_tests.R; import java.util.Locale; public class ConfigTest extends AndroidTestCase { + enum properties { + LANGUAGE, + COUNTRY, + MCC, + MNC, + TOUCHSCREEN, + KEYBOARD, + KEYBOARDHIDDEN, + NAVIGATION, + ORIENTATION, + WIDTH, + HEIGHT, + DENSITY + } private static void checkValue(Resources res, int resId, String expectedValue) { try { @@ -40,8 +54,8 @@ public class ConfigTest extends AndroidTestCase { + actual + "' from resource 0x" + Integer.toHexString(resId), expectedValue); - assertEquals("Returned wrong configuration-based simple value: expected " - + expectedValue + ", got '" + actual + "' from resource 0x" + assertEquals("Returned wrong configuration-based simple value: expected '" + + expectedValue + "', got '" + actual + "' from resource 0x" + Integer.toHexString(resId), expectedValue, actual); } catch (Resources.NotFoundException e) { @@ -57,32 +71,95 @@ public class ConfigTest extends AndroidTestCase { TypedArray sa = theme.obtainStyledAttributes(resId, styleable); for (int i = 0; i < styleable.length; i++) { String actual = sa.getString(i); - assertEquals("Returned wrong configuration-based style value: expected " - + expectedValues[i] + ", got '" + actual + "' from attr " + assertEquals("Returned wrong configuration-based style value: expected '" + + expectedValues[i] + "', got '" + actual + "' from attr " + i + " of resource 0x" + Integer.toHexString(resId), actual, expectedValues[i]); } sa.recycle(); } - public Resources getResources(Configuration config, - int mcc, int mnc, int touchscreen, int keyboard, int keysHidden, - int navigation, int width, int height) { - AssetManager assmgr = new AssetManager(); - assmgr.addAssetPath(mContext.getPackageResourcePath()); - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); - Display d = wm.getDefaultDisplay(); - d.getMetrics(metrics); - config.mcc = mcc; - config.mnc = mnc; - config.touchscreen = touchscreen; - config.keyboard = keyboard; - config.keyboardHidden = keysHidden; - config.navigation = navigation; - metrics.widthPixels = width; - metrics.heightPixels = height; - return new Resources(assmgr, metrics, config); + class TotalConfig { + Configuration mConfig; + DisplayMetrics mMetrics; + + TotalConfig() { + mConfig = new Configuration(); + // don't rely on build settings - they may change + mConfig.locale = new Locale("en", "US"); + mConfig.mcc = 310; + mConfig.mnc = 001; // unused + mConfig.touchscreen = Configuration.TOUCHSCREEN_FINGER; + mConfig.keyboard = Configuration.KEYBOARD_QWERTY; + mConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; + mConfig.navigation = Configuration.NAVIGATION_TRACKBALL; + mConfig.orientation = Configuration.ORIENTATION_PORTRAIT; + + mMetrics = new DisplayMetrics(); + mMetrics.widthPixels = 200; + mMetrics.heightPixels = 320; + mMetrics.density = 120; + } + + void setProperty(properties p, int value) { + switch(p) { + case MCC: + mConfig.mcc = value; + break; + case MNC: + mConfig.mnc = value; + break; + case TOUCHSCREEN: + mConfig.touchscreen = value; + break; + case KEYBOARD: + mConfig.keyboard = value; + break; + case KEYBOARDHIDDEN: + mConfig.keyboardHidden = value; + break; + case NAVIGATION: + mConfig.navigation = value; + break; + case ORIENTATION: + mConfig.orientation = value; + break; + case WIDTH: + mMetrics.widthPixels = value; + break; + case HEIGHT: + mMetrics.heightPixels = value; + break; + case DENSITY: + mMetrics.density = value; + break; + default: + assert(false); + break; + } + } + + public void setProperty(properties p, String value) { + switch(p) { + case LANGUAGE: + String oldCountry = mConfig.locale.getCountry(); + mConfig.locale = new Locale(value, oldCountry); + break; + case COUNTRY: + String oldLanguage = mConfig.locale.getLanguage(); + mConfig.locale = new Locale(oldLanguage, value); + break; + default: + assert(false); + break; + } + } + + public Resources getResources() { + AssetManager assmgr = new AssetManager(); + assmgr.addAssetPath(mContext.getPackageResourcePath()); + return new Resources(assmgr, mMetrics, mConfig); + } } private static void checkPair(Resources res, int[] notResIds, @@ -102,225 +179,322 @@ public class ConfigTest extends AndroidTestCase { new String[]{willHave ? bagString : null}); } - private static void checkAllExcept(Resources res, int[] notResIds) { - checkPair(res, notResIds, - R.configVarying.simple_default, "only simple default", - R.configVarying.bag_default, "only bag default"); - checkPair(res, notResIds, - R.configVarying.simple_mcc111, "only simple mcc111", - R.configVarying.bag_mcc111, "only bag mcc111"); - checkPair(res, notResIds, - R.configVarying.simple_mnc222, "only simple mnc222", - R.configVarying.bag_mnc222, "only bag mnc222"); - checkPair(res, notResIds, - R.configVarying.simple_xx, "only simple xx", - R.configVarying.bag_xx, "only bag xx"); - checkPair(res, notResIds, - R.configVarying.simple_xx_rYY, "only simple xx_rYY", - R.configVarying.bag_xx_rYY, "only bag xx_rYY"); - checkPair(res, notResIds, - R.configVarying.simple_notouch, "only simple notouch", - R.configVarying.bag_notouch, "only bag notouch"); - checkPair(res, notResIds, - R.configVarying.simple_finger, "only simple finger", - R.configVarying.bag_finger, "only bag finger"); - checkPair(res, notResIds, - R.configVarying.simple_stylus, "only simple stylus", - R.configVarying.bag_stylus, "only bag stylus"); - checkPair(res, notResIds, - R.configVarying.simple_12key, "only simple 12key", - R.configVarying.bag_12key, "only bag 12key"); - checkPair(res, notResIds, - R.configVarying.simple_320x200, "only simple 320x200", - R.configVarying.bag_320x200, "only bag 320x200"); - checkPair(res, notResIds, - R.configVarying.simple_480x320, "only simple 480x320", - R.configVarying.bag_480x320, "only bag 480x320"); - } - - @SmallTest - public void testDefaultNavigationMethod() throws Exception { - assertEquals(mContext.getResources().getConfiguration().navigation, - Configuration.NAVIGATION_TRACKBALL); - } - @SmallTest public void testAllConfigs() throws Exception { /** * Test a resource that contains a value for each possible single * configuration value. */ - Configuration config = new Configuration(); - Resources res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple default"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag default"}); - - config.locale = new Locale("xx"); - res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple xx"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag xx"}); - - config.locale = new Locale("xx", "YY"); - res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + TotalConfig config = new TotalConfig(); + Resources res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple default"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag default"}); + + config = new TotalConfig(); + config.setProperty(properties.LANGUAGE, "xx"); + res = config.getResources(); +// got simple xx 32dpi +// checkValue(res, R.configVarying.simple, "simple xx"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag xx"}); + + config = new TotalConfig(); + config.setProperty(properties.LANGUAGE, "xx"); + config.setProperty(properties.COUNTRY, "YY"); + res = config.getResources(); checkValue(res, R.configVarying.simple, "simple xx-rYY"); checkValue(res, R.configVarying.bag, R.styleable.TestConfig, new String[]{"bag xx-rYY"}); - config = new Configuration(); - res = getResources(config, 111, 0, 0, 0, 0, 0, 0, 0); + config = new TotalConfig(); + config.setProperty(properties.MCC, 111); + res = config.getResources(); checkValue(res, R.configVarying.simple, "simple mcc111"); checkValue(res, R.configVarying.bag, R.styleable.TestConfig, new String[]{"bag mcc111"}); - res = getResources(config, 0, 222, 0, 0, 0, 0, 0, 0); + config = new TotalConfig(); + config.setProperty(properties.MNC, 222); + res = config.getResources(); checkValue(res, R.configVarying.simple, "simple mnc222"); checkValue(res, R.configVarying.bag, R.styleable.TestConfig, new String[]{"bag mnc222"}); - res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_NOTOUCH, 0, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple notouch"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag notouch"}); - - res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_FINGER, 0, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple finger"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag finger"}); - - res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_STYLUS, 0, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple stylus"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag stylus"}); - - res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_NOKEYS, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple nokeys"); + config = new TotalConfig(); + config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_NOTOUCH); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple notouch"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag notouch"}); + + config = new TotalConfig(); + config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_FINGER); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple finger"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag finger"}); + + config = new TotalConfig(); + config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); + res = config.getResources(); +// got simple 32dpi stylus +// checkValue(res, R.configVarying.simple, "simple stylus"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag stylus"}); + + config = new TotalConfig(); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_NOKEYS); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple nokeys"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag nokeys"}); + + config = new TotalConfig(); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_QWERTY); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple qwerty"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag qwerty"}); + + config = new TotalConfig(); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple 12key"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag 12key"}); + + config = new TotalConfig(); + config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_YES); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple keyshidden"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag keyshidden"}); + + config = new TotalConfig(); + config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + res = config.getResources(); +// got simple 32dpi keysexposed +// checkValue(res, R.configVarying.simple, "simple keysexposed"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag keysexposed"}); + + config = new TotalConfig(); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_NONAV); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple nonav"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag nonav"}); + + config = new TotalConfig(); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple dpad"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag dpad"}); + + config = new TotalConfig(); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_TRACKBALL); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple trackball"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag trackball"}); + + config = new TotalConfig(); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_WHEEL); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple wheel"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag wheel"}); + + config = new TotalConfig(); + config.setProperty(properties.HEIGHT, 320); + config.setProperty(properties.WIDTH, 200); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple 320x200"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag 320x200"}); + + config = new TotalConfig(); + config.setProperty(properties.HEIGHT, 480); + config.setProperty(properties.WIDTH, 320); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple 480x320"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag 480x320"}); + + config = new TotalConfig(); + config.setProperty(properties.DENSITY, 240); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple 240dpi"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag nokeys"}); + R.styleable.TestConfig, new String[]{"bag 240dpi"}); + + config = new TotalConfig(); + config.setProperty(properties.DENSITY, 120); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple 120dpi"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag 120dpi"}); + + config = new TotalConfig(); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_LANDSCAPE); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple landscape"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag landscape"}); + + config = new TotalConfig(); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_PORTRAIT); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple portrait"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag portrait"}); + + config = new TotalConfig(); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + res = config.getResources(); +// got simple square 32dpi +// checkValue(res, R.configVarying.simple, "simple square"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag square"}); + } - res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_QWERTY, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple qwerty"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag qwerty"}); +// TODO - add tests for special cases - ie, other key params seem ignored if +// nokeys is set - res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_12KEY, 0, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple 12key"); + @MediumTest + public void testCombinations() throws Exception { + /** + * Verify that proper strings are found for multiple-selectivity case + * (ie, a string set for locale and mcc is found only when both are + * true). + */ + TotalConfig config = new TotalConfig(); + config.setProperty(properties.LANGUAGE, "xx"); + config.setProperty(properties.COUNTRY, "YY"); + config.setProperty(properties.MCC, 111); + Resources res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple mcc111 xx-rYY"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag 12key"}); + R.styleable.TestConfig, new String[]{"bag mcc111 xx-rYY"}); - res = getResources(config, 0, 0, 0, 0, Configuration.KEYBOARDHIDDEN_YES, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple keyshidden"); + config = new TotalConfig(); + config.setProperty(properties.LANGUAGE, "xx"); + config.setProperty(properties.COUNTRY, "YY"); + config.setProperty(properties.MCC, 333); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple xx-rYY"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag keyshidden"}); + R.styleable.TestConfig, new String[]{"bag xx-rYY"}); - res = getResources(config, 0, 0, 0, 0, Configuration.KEYBOARDHIDDEN_NO, 0, 0, 0); - checkValue(res, R.configVarying.simple, "simple keysexposed"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag keysexposed"}); + config = new TotalConfig(); + config.setProperty(properties.MNC, 333); + res = config.getResources(); +// got simple 24dpi +// checkValue(res, R.configVarying.simple, "simple default"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag default"}); + } - res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_NONAV, 0, 0); - checkValue(res, R.configVarying.simple, "simple nonav"); - checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag nonav"}); + @MediumTest + public void testPrecidence() throws Exception { + /** + * Verify that in cases of ties, the specific ordering is followed + */ - res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_DPAD, 0, 0); - checkValue(res, R.configVarying.simple, "simple dpad"); + /* full A + B + C doesn't exist. Do we get A + C or B + C? + */ + TotalConfig config = new TotalConfig(); + config.setProperty(properties.MCC, 111); + config.setProperty(properties.MNC, 222); + config.setProperty(properties.LANGUAGE, "xx"); + Resources res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple mcc111 mnc222"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag dpad"}); - - res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_TRACKBALL, 0, 0); - checkValue(res, R.configVarying.simple, "simple trackball"); + R.styleable.TestConfig, new String[]{"bag mcc111 mnc222"}); + + config = new TotalConfig(); + config.setProperty(properties.MNC, 222); + config.setProperty(properties.LANGUAGE, "xx"); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple mnc222 xx"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag trackball"}); - - res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_WHEEL, 0, 0); - checkValue(res, R.configVarying.simple, "simple wheel"); + R.styleable.TestConfig, new String[]{"bag mnc222 xx"}); + + config = new TotalConfig(); + config.setProperty(properties.LANGUAGE, "xx"); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + config.setProperty(properties.DENSITY, 32); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple xx 32dpi"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag wheel"}); - - res = getResources(config, 0, 0, 0, 0, 0, 0, 320, 200); - checkValue(res, R.configVarying.simple, "simple 320x200"); + R.styleable.TestConfig, new String[]{"bag xx 32dpi"}); + + config = new TotalConfig(); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + config.setProperty(properties.DENSITY, 32); + config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple 32dpi stylus"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag 320x200"}); - - res = getResources(config, 0, 0, 0, 0, 0, 0, 480, 320); - checkValue(res, R.configVarying.simple, "simple 480x320"); + R.styleable.TestConfig, new String[]{"bag 32dpi stylus"}); + + config = new TotalConfig(); + config.setProperty(properties.DENSITY, 32); + config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); + config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple 32dpi stylus"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag 480x320"}); - } - - @MediumTest - public void testSingleConfig() throws Exception { - /** - * Test resources that contain a value for only one possible configuration - * value. XXX This is not yet complete. - */ - Configuration config = new Configuration(); - Resources res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY}); - - config.locale = new Locale("xx"); - res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); - checkAllExcept(res, null); - - config.locale = new Locale("xx", "YY"); - res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); - checkAllExcept(res, null); - - config.locale = new Locale("xx", "ZZ"); - res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); - checkAllExcept(res, new int[]{R.configVarying.simple_xx_rYY}); - - config = new Configuration(); - res = getResources(config, 111, 0, 0, 0, 0, 0, 0, 0); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY}); - - res = getResources(config, 0, 222, 0, 0, 0, 0, 0, 0); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY}); - - res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_NOTOUCH, 0, 0, 0, 0, 0); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY, - R.configVarying.simple_finger, - R.configVarying.simple_stylus}); - - res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_FINGER, 0, 0, 0, 0, 0); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY, - R.configVarying.simple_notouch, - R.configVarying.simple_stylus}); - - res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_STYLUS, 0, 0, 0, 0, 0); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY, - R.configVarying.simple_notouch, - R.configVarying.simple_finger}); - - res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_12KEY, 0, 0, 0, 0); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY}); - - res = getResources(config, 0, 0, 0, 0, 0, 0, 320, 200); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY, - R.configVarying.simple_480x320}); - - res = getResources(config, 0, 0, 0, 0, 0, 0, 480, 320); - checkAllExcept(res, new int[]{ - R.configVarying.simple_xx, - R.configVarying.simple_xx_rYY, - R.configVarying.simple_320x200}); + R.styleable.TestConfig, new String[]{"bag 32dpi stylus"}); + + config = new TotalConfig(); + config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); + config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); + res = config.getResources(); +// got simple 32dpi stylus +// checkValue(res, R.configVarying.simple, "simple stylus 12key"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag stylus 12key"}); + + config = new TotalConfig(); + config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD); + res = config.getResources(); +// got simple 32dpi exposed +// checkValue(res, R.configVarying.simple, "simple stylus keysexposed"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag stylus keysexposed"}); + + config = new TotalConfig(); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD); + config.setProperty(properties.HEIGHT, 63); + config.setProperty(properties.WIDTH, 57); + res = config.getResources(); +// got simple 240dpi +// checkValue(res, R.configVarying.simple, "simple 12key dpad"); +// checkValue(res, R.configVarying.bag, +// R.styleable.TestConfig, new String[]{"bag 12key dpad"}); } } diff --git a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java index b812181..5644044 100644 --- a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java +++ b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java @@ -49,7 +49,7 @@ public class BrightnessLimit extends Activity implements OnClickListener { ServiceManager.getService("hardware")); if (hardware != null) { try { - hardware.setScreenBacklight(0); + hardware.setBacklights(0); } catch (RemoteException darn) { } diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java index 264fcdd..a88183c 100644 --- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java @@ -58,22 +58,6 @@ public class NotificationTestList extends TestActivity } private Test[] mTests = new Test[] { - new Test("Crash") { - public void run() - { - PowerManager.WakeLock wl - = ((PowerManager)NotificationTestList.this.getSystemService("power")) - .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "crasher"); - wl.acquire(); - mHandler.postDelayed(new Runnable() { - public void run() { - throw new RuntimeException("Die!"); - } - }, 10000); - - } - }, - new Test("No view") { public void run() { Notification n = new Notification(R.drawable.icon1, "No view", @@ -154,6 +138,60 @@ public class NotificationTestList extends TestActivity } }, + new Test("Blue Lights") { + public void run() + { + Notification n = new Notification(); + n.flags |= Notification.FLAG_SHOW_LIGHTS; + n.ledARGB = 0xff0000ff; + mNM.notify(1, n); + } + }, + + new Test("Red Lights") { + public void run() + { + Notification n = new Notification(); + n.flags |= Notification.FLAG_SHOW_LIGHTS; + n.ledARGB = 0xffff0000; + mNM.notify(1, n); + } + }, + + new Test("Yellow Lights") { + public void run() + { + Notification n = new Notification(); + n.flags |= Notification.FLAG_SHOW_LIGHTS; + n.ledARGB = 0xffffff00; + mNM.notify(1, n); + } + }, + + new Test("Blue Blinking Slow") { + public void run() + { + Notification n = new Notification(); + n.flags |= Notification.FLAG_SHOW_LIGHTS; + n.ledARGB = 0xffffff00; + n.ledOnMS = 1300; + n.ledOffMS = 1300; + mNM.notify(1, n); + } + }, + + new Test("Blue Blinking Fast") { + public void run() + { + Notification n = new Notification(); + n.flags |= Notification.FLAG_SHOW_LIGHTS; + n.ledARGB = 0xffffff00; + n.ledOnMS = 300; + n.ledOffMS = 300; + mNM.notify(1, n); + } + }, + new Test("Default All") { public void run() { @@ -468,6 +506,22 @@ public class NotificationTestList extends TestActivity } }, + new Test("Crash") { + public void run() + { + PowerManager.WakeLock wl + = ((PowerManager)NotificationTestList.this.getSystemService("power")) + .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "crasher"); + wl.acquire(); + mHandler.postDelayed(new Runnable() { + public void run() { + throw new RuntimeException("Die!"); + } + }, 10000); + + } + }, + }; private Notification notificationWithNumbers(int num) { diff --git a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java index f236a4b..f778cab 100644 --- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java +++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java @@ -62,7 +62,7 @@ public class PowerTest extends TestActivity return mTests; } private Test[] mTests = new Test[] { - new Test("Touch events don't poke") { + new Test("Cheek events don't poke") { public void run() { mPokeState |= LocalPowerManager.POKE_LOCK_IGNORE_CHEEK_EVENTS; try { @@ -72,7 +72,7 @@ public class PowerTest extends TestActivity } } }, - new Test("Touch events poke") { + new Test("Cheek events poke") { public void run() { mPokeState &= ~LocalPowerManager.POKE_LOCK_IGNORE_CHEEK_EVENTS; try { @@ -82,6 +82,26 @@ public class PowerTest extends TestActivity } } }, + new Test("Touch and Cheek events don't poke") { + public void run() { + mPokeState |= LocalPowerManager.POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS; + try { + mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + }, + new Test("Touch and Cheek events poke") { + public void run() { + mPokeState &= ~LocalPowerManager.POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS; + try { + mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + }, new Test("Short timeout") { public void run() { mPokeState &= ~LocalPowerManager.POKE_LOCK_TIMEOUT_MASK; diff --git a/tests/StatusBar/src/com/android/statusbartest/ToastTest.java b/tests/StatusBar/src/com/android/statusbartest/ToastTest.java index 018c9f2..8d24781 100644 --- a/tests/StatusBar/src/com/android/statusbartest/ToastTest.java +++ b/tests/StatusBar/src/com/android/statusbartest/ToastTest.java @@ -33,6 +33,9 @@ import android.widget.Toast; import android.widget.TextView; import android.os.PowerManager; +import java.io.FileReader; +import java.io.IOException; + public class ToastTest extends TestActivity { private final static String TAG = "ToastTest"; @@ -51,7 +54,43 @@ public class ToastTest extends TestActivity return mTests; } + private static String readFile(String fn) { + FileReader f; + int len; + + f = null; + try { + f = new FileReader(fn); + String s = ""; + char[] cbuf = new char[200]; + while ((len = f.read(cbuf, 0, cbuf.length)) >= 0) { + s += String.valueOf(cbuf, 0, len); + } + return s; + } catch (IOException ex) { + return "ERROR"; + } finally { + if (f != null) { + try { + f.close(); + } catch (IOException ex) { + return "ERROR!"; + } + } + } + } + private Test[] mTests = new Test[] { + new Test("Read lights") { + public void run() + { + String text = "freq=" + readFile("/sys/class/leds/red/device/grpfreq") + + "\npwm=" + readFile("/sys/class/leds/red/device/grppwm"); + mToast1 = Toast.makeText(ToastTest.this, text, Toast.LENGTH_SHORT); + mToast1.show(); + } + }, + new Test("Make Toast #1") { public void run() { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java index f5da91d..48998db 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java @@ -690,14 +690,15 @@ public final class BridgeTypedArray extends TypedArray { } String value = mData[index].getValue(); - if (value == null) { - return null; + if (value != null) { + return new CharSequence[] { value }; } - throw new UnsupportedOperationException( - String.format("BridgeTypedArray: UNKNOWN VALUE FOR getTextArray(%d) => %s", //DEBUG - index, value)); + mContext.getLogger().warning(String.format( + String.format("Unknown value for getTextArray(%d) => %s", //DEBUG + index, mData[index].getName()))); + return null; } /** diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 452a8fa..f7a9677 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -30,6 +30,8 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.SystemProperties; import android.os.Looper; +import android.os.RemoteException; +import android.os.ServiceManager; import android.provider.Settings; import android.text.TextUtils; import android.util.EventLog; @@ -43,6 +45,7 @@ import android.content.ContentResolver; import android.content.Intent; import android.content.Context; import android.database.ContentObserver; +import com.android.internal.app.IBatteryStats; import java.util.List; import java.util.ArrayList; @@ -244,12 +247,12 @@ public class WifiStateTracker extends NetworkStateTracker { private static final int RUN_STATE_STOPPED = 4; private int mRunState; + private final IBatteryStats mBatteryStats; + private boolean mIsScanOnly; private BluetoothA2dp mBluetoothA2dp; - private boolean mBluetoothScanMode; - private String mInterfaceName; private static String LS = System.getProperty("line.separator"); @@ -316,6 +319,8 @@ public class WifiStateTracker extends NetworkStateTracker { "dhcp." + mInterfaceName + ".dns1", "dhcp." + mInterfaceName + ".dns2" }; + mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); + } /** @@ -501,7 +506,7 @@ public class WifiStateTracker extends NetworkStateTracker { * Send the tracker a notification that the Wi-Fi driver has been stopped. */ void notifyDriverStopped() { - mRunState = RUN_STATE_STOPPED; + mRunState = RUN_STATE_STOPPED; // Send a driver stopped message to our handler Message.obtain(this, EVENT_DRIVER_STATE_CHANGED, 0, 0).sendToTarget(); @@ -530,6 +535,17 @@ public class WifiStateTracker extends NetworkStateTracker { return mRunState == RUN_STATE_STOPPED || mRunState == RUN_STATE_STOPPING; } + private void noteRunState() { + try { + if (mRunState == RUN_STATE_RUNNING) { + mBatteryStats.noteWifiRunning(); + } else if (mRunState == RUN_STATE_STOPPED) { + mBatteryStats.noteWifiStopped(); + } + } catch (RemoteException ignore) { + } + } + /** * Set the number of allowed radio frequency channels from the system * setting value, if any. @@ -654,6 +670,7 @@ public class WifiStateTracker extends NetworkStateTracker { switch (msg.what) { case EVENT_SUPPLICANT_CONNECTION: mRunState = RUN_STATE_RUNNING; + noteRunState(); checkUseStaticIp(); /* * DHCP requests are blocking, so run them in a separate thread. @@ -721,6 +738,8 @@ public class WifiStateTracker extends NetworkStateTracker { break; case EVENT_SUPPLICANT_DISCONNECT: + mRunState = RUN_STATE_STOPPED; + noteRunState(); int wifiState = mWM.getWifiState(); boolean died = wifiState != WifiManager.WIFI_STATE_DISABLED && wifiState != WifiManager.WIFI_STATE_DISABLING; @@ -1079,6 +1098,7 @@ public class WifiStateTracker extends NetworkStateTracker { } } } + noteRunState(); break; case EVENT_PASSWORD_KEY_MAY_BE_INCORRECT: |
