diff options
430 files changed, 12277 insertions, 4729 deletions
@@ -444,7 +444,7 @@ web_docs_sample_code_flags := \ ## SDK version identifiers used in the published docs # major[.minor] version for current SDK. (full releases only) -framework_docs_SDK_VERSION:=2.2 +framework_docs_SDK_VERSION:=2.3 # release version (ie "Release x") (full releases only) framework_docs_SDK_REL_ID:=1 # flag to build offline docs for a preview release diff --git a/api/current.xml b/api/current.xml index e2e9b92..42cdaf2 100644 --- a/api/current.xml +++ b/api/current.xml @@ -15041,6 +15041,17 @@ visibility="public" > </field> +<field name="Widget_ActionBar" + type="int" + transient="false" + volatile="false" + value="16973958" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="Widget_ActionButton" type="int" transient="false" @@ -15250,6 +15261,974 @@ visibility="public" > </field> +<field name="Widget_Holo" + type="int" + transient="false" + volatile="false" + value="16973959" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ActionBar" + type="int" + transient="false" + volatile="false" + value="16974001" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ActionButton" + type="int" + transient="false" + volatile="false" + value="16973996" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ActionButton_CloseMode" + type="int" + transient="false" + volatile="false" + value="16974000" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ActionButton_Overflow" + type="int" + transient="false" + volatile="false" + value="16973997" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ActionButton_TextButton" + type="int" + transient="false" + volatile="false" + value="16973998" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ActionMode" + type="int" + transient="false" + volatile="false" + value="16973999" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_AutoCompleteTextView" + type="int" + transient="false" + volatile="false" + value="16973965" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Button" + type="int" + transient="false" + volatile="false" + value="16973960" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Button_Inset" + type="int" + transient="false" + volatile="false" + value="16973962" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Button_Small" + type="int" + transient="false" + volatile="false" + value="16973961" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Button_Toggle" + type="int" + transient="false" + volatile="false" + value="16973963" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_CompoundButton_CheckBox" + type="int" + transient="false" + volatile="false" + value="16973966" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_CompoundButton_RadioButton" + type="int" + transient="false" + volatile="false" + value="16973983" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_CompoundButton_Star" + type="int" + transient="false" + volatile="false" + value="16973987" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_DropDownItem" + type="int" + transient="false" + volatile="false" + value="16973991" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_DropDownItem_Spinner" + type="int" + transient="false" + volatile="false" + value="16973992" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_EditText" + type="int" + transient="false" + volatile="false" + value="16973968" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ExpandableListView" + type="int" + transient="false" + volatile="false" + value="16973969" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_GridView" + type="int" + transient="false" + volatile="false" + value="16973970" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_HorizontalScrollView" + type="int" + transient="false" + volatile="false" + value="16973985" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ImageButton" + type="int" + transient="false" + volatile="false" + value="16973971" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light" + type="int" + transient="false" + volatile="false" + value="16974002" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ActionBar" + type="int" + transient="false" + volatile="false" + value="16974046" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ActionButton" + type="int" + transient="false" + volatile="false" + value="16974042" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ActionButton_CloseMode" + type="int" + transient="false" + volatile="false" + value="16974045" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ActionButton_Overflow" + type="int" + transient="false" + volatile="false" + value="16974043" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ActionMode" + type="int" + transient="false" + volatile="false" + value="16974044" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_AutoCompleteTextView" + type="int" + transient="false" + volatile="false" + value="16974008" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_Button" + type="int" + transient="false" + volatile="false" + value="16974003" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_Button_Inset" + type="int" + transient="false" + volatile="false" + value="16974005" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_Button_Small" + type="int" + transient="false" + volatile="false" + value="16974004" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_Button_Toggle" + type="int" + transient="false" + volatile="false" + value="16974006" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_CompoundButton_CheckBox" + type="int" + transient="false" + volatile="false" + value="16974009" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_CompoundButton_RadioButton" + type="int" + transient="false" + volatile="false" + value="16974029" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_CompoundButton_Star" + type="int" + transient="false" + volatile="false" + value="16974033" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_DropDownItem" + type="int" + transient="false" + volatile="false" + value="16974037" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_DropDownItem_Spinner" + type="int" + transient="false" + volatile="false" + value="16974038" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_EditText" + type="int" + transient="false" + volatile="false" + value="16974011" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ExpandableListView" + type="int" + transient="false" + volatile="false" + value="16974012" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_GridView" + type="int" + transient="false" + volatile="false" + value="16974013" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_HorizontalScrollView" + type="int" + transient="false" + volatile="false" + value="16974031" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ImageButton" + type="int" + transient="false" + volatile="false" + value="16974014" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ListPopupWindow" + type="int" + transient="false" + volatile="false" + value="16974040" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ListView" + type="int" + transient="false" + volatile="false" + value="16974015" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ListView_DropDown" + type="int" + transient="false" + volatile="false" + value="16974010" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_PopupMenu" + type="int" + transient="false" + volatile="false" + value="16974041" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_PopupWindow" + type="int" + transient="false" + volatile="false" + value="16974016" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar" + type="int" + transient="false" + volatile="false" + value="16974017" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar_Horizontal" + type="int" + transient="false" + volatile="false" + value="16974018" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar_Inverse" + type="int" + transient="false" + volatile="false" + value="16974022" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar_Large" + type="int" + transient="false" + volatile="false" + value="16974021" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar_Large_Inverse" + type="int" + transient="false" + volatile="false" + value="16974024" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar_Small" + type="int" + transient="false" + volatile="false" + value="16974019" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar_Small_Inverse" + type="int" + transient="false" + volatile="false" + value="16974023" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ProgressBar_Small_Title" + type="int" + transient="false" + volatile="false" + value="16974020" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_RatingBar" + type="int" + transient="false" + volatile="false" + value="16974026" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_RatingBar_Indicator" + type="int" + transient="false" + volatile="false" + value="16974027" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_RatingBar_Small" + type="int" + transient="false" + volatile="false" + value="16974028" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_ScrollView" + type="int" + transient="false" + volatile="false" + value="16974030" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_SeekBar" + type="int" + transient="false" + volatile="false" + value="16974025" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_Spinner" + type="int" + transient="false" + volatile="false" + value="16974032" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_TabWidget" + type="int" + transient="false" + volatile="false" + value="16974034" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_TextView" + type="int" + transient="false" + volatile="false" + value="16974007" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_TextView_SpinnerItem" + type="int" + transient="false" + volatile="false" + value="16974039" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_WebTextView" + type="int" + transient="false" + volatile="false" + value="16974035" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Light_WebView" + type="int" + transient="false" + volatile="false" + value="16974036" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ListPopupWindow" + type="int" + transient="false" + volatile="false" + value="16973994" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ListView" + type="int" + transient="false" + volatile="false" + value="16973972" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ListView_DropDown" + type="int" + transient="false" + volatile="false" + value="16973967" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_PopupMenu" + type="int" + transient="false" + volatile="false" + value="16973995" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_PopupWindow" + type="int" + transient="false" + volatile="false" + value="16973973" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ProgressBar" + type="int" + transient="false" + volatile="false" + value="16973974" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ProgressBar_Horizontal" + type="int" + transient="false" + volatile="false" + value="16973975" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ProgressBar_Large" + type="int" + transient="false" + volatile="false" + value="16973978" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ProgressBar_Small" + type="int" + transient="false" + volatile="false" + value="16973976" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ProgressBar_Small_Title" + type="int" + transient="false" + volatile="false" + value="16973977" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_RatingBar" + type="int" + transient="false" + volatile="false" + value="16973980" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_RatingBar_Indicator" + type="int" + transient="false" + volatile="false" + value="16973981" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_RatingBar_Small" + type="int" + transient="false" + volatile="false" + value="16973982" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_ScrollView" + type="int" + transient="false" + volatile="false" + value="16973984" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_SeekBar" + type="int" + transient="false" + volatile="false" + value="16973979" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_Spinner" + type="int" + transient="false" + volatile="false" + value="16973986" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_TabWidget" + type="int" + transient="false" + volatile="false" + value="16973988" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_TextView" + type="int" + transient="false" + volatile="false" + value="16973964" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_TextView_SpinnerItem" + type="int" + transient="false" + volatile="false" + value="16973993" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_WebTextView" + type="int" + transient="false" + volatile="false" + value="16973989" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="Widget_Holo_WebView" + type="int" + transient="false" + volatile="false" + value="16973990" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="Widget_ImageButton" type="int" transient="false" @@ -31226,7 +32205,7 @@ type="android.app.Notification" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="icon" type="int"> @@ -31275,7 +32254,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="context" type="android.content.Context"> @@ -31545,6 +32524,16 @@ visibility="public" > </field> +<field name="largeIcon" + type="android.graphics.Bitmap" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="ledARGB" type="int" transient="false" @@ -31595,19 +32584,18 @@ visibility="public" > </field> -<field name="tickerIcons" - type="android.graphics.Bitmap[]" +<field name="tickerText" + type="java.lang.CharSequence" transient="false" volatile="false" - value="null" static="false" final="false" deprecated="not deprecated" visibility="public" > </field> -<field name="tickerSubtitle" - type="java.lang.CharSequence" +<field name="tickerView" + type="android.widget.RemoteViews" transient="false" volatile="false" static="false" @@ -31616,18 +32604,19 @@ visibility="public" > </field> -<field name="tickerText" - type="java.lang.CharSequence" +<field name="vibrate" + type="long[]" transient="false" volatile="false" + value="null" static="false" final="false" deprecated="not deprecated" visibility="public" > </field> -<field name="tickerTitle" - type="java.lang.CharSequence" +<field name="when" + type="long" transient="false" volatile="false" static="false" @@ -31636,27 +32625,334 @@ visibility="public" > </field> -<field name="vibrate" - type="long[]" - transient="false" - volatile="false" - value="null" +</class> +<class name="Notification.Builder" + extends="java.lang.Object" + abstract="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="Notification.Builder" + type="android.app.Notification.Builder" static="false" final="false" deprecated="not deprecated" visibility="public" > -</field> -<field name="when" - type="long" - transient="false" - volatile="false" +<parameter name="context" type="android.content.Context"> +</parameter> +</constructor> +<method name="getNotification" + return="android.app.Notification" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -</field> +</method> +<method name="setAutoCancel" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="autoCancel" type="boolean"> +</parameter> +</method> +<method name="setContent" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="views" type="android.widget.RemoteViews"> +</parameter> +</method> +<method name="setContentInfo" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="info" type="java.lang.CharSequence"> +</parameter> +</method> +<method name="setContentIntent" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="intent" type="android.app.PendingIntent"> +</parameter> +</method> +<method name="setContentText" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="text" type="java.lang.CharSequence"> +</parameter> +</method> +<method name="setContentTitle" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="title" type="java.lang.CharSequence"> +</parameter> +</method> +<method name="setDefaults" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="defaults" type="int"> +</parameter> +</method> +<method name="setDeleteIntent" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="intent" type="android.app.PendingIntent"> +</parameter> +</method> +<method name="setFullScreenIntent" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="intent" type="android.app.PendingIntent"> +</parameter> +<parameter name="highPriority" type="boolean"> +</parameter> +</method> +<method name="setLargeIcon" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="icon" type="android.graphics.Bitmap"> +</parameter> +</method> +<method name="setLights" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="argb" type="int"> +</parameter> +<parameter name="onMs" type="int"> +</parameter> +<parameter name="offMs" type="int"> +</parameter> +</method> +<method name="setNumber" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="number" type="int"> +</parameter> +</method> +<method name="setOngoing" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="ongoing" type="boolean"> +</parameter> +</method> +<method name="setOnlyAlertOnce" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="onlyAlertOnce" type="boolean"> +</parameter> +</method> +<method name="setSmallIcon" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="icon" type="int"> +</parameter> +</method> +<method name="setSmallIcon" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="icon" type="int"> +</parameter> +<parameter name="level" type="int"> +</parameter> +</method> +<method name="setSound" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="sound" type="android.net.Uri"> +</parameter> +</method> +<method name="setSound" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="sound" type="android.net.Uri"> +</parameter> +<parameter name="streamType" type="int"> +</parameter> +</method> +<method name="setTicker" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="tickerText" type="java.lang.CharSequence"> +</parameter> +</method> +<method name="setTicker" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="tickerText" type="java.lang.CharSequence"> +</parameter> +<parameter name="views" type="android.widget.RemoteViews"> +</parameter> +</method> +<method name="setVibrate" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="pattern" type="long[]"> +</parameter> +</method> +<method name="setWhen" + return="android.app.Notification.Builder" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="when" type="long"> +</parameter> +</method> </class> <class name="NotificationManager" extends="java.lang.Object" @@ -57683,6 +58979,21 @@ <parameter name="flags" type="int"> </parameter> </method> +<method name="setInstallerPackageName" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="targetPackage" type="java.lang.String"> +</parameter> +<parameter name="installerPackageName" type="java.lang.String"> +</parameter> +</method> <field name="COMPONENT_ENABLED_STATE_DEFAULT" type="int" transient="false" @@ -97667,6 +98978,17 @@ visibility="public" > </field> +<field name="MODE_IN_COMMUNICATION" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="MODE_NORMAL" type="int" transient="false" @@ -154692,6 +156014,17 @@ visibility="public" > </field> +<field name="GROUP_IS_READ_ONLY" + type="java.lang.String" + transient="false" + volatile="false" + value=""group_is_read_only"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="NOTES" type="java.lang.String" transient="false" @@ -174750,6 +176083,21 @@ <parameter name="flags" type="int"> </parameter> </method> +<method name="setInstallerPackageName" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="targetPackage" type="java.lang.String"> +</parameter> +<parameter name="installerPackageName" type="java.lang.String"> +</parameter> +</method> <method name="setPackageObbPath" return="void" abstract="false" @@ -193150,53 +194498,6 @@ visibility="public" > </method> -<method name="obtain" - return="android.view.DragEvent" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="action" type="int"> -</parameter> -<parameter name="x" type="float"> -</parameter> -<parameter name="y" type="float"> -</parameter> -<parameter name="description" type="android.content.ClipDescription"> -</parameter> -<parameter name="data" type="android.content.ClipData"> -</parameter> -<parameter name="result" type="boolean"> -</parameter> -</method> -<method name="obtain" - return="android.view.DragEvent" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="source" type="android.view.DragEvent"> -</parameter> -</method> -<method name="recycle" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="true" - deprecated="not deprecated" - visibility="public" -> -</method> <method name="writeToParcel" return="void" abstract="false" @@ -247172,7 +248473,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="arg0" type="T"> +<parameter name="t" type="T"> </parameter> </method> </interface> diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index 654d9dc..93baefd 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -7,13 +7,16 @@ LOCAL_SRC_FILES:= \ SineSource.cpp LOCAL_SHARED_LIBRARIES := \ - libstagefright libmedia libutils libbinder libstagefright_foundation + libstagefright libmedia libutils libbinder libstagefright_foundation \ + libskia LOCAL_C_INCLUDES:= \ $(JNI_H_INCLUDE) \ frameworks/base/media/libstagefright \ frameworks/base/media/libstagefright/include \ - $(TOP)/frameworks/base/include/media/stagefright/openmax + $(TOP)/frameworks/base/include/media/stagefright/openmax \ + external/skia/include/core \ + external/skia/include/images \ LOCAL_CFLAGS += -Wno-multichar diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index f0758fd..7e7f6d1 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -49,6 +49,10 @@ #include <media/stagefright/MPEG2TSWriter.h> #include <media/stagefright/MPEG4Writer.h> +#include <private/media/VideoFrame.h> +#include <SkBitmap.h> +#include <SkImageEncoder.h> + #include <fcntl.h> using namespace android; @@ -107,6 +111,20 @@ static void displayDecodeHistogram(Vector<int64_t> *decodeTimesUs) { } } +static void displayAVCProfileLevelIfPossible(const sp<MetaData>& meta) { + uint32_t type; + const void *data; + size_t size; + if (meta->findData(kKeyAVCC, &type, &data, &size)) { + const uint8_t *ptr = (const uint8_t *)data; + CHECK(size >= 7); + CHECK(ptr[0] == 1); // configurationVersion == 1 + uint8_t profile = ptr[1]; + uint8_t level = ptr[3]; + fprintf(stderr, "AVC video profile %d and level %d\n", profile, level); + } +} + static void playSource(OMXClient *client, sp<MediaSource> &source) { sp<MetaData> meta = source->getFormat(); @@ -126,6 +144,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime); return; } + displayAVCProfileLevelIfPossible(meta); } source.clear(); @@ -666,6 +685,19 @@ int main(int argc, char **argv) { if (mem != NULL) { printf("captureFrame(%s) => OK\n", filename); + + VideoFrame *frame = (VideoFrame *)mem->pointer(); + + SkBitmap bitmap; + bitmap.setConfig( + SkBitmap::kRGB_565_Config, frame->mWidth, frame->mHeight); + + bitmap.setPixels((uint8_t *)frame + sizeof(VideoFrame)); + + CHECK(SkImageEncoder::EncodeFile( + "/sdcard/out.jpg", bitmap, + SkImageEncoder::kJPEG_Type, + SkImageEncoder::kDefaultQuality)); } else { mem = retriever->extractAlbumArt(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 3cead11..c0714e3 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -42,6 +42,9 @@ import android.database.sqlite.SQLiteDebug; import android.database.sqlite.SQLiteDebug.DbStats; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.net.IConnectivityManager; +import android.net.Proxy; +import android.net.ProxyProperties; import android.os.Build; import android.os.Bundle; import android.os.Debug; @@ -272,7 +275,7 @@ public final class ActivityThread { super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token); this.intent = intent; } - + Intent intent; ActivityInfo info; public String toString() { @@ -592,6 +595,10 @@ public final class ActivityThread { InetAddress.clearDnsCache(); } + public void setHttpProxy(String host, String port, String exclList) { + Proxy.setHttpProxySystemProperty(host, port, exclList); + } + public void processInBackground() { mH.removeMessages(H.GC_WHEN_IDLE); mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE)); @@ -3253,6 +3260,16 @@ public final class ActivityThread { } } + /** + * Initialize the default http proxy in this process for the reasons we set the time zone. + */ + IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); + IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); + try { + ProxyProperties proxyProperties = service.getProxy(); + Proxy.setHttpProxySystemProperty(proxyProperties); + } catch (RemoteException e) {} + if (data.instrumentationName != null) { ContextImpl appContext = new ContextImpl(); appContext.init(data.info, null, this); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index ce9501a..abb26e3 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -914,6 +914,16 @@ final class ApplicationPackageManager extends PackageManager { } @Override + public void setInstallerPackageName(String targetPackage, + String installerPackageName) { + try { + mPM.setInstallerPackageName(targetPackage, installerPackageName); + } catch (RemoteException e) { + // Should never happen! + } + } + + @Override public void movePackage(String packageName, IPackageMoveObserver observer, int flags) { try { mPM.movePackage(packageName, observer, flags); diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index b19fb59..801c3f9 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -276,7 +276,7 @@ public abstract class ApplicationThreadNative extends Binder requestThumbnail(b); return true; } - + case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -297,12 +297,21 @@ public abstract class ApplicationThreadNative extends Binder return true; } + case SET_HTTP_PROXY_TRANSACTION: { + data.enforceInterface(IApplicationThread.descriptor); + final String proxy = data.readString(); + final String port = data.readString(); + final String exclList = data.readString(); + setHttpProxy(proxy, port, exclList); + return true; + } + case PROCESS_IN_BACKGROUND_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); processInBackground(); return true; } - + case DUMP_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ParcelFileDescriptor fd = data.readFileDescriptor(); @@ -758,6 +767,16 @@ class ApplicationThreadProxy implements IApplicationThread { data.recycle(); } + public void setHttpProxy(String proxy, String port, String exclList) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeString(proxy); + data.writeString(port); + data.writeString(exclList); + mRemote.transact(SET_HTTP_PROXY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } + public void processInBackground() throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index dda3107..82b3f75 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -575,7 +575,8 @@ class ContextImpl extends Context { } Map map = null; - if (prefsFile.exists() && prefsFile.canRead()) { + FileStatus stat = new FileStatus(); + if (FileUtils.getFileStatus(prefsFile.getPath(), stat) && prefsFile.canRead()) { try { FileInputStream str = new FileInputStream(prefsFile); map = XmlUtils.readMapXml(str); @@ -588,7 +589,7 @@ class ContextImpl extends Context { Log.w(TAG, "getSharedPreferences", e); } } - sp.replace(map); + sp.replace(map, stat); } return sp; } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 830c702..eca84ef 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -88,6 +88,7 @@ public interface IApplicationThread extends IInterface { void scheduleConfigurationChanged(Configuration config) throws RemoteException; void updateTimeZone() throws RemoteException; void clearDnsCache() throws RemoteException; + void setHttpProxy(String proxy, String port, String exclList) throws RemoteException; void processInBackground() throws RemoteException; void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) throws RemoteException; @@ -148,4 +149,5 @@ public interface IApplicationThread extends IInterface { int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35; int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36; int CLEAR_DNS_CACHE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37; + int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38; } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index e602518..f5a46c5 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -16,6 +16,7 @@ package android.app; +import java.text.NumberFormat; import java.util.Date; import android.app.PendingIntent; @@ -29,8 +30,12 @@ import android.os.Parcelable; import android.text.TextUtils; import android.text.format.DateFormat; import android.text.format.DateUtils; +import android.util.Slog; +import android.view.View; import android.widget.RemoteViews; +import com.android.internal.R; + /** * A class that represents how a persistent notification is to be presented to * the user using the {@link android.app.NotificationManager}. @@ -41,6 +46,8 @@ import android.widget.RemoteViews; */ public class Notification implements Parcelable { + private static final String TAG = "Notification"; + /** * Use all default values (where applicable). */ @@ -84,6 +91,15 @@ public class Notification implements Parcelable public int icon; /** + * If the icon in the status bar is to have more than one level, you can set this. Otherwise, + * leave it at its default value of 0. + * + * @see android.widget.ImageView#setImageLevel + * @see android.graphics.drawable#setLevel + */ + public int iconLevel; + + /** * The number of events that this notification represents. For example, in a new mail * notification, this could be the number of unread messages. This number is superimposed over * the icon in the status bar. If the number is 0 or negative, it is not shown in the status @@ -132,38 +148,15 @@ public class Notification implements Parcelable * text for when the text scrolls in and when it is displayed all at once * in conjunction with one or more icons. * - * @see #tickerTitle - * @see #tickerSubtitle - * @see #tickerIcons + * @see #tickerView */ public CharSequence tickerText; /** - * The title line for the ticker over a the fat status bar on xlarge devices. - * - * @see #tickerText - * @see #tickerSubtitle - * @see #tickerIcons - */ - public CharSequence tickerTitle; - - /** - * The subtitle line for the ticker over a the fat status bar on xlarge devices. - * - * @see #tickerText - * @see #tickerTitle - * @see #tickerIcons - */ - public CharSequence tickerSubtitle; - - /** - * The icons to show to the left of the other ticker fields. - * - * @see #tickerText - * @see #tickerTitle - * @see #tickerSubtitle + * The view to show as the ticker in the status bar when the notification + * is posted. */ - public Bitmap[] tickerIcons; + public RemoteViews tickerView; /** * The view that will represent this notification in the expanded status bar. @@ -171,13 +164,9 @@ public class Notification implements Parcelable public RemoteViews contentView; /** - * If the icon in the status bar is to have more than one level, you can set this. Otherwise, - * leave it at its default value of 0. - * - * @see android.widget.ImageView#setImageLevel - * @see android.graphics.drawable#setLevel + * The bitmap that may escape the bounds of the panel and bar. */ - public int iconLevel; + public Bitmap largeIcon; /** * The sound to play. @@ -327,6 +316,7 @@ public class Notification implements Parcelable /** * Constructs a Notification object with everything set to 0. + * You might want to consider using {@link Builder} instead. */ public Notification() { @@ -334,7 +324,6 @@ public class Notification implements Parcelable } /** - * @deprecated use {@link #Notification(int,CharSequence,long)} and {@link #setLatestEventInfo}. * @hide */ public Notification(Context context, int icon, CharSequence tickerText, long when, @@ -356,7 +345,10 @@ public class Notification implements Parcelable * activates. * @param when The time to show in the time field. In the System.currentTimeMillis * timebase. + * + * @deprecated Use {@link Builder} instead. */ + @Deprecated public Notification(int icon, CharSequence tickerText, long when) { this.icon = icon; @@ -384,22 +376,13 @@ public class Notification implements Parcelable tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { - tickerTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); + tickerView = RemoteViews.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { - tickerSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); - } - final int tickerIconCount = parcel.readInt(); - if (tickerIconCount >= 0) { - tickerIcons = new Bitmap[tickerIconCount]; - for (int i=0; i<tickerIconCount; i++) { - if (parcel.readInt() != 0) { - tickerIcons[i] = Bitmap.CREATOR.createFromParcel(parcel); - } - } + contentView = RemoteViews.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { - contentView = RemoteViews.CREATOR.createFromParcel(parcel); + largeIcon = Bitmap.CREATOR.createFromParcel(parcel); } defaults = parcel.readInt(); flags = parcel.readInt(); @@ -434,22 +417,15 @@ public class Notification implements Parcelable if (this.tickerText != null) { that.tickerText = this.tickerText.toString(); } - if (this.tickerTitle != null) { - that.tickerTitle = this.tickerTitle.toString(); - } - if (this.tickerSubtitle != null) { - that.tickerSubtitle = this.tickerSubtitle.toString(); - } - if (this.tickerIcons != null) { - final int N = this.tickerIcons.length; - that.tickerIcons = new Bitmap[N]; - for (int i=0; i<N; i++) { - that.tickerIcons[i] = Bitmap.createBitmap(this.tickerIcons[i]); - } + if (this.tickerView != null) { + that.tickerView = this.tickerView.clone(); } if (this.contentView != null) { that.contentView = this.contentView.clone(); } + if (this.largeIcon != null) { + that.largeIcon = Bitmap.createBitmap(this.largeIcon); + } that.iconLevel = that.iconLevel; that.sound = this.sound; // android.net.Uri is immutable that.audioStreamType = this.audioStreamType; @@ -503,35 +479,21 @@ public class Notification implements Parcelable } else { parcel.writeInt(0); } - if (tickerTitle != null) { + if (tickerView != null) { parcel.writeInt(1); - TextUtils.writeToParcel(tickerTitle, parcel, flags); + tickerView.writeToParcel(parcel, 0); } else { parcel.writeInt(0); } - if (tickerSubtitle != null) { + if (contentView != null) { parcel.writeInt(1); - TextUtils.writeToParcel(tickerSubtitle, parcel, flags); + contentView.writeToParcel(parcel, 0); } else { parcel.writeInt(0); } - if (tickerIcons != null) { - final int N = tickerIcons.length; - parcel.writeInt(N); - for (int i=0; i<N; i++) { - if (tickerIcons[i] != null) { - parcel.writeInt(1); - tickerIcons[i].writeToParcel(parcel, flags); - } else { - parcel.writeInt(0); - } - } - } else { - parcel.writeInt(-1); - } - if (contentView != null) { + if (largeIcon != null) { parcel.writeInt(1); - contentView.writeToParcel(parcel, 0); + largeIcon.writeToParcel(parcel, 0); } else { parcel.writeInt(0); } @@ -591,22 +553,25 @@ public class Notification implements Parcelable * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires * that you take care of task management as described in * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application Fundamentals: Activities and Tasks</a>. + * + * @deprecated Use {@link Builder} instead. */ + @Deprecated public void setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) { RemoteViews contentView = new RemoteViews(context.getPackageName(), - com.android.internal.R.layout.status_bar_latest_event_content); + R.layout.status_bar_latest_event_content); if (this.icon != 0) { - contentView.setImageViewResource(com.android.internal.R.id.icon, this.icon); + contentView.setImageViewResource(R.id.icon, this.icon); } if (contentTitle != null) { - contentView.setTextViewText(com.android.internal.R.id.title, contentTitle); + contentView.setTextViewText(R.id.title, contentTitle); } if (contentText != null) { - contentView.setTextViewText(com.android.internal.R.id.text, contentText); + contentView.setTextViewText(R.id.text, contentText); } if (this.when != 0) { - contentView.setLong(com.android.internal.R.id.time, "setTime", when); + contentView.setLong(R.id.time, "setTime", when); } this.contentView = contentView; @@ -651,4 +616,243 @@ public class Notification implements Parcelable sb.append(")"); return sb.toString(); } + + public static class Builder { + private Context mContext; + + private long mWhen; + private int mSmallIcon; + private int mSmallIconLevel; + private int mNumber; + private CharSequence mContentTitle; + private CharSequence mContentText; + private CharSequence mContentInfo; + private PendingIntent mContentIntent; + private RemoteViews mContentView; + private PendingIntent mDeleteIntent; + private PendingIntent mFullScreenIntent; + private CharSequence mTickerText; + private RemoteViews mTickerView; + private Bitmap mLargeIcon; + private Uri mSound; + private int mAudioStreamType; + private long[] mVibrate; + private int mLedArgb; + private int mLedOnMs; + private int mLedOffMs; + private int mDefaults; + private int mFlags; + + public Builder(Context context) { + mContext = context; + mWhen = System.currentTimeMillis(); + } + + public Builder setWhen(long when) { + mWhen = when; + return this; + } + + public Builder setSmallIcon(int icon) { + mSmallIcon = icon; + return this; + } + + public Builder setSmallIcon(int icon, int level) { + mSmallIcon = icon; + mSmallIconLevel = level; + return this; + } + + public Builder setContentTitle(CharSequence title) { + mContentTitle = title; + return this; + } + + public Builder setContentText(CharSequence text) { + mContentText = text; + return this; + } + + public Builder setNumber(int number) { + mNumber = number; + return this; + } + + public Builder setContentInfo(CharSequence info) { + mContentInfo = info; + return this; + } + + public Builder setContent(RemoteViews views) { + mContentView = views; + return this; + } + + public Builder setContentIntent(PendingIntent intent) { + mContentIntent = intent; + return this; + } + + public Builder setDeleteIntent(PendingIntent intent) { + mDeleteIntent = intent; + return this; + } + + public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { + mFullScreenIntent = intent; + setFlag(FLAG_HIGH_PRIORITY, highPriority); + return this; + } + + public Builder setTicker(CharSequence tickerText) { + mTickerText = tickerText; + return this; + } + + public Builder setTicker(CharSequence tickerText, RemoteViews views) { + mTickerText = tickerText; + mTickerView = views; + return this; + } + + public Builder setLargeIcon(Bitmap icon) { + mLargeIcon = icon; + return this; + } + + public Builder setSound(Uri sound) { + mSound = sound; + mAudioStreamType = STREAM_DEFAULT; + return this; + } + + public Builder setSound(Uri sound, int streamType) { + mSound = sound; + mAudioStreamType = streamType; + return this; + } + + public Builder setVibrate(long[] pattern) { + mVibrate = pattern; + return this; + } + + public Builder setLights(int argb, int onMs, int offMs) { + mLedArgb = argb; + mLedOnMs = onMs; + mLedOffMs = offMs; + return this; + } + + public Builder setOngoing(boolean ongoing) { + setFlag(FLAG_ONGOING_EVENT, ongoing); + return this; + } + + public Builder setOnlyAlertOnce(boolean onlyAlertOnce) { + setFlag(FLAG_ONLY_ALERT_ONCE, onlyAlertOnce); + return this; + } + + public Builder setAutoCancel(boolean autoCancel) { + setFlag(FLAG_ONLY_ALERT_ONCE, autoCancel); + return this; + } + + public Builder setDefaults(int defaults) { + mDefaults = defaults; + return this; + } + + private void setFlag(int mask, boolean value) { + if (value) { + mFlags |= mask; + } else { + mFlags &= ~mask; + } + } + + private RemoteViews makeRemoteViews(int resId) { + RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); + if (mSmallIcon != 0) { + contentView.setImageViewResource(R.id.icon, mSmallIcon); + } + if (mContentTitle != null) { + contentView.setTextViewText(R.id.title, mContentTitle); + } + if (mContentText != null) { + contentView.setTextViewText(R.id.text, mContentText); + } + if (mContentInfo != null) { + contentView.setTextViewText(R.id.info, mContentInfo); + } else if (mNumber > 0) { + NumberFormat f = NumberFormat.getIntegerInstance(); + contentView.setTextViewText(R.id.info, f.format(mNumber)); + contentView.setFloat(R.id.info, "setTextSize", + mContext.getResources().getDimensionPixelSize( + R.dimen.status_bar_content_number_size)); + } else { + contentView.setViewVisibility(R.id.info, View.GONE); + } + if (mWhen != 0) { + contentView.setLong(R.id.time, "setTime", mWhen); + } + return contentView; + } + + private RemoteViews makeContentView() { + if (mContentView != null) { + return mContentView; + } else { + return makeRemoteViews(mLargeIcon == null + ? R.layout.status_bar_latest_event_content + : R.layout.status_bar_latest_event_content_large_icon); + } + } + + private RemoteViews makeTickerView() { + if (mTickerView != null) { + return mTickerView; + } else { + if (mContentView == null) { + return makeRemoteViews(mLargeIcon == null + ? R.layout.status_bar_latest_event_ticker + : R.layout.status_bar_latest_event_ticker_large_icon); + } else { + return null; + } + } + } + + public Notification getNotification() { + Notification n = new Notification(); + n.when = mWhen; + n.icon = mSmallIcon; + n.iconLevel = mSmallIconLevel; + n.number = mNumber; + n.contentView = makeContentView(); + n.contentIntent = mContentIntent; + n.deleteIntent = mDeleteIntent; + n.fullScreenIntent = mFullScreenIntent; + n.tickerText = mTickerText; + n.tickerView = makeTickerView(); + n.largeIcon = mLargeIcon; + n.sound = mSound; + n.audioStreamType = mAudioStreamType; + n.vibrate = mVibrate; + n.ledARGB = mLedArgb; + n.ledOnMS = mLedOnMs; + n.ledOffMS = mLedOffMs; + n.defaults = mDefaults; + n.flags = mFlags; + if (mLedOnMs != 0 && mLedOffMs != 0) { + n.flags |= FLAG_SHOW_LIGHTS; + } + if ((mDefaults & DEFAULT_LIGHTS) != 0) { + n.flags |= FLAG_SHOW_LIGHTS; + } + return n; + } + } } diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 18602df..0c280f9 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -1109,6 +1109,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * @return true if a successful launch, false if could not (e.g. bad position). */ protected boolean launchSuggestion(int position, int actionKey, String actionMsg) { + if (mSuggestionsAdapter == null) { + return false; + } Cursor c = mSuggestionsAdapter.getCursor(); if ((c != null) && c.moveToPosition(position)) { diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java index 2096a78..a807d3b 100644 --- a/core/java/android/app/SharedPreferencesImpl.java +++ b/core/java/android/app/SharedPreferencesImpl.java @@ -103,12 +103,16 @@ final class SharedPreferencesImpl implements SharedPreferences { } } - public void replace(Map newContents) { + /*package*/ void replace(Map newContents, FileStatus stat) { synchronized (this) { mLoaded = true; if (newContents != null) { mMap = newContents; } + if (stat != null) { + mStatTimestamp = stat.mtime; + mStatSize = stat.size; + } } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index a18fdac..f169cd7 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -691,8 +691,6 @@ public class DevicePolicyManager { * * <p>To disable password expiration, a value of 0 may be used for timeout. * - * <p>Timeout must be at least 1 day or IllegalArgumentException will be thrown. - * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this * method; if it has not, a security exception will be thrown. diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java index 85a6765..3e2b763 100644 --- a/core/java/android/content/ClipboardManager.java +++ b/core/java/android/content/ClipboardManager.java @@ -189,7 +189,7 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public boolean hasText() { try { - return getService().hasPrimaryClip(); + return getService().hasClipboardText(); } catch (RemoteException e) { return false; } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 4cff3bb..d01a68a 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -158,6 +158,8 @@ interface IPackageManager { void finishPackageInstall(int token); + void setInstallerPackageName(in String targetPackage, in String installerPackageName); + /** * Delete a package. * diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b5d1653..ac7a95a 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1918,6 +1918,24 @@ public abstract class PackageManager { String installerPackageName); /** + * Change the installer associated with a given package. There are limitations + * on how the installer package can be changed; in particular: + * <ul> + * <li> A SecurityException will be thrown if <var>installerPackageName</var> + * is not signed with the same certificate as the calling application. + * <li> A SecurityException will be thrown if <var>targetPackage</var> already + * has an installer package, and that installer package is not signed with + * the same certificate as the calling application. + * </ul> + * + * @param targetPackage The installed package whose installer will be changed. + * @param installerPackageName The package name of the new installer. May be + * null to clear the association. + */ + public abstract void setInstallerPackageName(String targetPackage, + String installerPackageName); + + /** * Attempts to delete a package. Since this may take a little while, the result will * be posted back to the given observer. A deletion will fail if the calling context * lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java index 5e90b91..23a6f97 100644 --- a/core/java/android/content/res/StringBlock.java +++ b/core/java/android/content/res/StringBlock.java @@ -87,21 +87,48 @@ final class StringBlock { if (style != null) { if (mStyleIDs == null) { mStyleIDs = new StyleIDs(); - mStyleIDs.boldId = nativeIndexOfString(mNative, "b"); - mStyleIDs.italicId = nativeIndexOfString(mNative, "i"); - mStyleIDs.underlineId = nativeIndexOfString(mNative, "u"); - mStyleIDs.ttId = nativeIndexOfString(mNative, "tt"); - mStyleIDs.bigId = nativeIndexOfString(mNative, "big"); - mStyleIDs.smallId = nativeIndexOfString(mNative, "small"); - mStyleIDs.supId = nativeIndexOfString(mNative, "sup"); - mStyleIDs.subId = nativeIndexOfString(mNative, "sub"); - mStyleIDs.strikeId = nativeIndexOfString(mNative, "strike"); - mStyleIDs.listItemId = nativeIndexOfString(mNative, "li"); - mStyleIDs.marqueeId = nativeIndexOfString(mNative, "marquee"); - - if (localLOGV) Log.v(TAG, "BoldId=" + mStyleIDs.boldId - + ", ItalicId=" + mStyleIDs.italicId - + ", UnderlineId=" + mStyleIDs.underlineId); + } + + // the style array is a flat array of <type, start, end> hence + // the magic constant 3. + for (int styleIndex = 0; styleIndex < style.length; styleIndex += 3) { + int styleId = style[styleIndex]; + + if (styleId == mStyleIDs.boldId || styleId == mStyleIDs.italicId + || styleId == mStyleIDs.underlineId || styleId == mStyleIDs.ttId + || styleId == mStyleIDs.bigId || styleId == mStyleIDs.smallId + || styleId == mStyleIDs.subId || styleId == mStyleIDs.supId + || styleId == mStyleIDs.strikeId || styleId == mStyleIDs.listItemId + || styleId == mStyleIDs.marqueeId) { + // id already found skip to next style + continue; + } + + String styleTag = nativeGetString(mNative, styleId); + + if (styleTag.equals("b")) { + mStyleIDs.boldId = styleId; + } else if (styleTag.equals("i")) { + mStyleIDs.italicId = styleId; + } else if (styleTag.equals("u")) { + mStyleIDs.underlineId = styleId; + } else if (styleTag.equals("tt")) { + mStyleIDs.ttId = styleId; + } else if (styleTag.equals("big")) { + mStyleIDs.bigId = styleId; + } else if (styleTag.equals("small")) { + mStyleIDs.smallId = styleId; + } else if (styleTag.equals("sup")) { + mStyleIDs.supId = styleId; + } else if (styleTag.equals("sub")) { + mStyleIDs.subId = styleId; + } else if (styleTag.equals("strike")) { + mStyleIDs.strikeId = styleId; + } else if (styleTag.equals("li")) { + mStyleIDs.listItemId = styleId; + } else if (styleTag.equals("marquee")) { + mStyleIDs.marqueeId = styleId; + } } res = applyStyles(str, style, mStyleIDs); @@ -119,17 +146,17 @@ final class StringBlock { } static final class StyleIDs { - private int boldId; - private int italicId; - private int underlineId; - private int ttId; - private int bigId; - private int smallId; - private int subId; - private int supId; - private int strikeId; - private int listItemId; - private int marqueeId; + private int boldId = -1; + private int italicId = -1; + private int underlineId = -1; + private int ttId = -1; + private int bigId = -1; + private int smallId = -1; + private int subId = -1; + private int supId = -1; + private int strikeId = -1; + private int listItemId = -1; + private int marqueeId = -1; } private CharSequence applyStyles(String str, int[] style, StyleIDs ids) { @@ -403,6 +430,5 @@ final class StringBlock { private static final native int nativeGetSize(int obj); private static final native String nativeGetString(int obj, int idx); private static final native int[] nativeGetStyle(int obj, int idx); - private static final native int nativeIndexOfString(int obj, String str); private static final native void nativeDestroy(int obj); } diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 378189e..f3b2c81 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -906,6 +906,7 @@ public class Camera { * Changes the settings for this Camera service. * * @param params the Parameters to use for this Camera service + * @throws RuntimeException if any parameter is invalid or not supported. * @see #getParameters() */ public void setParameters(Parameters params) { diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 3f6e4ce..c178aee 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -1158,7 +1158,7 @@ public class SensorManager * * <p> * <center><img src="../../../images/axis_globe.png" - * alt="Sensors coordinate-system diagram." border="0" /></center> + * alt="World coordinate-system diagram." border="0" /></center> * </p> * * <p> @@ -1521,9 +1521,19 @@ public class SensorManager * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li> * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li> * </ul> + * <p>The reference coordinate-system used is different from the world + * coordinate-system defined for the rotation matrix:</p> + * <ul> + * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to + * the ground at the device's current location and roughly points West).</li> + * <li>Y is tangential to the ground at the device's current location and + * points towards the magnetic North Pole.</li> + * <li>Z points towards the center of the Earth and is perpendicular to the ground.</li> + * </ul> + * * <p> - * <center><img src="../../../images/axis_device.png" - * alt="Sensors coordinate-system diagram." border="0" /></center> + * <center><img src="../../../images/axis_device_inverted.png" + * alt="Inverted world coordinate-system diagram." border="0" /></center> * </p> * <p> * All three angles above are in <b>radians</b> and <b>positive</b> in the diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index dd9c8f0..ecfa2c1 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -624,4 +624,39 @@ public class ConnectivityManager } catch (RemoteException e) { } } + + /** + * @param proxyProperties The definition for the new global http proxy + * {@hide} + */ + public void setGlobalProxy(ProxyProperties p) { + try { + mService.setGlobalProxy(p); + } catch (RemoteException e) { + } + } + + /** + * @return proxyProperties for the current global proxy + * {@hide} + */ + public ProxyProperties getGlobalProxy() { + try { + return mService.getGlobalProxy(); + } catch (RemoteException e) { + return null; + } + } + + /** + * @return proxyProperties for the current proxy (global if set, network specific if not) + * {@hide} + */ + public ProxyProperties getProxy() { + try { + return mService.getProxy(); + } catch (RemoteException e) { + return null; + } + } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 35054d6..70ab4f1 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.LinkProperties; import android.net.NetworkInfo; +import android.net.ProxyProperties; import android.os.IBinder; /** @@ -85,4 +86,10 @@ interface IConnectivityManager void requestNetworkTransitionWakelock(in String forWhom); void reportInetCondition(int networkType, int percentage); + + ProxyProperties getGlobalProxy(); + + void setGlobalProxy(in ProxyProperties p); + + ProxyProperties getProxy(); } diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java index 21c485e..3b9b9fe 100644 --- a/core/java/android/net/Proxy.java +++ b/core/java/android/net/Proxy.java @@ -16,9 +16,12 @@ package android.net; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; +import android.net.ProxyProperties; import android.os.Handler; import android.os.SystemProperties; import android.text.TextUtils; @@ -55,17 +58,22 @@ public final class Proxy { // Set to true to enable extra debugging. private static final boolean DEBUG = false; + private static final String TAG = "Proxy"; - // Used to notify an app that's caching the default connection proxy - // that either the default connection or its proxy has changed - public static final String PROXY_CHANGE_ACTION = - "android.intent.action.PROXY_CHANGE"; - - private static ReadWriteLock sProxyInfoLock = new ReentrantReadWriteLock(); - - private static SettingsObserver sGlobalProxyChangedObserver = null; - - private static ProxySpec sGlobalProxySpec = null; + /** + * Used to notify an app that's caching the default connection proxy + * that either the default connection or its proxy has changed. + * The intent will have the following extra value:</p> + * <ul> + * <li><em>EXTRA_PROXY_INFO</em> - The ProxyProperties for the proxy + * </ul> + * + * <p class="note">This is a protected intent that can only be sent by the system + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; + /** {@hide} **/ + public static final String EXTRA_PROXY_INFO = "proxy"; private static ConnectivityManager sConnectivityManager = null; @@ -88,62 +96,6 @@ public final class Proxy { EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP); } - // useful because it holds the processed exclusion list - don't want to reparse it each time - private static class ProxySpec { - String[] exclusionList; - InetSocketAddress address = null; - public ProxySpec() { - exclusionList = new String[0]; - }; - } - - private static boolean isURLInExclusionList(String url, String[] exclusionList) { - if (url == null) { - return false; - } - Uri u = Uri.parse(url); - String urlDomain = u.getHost(); - // If the domain is defined as ".android.com" or "android.com", we wish to match - // http://android.com as well as http://xxx.android.com , but not - // http://myandroid.com . This code works out the logic. - for (String excludedDomain : exclusionList) { - String dotDomain = "." + excludedDomain; - if (urlDomain.equals(excludedDomain)) { - return true; - } - if (urlDomain.endsWith(dotDomain)) { - return true; - } - } - // No match - return false; - } - - private static String parseHost(String proxySpec) { - int i = proxySpec.indexOf(':'); - if (i == -1) { - if (DEBUG) { - Assert.assertTrue(proxySpec.length() == 0); - } - return null; - } - return proxySpec.substring(0, i); - } - - private static int parsePort(String proxySpec) { - int i = proxySpec.indexOf(':'); - if (i == -1) { - if (DEBUG) { - Assert.assertTrue(proxySpec.length() == 0); - } - return -1; - } - if (DEBUG) { - Assert.assertTrue(i < proxySpec.length()); - } - return Integer.parseInt(proxySpec.substring(i+1)); - } - /** * Return the proxy object to be used for the URL given as parameter. * @param ctx A Context used to get the settings for the proxy host. @@ -154,34 +106,31 @@ public final class Proxy { * {@hide} */ public static final java.net.Proxy getProxy(Context ctx, String url) { - sProxyInfoLock.readLock().lock(); - java.net.Proxy retval; - try { - if (sGlobalProxyChangedObserver == null) { - registerContentObserversReadLocked(ctx); - parseGlobalProxyInfoReadLocked(ctx); + String host = ""; + if (url != null) { + URI uri = URI.create(url); + host = uri.getHost(); + } + + if (!isLocalHost(host)) { + if (sConnectivityManager == null) { + sConnectivityManager = (ConnectivityManager)ctx.getSystemService( + Context.CONNECTIVITY_SERVICE); } - if (sGlobalProxySpec != null) { - // Proxy defined - Apply exclusion rules - if (isURLInExclusionList(url, sGlobalProxySpec.exclusionList)) { - // Return no proxy - retval = java.net.Proxy.NO_PROXY; - } else { - retval = - new java.net.Proxy(java.net.Proxy.Type.HTTP, sGlobalProxySpec.address); + if (sConnectivityManager == null) return java.net.Proxy.NO_PROXY; + + ProxyProperties proxyProperties = sConnectivityManager.getProxy(); + + if (proxyProperties != null) { + if (!proxyProperties.isExcluded(host)) { + return proxyProperties.makeProxy(); } - } else { - retval = getDefaultProxy(ctx, url); } - } finally { - sProxyInfoLock.readLock().unlock(); - } - if ((retval != java.net.Proxy.NO_PROXY) && (isLocalHost(url))) { - retval = java.net.Proxy.NO_PROXY; } - return retval; + return java.net.Proxy.NO_PROXY; } + // TODO: deprecate this function /** * Return the proxy host set by the user. @@ -236,35 +185,6 @@ public final class Proxy { return -1; } - // TODO - cache the details for each network so we don't have to fetch and parse - // on each request - private static final java.net.Proxy getDefaultProxy(Context context, String url) { - if (sConnectivityManager == null) { - sConnectivityManager = (ConnectivityManager)context.getSystemService( - Context.CONNECTIVITY_SERVICE); - } - if (sConnectivityManager == null) return java.net.Proxy.NO_PROXY; - - LinkProperties linkProperties = sConnectivityManager.getActiveLinkProperties(); - - if (linkProperties != null) { - ProxyProperties proxyProperties = linkProperties.getHttpProxy(); - - if (proxyProperties != null) { - String exclusionList = proxyProperties.getExclusionList(); - SocketAddress socketAddr = proxyProperties.getSocketAddress(); - if (socketAddr != null) { - String[] parsedExclusionArray = - parsedExclusionArray = parseExclusionList(exclusionList); - if (!isURLInExclusionList(url, parsedExclusionArray)) { - return new java.net.Proxy(java.net.Proxy.Type.HTTP, socketAddr); - } - } - } - } - return java.net.Proxy.NO_PROXY; - } - // TODO: remove this function / deprecate /** * Returns the preferred proxy to be used by clients. This is a wrapper @@ -291,13 +211,11 @@ public final class Proxy { } } - private static final boolean isLocalHost(String url) { - if (url == null) { + private static final boolean isLocalHost(String host) { + if (host == null) { return false; } try { - final URI uri = URI.create(url); - final String host = uri.getHost(); if (host != null) { if (host.equalsIgnoreCase("localhost")) { return true; @@ -317,92 +235,6 @@ public final class Proxy { return false; } - private static class SettingsObserver extends ContentObserver { - - private Context mContext; - - SettingsObserver(Context ctx) { - super(new Handler(ctx.getMainLooper())); - mContext = ctx; - } - - @Override - public void onChange(boolean selfChange) { - sProxyInfoLock.readLock().lock(); - parseGlobalProxyInfoReadLocked(mContext); - sProxyInfoLock.readLock().unlock(); - } - } - - private static final void registerContentObserversReadLocked(Context ctx) { - Uri uriGlobalProxy = Settings.Secure.getUriFor(Settings.Secure.HTTP_PROXY); - Uri uriGlobalExclList = - Settings.Secure.getUriFor(Settings.Secure.HTTP_PROXY_EXCLUSION_LIST); - - // No lock upgrading (from read to write) allowed - sProxyInfoLock.readLock().unlock(); - sProxyInfoLock.writeLock().lock(); - try { - sGlobalProxyChangedObserver = new SettingsObserver(ctx); - } finally { - // Downgrading locks (from write to read) is allowed - sProxyInfoLock.readLock().lock(); - sProxyInfoLock.writeLock().unlock(); - } - ctx.getContentResolver().registerContentObserver(uriGlobalProxy, false, - sGlobalProxyChangedObserver); - ctx.getContentResolver().registerContentObserver(uriGlobalExclList, false, - sGlobalProxyChangedObserver); - } - - private static final void parseGlobalProxyInfoReadLocked(Context ctx) { - ContentResolver contentResolver = ctx.getContentResolver(); - String proxyHost = Settings.Secure.getString( - contentResolver, - Settings.Secure.HTTP_PROXY); - if (TextUtils.isEmpty(proxyHost)) { - // Clear signal - sProxyInfoLock.readLock().unlock(); - sProxyInfoLock.writeLock().lock(); - sGlobalProxySpec = null; - sProxyInfoLock.readLock().lock(); - sProxyInfoLock.writeLock().unlock(); - return; - } - String exclusionListSpec = Settings.Secure.getString( - contentResolver, - Settings.Secure.HTTP_PROXY_EXCLUSION_LIST); - String host = parseHost(proxyHost); - int port = parsePort(proxyHost); - ProxySpec tmpProxySpec = null; - if (proxyHost != null) { - tmpProxySpec = new ProxySpec(); - tmpProxySpec.address = new InetSocketAddress(host, port); - tmpProxySpec.exclusionList = parseExclusionList(exclusionListSpec); - } - sProxyInfoLock.readLock().unlock(); - sProxyInfoLock.writeLock().lock(); - sGlobalProxySpec = tmpProxySpec; - sProxyInfoLock.readLock().lock(); - sProxyInfoLock.writeLock().unlock(); - } - - private static String[] parseExclusionList(String exclusionList) { - String[] processedArray = new String[0]; - if (!TextUtils.isEmpty(exclusionList)) { - String[] exclusionListArray = exclusionList.toLowerCase().split(","); - processedArray = new String[exclusionListArray.length]; - for (int i = 0; i < exclusionListArray.length; i++) { - String entry = exclusionListArray[i].trim(); - if (entry.startsWith(".")) { - entry = entry.substring(1); - } - processedArray[i] = entry; - } - } - return processedArray; - } - /** * Validate syntax of hostname, port and exclusion list entries * {@hide} @@ -480,4 +312,44 @@ public final class Proxy { new SchemeRegistry(), ProxySelector.getDefault(), context); return ret; } + + /** @hide */ + public static final void setHttpProxySystemProperty(ProxyProperties p) { + String host = null; + String port = null; + String exclList = null; + if (p != null) { + host = p.getHost(); + port = Integer.toString(p.getPort()); + exclList = p.getExclusionList(); + } + setHttpProxySystemProperty(host, port, exclList); + } + + /** @hide */ + public static final void setHttpProxySystemProperty(String host, String port, String exclList) { + if (exclList != null) exclList = exclList.replace(",", "|"); + if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); + if (host != null) { + System.setProperty("http.proxyHost", host); + System.setProperty("https.proxyHost", host); + } else { + System.clearProperty("http.proxyHost"); + System.clearProperty("https.proxyHost"); + } + if (port != null) { + System.setProperty("http.proxyPort", port); + System.setProperty("https.proxyPort", port); + } else { + System.clearProperty("http.proxyPort"); + System.clearProperty("https.proxyPort"); + } + if (exclList != null) { + System.setProperty("http.nonProxyHosts", exclList); + System.setProperty("https.nonProxyHosts", exclList); + } else { + System.clearProperty("http.nonProxyHosts"); + System.clearProperty("https.nonProxyHosts"); + } + } } diff --git a/core/java/android/net/ProxyProperties.aidl b/core/java/android/net/ProxyProperties.aidl new file mode 100644 index 0000000..02ea15d --- /dev/null +++ b/core/java/android/net/ProxyProperties.aidl @@ -0,0 +1,21 @@ +/* +** +** Copyright (C) 2010 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.net; + +parcelable ProxyProperties; + diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java index 5fd0d89..cbe4445 100644 --- a/core/java/android/net/ProxyProperties.java +++ b/core/java/android/net/ProxyProperties.java @@ -19,6 +19,8 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; +import android.util.Log; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -30,44 +32,108 @@ import java.net.UnknownHostException; */ public class ProxyProperties implements Parcelable { - private InetSocketAddress mProxy; + private String mHost; + private int mPort; private String mExclusionList; + private String[] mParsedExclusionList; - public ProxyProperties() { + public ProxyProperties(String host, int port, String exclList) { + mHost = host; + mPort = port; + setExclusionList(exclList); + } + + private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) { + mHost = host; + mPort = port; + mExclusionList = exclList; + mParsedExclusionList = parsedExclList; } // copy constructor instead of clone public ProxyProperties(ProxyProperties source) { if (source != null) { - mProxy = source.getSocketAddress(); - String exclusionList = source.getExclusionList(); - if (exclusionList != null) { - mExclusionList = new String(exclusionList); - } + mHost = source.getHost(); + mPort = source.getPort(); + mExclusionList = source.getExclusionList(); + mParsedExclusionList = source.mParsedExclusionList; } } public InetSocketAddress getSocketAddress() { - return mProxy; + InetSocketAddress inetSocketAddress = null; + try { + inetSocketAddress = new InetSocketAddress(mHost, mPort); + } catch (IllegalArgumentException e) { } + return inetSocketAddress; } - public void setSocketAddress(InetSocketAddress proxy) { - mProxy = proxy; + public String getHost() { + return mHost; } + public int getPort() { + return mPort; + } + + // comma separated public String getExclusionList() { return mExclusionList; } - public void setExclusionList(String exclusionList) { + // comma separated + private void setExclusionList(String exclusionList) { mExclusionList = exclusionList; + if (mExclusionList == null) { + mParsedExclusionList = new String[0]; + } else { + String splitExclusionList[] = exclusionList.toLowerCase().split(","); + mParsedExclusionList = new String[splitExclusionList.length * 2]; + for (int i = 0; i < splitExclusionList.length; i++) { + String s = splitExclusionList[i].trim(); + if (s.startsWith(".")) s = s.substring(1); + mParsedExclusionList[i*2] = s; + mParsedExclusionList[(i*2)+1] = "." + s; + } + } + } + + public boolean isExcluded(String url) { + if (TextUtils.isEmpty(url) || mParsedExclusionList == null || + mParsedExclusionList.length == 0) return false; + + Uri u = Uri.parse(url); + String urlDomain = u.getHost(); + if (urlDomain == null) return false; + for (int i = 0; i< mParsedExclusionList.length; i+=2) { + if (urlDomain.equals(mParsedExclusionList[i]) || + urlDomain.endsWith(mParsedExclusionList[i+1])) { + return true; + } + } + return false; + } + + public java.net.Proxy makeProxy() { + java.net.Proxy proxy = java.net.Proxy.NO_PROXY; + if (mHost != null) { + try { + InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort); + proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress); + } catch (IllegalArgumentException e) { + } + } + return proxy; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - if (mProxy != null) { - sb.append(mProxy.toString()); + if (mHost != null) { + sb.append("["); + sb.append(mHost); + sb.append("] "); + sb.append(Integer.toString(mPort)); if (mExclusionList != null) { sb.append(" xl=").append(mExclusionList); } @@ -75,6 +141,20 @@ public class ProxyProperties implements Parcelable { return sb.toString(); } + @Override + public boolean equals(Object o) { + if (!(o instanceof ProxyProperties)) return false; + ProxyProperties p = (ProxyProperties)o; + if (mExclusionList != null && !mExclusionList.equals(p.getExclusionList())) return false; + if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) { + return false; + } + if (mHost != null && p.mHost == null) return false; + if (mHost == null && p.mHost != null) return false; + if (mPort != p.mPort) return false; + return true; + } + /** * Implement the Parcelable interface * @hide @@ -88,27 +168,15 @@ public class ProxyProperties implements Parcelable { * @hide */ public void writeToParcel(Parcel dest, int flags) { - String host = null; - if (mProxy != null) { - try { - InetAddress addr = mProxy.getAddress(); - if (addr != null) { - host = addr.getHostAddress(); - } else { - /* Does not resolve when addr is null */ - host = mProxy.getHostName(); - } - } catch (Exception e) { } - } - - if (host != null) { + if (mHost != null) { dest.writeByte((byte)1); - dest.writeString(host); - dest.writeInt(mProxy.getPort()); + dest.writeString(mHost); + dest.writeInt(mPort); } else { dest.writeByte((byte)0); } dest.writeString(mExclusionList); + dest.writeStringArray(mParsedExclusionList); } /** @@ -118,16 +186,16 @@ public class ProxyProperties implements Parcelable { public static final Creator<ProxyProperties> CREATOR = new Creator<ProxyProperties>() { public ProxyProperties createFromParcel(Parcel in) { - ProxyProperties proxyProperties = new ProxyProperties(); + String host = null; + int port = 0; if (in.readByte() == 1) { - try { - String host = in.readString(); - int port = in.readInt(); - proxyProperties.setSocketAddress(InetSocketAddress.createUnresolved( - host, port)); - } catch (IllegalArgumentException e) { } + host = in.readString(); + port = in.readInt(); } - proxyProperties.setExclusionList(in.readString()); + String exclList = in.readString(); + String[] parsedExclList = in.readStringArray(); + ProxyProperties proxyProperties = + new ProxyProperties(host, port, exclList, parsedExclList); return proxyProperties; } diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 93542c6..4facc39 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -32,6 +32,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; +import java.util.concurrent.atomic.AtomicInteger; /** * <p>StrictMode is a developer tool which detects things you might be @@ -104,7 +105,7 @@ import java.util.HashMap; */ public final class StrictMode { private static final String TAG = "StrictMode"; - private static final boolean LOG_V = false; + private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE); private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE); @@ -208,6 +209,12 @@ public final class StrictMode { */ private static volatile int sVmPolicyMask = 0; + /** + * The number of threads trying to do an async dropbox write. + * Just to limit ourselves out of paranoia. + */ + private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0); + private StrictMode() {} /** @@ -984,7 +991,6 @@ public final class StrictMode { if (violationMaskSubset != 0) { int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage); violationMaskSubset |= violationBit; - final int violationMaskSubsetFinal = violationMaskSubset; final int savedPolicyMask = getThreadPolicyMask(); final boolean justDropBox = (info.policy & PENALTY_MASK) == PENALTY_DROPBOX; @@ -995,20 +1001,7 @@ public final class StrictMode { // call synchronously which Binder data suggests // isn't always super fast, despite the implementation // in the ActivityManager trying to be mostly async. - new Thread("callActivityManagerForStrictModeDropbox") { - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - try { - ActivityManagerNative.getDefault(). - handleApplicationStrictModeViolation( - RuntimeInit.getApplicationObject(), - violationMaskSubsetFinal, - info); - } catch (RemoteException e) { - Log.e(TAG, "RemoteException handling StrictMode violation", e); - } - } - }.start(); + dropboxViolationAsync(violationMaskSubset, info); return; } @@ -1040,6 +1033,44 @@ public final class StrictMode { } } + /** + * In the common case, as set by conditionallyEnableDebugLogging, + * we're just dropboxing any violations but not showing a dialog, + * not loggging, and not killing the process. In these cases we + * don't need to do a synchronous call to the ActivityManager. + * This is used by both per-thread and vm-wide violations when + * applicable. + */ + private static void dropboxViolationAsync( + final int violationMaskSubset, final ViolationInfo info) { + int outstanding = sDropboxCallsInFlight.incrementAndGet(); + if (outstanding > 20) { + // What's going on? Let's not make make the situation + // worse and just not log. + sDropboxCallsInFlight.decrementAndGet(); + return; + } + + if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding); + + new Thread("callActivityManagerForStrictModeDropbox") { + public void run() { + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + try { + ActivityManagerNative.getDefault(). + handleApplicationStrictModeViolation( + RuntimeInit.getApplicationObject(), + violationMaskSubset, + info); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException handling StrictMode violation", e); + } + int outstanding = sDropboxCallsInFlight.decrementAndGet(); + if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding); + } + }.start(); + } + private static class AndroidCloseGuardReporter implements CloseGuard.Reporter { public void report (String message, Throwable allocationSite) { onVmPolicyViolation(message, allocationSite); @@ -1130,14 +1161,25 @@ public final class StrictMode { Log.e(TAG, message, originStack); } - if ((sVmPolicyMask & PENALTY_DROPBOX) != 0) { - final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask); + boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0; + boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0; + + int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS; + ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask); + + if (penaltyDropbox && !penaltyDeath) { + // Common case for userdebug/eng builds. If no death and + // just dropboxing, we can do the ActivityManager call + // asynchronously. + dropboxViolationAsync(violationMaskSubset, info); + return; + } + if (penaltyDropbox) { // The violationMask, passed to ActivityManager, is a // subset of the original StrictMode policy bitmask, with // only the bit violated and penalty bits to be executed // by the ActivityManagerService remaining set. - int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS; final int savedPolicyMask = getThreadPolicyMask(); try { // First, remove any policy before we call into the Activity Manager, @@ -1158,7 +1200,7 @@ public final class StrictMode { } } - if ((sVmPolicyMask & PENALTY_DEATH) != 0) { + if (penaltyDeath) { System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down."); Process.killProcess(Process.myPid()); System.exit(10); diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 2d2f205..d1ca0c9 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -5669,6 +5669,13 @@ public final class ContactsContract { * Type: INTEGER (boolean) */ public static final String FAVORITES = "favorites"; + + /** + * The "read-only" flag: "0" by default, "1" if the row cannot be modified or + * deleted except by a sync adapter. See {@link ContactsContract#CALLER_IS_SYNCADAPTER}. + * <P>Type: INTEGER</P> + */ + public static final String GROUP_IS_READ_ONLY = "group_is_read_only"; } /** diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java index de161e7..78110ef 100644 --- a/core/java/android/provider/Mtp.java +++ b/core/java/android/provider/Mtp.java @@ -113,6 +113,25 @@ public final class Mtp } /** + * Used for copying files from device to host. + * Constructs a Uri based on the ID of the device and object for the source file, + * and the path for the destination file. + * When passed to the ContentProvider.insert() method, the file will be transferred + * to the specified destination directory and insert() will return a content Uri + * for the new file in the MediaProvider. + * ContentProvider.insert() will throw IllegalArgumentException if the destination + * path is not in the external storage or internal media directory. + */ + public static Uri getContentUriForImport(int deviceID, long objectID, String destPath) { + if (destPath.length() == 0 || destPath.charAt(0) != '/') { + throw new IllegalArgumentException( + "destPath must be a full path in getContentUriForImport"); + } + return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + + "/import/" + objectID + "?" + destPath); + } + + /** * The following columns correspond to the fields in the ObjectInfo dataset * as described in the MTP specification. */ diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 1fe2c5a..4ea4a16 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2424,17 +2424,32 @@ public final class Settings { public static final String DISABLED_SYSTEM_INPUT_METHODS = "disabled_system_input_methods"; /** - * Host name and port for global proxy. + * Host name and port for global http proxy. Uses ':' seperator for between host and port + * TODO - deprecate in favor of global_http_proxy_host, etc */ public static final String HTTP_PROXY = "http_proxy"; /** + * Host name for global http proxy. Set via ConnectivityManager. + * @hide + */ + public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host"; + + /** + * Integer host port for global http proxy. Set via ConnectivityManager. + * @hide + */ + public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port"; + + /** * Exclusion list for global proxy. This string contains a list of comma-separated * domains where the global proxy does not apply. Domains should be listed in a comma- * separated list. Example of acceptable formats: ".domain1.com,my.domain2.com" + * Use ConnectivityManager to set/get. * @hide */ - public static final String HTTP_PROXY_EXCLUSION_LIST = "http_proxy_exclusion_list"; + public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST = + "global_http_proxy_exclusion_list"; /** * Enables the UI setting to allow the user to specify the global HTTP proxy @@ -3303,20 +3318,6 @@ public final class Settings { "pdp_watchdog_max_pdp_reset_fail_count"; /** - * Address to ping as a last sanity check before attempting any recovery. - * Unset or set to "0.0.0.0" to skip this check. - * @hide - */ - public static final String PDP_WATCHDOG_PING_ADDRESS = "pdp_watchdog_ping_address"; - - /** - * The "-w deadline" parameter for the ping, ie, the max time in - * seconds to spend pinging. - * @hide - */ - public static final String PDP_WATCHDOG_PING_DEADLINE = "pdp_watchdog_ping_deadline"; - - /** * The interval in milliseconds at which to check gprs registration * after the first registration mismatch of gprs and voice service, * to detect possible data network registration problems. diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 56ab6bf..4f56281 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -287,6 +287,8 @@ class BluetoothEventLoop { mBluetoothService.setIsDiscovering(true); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED); } else { + // Stop the discovery. + mBluetoothService.cancelDiscovery(); mBluetoothService.setIsDiscovering(false); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index cc969cb..3dd1ecd 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -21,10 +21,10 @@ import com.android.internal.util.ArrayUtils; import android.graphics.Bitmap; import android.graphics.Paint; import android.text.style.LeadingMarginSpan; +import android.text.style.LeadingMarginSpan.LeadingMarginSpan2; import android.text.style.LineHeightSpan; import android.text.style.MetricAffectingSpan; import android.text.style.TabStopSpan; -import android.text.style.LeadingMarginSpan.LeadingMarginSpan2; /** * StaticLayout is a Layout for text that will not be edited after it @@ -36,9 +36,7 @@ import android.text.style.LeadingMarginSpan.LeadingMarginSpan2; * float, float, android.graphics.Paint) * Canvas.drawText()} directly.</p> */ -public class -StaticLayout -extends Layout +public class StaticLayout extends Layout { public StaticLayout(CharSequence source, TextPaint paint, int width, @@ -260,7 +258,7 @@ extends Layout float before = w; if (c == '\n') { - ; + // intentionally left empty } else if (c == '\t') { if (hasTab == false) { hasTab = true; @@ -837,6 +835,7 @@ extends Layout // rather than relying on member functions. // The logic mirrors that of Layout.getLineForVertical // FIXME: It may be faster to do a linear search for layouts without many lines. + @Override public int getLineForVertical(int vertical) { int high = mLineCount; int low = -1; @@ -857,38 +856,47 @@ extends Layout } } + @Override public int getLineCount() { return mLineCount; } + @Override public int getLineTop(int line) { return mLines[mColumns * line + TOP]; } + @Override public int getLineDescent(int line) { return mLines[mColumns * line + DESCENT]; } + @Override public int getLineStart(int line) { return mLines[mColumns * line + START] & START_MASK; } + @Override public int getParagraphDirection(int line) { return mLines[mColumns * line + DIR] >> DIR_SHIFT; } + @Override public boolean getLineContainsTab(int line) { return (mLines[mColumns * line + TAB] & TAB_MASK) != 0; } + @Override public final Directions getLineDirections(int line) { return mLineDirections[line]; } + @Override public int getTopPadding() { return mTopPadding; } + @Override public int getBottomPadding() { return mBottomPadding; } @@ -935,7 +943,6 @@ extends Layout private Directions[] mLineDirections; private static final int START_MASK = 0x1FFFFFFF; - private static final int DIR_MASK = 0xC0000000; private static final int DIR_SHIFT = 30; private static final int TAB_MASK = 0x20000000; diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java index d13d97a..8025545 100644 --- a/core/java/android/util/JsonReader.java +++ b/core/java/android/util/JsonReader.java @@ -169,6 +169,9 @@ import java.util.List; */ public final class JsonReader implements Closeable { + private static final String TRUE = "true"; + private static final String FALSE = "false"; + /** The input JSON. */ private final Reader in; @@ -178,6 +181,8 @@ public final class JsonReader implements Closeable { /** * Use a manual buffer to easily read and unread upcoming characters, and * also so we can create strings without an intermediate StringBuilder. + * We decode literals directly out of this buffer, so it must be at least as + * long as the longest token that can be reported as a number. */ private final char[] buffer = new char[1024]; private int pos = 0; @@ -189,26 +194,21 @@ public final class JsonReader implements Closeable { } /** - * True if we've already read the next token. If we have, the string value - * for that token will be assigned to {@code value} if such a string value - * exists. And the token type will be assigned to {@code token} if the token - * type is known. The token type may be null for literals, since we derive - * that lazily. - */ - private boolean hasToken; - - /** * The type of the next token to be returned by {@link #peek} and {@link - * #advance}, or {@code null} if it is unknown and must first be derived - * from {@code value}. This value is undefined if {@code hasToken} is false. + * #advance}. If null, peek() will assign a value. */ private JsonToken token; /** The text of the next name. */ private String name; - /** The text of the next literal value. */ + /* + * For the next literal value, we may have the text value, or the position + * and length in the buffer. + */ private String value; + private int valuePos; + private int valueLength; /** True if we're currently handling a skipValue() call. */ private boolean skipping = false; @@ -284,7 +284,7 @@ public final class JsonReader implements Closeable { * Consumes {@code expected}. */ private void expect(JsonToken expected) throws IOException { - quickPeek(); + peek(); if (token != expected) { throw new IllegalStateException("Expected " + expected + " but was " + peek()); } @@ -295,7 +295,7 @@ public final class JsonReader implements Closeable { * Returns true if the current array or object has another element. */ public boolean hasNext() throws IOException { - quickPeek(); + peek(); return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY; } @@ -303,23 +303,8 @@ public final class JsonReader implements Closeable { * Returns the type of the next token without consuming it. */ public JsonToken peek() throws IOException { - quickPeek(); - - if (token == null) { - decodeLiteral(); - } - - return token; - } - - /** - * Ensures that a token is ready. After this call either {@code token} or - * {@code value} will be non-null. To ensure {@code token} has a definitive - * value, use {@link #peek()} - */ - private JsonToken quickPeek() throws IOException { - if (hasToken) { - return token; + if (token != null) { + return token; } switch (peekStack()) { @@ -342,7 +327,6 @@ public final class JsonReader implements Closeable { case NONEMPTY_OBJECT: return nextInObject(false); case NONEMPTY_DOCUMENT: - hasToken = true; return token = JsonToken.END_DOCUMENT; case CLOSED: throw new IllegalStateException("JsonReader is closed"); @@ -355,10 +339,9 @@ public final class JsonReader implements Closeable { * Advances the cursor in the JSON stream to the next token. */ private JsonToken advance() throws IOException { - quickPeek(); + peek(); JsonToken result = token; - hasToken = false; token = null; value = null; name = null; @@ -373,7 +356,7 @@ public final class JsonReader implements Closeable { * name. */ public String nextName() throws IOException { - quickPeek(); + peek(); if (token != JsonToken.NAME) { throw new IllegalStateException("Expected a name but was " + peek()); } @@ -392,7 +375,7 @@ public final class JsonReader implements Closeable { */ public String nextString() throws IOException { peek(); - if (value == null || (token != JsonToken.STRING && token != JsonToken.NUMBER)) { + if (token != JsonToken.STRING && token != JsonToken.NUMBER) { throw new IllegalStateException("Expected a string but was " + peek()); } @@ -409,20 +392,12 @@ public final class JsonReader implements Closeable { * this reader is closed. */ public boolean nextBoolean() throws IOException { - quickPeek(); - if (value == null || token == JsonToken.STRING) { - throw new IllegalStateException("Expected a boolean but was " + peek()); - } - - boolean result; - if (value.equalsIgnoreCase("true")) { - result = true; - } else if (value.equalsIgnoreCase("false")) { - result = false; - } else { - throw new IllegalStateException("Not a boolean: " + value); + peek(); + if (token != JsonToken.BOOLEAN) { + throw new IllegalStateException("Expected a boolean but was " + token); } + boolean result = (value == TRUE); advance(); return result; } @@ -435,13 +410,9 @@ public final class JsonReader implements Closeable { * reader is closed. */ public void nextNull() throws IOException { - quickPeek(); - if (value == null || token == JsonToken.STRING) { - throw new IllegalStateException("Expected null but was " + peek()); - } - - if (!value.equalsIgnoreCase("null")) { - throw new IllegalStateException("Not a null: " + value); + peek(); + if (token != JsonToken.NULL) { + throw new IllegalStateException("Expected null but was " + token); } advance(); @@ -450,27 +421,17 @@ public final class JsonReader implements Closeable { /** * Returns the {@link JsonToken#NUMBER double} value of the next token, * consuming it. If the next token is a string, this method will attempt to - * parse it as a double. + * parse it as a double using {@link Double#parseDouble(String)}. * * @throws IllegalStateException if the next token is not a literal value. - * @throws NumberFormatException if the next literal value cannot be parsed - * as a double, or is non-finite. */ public double nextDouble() throws IOException { - quickPeek(); - if (value == null) { - throw new IllegalStateException("Expected a double but was " + peek()); + peek(); + if (token != JsonToken.STRING && token != JsonToken.NUMBER) { + throw new IllegalStateException("Expected a double but was " + token); } double result = Double.parseDouble(value); - - if ((result >= 1.0d && value.startsWith("0")) - || Double.isNaN(result) - || Double.isInfinite(result)) { - throw new NumberFormatException( - "JSON forbids octal prefixes, NaN and infinities: " + value); - } - advance(); return result; } @@ -486,9 +447,9 @@ public final class JsonReader implements Closeable { * as a number, or exactly represented as a long. */ public long nextLong() throws IOException { - quickPeek(); - if (value == null) { - throw new IllegalStateException("Expected a long but was " + peek()); + peek(); + if (token != JsonToken.STRING && token != JsonToken.NUMBER) { + throw new IllegalStateException("Expected a long but was " + token); } long result; @@ -502,10 +463,6 @@ public final class JsonReader implements Closeable { } } - if (result >= 1L && value.startsWith("0")) { - throw new NumberFormatException("JSON forbids octal prefixes: " + value); - } - advance(); return result; } @@ -521,9 +478,9 @@ public final class JsonReader implements Closeable { * as a number, or exactly represented as an int. */ public int nextInt() throws IOException { - quickPeek(); - if (value == null) { - throw new IllegalStateException("Expected an int but was " + peek()); + peek(); + if (token != JsonToken.STRING && token != JsonToken.NUMBER) { + throw new IllegalStateException("Expected an int but was " + token); } int result; @@ -537,10 +494,6 @@ public final class JsonReader implements Closeable { } } - if (result >= 1L && value.startsWith("0")) { - throw new NumberFormatException("JSON forbids octal prefixes: " + value); - } - advance(); return result; } @@ -549,7 +502,6 @@ public final class JsonReader implements Closeable { * Closes this JSON reader and the underlying {@link Reader}. */ public void close() throws IOException { - hasToken = false; value = null; token = null; stack.clear(); @@ -606,7 +558,6 @@ public final class JsonReader implements Closeable { switch (nextNonWhitespace()) { case ']': pop(); - hasToken = true; return token = JsonToken.END_ARRAY; case ';': checkLenient(); // fall-through @@ -621,7 +572,6 @@ public final class JsonReader implements Closeable { case ']': if (firstElement) { pop(); - hasToken = true; return token = JsonToken.END_ARRAY; } // fall-through to handle ",]" @@ -630,7 +580,6 @@ public final class JsonReader implements Closeable { /* In lenient mode, a 0-length literal means 'null' */ checkLenient(); pos--; - hasToken = true; value = "null"; return token = JsonToken.NULL; default: @@ -650,7 +599,6 @@ public final class JsonReader implements Closeable { switch (nextNonWhitespace()) { case '}': pop(); - hasToken = true; return token = JsonToken.END_OBJECT; default: pos--; @@ -659,7 +607,6 @@ public final class JsonReader implements Closeable { switch (nextNonWhitespace()) { case '}': pop(); - hasToken = true; return token = JsonToken.END_OBJECT; case ';': case ',': @@ -680,14 +627,13 @@ public final class JsonReader implements Closeable { default: checkLenient(); pos--; - name = nextLiteral(); + name = nextLiteral(false); if (name.isEmpty()) { throw syntaxError("Expected name"); } } replaceTop(JsonScope.DANGLING_NAME); - hasToken = true; return token = JsonToken.NAME; } @@ -718,19 +664,16 @@ public final class JsonReader implements Closeable { switch (c) { case '{': push(JsonScope.EMPTY_OBJECT); - hasToken = true; return token = JsonToken.BEGIN_OBJECT; case '[': push(JsonScope.EMPTY_ARRAY); - hasToken = true; return token = JsonToken.BEGIN_ARRAY; case '\'': checkLenient(); // fall-through case '"': value = nextString((char) c); - hasToken = true; return token = JsonToken.STRING; default: @@ -899,54 +842,86 @@ public final class JsonReader implements Closeable { } /** - * Returns the string up to but not including any delimiter characters. This + * Reads the value up to but not including any delimiter characters. This * does not consume the delimiter character. + * + * @param assignOffsetsOnly true for this method to only set the valuePos + * and valueLength fields and return a null result. This only works if + * the literal is short; a string is returned otherwise. */ - private String nextLiteral() throws IOException { + private String nextLiteral(boolean assignOffsetsOnly) throws IOException { StringBuilder builder = null; - do { - /* the index of the first character not yet appended to the builder. */ - int start = pos; - while (pos < limit) { - int c = buffer[pos++]; - switch (c) { - case '/': - case '\\': - case ';': - case '#': - case '=': - checkLenient(); // fall-through - - case '{': - case '}': - case '[': - case ']': - case ':': - case ',': - case ' ': - case '\t': - case '\f': - case '\r': - case '\n': - pos--; - if (skipping) { - return "skipped!"; - } else if (builder == null) { - return new String(buffer, start, pos - start); - } else { - builder.append(buffer, start, pos - start); - return builder.toString(); - } + valuePos = -1; + valueLength = 0; + int i = 0; + + findNonLiteralCharacter: + while (true) { + for (; pos + i < limit; i++) { + switch (buffer[pos + i]) { + case '/': + case '\\': + case ';': + case '#': + case '=': + checkLenient(); // fall-through + case '{': + case '}': + case '[': + case ']': + case ':': + case ',': + case ' ': + case '\t': + case '\f': + case '\r': + case '\n': + break findNonLiteralCharacter; + } + } + + /* + * Attempt to load the entire literal into the buffer at once. If + * we run out of input, add a non-literal character at the end so + * that decoding doesn't need to do bounds checks. + */ + if (i < buffer.length) { + if (fillBuffer(i + 1)) { + continue; + } else { + buffer[limit] = '\0'; + break; } } + // use a StringBuilder when the value is too long. It must be an unquoted string. if (builder == null) { builder = new StringBuilder(); } - builder.append(buffer, start, pos - start); - } while (fillBuffer(1)); + builder.append(buffer, pos, i); + valueLength += i; + pos += i; + i = 0; + if (!fillBuffer(1)) { + break; + } + } - return builder.toString(); + String result; + if (assignOffsetsOnly && builder == null) { + valuePos = pos; + result = null; + } else if (skipping) { + result = "skipped!"; + } else if (builder == null) { + result = new String(buffer, pos, i); + } else { + builder.append(buffer, pos, i); + result = builder.toString(); + } + valueLength += i; + pos += i; + return result; } @Override public String toString() { @@ -1004,32 +979,105 @@ public final class JsonReader implements Closeable { * Reads a null, boolean, numeric or unquoted string literal value. */ private JsonToken readLiteral() throws IOException { - String literal = nextLiteral(); - if (literal.isEmpty()) { + value = nextLiteral(true); + if (valueLength == 0) { throw syntaxError("Expected literal value"); } - value = literal; - hasToken = true; - return token = null; // use decodeLiteral() to get the token type + token = decodeLiteral(); + if (token == JsonToken.STRING) { + checkLenient(); + } + return token; } /** * Assigns {@code nextToken} based on the value of {@code nextValue}. */ - private void decodeLiteral() throws IOException { - if (value.equalsIgnoreCase("null")) { - token = JsonToken.NULL; - } else if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { - token = JsonToken.BOOLEAN; + private JsonToken decodeLiteral() throws IOException { + if (valuePos == -1) { + // it was too long to fit in the buffer so it can only be a string + return JsonToken.STRING; + } else if (valueLength == 4 + && ('n' == buffer[valuePos ] || 'N' == buffer[valuePos ]) + && ('u' == buffer[valuePos + 1] || 'U' == buffer[valuePos + 1]) + && ('l' == buffer[valuePos + 2] || 'L' == buffer[valuePos + 2]) + && ('l' == buffer[valuePos + 3] || 'L' == buffer[valuePos + 3])) { + value = "null"; + return JsonToken.NULL; + } else if (valueLength == 4 + && ('t' == buffer[valuePos ] || 'T' == buffer[valuePos ]) + && ('r' == buffer[valuePos + 1] || 'R' == buffer[valuePos + 1]) + && ('u' == buffer[valuePos + 2] || 'U' == buffer[valuePos + 2]) + && ('e' == buffer[valuePos + 3] || 'E' == buffer[valuePos + 3])) { + value = TRUE; + return JsonToken.BOOLEAN; + } else if (valueLength == 5 + && ('f' == buffer[valuePos ] || 'F' == buffer[valuePos ]) + && ('a' == buffer[valuePos + 1] || 'A' == buffer[valuePos + 1]) + && ('l' == buffer[valuePos + 2] || 'L' == buffer[valuePos + 2]) + && ('s' == buffer[valuePos + 3] || 'S' == buffer[valuePos + 3]) + && ('e' == buffer[valuePos + 4] || 'E' == buffer[valuePos + 4])) { + value = FALSE; + return JsonToken.BOOLEAN; } else { - try { - Double.parseDouble(value); // this work could potentially be cached - token = JsonToken.NUMBER; - } catch (NumberFormatException ignored) { - // this must be an unquoted string - checkLenient(); - token = JsonToken.STRING; + value = new String(buffer, valuePos, valueLength); + return decodeNumber(buffer, valuePos, valueLength); + } + } + + /** + * Determine whether the characters is a JSON number. Numbers are of the + * form -12.34e+56. Fractional and exponential parts are optional. Leading + * zeroes are not allowed in the value or exponential part, but are allowed + * in the fraction. + * + * <p>This has a side effect of setting isInteger. + */ + private JsonToken decodeNumber(char[] chars, int offset, int length) { + int i = offset; + int c = chars[i]; + + if (c == '-') { + c = chars[++i]; + } + + if (c == '0') { + c = chars[++i]; + } else if (c >= '1' && c <= '9') { + c = chars[++i]; + while (c >= '0' && c <= '9') { + c = chars[++i]; + } + } else { + return JsonToken.STRING; + } + + if (c == '.') { + c = chars[++i]; + while (c >= '0' && c <= '9') { + c = chars[++i]; + } + } + + if (c == 'e' || c == 'E') { + c = chars[++i]; + if (c == '+' || c == '-') { + c = chars[++i]; } + if (c >= '0' && c <= '9') { + c = chars[++i]; + while (c >= '0' && c <= '9') { + c = chars[++i]; + } + } else { + return JsonToken.STRING; + } + } + + if (i == offset + length) { + return JsonToken.NUMBER; + } else { + return JsonToken.STRING; } } diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java index bbac14c..07e87d6 100644 --- a/core/java/android/view/DragEvent.java +++ b/core/java/android/view/DragEvent.java @@ -41,16 +41,90 @@ public class DragEvent implements Parcelable { private static DragEvent gRecyclerTop = null; /** - * action constants for DragEvent dispatch + * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose + * action is ACTION_DRAG_STARTED means that a drag operation has been initiated. The + * view receiving this DragEvent should inspect the metadata of the dragged content, + * available via {@link #getClipDescription()}, and return {@code true} from + * {@link View#onDragEvent(DragEvent)} if the view is prepared to accept a drop of + * that clip data. If the view chooses to present a visual indication that it is + * a valid target of the ongoing drag, then it should draw that indication in response + * to this event. + * <p> + * A view will only receive ACTION_DRAG_ENTERED, ACTION_DRAG_LOCATION, ACTION_DRAG_EXITED, + * and ACTION_DRAG_LOCATION events if it returns {@code true} in response to the + * ACTION_DRAG_STARTED event. */ public static final int ACTION_DRAG_STARTED = 1; + + /** + * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose + * action is ACTION_DRAG_LOCATION means that the drag operation is currently hovering + * over the view. The {@link #getX()} and {@link #getY()} methods supply the location + * of the drag point within the view's coordinate system. + * <p> + * A view will receive an ACTION_DRAG_ENTERED event before receiving any + * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an + * ACTION_DRAG_EXITED event is delivered to the view, after which no more + * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view, + * of course). + */ public static final int ACTION_DRAG_LOCATION = 2; + + /** + * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose + * action is ACTION_DROP means that the dragged content has been dropped on this view. + * The view should retrieve the content via {@link #getClipData()} and act on it + * appropriately. The {@link #getX()} and {@link #getY()} methods supply the location + * of the drop point within the view's coordinate system. + * <p> + * The view should return {@code true} from its {@link View#onDragEvent(DragEvent)} + * method in response to this event if it accepted the content, and {@code false} + * if it ignored the drop. + */ public static final int ACTION_DROP = 3; + + /** + * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose + * action is ACTION_DRAG_ENDED means that the drag operation has concluded. A view + * that is drawing a visual indication of drag acceptance should return to its usual + * drawing state in response to this event. + * <p> + * All views that received an ACTION_DRAG_STARTED event will receive the + * ACTION_DRAG_ENDED event even if they are not currently visible when the drag + * ends. + */ public static final int ACTION_DRAG_ENDED = 4; + + /** + * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose + * action is ACTION_DRAG_ENTERED means that the drag point has entered the view's + * bounds. If the view changed its visual state in response to the ACTION_DRAG_ENTERED + * event, it should return to its normal drag-in-progress visual state in response to + * this event. + * <p> + * A view will receive an ACTION_DRAG_ENTERED event before receiving any + * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an + * ACTION_DRAG_EXITED event is delivered to the view, after which no more + * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view, + * of course). + */ public static final int ACTION_DRAG_ENTERED = 5; - public static final int ACTION_DRAG_EXITED = 6; - /* hide the constructor behind package scope */ + /** + * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose + * action is ACTION_DRAG_ENTERED means that the drag point has entered the view's + * bounds. If the view chooses to present a visual indication that it will receive + * the drop if it occurs now, then it should draw that indication in response to + * this event. + * <p> + * A view will receive an ACTION_DRAG_ENTERED event before receiving any + * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an + * ACTION_DRAG_EXITED event is delivered to the view, after which no more + * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view, + * of course). + */ +public static final int ACTION_DRAG_EXITED = 6; + private DragEvent() { } @@ -68,6 +142,7 @@ public class DragEvent implements Parcelable { return DragEvent.obtain(0, 0f, 0f, null, null, false); } + /** @hide */ public static DragEvent obtain(int action, float x, float y, ClipDescription description, ClipData data, boolean result) { final DragEvent ev; @@ -90,31 +165,64 @@ public class DragEvent implements Parcelable { return ev; } + /** @hide */ public static DragEvent obtain(DragEvent source) { return obtain(source.mAction, source.mX, source.mY, source.mClipDescription, source.mClipData, source.mDragResult); } + /** + * Inspect the action value of this event. + * @return One of {@link #ACTION_DRAG_STARTED}, {@link #ACTION_DRAG_ENDED}, + * {@link #ACTION_DROP}, {@link #ACTION_DRAG_ENTERED}, {@link #ACTION_DRAG_EXITED}, + * or {@link #ACTION_DRAG_LOCATION}. + */ public int getAction() { return mAction; } + /** + * For ACTION_DRAG_LOCATION and ACTION_DROP events, returns the x coordinate of the + * drag point. + * @return The current drag point's x coordinate, when relevant. + */ public float getX() { return mX; } + /** + * For ACTION_DRAG_LOCATION and ACTION_DROP events, returns the y coordinate of the + * drag point. + * @return The current drag point's y coordinate, when relevant. + */ public float getY() { return mY; } + /** + * Provides the data payload of the drag operation. This payload is only available + * for events whose action value is ACTION_DROP. + * @return The ClipData containing the data being dropped on the view. + */ public ClipData getClipData() { return mClipData; } + /** + * Provides a description of the drag operation's data payload. This payload is + * available for all DragEvents other than ACTION_DROP. + * @return A ClipDescription describing the contents of the data being dragged. + */ public ClipDescription getClipDescription() { return mClipDescription; } + /** + * Provides an indication of whether the drag operation concluded successfully. + * This method is only available on ACTION_DRAG_ENDED events. + * @return {@code true} if the drag operation ended with an accepted drop; {@code false} + * otherwise. + */ public boolean getResult() { return mDragResult; } @@ -122,6 +230,8 @@ public class DragEvent implements Parcelable { /** * Recycle the DragEvent, to be re-used by a later caller. After calling * this function you must never touch the event again. + * + * @hide */ public final void recycle() { // Ensure recycle is only called once! diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index a64ee9d..784951f 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -922,7 +922,6 @@ public interface WindowManager extends ViewManager { */ public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - public LayoutParams() { super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = TYPE_APPLICATION; diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java index c6fae9d..13d0ec1 100644 --- a/core/java/android/view/animation/Animation.java +++ b/core/java/android/view/animation/Animation.java @@ -18,9 +18,11 @@ package android.view.animation; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.RectF; +import android.os.SystemProperties; import android.util.AttributeSet; import android.util.TypedValue; -import android.graphics.RectF; +import dalvik.system.CloseGuard; /** * Abstraction for an Animation that can be applied to Views, Surfaces, or @@ -86,7 +88,10 @@ public abstract class Animation implements Cloneable { * content for the duration of the animation. */ public static final int ZORDER_BOTTOM = -1; - + + private static final boolean USE_CLOSEGUARD + = SystemProperties.getBoolean("log.closeguard.Animation", false); + /** * Set by {@link #getTransformation(long, Transformation)} when the animation ends. */ @@ -194,6 +199,8 @@ public abstract class Animation implements Cloneable { Transformation mTransformation = new Transformation(); Transformation mPreviousTransformation = new Transformation(); + private final CloseGuard guard = CloseGuard.get(); + /** * Creates a new animation with a duration of 0ms, the default interpolator, with * fillBefore set to true and fillAfter set to false @@ -276,6 +283,7 @@ public abstract class Animation implements Cloneable { if (mStarted && !mEnded) { if (mListener != null) mListener.onAnimationEnd(this); mEnded = true; + guard.close(); } // Make sure we move the animation to the end mStartTime = Long.MIN_VALUE; @@ -288,6 +296,7 @@ public abstract class Animation implements Cloneable { public void detach() { if (mStarted && !mEnded) { mEnded = true; + guard.close(); if (mListener != null) mListener.onAnimationEnd(this); } } @@ -781,6 +790,9 @@ public abstract class Animation implements Cloneable { mListener.onAnimationStart(this); } mStarted = true; + if (USE_CLOSEGUARD) { + guard.open("cancel or detach or getTransformation"); + } } if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f); @@ -797,6 +809,7 @@ public abstract class Animation implements Cloneable { if (mRepeatCount == mRepeated) { if (!mEnded) { mEnded = true; + guard.close(); if (mListener != null) { mListener.onAnimationEnd(this); } @@ -953,6 +966,16 @@ public abstract class Animation implements Cloneable { } } + protected void finalize() throws Throwable { + try { + if (guard != null) { + guard.warnIfOpen(); + } + } finally { + super.finalize(); + } + } + /** * Utility class to parse a string description of a size. */ diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index d3c0ffd..9568e4f 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -780,50 +780,11 @@ class BrowserFrame extends Handler { if (cacheMode == WebSettings.LOAD_NORMAL) { cacheMode = WebSettings.LOAD_NO_CACHE; } - if (mSettings.getSavePassword() && hasPasswordField()) { - try { - if (DebugFlags.BROWSER_FRAME) { - Assert.assertNotNull(mCallbackProxy.getBackForwardList() - .getCurrentItem()); - } - WebAddress uri = new WebAddress(mCallbackProxy - .getBackForwardList().getCurrentItem().getUrl()); - String schemePlusHost = uri.getScheme() + uri.getHost(); - String[] ret = getUsernamePassword(); - // Has the user entered a username/password pair and is - // there some POST data - if (ret != null && postData != null && - ret[0].length() > 0 && ret[1].length() > 0) { - // Check to see if the username & password appear in - // the post data (there could be another form on the - // page and that was posted instead. - String postString = new String(postData); - if (postString.contains(URLEncoder.encode(ret[0])) && - postString.contains(URLEncoder.encode(ret[1]))) { - String[] saved = mDatabase.getUsernamePassword( - schemePlusHost); - if (saved != null) { - // null username implies that user has chosen not to - // save password - if (saved[0] != null) { - // non-null username implies that user has - // chosen to save password, so update the - // recorded password - mDatabase.setUsernamePassword( - schemePlusHost, ret[0], ret[1]); - } - } else { - // CallbackProxy will handle creating the resume - // message - mCallbackProxy.onSavePassword(schemePlusHost, ret[0], - ret[1], null); - } - } - } - } catch (ParseException ex) { - // if it is bad uri, don't save its password - } - + String[] ret = getUsernamePassword(); + if (ret != null) { + String domUsername = ret[0]; + String domPassword = ret[1]; + maybeSavePassword(postData, domUsername, domPassword); } } @@ -874,6 +835,68 @@ class BrowserFrame extends Handler { return !synchronous ? loadListener : null; } + /** + * If this looks like a POST request (form submission) containing a username + * and password, give the user the option of saving them. Will either do + * nothing, or block until the UI interaction is complete. + * + * Called by startLoadingResource when using the Apache HTTP stack. + * Called directly by WebKit when using the Chrome HTTP stack. + * + * @param postData The data about to be sent as the body of a POST request. + * @param username The username entered by the user (sniffed from the DOM). + * @param password The password entered by the user (sniffed from the DOM). + */ + private void maybeSavePassword( + byte[] postData, String username, String password) { + if (postData == null + || username == null || username.isEmpty() + || password == null || password.isEmpty()) { + return; // No password to save. + } + + if (!mSettings.getSavePassword()) { + return; // User doesn't want to save passwords. + } + + try { + if (DebugFlags.BROWSER_FRAME) { + Assert.assertNotNull(mCallbackProxy.getBackForwardList() + .getCurrentItem()); + } + WebAddress uri = new WebAddress(mCallbackProxy + .getBackForwardList().getCurrentItem().getUrl()); + String schemePlusHost = uri.getScheme() + uri.getHost(); + // Check to see if the username & password appear in + // the post data (there could be another form on the + // page and that was posted instead. + String postString = new String(postData); + if (postString.contains(URLEncoder.encode(username)) && + postString.contains(URLEncoder.encode(password))) { + String[] saved = mDatabase.getUsernamePassword( + schemePlusHost); + if (saved != null) { + // null username implies that user has chosen not to + // save password + if (saved[0] != null) { + // non-null username implies that user has + // chosen to save password, so update the + // recorded password + mDatabase.setUsernamePassword( + schemePlusHost, username, password); + } + } else { + // CallbackProxy will handle creating the resume + // message + mCallbackProxy.onSavePassword(schemePlusHost, username, + password, null); + } + } + } catch (ParseException ex) { + // if it is bad uri, don't save its password + } + } + // Called by jni from the chrome network stack. private WebResourceResponse shouldInterceptRequest(String url) { InputStream androidResource = inputStreamForAndroidResource(url); @@ -1075,6 +1098,18 @@ class BrowserFrame extends Handler { */ private void downloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) { + // This will only work if the url ends with the filename + if (mimeType.isEmpty()) { + try { + String extension = url.substring(url.lastIndexOf('.') + 1); + mimeType = libcore.net.MimeUtils.guessMimeTypeFromExtension(extension); + // MimeUtils might return null, not sure if downloadmanager is happy with that + if (mimeType == null) + mimeType = ""; + } catch(IndexOutOfBoundsException exception) { + // mimeType string end with a '.', not much to do + } + } mimeType = MimeTypeMap.getSingleton().remapGenericMimeType( mimeType, url, contentDisposition); mCallbackProxy.onDownloadStart(url, userAgent, diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 4d582ef..f4caa74 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -483,11 +483,11 @@ public class WebSettings { // default to "en" buffer.append("en"); } + buffer.append("; "); // add the model for the release build if ("REL".equals(Build.VERSION.CODENAME)) { final String model = Build.MODEL; if (model.length() > 0) { - buffer.append("; "); buffer.append(model); } } diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 1caa707..fafb6be 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -26,9 +26,12 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.text.BoringLayout.Metrics; +import android.text.DynamicLayout; import android.text.Editable; import android.text.InputFilter; import android.text.Layout; +import android.text.Layout.Alignment; import android.text.Selection; import android.text.Spannable; import android.text.TextPaint; @@ -359,6 +362,68 @@ import junit.framework.Assert; } } + @Override + protected void makeNewLayout(int w, int hintWidth, Metrics boring, + Metrics hintBoring, int ellipsisWidth, boolean bringIntoView) { + // Necessary to get a Layout to work with, and to do the other work that + // makeNewLayout does. + super.makeNewLayout(w, hintWidth, boring, hintBoring, ellipsisWidth, + bringIntoView); + + // For fields that do not draw, create a layout which is altered so that + // the text lines up. + if (DebugFlags.DRAW_WEBTEXTVIEW || willNotDraw()) { + float lineHeight = -1; + if (mWebView != null) { + float height = mWebView.nativeFocusCandidateLineHeight(); + if (height != -1) { + lineHeight = height * mWebView.getScale(); + } + } + CharSequence text = getText(); + // Copy from the existing Layout. + mLayout = new WebTextViewLayout(text, text, getPaint(), w, + mLayout.getAlignment(), mLayout.getSpacingMultiplier(), + mLayout.getSpacingAdd(), false, null, ellipsisWidth, + lineHeight); + } + } + + /** + * Custom layout which figures out its line spacing. If -1 is passed in for + * the height, it will use the ascent and descent from the paint to + * determine the line spacing. Otherwise it will use the spacing provided. + */ + private static class WebTextViewLayout extends DynamicLayout { + private float mLineHeight; + private float mDifference; + public WebTextViewLayout(CharSequence base, CharSequence display, + TextPaint paint, + int width, Alignment align, + float spacingMult, float spacingAdd, + boolean includepad, + TextUtils.TruncateAt ellipsize, int ellipsizedWidth, + float lineHeight) { + super(base, display, paint, width, align, spacingMult, spacingAdd, + includepad, ellipsize, ellipsizedWidth); + float paintLineHeight = paint.descent() - paint.ascent(); + if (lineHeight == -1f) { + mLineHeight = paintLineHeight; + mDifference = 0f; + } else { + mLineHeight = lineHeight; + // Through trial and error, I found this calculation to improve + // the accuracy of line placement. + mDifference = (lineHeight - paintLineHeight) / 2; + } + } + + @Override + public int getLineTop(int line) { + return Math.round(mLineHeight * line - mDifference); + } + } + @Override public InputConnection onCreateInputConnection( EditorInfo outAttrs) { InputConnection connection = super.onCreateInputConnection(outAttrs); diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 383e977..602975f 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -906,6 +906,7 @@ public class WebView extends AbsoluteLayout mCallbackProxy = new CallbackProxy(context, this); mViewManager = new ViewManager(this); + L10nUtils.loadStrings(context); mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javascriptInterfaces); mDatabase = WebViewDatabase.getInstance(context); mScroller = new Scroller(context); @@ -922,7 +923,6 @@ public class WebView extends AbsoluteLayout startPrivateBrowsing(); } - L10nUtils.loadStrings(context); mAutoFillData = new WebViewCore.AutoFillData(); } @@ -2187,14 +2187,6 @@ public class WebView extends AbsoluteLayout private View mTitleBar; /** - * Since we draw the title bar ourselves, we removed the shadow from the - * browser's activity. We do want a shadow at the bottom of the title bar, - * or at the top of the screen if the title bar is not visible. This - * drawable serves that purpose. - */ - private Drawable mTitleShadow; - - /** * Add or remove a title bar to be embedded into the WebView, and scroll * along with it vertically, while remaining in view horizontally. Pass * null to remove the title bar from the WebView, and return to drawing @@ -2220,10 +2212,6 @@ public class WebView extends AbsoluteLayout addView(v, new AbsoluteLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0)); - if (mTitleShadow == null) { - mTitleShadow = (Drawable) mContext.getResources().getDrawable( - com.android.internal.R.drawable.title_bar_shadow); - } } mTitleBar = v; } @@ -3470,15 +3458,6 @@ public class WebView extends AbsoluteLayout drawContent(canvas); canvas.restoreToCount(saveCount); - // Now draw the shadow. - int titleH = getVisibleTitleHeight(); - if (mTitleBar != null && titleH == 0) { - int height = (int) (5f * getContext().getResources() - .getDisplayMetrics().density); - mTitleShadow.setBounds(mScrollX, mScrollY, mScrollX + getWidth(), - mScrollY + height); - mTitleShadow.draw(canvas); - } if (AUTO_REDRAW_HACK && mAutoRedraw) { invalidate(); } @@ -3570,6 +3549,15 @@ public class WebView extends AbsoluteLayout * click action, look for a word under the click. If one is found, * animate the text selection into view. * FIXME: no animation code yet */ + return selectText(); + } + + /** + * Select the word at the last click point. + * + * @hide pending API council approval + */ + public boolean selectText() { int x = viewToContentX((int) mLastTouchX + mScrollX); int y = viewToContentY((int) mLastTouchY + mScrollY); setUpSelect(); @@ -7482,6 +7470,7 @@ public class WebView extends AbsoluteLayout /* package */ native int nativeFocusCandidatePointer(); private native String nativeFocusCandidateText(); /* package */ native float nativeFocusCandidateTextSize(); + /* package */ native int nativeFocusCandidateLineHeight(); /** * Returns an integer corresponding to WebView.cpp::type. * See WebTextView.setType() diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index d388985..70cfee9 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -2542,7 +2542,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mTouchMode = TOUCH_MODE_SCROLL; mMotionCorrection = 0; motionPosition = findMotionRow(y); - reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); mFlingRunnable.flywheelTouch(); } } @@ -2968,6 +2967,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } else { endFling(); mTouchMode = TOUCH_MODE_SCROLL; + reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); } } }; @@ -3018,6 +3018,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); clearScrollingCache(); mScroller.abortAnimation(); + + if (mFlingStrictSpan != null) { + mFlingStrictSpan.finish(); + mFlingStrictSpan = null; + } } void flywheelTouch() { @@ -3086,11 +3091,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te Debug.stopMethodTracing(); mFlingProfilingStarted = false; } - - if (mFlingStrictSpan != null) { - mFlingStrictSpan.finish(); - mFlingStrictSpan = null; - } } } } diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index a371290..595b487 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -22,6 +22,7 @@ import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; import android.text.format.DateFormat; +import android.text.format.DateUtils; import android.util.AttributeSet; import android.util.SparseArray; import android.view.LayoutInflater; @@ -33,6 +34,7 @@ import com.android.internal.R; import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Locale; /** * A view for selecting a month / year / day based on a calendar like layout. @@ -47,7 +49,10 @@ public class DatePicker extends FrameLayout { private static final int DEFAULT_START_YEAR = 1900; private static final int DEFAULT_END_YEAR = 2100; - + + // This ignores Undecimber, but we only support real Gregorian calendars. + private static final int NUMBER_OF_MONTHS = 12; + /* UI Components */ private final NumberPicker mDayPicker; private final NumberPicker mMonthPicker; @@ -62,6 +67,10 @@ public class DatePicker extends FrameLayout { private int mMonth; private int mYear; + private Object mMonthUpdateLock = new Object(); + private volatile Locale mMonthLocale; + private String[] mShortMonths; + /** * The callback used to indicate the user changes the date. */ @@ -102,8 +111,7 @@ public class DatePicker extends FrameLayout { }); mMonthPicker = (NumberPicker) findViewById(R.id.month); mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER); - DateFormatSymbols dfs = new DateFormatSymbols(); - String[] months = dfs.getShortMonths(); + final String[] months = getShortMonths(); /* * If the user is in a locale where the month names are numeric, @@ -114,9 +122,9 @@ public class DatePicker extends FrameLayout { for (int i = 0; i < months.length; i++) { months[i] = String.valueOf(i + 1); } - mMonthPicker.setRange(1, 12); + mMonthPicker.setRange(1, NUMBER_OF_MONTHS); } else { - mMonthPicker.setRange(1, 12, months); + mMonthPicker.setRange(1, NUMBER_OF_MONTHS, months); } mMonthPicker.setSpeed(200); @@ -246,11 +254,30 @@ public class DatePicker extends FrameLayout { mMonth = monthOfYear; mDay = dayOfMonth; updateSpinners(); - reorderPickers(new DateFormatSymbols().getShortMonths()); + reorderPickers(getShortMonths()); notifyDateChanged(); } } + private String[] getShortMonths() { + final Locale currentLocale = Locale.getDefault(); + if (currentLocale.equals(mMonthLocale) && mShortMonths != null) { + return mShortMonths; + } else { + synchronized (mMonthUpdateLock) { + if (!currentLocale.equals(mMonthLocale)) { + mShortMonths = new String[NUMBER_OF_MONTHS]; + for (int i = 0; i < NUMBER_OF_MONTHS; i++) { + mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i, + DateUtils.LENGTH_MEDIUM); + } + mMonthLocale = currentLocale; + } + } + return mShortMonths; + } + } + private static class SavedState extends BaseSavedState { private final int mYear; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index e6503a9..78f3cd9 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -7117,7 +7117,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener csr = new CommitSelectionReceiver(oldSelStart, oldSelEnd); } - handled |= imm.showSoftInput(this, 0, csr) && (csr != null); + if (!mTextIsSelectable) { + // Selection in read-only text should not bring up the IME. + handled |= imm.showSoftInput(this, 0, csr) && (csr != null); + } // Cannot be done by CommitSelectionReceiver, which might not always be called, // for instance when dealing with an ExtractEditText. @@ -9012,7 +9015,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mUserSetTextScaleX; private final Paint mHighlightPaint; private int mHighlightColor = 0xCC475925; - private Layout mLayout; + /** + * This is temporarily visible to fix bug 3085564 in webView. Do not rely on + * this field being protected. Will be restored as private when lineHeight + * feature request 3215097 is implemented + * @hide + */ + protected Layout mLayout; private long mShowCursor; private Blink mBlink; diff --git a/core/jni/android_util_StringBlock.cpp b/core/jni/android_util_StringBlock.cpp index 641fbce..a021efd 100644 --- a/core/jni/android_util_StringBlock.cpp +++ b/core/jni/android_util_StringBlock.cpp @@ -147,25 +147,6 @@ static jintArray android_content_StringBlock_nativeGetStyle(JNIEnv* env, jobject return array; } -static jint android_content_StringBlock_nativeIndexOfString(JNIEnv* env, jobject clazz, - jint token, jstring str) -{ - ResStringPool* osb = (ResStringPool*)token; - if (osb == NULL || str == NULL) { - doThrow(env, "java/lang/NullPointerException"); - return 0; - } - - const char16_t* str16 = env->GetStringChars(str, NULL); - jsize strLen = env->GetStringLength(str); - - ssize_t idx = osb->indexOfString(str16, strLen); - - env->ReleaseStringChars(str, str16); - - return idx; -} - static void android_content_StringBlock_nativeDestroy(JNIEnv* env, jobject clazz, jint token) { @@ -193,8 +174,6 @@ static JNINativeMethod gStringBlockMethods[] = { (void*) android_content_StringBlock_nativeGetString }, { "nativeGetStyle", "(II)[I", (void*) android_content_StringBlock_nativeGetStyle }, - { "nativeIndexOfString","(ILjava/lang/String;)I", - (void*) android_content_StringBlock_nativeIndexOfString }, { "nativeDestroy", "(I)V", (void*) android_content_StringBlock_nativeDestroy }, }; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index d02ca64..ddc63dd 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -92,6 +92,7 @@ <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" /> <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" /> <protected-broadcast android:name="android.intent.action.CLEAR_DNS_CACHE" /> + <protected-broadcast android:name="android.intent.action.PROXY_CHANGE" /> <!-- ====================================== --> <!-- Permissions for things that cost money --> diff --git a/core/res/res/anim/accelerate_cubic_interpolator.xml b/core/res/res/anim/accelerate_cubic_interpolator.xml index c736766..90f62da 100644 --- a/core/res/res/anim/accelerate_cubic_interpolator.xml +++ b/core/res/res/anim/accelerate_cubic_interpolator.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/ease_in_interpolator.xml -** +/* ** Copyright 2010, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/res/res/anim/accelerate_decelerate_interpolator.xml b/core/res/res/anim/accelerate_decelerate_interpolator.xml index 4a0216b..e7f9d9f 100644 --- a/core/res/res/anim/accelerate_decelerate_interpolator.xml +++ b/core/res/res/anim/accelerate_decelerate_interpolator.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/ease_in_out_interpolator.xml -** +/* ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/res/res/anim/accelerate_interpolator.xml b/core/res/res/anim/accelerate_interpolator.xml index 13f87f3..18207f2 100644 --- a/core/res/res/anim/accelerate_interpolator.xml +++ b/core/res/res/anim/accelerate_interpolator.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/ease_in_interpolator.xml -** +/* ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/res/res/anim/accelerate_quint_interpolator.xml b/core/res/res/anim/accelerate_quint_interpolator.xml index 5ab4909..cd3595c 100644 --- a/core/res/res/anim/accelerate_quint_interpolator.xml +++ b/core/res/res/anim/accelerate_quint_interpolator.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/ease_in_interpolator.xml -** +/* ** Copyright 2010, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/res/res/anim/decelerate_cubic_interpolator.xml b/core/res/res/anim/decelerate_cubic_interpolator.xml index 78bdb40..550a591 100644 --- a/core/res/res/anim/decelerate_cubic_interpolator.xml +++ b/core/res/res/anim/decelerate_cubic_interpolator.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/ease_in_interpolator.xml -** +/* ** Copyright 2010, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/res/res/anim/decelerate_interpolator.xml b/core/res/res/anim/decelerate_interpolator.xml index 7b29fb3..48e2308 100644 --- a/core/res/res/anim/decelerate_interpolator.xml +++ b/core/res/res/anim/decelerate_interpolator.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/ease_out_interpolator.xml -** +/* ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/res/res/anim/decelerate_quint_interpolator.xml b/core/res/res/anim/decelerate_quint_interpolator.xml index 0e543e6..7545b17 100644 --- a/core/res/res/anim/decelerate_quint_interpolator.xml +++ b/core/res/res/anim/decelerate_quint_interpolator.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/anim/ease_in_interpolator.xml -** +/* ** Copyright 2010, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/res/res/anim/window_move_from_decor.xml b/core/res/res/anim/window_move_from_decor.xml new file mode 100644 index 0000000..94062db --- /dev/null +++ b/core/res/res/anim/window_move_from_decor.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 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. +*/ +--> + +<!-- Animation when a window is being moved on screen because the decors + around it (such as the IME) have changed. In this case the parent + container size is actually the amount the window has moved. Yes, + a nasty hack. --> +<translate xmlns:android="http://schemas.android.com/apk/res/android" + android:fromYDelta="100%p" android:toYDelta="0" + android:fromXDelta="100%p" android:toXDelta="0" + android:interpolator="@anim/decelerate_quint_interpolator" + android:duration="@android:integer/config_mediumAnimTime" /> diff --git a/core/res/res/drawable-hdpi/overscroll_edge.png b/core/res/res/drawable-hdpi/overscroll_edge.png Binary files differindex 58b4f19..6d3c26d 100644 --- a/core/res/res/drawable-hdpi/overscroll_edge.png +++ b/core/res/res/drawable-hdpi/overscroll_edge.png diff --git a/core/res/res/drawable-hdpi/overscroll_glow.png b/core/res/res/drawable-hdpi/overscroll_glow.png Binary files differindex fa58f1e..0b0b936 100644 --- a/core/res/res/drawable-hdpi/overscroll_glow.png +++ b/core/res/res/drawable-hdpi/overscroll_glow.png diff --git a/core/res/res/drawable-hdpi/title_bar_shadow.9.png b/core/res/res/drawable-hdpi/title_bar_shadow.9.png Binary files differdeleted file mode 100644 index e6dab63..0000000 --- a/core/res/res/drawable-hdpi/title_bar_shadow.9.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/title_bar_shadow.9.png b/core/res/res/drawable-ldpi/title_bar_shadow.9.png Binary files differdeleted file mode 100644 index fc45ee8..0000000 --- a/core/res/res/drawable-ldpi/title_bar_shadow.9.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/overscroll_edge.png b/core/res/res/drawable-mdpi/overscroll_edge.png Binary files differindex 22f4ef8..6d3c26d 100644 --- a/core/res/res/drawable-mdpi/overscroll_edge.png +++ b/core/res/res/drawable-mdpi/overscroll_edge.png diff --git a/core/res/res/drawable-mdpi/overscroll_glow.png b/core/res/res/drawable-mdpi/overscroll_glow.png Binary files differindex 761fb74..0b0b936 100644 --- a/core/res/res/drawable-mdpi/overscroll_glow.png +++ b/core/res/res/drawable-mdpi/overscroll_glow.png diff --git a/core/res/res/drawable-mdpi/stat_notify_error.png b/core/res/res/drawable-mdpi/stat_notify_error.png Binary files differindex 6ced2b7..1275738 100644 --- a/core/res/res/drawable-mdpi/stat_notify_error.png +++ b/core/res/res/drawable-mdpi/stat_notify_error.png diff --git a/core/res/res/drawable-mdpi/stat_notify_sdcard.png b/core/res/res/drawable-mdpi/stat_notify_sdcard.png Binary files differindex 23093ac..fc0784d 100644 --- a/core/res/res/drawable-mdpi/stat_notify_sdcard.png +++ b/core/res/res/drawable-mdpi/stat_notify_sdcard.png diff --git a/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png Binary files differindex 9abb1c9..93fad38 100644 --- a/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png +++ b/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png diff --git a/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png Binary files differindex 9880694..cda4546 100644 --- a/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png +++ b/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png diff --git a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png Binary files differindex e9c74b4..517c515 100644 --- a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-mdpi/stat_sys_adb.png b/core/res/res/drawable-mdpi/stat_sys_adb.png Binary files differindex 12abeda..f0fad76 100644 --- a/core/res/res/drawable-mdpi/stat_sys_adb.png +++ b/core/res/res/drawable-mdpi/stat_sys_adb.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_0.png b/core/res/res/drawable-mdpi/stat_sys_battery_0.png Binary files differindex 4a5e99e..750e652 100644 --- a/core/res/res/drawable-mdpi/stat_sys_battery_0.png +++ b/core/res/res/drawable-mdpi/stat_sys_battery_0.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_10.png b/core/res/res/drawable-mdpi/stat_sys_battery_10.png Binary files differdeleted file mode 100755 index b789f23..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_10.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_100.png b/core/res/res/drawable-mdpi/stat_sys_battery_100.png Binary files differindex d280aeb..70d7fa4 100644 --- a/core/res/res/drawable-mdpi/stat_sys_battery_100.png +++ b/core/res/res/drawable-mdpi/stat_sys_battery_100.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_15.png b/core/res/res/drawable-mdpi/stat_sys_battery_15.png Binary files differnew file mode 100644 index 0000000..0eb58e1 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_15.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_20.png b/core/res/res/drawable-mdpi/stat_sys_battery_20.png Binary files differdeleted file mode 100644 index 009a9fd..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_20.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_28.png b/core/res/res/drawable-mdpi/stat_sys_battery_28.png Binary files differnew file mode 100644 index 0000000..f634dde --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_28.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_40.png b/core/res/res/drawable-mdpi/stat_sys_battery_40.png Binary files differdeleted file mode 100644 index 15b57f4..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_40.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_43.png b/core/res/res/drawable-mdpi/stat_sys_battery_43.png Binary files differnew file mode 100644 index 0000000..f0376bd --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_43.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_57.png b/core/res/res/drawable-mdpi/stat_sys_battery_57.png Binary files differnew file mode 100644 index 0000000..840af66 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_57.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_60.png b/core/res/res/drawable-mdpi/stat_sys_battery_60.png Binary files differdeleted file mode 100644 index 21078fd..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_60.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_71.png b/core/res/res/drawable-mdpi/stat_sys_battery_71.png Binary files differnew file mode 100644 index 0000000..04c3569 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_71.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_80.png b/core/res/res/drawable-mdpi/stat_sys_battery_80.png Binary files differdeleted file mode 100644 index 9268f7b..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_80.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_85.png b/core/res/res/drawable-mdpi/stat_sys_battery_85.png Binary files differnew file mode 100644 index 0000000..c742da7 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_85.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png Binary files differindex ff3cabd..957dab3 100644 --- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim1.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim1.png Binary files differdeleted file mode 100644 index b563701..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim1.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim100.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim100.png Binary files differnew file mode 100644 index 0000000..e6d7da0 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim100.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim15.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim15.png Binary files differnew file mode 100644 index 0000000..957dab3 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim15.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim2.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim2.png Binary files differdeleted file mode 100644 index 904989e..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim2.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim28.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim28.png Binary files differnew file mode 100644 index 0000000..5aba0bb --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim28.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim3.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim3.png Binary files differdeleted file mode 100644 index ba011c9..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim3.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim4.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim4.png Binary files differdeleted file mode 100644 index 4f1c485..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim4.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim43.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim43.png Binary files differnew file mode 100644 index 0000000..dc5fac6 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim43.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim5.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim5.png Binary files differdeleted file mode 100644 index 4d3396d..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim5.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim57.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim57.png Binary files differnew file mode 100644 index 0000000..1233ed8 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim57.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim71.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim71.png Binary files differnew file mode 100644 index 0000000..06d397b --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim71.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim85.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim85.png Binary files differnew file mode 100644 index 0000000..1056faf --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim85.png diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png b/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png Binary files differindex ed72ebf..44eb313 100644 --- a/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png +++ b/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim0.png b/core/res/res/drawable-mdpi/stat_sys_download_anim0.png Binary files differindex 69b95cd..01b65e0 100755 --- a/core/res/res/drawable-mdpi/stat_sys_download_anim0.png +++ b/core/res/res/drawable-mdpi/stat_sys_download_anim0.png diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim1.png b/core/res/res/drawable-mdpi/stat_sys_download_anim1.png Binary files differindex 1e18eb5..2b0633f 100755 --- a/core/res/res/drawable-mdpi/stat_sys_download_anim1.png +++ b/core/res/res/drawable-mdpi/stat_sys_download_anim1.png diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim2.png b/core/res/res/drawable-mdpi/stat_sys_download_anim2.png Binary files differindex d7f2312..2295a6d 100755 --- a/core/res/res/drawable-mdpi/stat_sys_download_anim2.png +++ b/core/res/res/drawable-mdpi/stat_sys_download_anim2.png diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim3.png b/core/res/res/drawable-mdpi/stat_sys_download_anim3.png Binary files differindex 83f8d0f..99db712 100755 --- a/core/res/res/drawable-mdpi/stat_sys_download_anim3.png +++ b/core/res/res/drawable-mdpi/stat_sys_download_anim3.png diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim4.png b/core/res/res/drawable-mdpi/stat_sys_download_anim4.png Binary files differindex 9c1bd47..738dc87 100755 --- a/core/res/res/drawable-mdpi/stat_sys_download_anim4.png +++ b/core/res/res/drawable-mdpi/stat_sys_download_anim4.png diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim5.png b/core/res/res/drawable-mdpi/stat_sys_download_anim5.png Binary files differindex 3a81164..00ff542 100755 --- a/core/res/res/drawable-mdpi/stat_sys_download_anim5.png +++ b/core/res/res/drawable-mdpi/stat_sys_download_anim5.png diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png Binary files differindex b7a5978..f6fcc7a 100755 --- a/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png +++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png Binary files differindex a203e15..5d05381 100755 --- a/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png +++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png Binary files differindex 4af7630..a8699bc 100755 --- a/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png +++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png Binary files differindex 1dd76b1..f5ad44a 100755 --- a/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png +++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png Binary files differindex 36c18bf..b5884f6 100755 --- a/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png +++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png Binary files differindex 748331f..ae6b8a9 100755 --- a/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png +++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png diff --git a/core/res/res/drawable-mdpi/title_bar_shadow.9.png b/core/res/res/drawable-mdpi/title_bar_shadow.9.png Binary files differdeleted file mode 100644 index dbcefee..0000000 --- a/core/res/res/drawable-mdpi/title_bar_shadow.9.png +++ /dev/null diff --git a/core/res/res/drawable/item_background.xml b/core/res/res/drawable/item_background.xml index a1c9ff8..f7fef82 100644 --- a/core/res/res/drawable/item_background.xml +++ b/core/res/res/drawable/item_background.xml @@ -14,7 +14,8 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> +<selector xmlns:android="http://schemas.android.com/apk/res/android" + android:exitFadeDuration="@android:integer/config_mediumAnimTime"> <item android:state_window_focused="false" android:drawable="@color/transparent" /> diff --git a/core/res/res/drawable/stat_sys_battery.xml b/core/res/res/drawable/stat_sys_battery.xml index 968595d..1060375 100644 --- a/core/res/res/drawable/stat_sys_battery.xml +++ b/core/res/res/drawable/stat_sys_battery.xml @@ -20,11 +20,12 @@ <level-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:maxLevel="4" android:drawable="@android:drawable/stat_sys_battery_0" /> - <item android:maxLevel="14" android:drawable="@android:drawable/stat_sys_battery_10" /> - <item android:maxLevel="29" android:drawable="@android:drawable/stat_sys_battery_20" /> - <item android:maxLevel="49" android:drawable="@android:drawable/stat_sys_battery_40" /> - <item android:maxLevel="69" android:drawable="@android:drawable/stat_sys_battery_60" /> - <item android:maxLevel="89" android:drawable="@android:drawable/stat_sys_battery_80" /> + <item android:maxLevel="15" android:drawable="@android:drawable/stat_sys_battery_15" /> + <item android:maxLevel="35" android:drawable="@android:drawable/stat_sys_battery_28" /> + <item android:maxLevel="49" android:drawable="@android:drawable/stat_sys_battery_43" /> + <item android:maxLevel="60" android:drawable="@android:drawable/stat_sys_battery_57" /> + <item android:maxLevel="75" android:drawable="@android:drawable/stat_sys_battery_71" /> + <item android:maxLevel="90" android:drawable="@android:drawable/stat_sys_battery_85" /> <item android:maxLevel="100" android:drawable="@android:drawable/stat_sys_battery_100" /> </level-list> diff --git a/core/res/res/drawable/stat_sys_battery_charge.xml b/core/res/res/drawable/stat_sys_battery_charge.xml index 92d7c4f..a6c4575 100644 --- a/core/res/res/drawable/stat_sys_battery_charge.xml +++ b/core/res/res/drawable/stat_sys_battery_charge.xml @@ -1,7 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/drawable/stat_sys_battery.xml -** ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,56 +17,14 @@ --> <level-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:maxLevel="14"> - <animation-list - xmlns:android="http://schemas.android.com/apk/res/android" - android:oneshot="false"> - <item android:drawable="@drawable/stat_sys_battery_charge_anim0" android:duration="2000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim1" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim2" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim3" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim4" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim5" android:duration="1000" /> - </animation-list> - </item> - <item android:maxLevel="29"> - <animation-list - xmlns:android="http://schemas.android.com/apk/res/android" - android:oneshot="false"> - <item android:drawable="@drawable/stat_sys_battery_charge_anim1" android:duration="2000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim2" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim3" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim4" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim5" android:duration="1000" /> - </animation-list> - </item> - <item android:maxLevel="49"> - <animation-list - xmlns:android="http://schemas.android.com/apk/res/android" - android:oneshot="false"> - <item android:drawable="@drawable/stat_sys_battery_charge_anim2" android:duration="2000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim3" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim4" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim5" android:duration="1000" /> - </animation-list> - </item> - <item android:maxLevel="69"> - <animation-list - xmlns:android="http://schemas.android.com/apk/res/android" - android:oneshot="false"> - <item android:drawable="@drawable/stat_sys_battery_charge_anim3" android:duration="2000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim4" android:duration="1000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim5" android:duration="1000" /> - </animation-list> - </item> - <item android:maxLevel="89"> - <animation-list - xmlns:android="http://schemas.android.com/apk/res/android" - android:oneshot="false"> - <item android:drawable="@drawable/stat_sys_battery_charge_anim4" android:duration="2000" /> - <item android:drawable="@drawable/stat_sys_battery_charge_anim5" android:duration="1000" /> - </animation-list> - </item> - <item android:maxLevel="101" android:drawable="@drawable/stat_sys_battery_charge_anim5" /> + <item android:maxLevel="4" android:drawable="@android:drawable/stat_sys_battery_charge_anim0" /> + <item android:maxLevel="15" android:drawable="@android:drawable/stat_sys_battery_charge_anim15" /> + <item android:maxLevel="35" android:drawable="@android:drawable/stat_sys_battery_charge_anim28" /> + <item android:maxLevel="49" android:drawable="@android:drawable/stat_sys_battery_charge_anim43" /> + <item android:maxLevel="60" android:drawable="@android:drawable/stat_sys_battery_charge_anim57" /> + <item android:maxLevel="75" android:drawable="@android:drawable/stat_sys_battery_charge_anim71" /> + <item android:maxLevel="90" android:drawable="@android:drawable/stat_sys_battery_charge_anim85" /> + <item android:maxLevel="100" android:drawable="@android:drawable/stat_sys_battery_charge_anim100" /> </level-list> + diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_content.xml b/core/res/res/layout-xlarge/status_bar_latest_event_content.xml index d599154..e4aa270 100644 --- a/core/res/res/layout-xlarge/status_bar_latest_event_content.xml +++ b/core/res/res/layout-xlarge/status_bar_latest_event_content.xml @@ -1,23 +1,20 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - > - + android:layout_width="match_parent" + android:layout_height="match_parent" + > <ImageView android:id="@+id/icon" android:layout_width="48dp" android:layout_height="64dp" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" + android:layout_marginLeft="4dp" android:scaleType="center" /> - <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" android:orientation="vertical" - android:paddingLeft="16dp" + android:paddingLeft="8dp" > <TextView android:id="@+id/title" android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title" @@ -37,5 +34,13 @@ android:fadingEdge="horizontal" /> </LinearLayout> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:singleLine="true" + android:gravity="center_vertical" + android:paddingLeft="8dp" + /> </LinearLayout> diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_content_large_icon.xml b/core/res/res/layout-xlarge/status_bar_latest_event_content_large_icon.xml new file mode 100644 index 0000000..1e1f9de --- /dev/null +++ b/core/res/res/layout-xlarge/status_bar_latest_event_content_large_icon.xml @@ -0,0 +1,44 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + > + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_weight="1" + android:orientation="vertical" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + </LinearLayout> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:singleLine="true" + android:gravity="center_vertical" + android:paddingLeft="8dp" + /> + <ImageView android:id="@+id/icon" + android:layout_width="48dp" + android:layout_height="64dp" + android:scaleType="center" + /> +</LinearLayout> + diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_ticker.xml b/core/res/res/layout-xlarge/status_bar_latest_event_ticker.xml new file mode 100644 index 0000000..b09ed44 --- /dev/null +++ b/core/res/res/layout-xlarge/status_bar_latest_event_ticker.xml @@ -0,0 +1,44 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="@dimen/status_bar_height" + > + <ImageView android:id="@+id/icon" + android:layout_width="48dp" + android:layout_height="match_parent" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_weight="1" + android:orientation="vertical" + android:paddingLeft="16dp" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + </LinearLayout> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:singleLine="true" + android:gravity="center_vertical" + /> +</LinearLayout> + diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_ticker_large_icon.xml b/core/res/res/layout-xlarge/status_bar_latest_event_ticker_large_icon.xml new file mode 100644 index 0000000..6c2e6f7 --- /dev/null +++ b/core/res/res/layout-xlarge/status_bar_latest_event_ticker_large_icon.xml @@ -0,0 +1,44 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + > + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_weight="1" + android:orientation="vertical" + android:paddingLeft="16dp" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + </LinearLayout> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:singleLine="true" + android:gravity="center_vertical" + /> + <ImageView android:id="@+id/icon" + android:layout_width="48dp" + android:layout_height="match_parent" + android:scaleType="center" + /> +</LinearLayout> + diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml index 4133ea9..0ffe8de 100644 --- a/core/res/res/layout/grant_credentials_permission.xml +++ b/core/res/res/layout/grant_credentials_permission.xml @@ -47,8 +47,7 @@ android:layout_height="wrap_content" android:fillViewport="true" android:layout_weight="1" - android:gravity="top|center_horizontal" - android:foreground="@drawable/title_bar_shadow"> + android:gravity="top|center_horizontal"> <LinearLayout android:layout_width="match_parent" diff --git a/core/res/res/values-ar/donottranslate-cldr.xml b/core/res/res/values-ar/donottranslate-cldr.xml new file mode 100644 index 0000000..d662590 --- /dev/null +++ b/core/res/res/values-ar/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">يناير</string> + <string name="month_long_standalone_february">فبراير</string> + <string name="month_long_standalone_march">مارس</string> + <string name="month_long_standalone_april">أبريل</string> + <string name="month_long_standalone_may">مايو</string> + <string name="month_long_standalone_june">يونيو</string> + <string name="month_long_standalone_july">يوليو</string> + <string name="month_long_standalone_august">أغسطس</string> + <string name="month_long_standalone_september">سبتمبر</string> + <string name="month_long_standalone_october">أكتوبر</string> + <string name="month_long_standalone_november">نوفمبر</string> + <string name="month_long_standalone_december">ديسمبر</string> + + <string name="month_long_january">يناير</string> + <string name="month_long_february">فبراير</string> + <string name="month_long_march">مارس</string> + <string name="month_long_april">أبريل</string> + <string name="month_long_may">مايو</string> + <string name="month_long_june">يونيو</string> + <string name="month_long_july">يوليو</string> + <string name="month_long_august">أغسطس</string> + <string name="month_long_september">سبتمبر</string> + <string name="month_long_october">أكتوبر</string> + <string name="month_long_november">نوفمبر</string> + <string name="month_long_december">ديسمبر</string> + + <string name="month_medium_january">يناير</string> + <string name="month_medium_february">فبراير</string> + <string name="month_medium_march">مارس</string> + <string name="month_medium_april">أبريل</string> + <string name="month_medium_may">مايو</string> + <string name="month_medium_june">يونيو</string> + <string name="month_medium_july">يوليو</string> + <string name="month_medium_august">أغسطس</string> + <string name="month_medium_september">سبتمبر</string> + <string name="month_medium_october">أكتوبر</string> + <string name="month_medium_november">نوفمبر</string> + <string name="month_medium_december">ديسمبر</string> + + <string name="month_shortest_january">ي</string> + <string name="month_shortest_february">ف</string> + <string name="month_shortest_march">م</string> + <string name="month_shortest_april">أ</string> + <string name="month_shortest_may">و</string> + <string name="month_shortest_june">ن</string> + <string name="month_shortest_july">ل</string> + <string name="month_shortest_august">غ</string> + <string name="month_shortest_september">س</string> + <string name="month_shortest_october">ك</string> + <string name="month_shortest_november">ب</string> + <string name="month_shortest_december">د</string> + + <string name="day_of_week_long_sunday">الأحد</string> + <string name="day_of_week_long_monday">الإثنين</string> + <string name="day_of_week_long_tuesday">الثلاثاء</string> + <string name="day_of_week_long_wednesday">الأربعاء</string> + <string name="day_of_week_long_thursday">الخميس</string> + <string name="day_of_week_long_friday">الجمعة</string> + <string name="day_of_week_long_saturday">السبت</string> + + <string name="day_of_week_medium_sunday">أحد</string> + <string name="day_of_week_medium_monday">إثنين</string> + <string name="day_of_week_medium_tuesday">ثلاثاء</string> + <string name="day_of_week_medium_wednesday">أربعاء</string> + <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_shortest_sunday">ح</string> + <string name="day_of_week_shortest_monday">ن</string> + <string name="day_of_week_shortest_tuesday">ث</string> + <string name="day_of_week_shortest_wednesday">ر</string> + <string name="day_of_week_shortest_thursday">خ</string> + <string name="day_of_week_shortest_friday">ج</string> + <string name="day_of_week_shortest_saturday">س</string> + + <string name="am">ص</string> + <string name="pm">م</string> + <string name="yesterday">أمس</string> + <string name="today">اليوم</string> + <string name="tomorrow">غدًا</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e/%-m/%Y</string> + <string name="numeric_date_format">d/M/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B، %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%-l:%M:%S %p %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%m/%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s – %2$s</string> + <string name="date1_date2">%2$s – %5$s</string> + <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s، %3$s/%2$s - %6$s، %8$s/%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s، %3$s/%2$s/%4$s - %6$s، %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s، %3$s/%2$s/%4$s – %10$s %6$s، %8$s/%7$s/%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s، %3$s-%2$s – %10$s %6$s، %8$s-%7$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s، %4$s – %10$s %8$s %7$s، %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s، %4$s – %10$s %8$s %7$s، %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s، %3$s %2$s %4$s – %10$s %6$s، %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s، %3$s %2$s %4$s – %10$s %6$s، %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s، %3$s %2$s %4$s – %6$s، %8$s %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s-%8$s %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s، %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s، %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s، %3$s %2$s - %6$s، %8$s %7$s، %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE، d MMMM y</string> +</resources> diff --git a/core/res/res/values-bg/donottranslate-cldr.xml b/core/res/res/values-bg/donottranslate-cldr.xml new file mode 100644 index 0000000..c15e4a7 --- /dev/null +++ b/core/res/res/values-bg/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">януари</string> + <string name="month_long_standalone_february">февруари</string> + <string name="month_long_standalone_march">март</string> + <string name="month_long_standalone_april">април</string> + <string name="month_long_standalone_may">май</string> + <string name="month_long_standalone_june">юни</string> + <string name="month_long_standalone_july">юли</string> + <string name="month_long_standalone_august">август</string> + <string name="month_long_standalone_september">септември</string> + <string name="month_long_standalone_october">октомври</string> + <string name="month_long_standalone_november">ноември</string> + <string name="month_long_standalone_december">декември</string> + + <string name="month_long_january">януари</string> + <string name="month_long_february">февруари</string> + <string name="month_long_march">март</string> + <string name="month_long_april">април</string> + <string name="month_long_may">май</string> + <string name="month_long_june">юни</string> + <string name="month_long_july">юли</string> + <string name="month_long_august">август</string> + <string name="month_long_september">септември</string> + <string name="month_long_october">октомври</string> + <string name="month_long_november">ноември</string> + <string name="month_long_december">декември</string> + + <string name="month_medium_january">ян.</string> + <string name="month_medium_february">февр.</string> + <string name="month_medium_march">март</string> + <string name="month_medium_april">апр.</string> + <string name="month_medium_may">май</string> + <string name="month_medium_june">юни</string> + <string name="month_medium_july">юли</string> + <string name="month_medium_august">авг.</string> + <string name="month_medium_september">септ.</string> + <string name="month_medium_october">окт.</string> + <string name="month_medium_november">ноем.</string> + <string name="month_medium_december">дек.</string> + + <string name="month_shortest_january">я</string> + <string name="month_shortest_february">ф</string> + <string name="month_shortest_march">м</string> + <string name="month_shortest_april">а</string> + <string name="month_shortest_may">м</string> + <string name="month_shortest_june">ю</string> + <string name="month_shortest_july">ю</string> + <string name="month_shortest_august">а</string> + <string name="month_shortest_september">с</string> + <string name="month_shortest_october">о</string> + <string name="month_shortest_november">н</string> + <string name="month_shortest_december">д</string> + + <string name="day_of_week_long_sunday">неделя</string> + <string name="day_of_week_long_monday">понеделник</string> + <string name="day_of_week_long_tuesday">вторник</string> + <string name="day_of_week_long_wednesday">сряда</string> + <string name="day_of_week_long_thursday">четвъртък</string> + <string name="day_of_week_long_friday">петък</string> + <string name="day_of_week_long_saturday">събота</string> + + <string name="day_of_week_medium_sunday">нд</string> + <string name="day_of_week_medium_monday">пн</string> + <string name="day_of_week_medium_tuesday">вт</string> + <string name="day_of_week_medium_wednesday">ср</string> + <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_shortest_sunday">н</string> + <string name="day_of_week_shortest_monday">п</string> + <string name="day_of_week_shortest_tuesday">в</string> + <string name="day_of_week_shortest_wednesday">с</string> + <string name="day_of_week_shortest_thursday">ч</string> + <string name="day_of_week_shortest_friday">п</string> + <string name="day_of_week_shortest_saturday">с</string> + + <string name="am">пр. об.</string> + <string name="pm">сл. об.</string> + <string name="yesterday">Вчера</string> + <string name="today">Днес</string> + <string name="tomorrow">Утре</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d.%m.%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%3$s.%2$s, %1$s - %8$s.%7$s, %6$s</string> + <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s, %1$s - %8$s.%7$s.%9$s, %6$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s.%2$s.%4$s, %1$s - %10$s %8$s.%7$s.%9$s, %6$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %3$s.%2$s, %1$s - %10$s %8$s.%7$s, %6$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s, %1$s - %6$s %5$s, %4$s</string> + <string name="wday1_date1_wday2_date2">%2$s, %1$s - %5$s, %4$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %3$s, %2$s</string> + <string name="wday_date">%3$s, %2$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%3$s %2$s %4$s, %1$s - %8$s %7$s %9$s, %6$s</string> + <string name="same_month_md1_md2">%3$s-%8$s %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s, %1$s - %8$s %7$s y, %6$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">d MMM y, E</string> +</resources> diff --git a/core/res/res/values-ca/donottranslate-cldr.xml b/core/res/res/values-ca/donottranslate-cldr.xml new file mode 100644 index 0000000..a77aa38 --- /dev/null +++ b/core/res/res/values-ca/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">gener</string> + <string name="month_long_standalone_february">febrer</string> + <string name="month_long_standalone_march">març</string> + <string name="month_long_standalone_april">abril</string> + <string name="month_long_standalone_may">maig</string> + <string name="month_long_standalone_june">juny</string> + <string name="month_long_standalone_july">juliol</string> + <string name="month_long_standalone_august">agost</string> + <string name="month_long_standalone_september">setembre</string> + <string name="month_long_standalone_october">octubre</string> + <string name="month_long_standalone_november">novembre</string> + <string name="month_long_standalone_december">desembre</string> + + <string name="month_long_january">gener</string> + <string name="month_long_february">febrer</string> + <string name="month_long_march">març</string> + <string name="month_long_april">abril</string> + <string name="month_long_may">maig</string> + <string name="month_long_june">juny</string> + <string name="month_long_july">juliol</string> + <string name="month_long_august">agost</string> + <string name="month_long_september">setembre</string> + <string name="month_long_october">octubre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">desembre</string> + + <string name="month_medium_january">gen.</string> + <string name="month_medium_february">febr.</string> + <string name="month_medium_march">març</string> + <string name="month_medium_april">abr.</string> + <string name="month_medium_may">maig</string> + <string name="month_medium_june">juny</string> + <string name="month_medium_july">jul.</string> + <string name="month_medium_august">ag.</string> + <string name="month_medium_september">set.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">des.</string> + + <string name="month_shortest_january">g</string> + <string name="month_shortest_february">f</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">a</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">j</string> + <string name="month_shortest_july">j</string> + <string name="month_shortest_august">a</string> + <string name="month_shortest_september">s</string> + <string name="month_shortest_october">o</string> + <string name="month_shortest_november">n</string> + <string name="month_shortest_december">d</string> + + <string name="day_of_week_long_sunday">diumenge</string> + <string name="day_of_week_long_monday">dilluns</string> + <string name="day_of_week_long_tuesday">dimarts</string> + <string name="day_of_week_long_wednesday">dimecres</string> + <string name="day_of_week_long_thursday">dijous</string> + <string name="day_of_week_long_friday">divendres</string> + <string name="day_of_week_long_saturday">dissabte</string> + + <string name="day_of_week_medium_sunday">dg.</string> + <string name="day_of_week_medium_monday">dl.</string> + <string name="day_of_week_medium_tuesday">dt.</string> + <string name="day_of_week_medium_wednesday">dc.</string> + <string name="day_of_week_medium_thursday">dj.</string> + <string name="day_of_week_medium_friday">dv.</string> + <string name="day_of_week_medium_saturday">ds.</string> + + <string name="day_of_week_short_sunday">dg.</string> + <string name="day_of_week_short_monday">dl.</string> + <string name="day_of_week_short_tuesday">dt.</string> + <string name="day_of_week_short_wednesday">dc.</string> + <string name="day_of_week_short_thursday">dj.</string> + <string name="day_of_week_short_friday">dv.</string> + <string name="day_of_week_short_saturday">ds.</string> + + <string name="day_of_week_shortest_sunday">g</string> + <string name="day_of_week_shortest_monday">l</string> + <string name="day_of_week_shortest_tuesday">t</string> + <string name="day_of_week_shortest_wednesday">c</string> + <string name="day_of_week_shortest_thursday">j</string> + <string name="day_of_week_shortest_friday">v</string> + <string name="day_of_week_shortest_saturday">s</string> + + <string name="am">a.m.</string> + <string name="pm">p.m.</string> + <string name="yesterday">ahir</string> + <string name="today">avui</string> + <string name="tomorrow">demà</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%m/%Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%-B del %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s - %10$s %6$s %8$s/%7$s/%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s-%8$s de %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s de %2$s - %8$s de %7$s de %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s - %6$s %8$s de %7$s de %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE d MMM y</string> +</resources> diff --git a/core/res/res/values-fa/donottranslate-cldr.xml b/core/res/res/values-fa/donottranslate-cldr.xml new file mode 100644 index 0000000..83f4942 --- /dev/null +++ b/core/res/res/values-fa/donottranslate-cldr.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">ژانویه</string> + <string name="month_long_standalone_february">فوریه</string> + <string name="month_long_standalone_march">مارس</string> + <string name="month_long_standalone_april">آوریل</string> + <string name="month_long_standalone_may">مه</string> + <string name="month_long_standalone_june">ژوئن</string> + <string name="month_long_standalone_july">ژوئیه</string> + <string name="month_long_standalone_august">اوت</string> + <string name="month_long_standalone_september">سپتامبر</string> + <string name="month_long_standalone_october">اکتبر</string> + <string name="month_long_standalone_november">نوامبر</string> + <string name="month_long_standalone_december">دسامبر</string> + + <string name="month_long_january">ژانویهٔ</string> + <string name="month_long_february">فوریهٔ</string> + <string name="month_long_march">مارس</string> + <string name="month_long_april">آوریل</string> + <string name="month_long_may">مهٔ</string> + <string name="month_long_june">ژوئن</string> + <string name="month_long_july">ژوئیهٔ</string> + <string name="month_long_august">اوت</string> + <string name="month_long_september">سپتامبر</string> + <string name="month_long_october">اکتبر</string> + <string name="month_long_november">نوامبر</string> + <string name="month_long_december">دسامبر</string> + + <string name="month_medium_january">ژانویهٔ</string> + <string name="month_medium_february">فوریهٔ</string> + <string name="month_medium_march">مارس</string> + <string name="month_medium_april">آوریل</string> + <string name="month_medium_may">مهٔ</string> + <string name="month_medium_june">ژوئن</string> + <string name="month_medium_july">ژوئیهٔ</string> + <string name="month_medium_august">اوت</string> + <string name="month_medium_september">سپتامبر</string> + <string name="month_medium_october">اکتبر</string> + <string name="month_medium_november">نوامبر</string> + <string name="month_medium_december">دسامبر</string> + + <string name="month_shortest_january">ژ</string> + <string name="month_shortest_february">ف</string> + <string name="month_shortest_march">م</string> + <string name="month_shortest_april">آ</string> + <string name="month_shortest_may">م</string> + <string name="month_shortest_june">ژ</string> + <string name="month_shortest_july">ژ</string> + <string name="month_shortest_august">ا</string> + <string name="month_shortest_september">س</string> + <string name="month_shortest_october">ا</string> + <string name="month_shortest_november">ن</string> + <string name="month_shortest_december">د</string> + + <string name="day_of_week_long_sunday">یکشنبه</string> + <string name="day_of_week_long_monday">دوشنبه</string> + <string name="day_of_week_long_tuesday">سهشنبه</string> + <string name="day_of_week_long_wednesday">چهارشنبه</string> + <string name="day_of_week_long_thursday">پنجشنبه</string> + <string name="day_of_week_long_friday">جمعه</string> + <string name="day_of_week_long_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> + <string name="day_of_week_shortest_wednesday">چ</string> + <string name="day_of_week_shortest_thursday">پ</string> + <string name="day_of_week_shortest_friday">ج</string> + <string name="day_of_week_shortest_saturday">ش</string> + + <string name="am">قبل از ظهر</string> + <string name="pm">بعد از ظهر</string> + <string name="yesterday">دیروز</string> + <string name="today">امروز</string> + <string name="tomorrow">فردا</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y/%-m/%-e</string> + <string name="numeric_date_format">yyyy/M/d</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S، %Y/%-m/%-e</string> + <string name="date_time">%2$s، %1$s</string> + <string name="time_date">%1$s، %3$s</string> + <string name="abbrev_month_day_year">%Y/%-m/%-e</string> + <string name="month_day">%-e %-B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %-b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s تا %2$s</string> + <string name="date1_date2">%2$s تا %5$s</string> + <string name="numeric_md1_md2">%2$s/%3$s تا %7$s/%8$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s %2$s/%3$s تا %6$s %7$s/%8$s</string> + <string name="numeric_mdy1_mdy2">%4$s/%2$s/%3$s تا %9$s/%7$s/%8$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %4$s/%2$s/%3$s تا %6$s %9$s/%7$s/%8$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s، %1$s %4$s/%2$s/%3$s تا %10$s، %6$s %9$s/%7$s/%8$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s، %2$s/%3$s تا %10$s، %7$s/%8$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s، %1$s %2$s/%3$s تا %10$s، %6$s %7$s/%8$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s، %4$s/%2$s/%3$s تا %10$s، %9$s/%7$s/%8$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s، %1$s %2$s تا %6$s، %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s تا %4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s، %2$s تا %6$s، %5$s</string> + <string name="time_wday_date">%1$s، %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s، %2$s</string> + <string name="same_year_md1_md2">%3$s LLLL تا %8$s LLLL</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string> + <string name="same_year_md1_time1_md2_time2">%5$s، %3$s LLLL تا %10$s، %8$s LLLL</string> + <string name="same_month_md1_time1_md2_time2">%5$s، %3$s LLLL تا %10$s، %8$s LLLL</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s، %1$s %3$s LLLL تا %10$s، %6$s %8$s LLLL</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s، %1$s %3$s LLLL تا %10$s، %6$s %8$s LLLL</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s، %3$s %2$s %4$s تا %10$s، %8$s %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s، %3$s %2$s %4$s تا %10$s، %8$s %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s، %1$s %3$s %2$s %4$s تا %10$s، %6$s %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s، %1$s %3$s %2$s %4$s تا %10$s، %6$s %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s تا %6$s %8$s %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s تا %8$s LLL</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string> + <string name="same_year_mdy1_mdy2">%3$s LLL تا %8$s %2$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s تا %8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s LLL تا %6$s %8$s %2$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E d LLLL</string> + <string name="abbrev_wday_month_day_year">E d MMM y</string> +</resources> diff --git a/core/res/res/values-fi/donottranslate-cldr.xml b/core/res/res/values-fi/donottranslate-cldr.xml new file mode 100644 index 0000000..5146a0a --- /dev/null +++ b/core/res/res/values-fi/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">tammikuu</string> + <string name="month_long_standalone_february">helmikuu</string> + <string name="month_long_standalone_march">maaliskuu</string> + <string name="month_long_standalone_april">huhtikuu</string> + <string name="month_long_standalone_may">toukokuu</string> + <string name="month_long_standalone_june">kesäkuu</string> + <string name="month_long_standalone_july">heinäkuu</string> + <string name="month_long_standalone_august">elokuu</string> + <string name="month_long_standalone_september">syyskuu</string> + <string name="month_long_standalone_october">lokakuu</string> + <string name="month_long_standalone_november">marraskuu</string> + <string name="month_long_standalone_december">joulukuu</string> + + <string name="month_long_january">tammikuuta</string> + <string name="month_long_february">helmikuuta</string> + <string name="month_long_march">maaliskuuta</string> + <string name="month_long_april">huhtikuuta</string> + <string name="month_long_may">toukokuuta</string> + <string name="month_long_june">kesäkuuta</string> + <string name="month_long_july">heinäkuuta</string> + <string name="month_long_august">elokuuta</string> + <string name="month_long_september">syyskuuta</string> + <string name="month_long_october">lokakuuta</string> + <string name="month_long_november">marraskuuta</string> + <string name="month_long_december">joulukuuta</string> + + <string name="month_medium_january">tammikuuta</string> + <string name="month_medium_february">helmikuuta</string> + <string name="month_medium_march">maaliskuuta</string> + <string name="month_medium_april">huhtikuuta</string> + <string name="month_medium_may">toukokuuta</string> + <string name="month_medium_june">kesäkuuta</string> + <string name="month_medium_july">heinäkuuta</string> + <string name="month_medium_august">elokuuta</string> + <string name="month_medium_september">syyskuuta</string> + <string name="month_medium_october">lokakuuta</string> + <string name="month_medium_november">marraskuuta</string> + <string name="month_medium_december">joulukuuta</string> + + <string name="month_shortest_january">T</string> + <string name="month_shortest_february">H</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">H</string> + <string name="month_shortest_may">T</string> + <string name="month_shortest_june">K</string> + <string name="month_shortest_july">H</string> + <string name="month_shortest_august">E</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">L</string> + <string name="month_shortest_november">M</string> + <string name="month_shortest_december">J</string> + + <string name="day_of_week_long_sunday">sunnuntaina</string> + <string name="day_of_week_long_monday">maanantaina</string> + <string name="day_of_week_long_tuesday">tiistaina</string> + <string name="day_of_week_long_wednesday">keskiviikkona</string> + <string name="day_of_week_long_thursday">torstaina</string> + <string name="day_of_week_long_friday">perjantaina</string> + <string name="day_of_week_long_saturday">lauantaina</string> + + <string name="day_of_week_medium_sunday">su</string> + <string name="day_of_week_medium_monday">ma</string> + <string name="day_of_week_medium_tuesday">ti</string> + <string name="day_of_week_medium_wednesday">ke</string> + <string name="day_of_week_medium_thursday">to</string> + <string name="day_of_week_medium_friday">pe</string> + <string name="day_of_week_medium_saturday">la</string> + + <string name="day_of_week_short_sunday">su</string> + <string name="day_of_week_short_monday">ma</string> + <string name="day_of_week_short_tuesday">ti</string> + <string name="day_of_week_short_wednesday">ke</string> + <string name="day_of_week_short_thursday">to</string> + <string name="day_of_week_short_friday">pe</string> + <string name="day_of_week_short_saturday">la</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">K</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">L</string> + + <string name="am">ap.</string> + <string name="pm">ip.</string> + <string name="yesterday">eilen</string> + <string name="today">tänään</string> + <string name="tomorrow">huomenna</string> + + <string name="hour_minute_24">%-k.%M</string> + <string name="hour_minute_ampm">%-l.%M %p</string> + <string name="hour_minute_cap_ampm">%-l.%M %^p</string> + <string name="twelve_hour_time_format">h.mm a</string> + <string name="twenty_four_hour_time_format">H.mm</string> + <string name="numeric_date">%-e.%-m.%Y</string> + <string name="numeric_date_format">d.M.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%-k.%M.%S</string> + <string name="date_and_time">%-k.%M.%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e.%-m.%Y</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-b</string> + <string name="month_year">%-B %Y</string> + <string name="abbrev_month_day">%-e. %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%-b %Y</string> + <string name="time1_time2">%1$s–%2$s</string> + <string name="date1_date2">%2$s–%5$s</string> + <string name="numeric_md1_md2">%3$s.%2$s.–%8$s.%7$s.</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s.%2$s. – %6$s %8$s.%7$s.</string> + <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s–%8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s.%2$s.%4$s – %6$s %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s.%2$s.%4$s–%10$s %6$s %8$s.%7$s.%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s.–%10$s %8$s.%7$s.</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s.%2$s.–%10$s %6$s %8$s.%7$s.</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s–%10$s %8$s.%7$s.%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s–%6$s %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s–%4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s–%6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s. %2$s–%8$s. %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s–%6$s %8$s. %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s–%10$s %8$s. %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s–%10$s %8$s. %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s %4$s–%6$s %8$s. %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s.–%8$s. %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s–%6$s %8$s. %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s. %2$s – %8$s. %7$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s – %6$s %8$s. %7$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE d. MMM y</string> +</resources> diff --git a/core/res/res/values-he/donottranslate-cldr.xml b/core/res/res/values-he/donottranslate-cldr.xml new file mode 100644 index 0000000..d373a34 --- /dev/null +++ b/core/res/res/values-he/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">ינואר</string> + <string name="month_long_standalone_february">פברואר</string> + <string name="month_long_standalone_march">מרס</string> + <string name="month_long_standalone_april">אפריל</string> + <string name="month_long_standalone_may">מאי</string> + <string name="month_long_standalone_june">יוני</string> + <string name="month_long_standalone_july">יולי</string> + <string name="month_long_standalone_august">אוגוסט</string> + <string name="month_long_standalone_september">ספטמבר</string> + <string name="month_long_standalone_october">אוקטובר</string> + <string name="month_long_standalone_november">נובמבר</string> + <string name="month_long_standalone_december">דצמבר</string> + + <string name="month_long_january">ינואר</string> + <string name="month_long_february">פברואר</string> + <string name="month_long_march">מרס</string> + <string name="month_long_april">אפריל</string> + <string name="month_long_may">מאי</string> + <string name="month_long_june">יוני</string> + <string name="month_long_july">יולי</string> + <string name="month_long_august">אוגוסט</string> + <string name="month_long_september">ספטמבר</string> + <string name="month_long_october">אוקטובר</string> + <string name="month_long_november">נובמבר</string> + <string name="month_long_december">דצמבר</string> + + <string name="month_medium_january">ינו</string> + <string name="month_medium_february">פבר</string> + <string name="month_medium_march">מרס</string> + <string name="month_medium_april">אפר</string> + <string name="month_medium_may">מאי</string> + <string name="month_medium_june">יונ</string> + <string name="month_medium_july">יול</string> + <string name="month_medium_august">אוג</string> + <string name="month_medium_september">ספט</string> + <string name="month_medium_october">אוק</string> + <string name="month_medium_november">נוב</string> + <string name="month_medium_december">דצמ</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">יום ראשון</string> + <string name="day_of_week_long_monday">יום שני</string> + <string name="day_of_week_long_tuesday">יום שלישי</string> + <string name="day_of_week_long_wednesday">יום רביעי</string> + <string name="day_of_week_long_thursday">יום חמישי</string> + <string name="day_of_week_long_friday">יום שישי</string> + <string name="day_of_week_long_saturday">יום שבת</string> + + <string name="day_of_week_medium_sunday">יום א\'</string> + <string name="day_of_week_medium_monday">יום ב\'</string> + <string name="day_of_week_medium_tuesday">יום ג\'</string> + <string name="day_of_week_medium_wednesday">יום ד\'</string> + <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_shortest_sunday">א</string> + <string name="day_of_week_shortest_monday">ב</string> + <string name="day_of_week_shortest_tuesday">ג</string> + <string name="day_of_week_shortest_wednesday">ד</string> + <string name="day_of_week_shortest_thursday">ה</string> + <string name="day_of_week_shortest_friday">ו</string> + <string name="day_of_week_shortest_saturday">ש</string> + + <string name="am">לפנה"צ</string> + <string name="pm">אחה"צ</string> + <string name="yesterday">אתמול</string> + <string name="today">היום</string> + <string name="tomorrow">מחר</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e ב%B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e.%-m.%Y</string> + <string name="month_day">%-e ב%B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%b %-e</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y %b</string> + <string name="time1_time2">%1$s – %2$s</string> + <string name="date1_date2">%2$s – %5$s</string> + <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s – %10$s %6$s, %8$s.%7$s.%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s ב%2$s – %8$s ב%7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s ב%2$s – %10$s %8$s ב%7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s ב%2$s – %10$s %8$s ב%7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string> + <string name="same_month_md1_md2">%3$s-%8$s %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, y MMM d</string> +</resources> diff --git a/core/res/res/values-hr/donottranslate-cldr.xml b/core/res/res/values-hr/donottranslate-cldr.xml new file mode 100644 index 0000000..23332aa --- /dev/null +++ b/core/res/res/values-hr/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">siječanj</string> + <string name="month_long_standalone_february">veljača</string> + <string name="month_long_standalone_march">ožujak</string> + <string name="month_long_standalone_april">travanj</string> + <string name="month_long_standalone_may">svibanj</string> + <string name="month_long_standalone_june">lipanj</string> + <string name="month_long_standalone_july">srpanj</string> + <string name="month_long_standalone_august">kolovoz</string> + <string name="month_long_standalone_september">rujan</string> + <string name="month_long_standalone_october">listopad</string> + <string name="month_long_standalone_november">studeni</string> + <string name="month_long_standalone_december">prosinac</string> + + <string name="month_long_january">siječnja</string> + <string name="month_long_february">veljače</string> + <string name="month_long_march">ožujka</string> + <string name="month_long_april">travnja</string> + <string name="month_long_may">svibnja</string> + <string name="month_long_june">lipnja</string> + <string name="month_long_july">srpnja</string> + <string name="month_long_august">kolovoza</string> + <string name="month_long_september">rujna</string> + <string name="month_long_october">listopada</string> + <string name="month_long_november">studenoga</string> + <string name="month_long_december">prosinca</string> + + <string name="month_medium_january">01.</string> + <string name="month_medium_february">02.</string> + <string name="month_medium_march">03.</string> + <string name="month_medium_april">04.</string> + <string name="month_medium_may">05.</string> + <string name="month_medium_june">06.</string> + <string name="month_medium_july">07.</string> + <string name="month_medium_august">08.</string> + <string name="month_medium_september">09.</string> + <string name="month_medium_october">10.</string> + <string name="month_medium_november">11.</string> + <string name="month_medium_december">12.</string> + + <string name="month_shortest_january">1.</string> + <string name="month_shortest_february">2.</string> + <string name="month_shortest_march">3.</string> + <string name="month_shortest_april">4.</string> + <string name="month_shortest_may">5.</string> + <string name="month_shortest_june">6.</string> + <string name="month_shortest_july">7.</string> + <string name="month_shortest_august">8.</string> + <string name="month_shortest_september">9.</string> + <string name="month_shortest_october">10.</string> + <string name="month_shortest_november">11.</string> + <string name="month_shortest_december">12.</string> + + <string name="day_of_week_long_sunday">nedjelja</string> + <string name="day_of_week_long_monday">ponedjeljak</string> + <string name="day_of_week_long_tuesday">utorak</string> + <string name="day_of_week_long_wednesday">srijeda</string> + <string name="day_of_week_long_thursday">četvrtak</string> + <string name="day_of_week_long_friday">petak</string> + <string name="day_of_week_long_saturday">subota</string> + + <string name="day_of_week_medium_sunday">ned</string> + <string name="day_of_week_medium_monday">pon</string> + <string name="day_of_week_medium_tuesday">uto</string> + <string name="day_of_week_medium_wednesday">sri</string> + <string name="day_of_week_medium_thursday">čet</string> + <string name="day_of_week_medium_friday">pet</string> + <string name="day_of_week_medium_saturday">sub</string> + + <string name="day_of_week_short_sunday">ned</string> + <string name="day_of_week_short_monday">pon</string> + <string name="day_of_week_short_tuesday">uto</string> + <string name="day_of_week_short_wednesday">sri</string> + <string name="day_of_week_short_thursday">čet</string> + <string name="day_of_week_short_friday">pet</string> + <string name="day_of_week_short_saturday">sub</string> + + <string name="day_of_week_shortest_sunday">n</string> + <string name="day_of_week_shortest_monday">p</string> + <string name="day_of_week_shortest_tuesday">u</string> + <string name="day_of_week_shortest_wednesday">s</string> + <string name="day_of_week_shortest_thursday">č</string> + <string name="day_of_week_shortest_friday">p</string> + <string name="day_of_week_shortest_saturday">s</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">jučer</string> + <string name="today">danas</string> + <string name="tomorrow">sutra</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e.%-m.%Y.</string> + <string name="numeric_date_format">d.M.yyyy.</string> + <string name="numeric_date_template">"%s.%s.%s."</string> + <string name="month_day_year">%-e. %B %Y.</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e.%b.%Y.</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e.%b.%Y.</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y.</string> + <string name="abbrev_month_day">%-e.%b.</string> + <string name="abbrev_month">%-b.</string> + <string name="abbrev_month_year">%b.%Y.</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string> + <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s. - %8$s.%7$s.%9$s.</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s. - %6$s, %8$s.%7$s.%9$s.</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s. - %10$s %6$s, %8$s.%7$s.%9$s.</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s. - %10$s %8$s.%7$s.%9$s.</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s, %3$s</string> + <string name="wday_date">%2$s, %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s. - %10$s %8$s.%7$s.%9$s.</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s. - %10$s %8$s.%7$s.%9$s.</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s. - %10$s %6$s, %8$s.%7$s.%9$s.</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s. - %10$s %6$s, %8$s.%7$s.%9$s.</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s. - %6$s, %8$s.%7$s.%9$s.</string> + <string name="same_month_md1_md2">%3$s. - %8$s.%2$s.</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s.%2$s. - %8$s.%7$s.%9$s.</string> + <string name="same_month_mdy1_mdy2">%3$s. - %8$s.%2$s.%9$s.</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.%9$s.</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E, d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d.MMM.y.</string> +</resources> diff --git a/core/res/res/values-hu/donottranslate-cldr.xml b/core/res/res/values-hu/donottranslate-cldr.xml new file mode 100644 index 0000000..996eefb --- /dev/null +++ b/core/res/res/values-hu/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">január</string> + <string name="month_long_standalone_february">február</string> + <string name="month_long_standalone_march">március</string> + <string name="month_long_standalone_april">április</string> + <string name="month_long_standalone_may">május</string> + <string name="month_long_standalone_june">június</string> + <string name="month_long_standalone_july">július</string> + <string name="month_long_standalone_august">augusztus</string> + <string name="month_long_standalone_september">szeptember</string> + <string name="month_long_standalone_october">október</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">január</string> + <string name="month_long_february">február</string> + <string name="month_long_march">március</string> + <string name="month_long_april">április</string> + <string name="month_long_may">május</string> + <string name="month_long_june">június</string> + <string name="month_long_july">július</string> + <string name="month_long_august">augusztus</string> + <string name="month_long_september">szeptember</string> + <string name="month_long_october">október</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">febr.</string> + <string name="month_medium_march">márc.</string> + <string name="month_medium_april">ápr.</string> + <string name="month_medium_may">máj.</string> + <string name="month_medium_june">jún.</string> + <string name="month_medium_july">júl.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">szept.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">Á</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">vasárnap</string> + <string name="day_of_week_long_monday">hétfő</string> + <string name="day_of_week_long_tuesday">kedd</string> + <string name="day_of_week_long_wednesday">szerda</string> + <string name="day_of_week_long_thursday">csütörtök</string> + <string name="day_of_week_long_friday">péntek</string> + <string name="day_of_week_long_saturday">szombat</string> + + <string name="day_of_week_medium_sunday">V</string> + <string name="day_of_week_medium_monday">H</string> + <string name="day_of_week_medium_tuesday">K</string> + <string name="day_of_week_medium_wednesday">Sze</string> + <string name="day_of_week_medium_thursday">Cs</string> + <string name="day_of_week_medium_friday">P</string> + <string name="day_of_week_medium_saturday">Szo</string> + + <string name="day_of_week_short_sunday">V</string> + <string name="day_of_week_short_monday">H</string> + <string name="day_of_week_short_tuesday">K</string> + <string name="day_of_week_short_wednesday">Sze</string> + <string name="day_of_week_short_thursday">Cs</string> + <string name="day_of_week_short_friday">P</string> + <string name="day_of_week_short_saturday">Szo</string> + + <string name="day_of_week_shortest_sunday">V</string> + <string name="day_of_week_shortest_monday">H</string> + <string name="day_of_week_shortest_tuesday">K</string> + <string name="day_of_week_shortest_wednesday">S</string> + <string name="day_of_week_shortest_thursday">C</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">de.</string> + <string name="pm">du.</string> + <string name="yesterday">tegnap</string> + <string name="today">ma</string> + <string name="tomorrow">holnap</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%Y.%m.%d.</string> + <string name="numeric_date_format">yyyy.MM.dd.</string> + <string name="numeric_date_template">"%s.%s.%s."</string> + <string name="month_day_year">%Y. %B %-e.</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %Y.%m.%d.</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y.%m.%d.</string> + <string name="month_day">%B %-e.</string> + <string name="month">%-B</string> + <string name="month_year">%Y. %B</string> + <string name="abbrev_month_day">%b %-e.</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y. %b</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%2$s.%3$s. - %7$s.%8$s.</string> + <string name="numeric_wday1_md1_wday2_md2">%2$s.%3$s., %1$s - %7$s.%8$s., %6$s</string> + <string name="numeric_mdy1_mdy2">%4$s.%2$s.%3$s. - %9$s.%7$s.%8$s.</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s.%2$s.%3$s., %1$s - %9$s.%7$s.%8$s., %6$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s.%2$s.%3$s., %1$s - %10$s %9$s.%7$s.%8$s., %6$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %2$s. %3$s. - %10$s %7$s. %8$s.</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s. %3$s., %1$s - %10$s %7$s. %8$s., %6$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s.%2$s.%3$s. - %10$s %9$s.%7$s.%8$s.</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s, %1$s - %6$s %5$s, %4$s</string> + <string name="wday1_date1_wday2_date2">%2$s, %1$s - %5$s, %4$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %3$s, %2$s</string> + <string name="wday_date">%3$s, %2$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%2$s %3$s. - %7$s %8$s.</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string> + <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s. %2$s %3$s., %1$s - %9$s. %7$s %8$s., %6$s</string> + <string name="same_month_md1_md2">%2$s %3$s-%8$s.</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%9$s. %2$s %3$s. - %7$s %8$s.</string> + <string name="same_month_mdy1_mdy2">%9$s. %2$s %3$s-%8$s.</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s. %2$s %3$s., %1$s - %7$s %8$s., %6$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">y. MMM d., E</string> +</resources> diff --git a/core/res/res/values-id/donottranslate-cldr.xml b/core/res/res/values-id/donottranslate-cldr.xml new file mode 100644 index 0000000..7a58a19 --- /dev/null +++ b/core/res/res/values-id/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Januari</string> + <string name="month_long_standalone_february">Februari</string> + <string name="month_long_standalone_march">Maret</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">Mei</string> + <string name="month_long_standalone_june">Juni</string> + <string name="month_long_standalone_july">Juli</string> + <string name="month_long_standalone_august">Agustus</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">Oktober</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">Desember</string> + + <string name="month_long_january">Januari</string> + <string name="month_long_february">Februari</string> + <string name="month_long_march">Maret</string> + <string name="month_long_april">April</string> + <string name="month_long_may">Mei</string> + <string name="month_long_june">Juni</string> + <string name="month_long_july">Juli</string> + <string name="month_long_august">Agustus</string> + <string name="month_long_september">September</string> + <string name="month_long_october">Oktober</string> + <string name="month_long_november">November</string> + <string name="month_long_december">Desember</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">Mei</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Agu</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Okt</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Des</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">Minggu</string> + <string name="day_of_week_long_monday">Senin</string> + <string name="day_of_week_long_tuesday">Selasa</string> + <string name="day_of_week_long_wednesday">Rabu</string> + <string name="day_of_week_long_thursday">Kamis</string> + <string name="day_of_week_long_friday">Jumat</string> + <string name="day_of_week_long_saturday">Sabtu</string> + + <string name="day_of_week_medium_sunday">Min</string> + <string name="day_of_week_medium_monday">Sen</string> + <string name="day_of_week_medium_tuesday">Sel</string> + <string name="day_of_week_medium_wednesday">Rab</string> + <string name="day_of_week_medium_thursday">Kam</string> + <string name="day_of_week_medium_friday">Jum</string> + <string name="day_of_week_medium_saturday">Sab</string> + + <string name="day_of_week_short_sunday">Min</string> + <string name="day_of_week_short_monday">Sen</string> + <string name="day_of_week_short_tuesday">Sel</string> + <string name="day_of_week_short_wednesday">Rab</string> + <string name="day_of_week_short_thursday">Kam</string> + <string name="day_of_week_short_friday">Jum</string> + <string name="day_of_week_short_saturday">Sab</string> + + <string name="day_of_week_shortest_sunday">1</string> + <string name="day_of_week_shortest_monday">2</string> + <string name="day_of_week_shortest_tuesday">3</string> + <string name="day_of_week_shortest_wednesday">4</string> + <string name="day_of_week_shortest_thursday">5</string> + <string name="day_of_week_shortest_friday">6</string> + <string name="day_of_week_shortest_saturday">7</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%b %-e</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y %b</string> + <string name="time1_time2">%1$s – %2$s</string> + <string name="date1_date2">%2$s – %5$s</string> + <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string> + <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string> + <string name="same_month_md1_md2">%2$s-%3$s – %8$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%9$s-%2$s-%3$s – %7$s-%8$s</string> + <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, y MMM d</string> +</resources> diff --git a/core/res/res/values-lt/donottranslate-cldr.xml b/core/res/res/values-lt/donottranslate-cldr.xml new file mode 100644 index 0000000..25458bd --- /dev/null +++ b/core/res/res/values-lt/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Sausis</string> + <string name="month_long_standalone_february">Vasaris</string> + <string name="month_long_standalone_march">Kovas</string> + <string name="month_long_standalone_april">Balandis</string> + <string name="month_long_standalone_may">Gegužė</string> + <string name="month_long_standalone_june">Birželis</string> + <string name="month_long_standalone_july">Liepa</string> + <string name="month_long_standalone_august">Rugpjūtis</string> + <string name="month_long_standalone_september">Rugsėjis</string> + <string name="month_long_standalone_october">Spalis</string> + <string name="month_long_standalone_november">Lapkritis</string> + <string name="month_long_standalone_december">Gruodis</string> + + <string name="month_long_january">sausio</string> + <string name="month_long_february">vasario</string> + <string name="month_long_march">kovo</string> + <string name="month_long_april">balandžio</string> + <string name="month_long_may">gegužės</string> + <string name="month_long_june">birželio</string> + <string name="month_long_july">liepos</string> + <string name="month_long_august">rugpjūčio</string> + <string name="month_long_september">rugsėjo</string> + <string name="month_long_october">spalio</string> + <string name="month_long_november">lapkričio</string> + <string name="month_long_december">gruodžio</string> + + <string name="month_medium_january">Sau</string> + <string name="month_medium_february">Vas</string> + <string name="month_medium_march">Kov</string> + <string name="month_medium_april">Bal</string> + <string name="month_medium_may">Geg</string> + <string name="month_medium_june">Bir</string> + <string name="month_medium_july">Lie</string> + <string name="month_medium_august">Rgp</string> + <string name="month_medium_september">Rgs</string> + <string name="month_medium_october">Spl</string> + <string name="month_medium_november">Lap</string> + <string name="month_medium_december">Grd</string> + + <string name="month_shortest_january">S</string> + <string name="month_shortest_february">V</string> + <string name="month_shortest_march">K</string> + <string name="month_shortest_april">B</string> + <string name="month_shortest_may">G</string> + <string name="month_shortest_june">B</string> + <string name="month_shortest_july">L</string> + <string name="month_shortest_august">R</string> + <string name="month_shortest_september">R</string> + <string name="month_shortest_october">S</string> + <string name="month_shortest_november">L</string> + <string name="month_shortest_december">G</string> + + <string name="day_of_week_long_sunday">sekmadienis</string> + <string name="day_of_week_long_monday">pirmadienis</string> + <string name="day_of_week_long_tuesday">antradienis</string> + <string name="day_of_week_long_wednesday">trečiadienis</string> + <string name="day_of_week_long_thursday">ketvirtadienis</string> + <string name="day_of_week_long_friday">penktadienis</string> + <string name="day_of_week_long_saturday">šeštadienis</string> + + <string name="day_of_week_medium_sunday">Sk</string> + <string name="day_of_week_medium_monday">Pr</string> + <string name="day_of_week_medium_tuesday">An</string> + <string name="day_of_week_medium_wednesday">Tr</string> + <string name="day_of_week_medium_thursday">Kt</string> + <string name="day_of_week_medium_friday">Pn</string> + <string name="day_of_week_medium_saturday">Št</string> + + <string name="day_of_week_short_sunday">Sk</string> + <string name="day_of_week_short_monday">Pr</string> + <string name="day_of_week_short_tuesday">An</string> + <string name="day_of_week_short_wednesday">Tr</string> + <string name="day_of_week_short_thursday">Kt</string> + <string name="day_of_week_short_friday">Pn</string> + <string name="day_of_week_short_saturday">Št</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">A</string> + <string name="day_of_week_shortest_wednesday">T</string> + <string name="day_of_week_shortest_thursday">K</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">Š</string> + + <string name="am">priešpiet</string> + <string name="pm">popiet</string> + <string name="yesterday">vakar</string> + <string name="today">šiandien</string> + <string name="tomorrow">rytoj</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y-%m-%d</string> + <string name="numeric_date_format">yyyy-MM-dd</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%Y m. %B %-e d.</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %Y.%m.%d</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y.%m.%d</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%Y %B</string> + <string name="abbrev_month_day">%b %-e d.</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%Y m. %b</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%2$s-%3$s - %7$s-%8$s</string> + <string name="numeric_wday1_md1_wday2_md2">%2$s-%3$s%1$s - %7$s-%8$s%6$s</string> + <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s%1$s - %9$s-%7$s-%8$s%6$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s-%2$s-%3$s%1$s - %10$s %9$s-%7$s-%8$s%6$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s-%3$s%1$s - %10$s %7$s-%8$s%6$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s - %10$s %9$s-%7$s-%8$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s%1$s - %6$s %5$s%4$s</string> + <string name="wday1_date1_wday2_date2">%2$s%1$s - %5$s%4$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %3$s%2$s</string> + <string name="wday_date">%3$s%2$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s m. %2$s %3$s d.,%1$s - %9$s m. %7$s %8$s d.,%6$s</string> + <string name="same_month_md1_md2">%2$s %3$s d.-%8$s d.</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%9$s m. %2$s %3$s d. - %7$s %8$s d.</string> + <string name="same_month_mdy1_mdy2">%9$s m. %2$s %3$s d.-%8$s d.</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s m. %2$s %3$s d.,%1$s - %7$s %8$s d.,%6$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">y \'m\'. MMM d \'d\'.,E</string> +</resources> diff --git a/core/res/res/values-lv/donottranslate-cldr.xml b/core/res/res/values-lv/donottranslate-cldr.xml new file mode 100644 index 0000000..2de9367 --- /dev/null +++ b/core/res/res/values-lv/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janvāris</string> + <string name="month_long_standalone_february">februāris</string> + <string name="month_long_standalone_march">marts</string> + <string name="month_long_standalone_april">aprīlis</string> + <string name="month_long_standalone_may">maijs</string> + <string name="month_long_standalone_june">jūnijs</string> + <string name="month_long_standalone_july">jūlijs</string> + <string name="month_long_standalone_august">augusts</string> + <string name="month_long_standalone_september">septembris</string> + <string name="month_long_standalone_october">oktobris</string> + <string name="month_long_standalone_november">novembris</string> + <string name="month_long_standalone_december">decembris</string> + + <string name="month_long_january">janvāris</string> + <string name="month_long_february">februāris</string> + <string name="month_long_march">marts</string> + <string name="month_long_april">aprīlis</string> + <string name="month_long_may">maijs</string> + <string name="month_long_june">jūnijs</string> + <string name="month_long_july">jūlijs</string> + <string name="month_long_august">augusts</string> + <string name="month_long_september">septembris</string> + <string name="month_long_october">oktobris</string> + <string name="month_long_november">novembris</string> + <string name="month_long_december">decembris</string> + + <string name="month_medium_january">janv.</string> + <string name="month_medium_february">febr.</string> + <string name="month_medium_march">marts</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">maijs</string> + <string name="month_medium_june">jūn.</string> + <string name="month_medium_july">jūl.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">svētdiena</string> + <string name="day_of_week_long_monday">pirmdiena</string> + <string name="day_of_week_long_tuesday">otrdiena</string> + <string name="day_of_week_long_wednesday">trešdiena</string> + <string name="day_of_week_long_thursday">ceturtdiena</string> + <string name="day_of_week_long_friday">piektdiena</string> + <string name="day_of_week_long_saturday">sestdiena</string> + + <string name="day_of_week_medium_sunday">Sv</string> + <string name="day_of_week_medium_monday">Pr</string> + <string name="day_of_week_medium_tuesday">Ot</string> + <string name="day_of_week_medium_wednesday">Tr</string> + <string name="day_of_week_medium_thursday">Ce</string> + <string name="day_of_week_medium_friday">Pk</string> + <string name="day_of_week_medium_saturday">Se</string> + + <string name="day_of_week_short_sunday">Sv</string> + <string name="day_of_week_short_monday">Pr</string> + <string name="day_of_week_short_tuesday">Ot</string> + <string name="day_of_week_short_wednesday">Tr</string> + <string name="day_of_week_short_thursday">Ce</string> + <string name="day_of_week_short_friday">Pk</string> + <string name="day_of_week_short_saturday">Se</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">O</string> + <string name="day_of_week_shortest_wednesday">T</string> + <string name="day_of_week_shortest_thursday">C</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">vakar</string> + <string name="today">šodien</string> + <string name="tomorrow">rīt</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%Y. gada %-e. %B</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %Y. gada %-e. %b</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y. gada %-e. %b</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-B</string> + <string name="month_year">%Y. g. %B</string> + <string name="abbrev_month_day">%-e. %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y. g. %b</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s.mm–%8$s.mm</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s.mm.%4$s.–%8$s.mm.%9$s.</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.mm.%4$s. – %6$s, %8$s.mm.%9$s.</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.mm.%4$s. - %10$s %6$s, %8$s.mm.%9$s.</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s.mm. - %10$s %8$s.mm.</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s, %3$s</string> + <string name="wday_date">%2$s, %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s. gada %3$s. %2$s - %10$s %9$s. gada %8$s. %7$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s. gada %3$s. %2$s - %10$s %9$s. gada %8$s. %7$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s. g. %3$s. %2$s - %10$s %6$s, %9$s. g. %8$s. %7$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s. g. %3$s. %2$s - %10$s %6$s, %9$s. g. %8$s. %7$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s. g. %3$s. %2$s - %6$s, %9$s. g. %8$s. %7$s</string> + <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string> + <string name="same_year_mdy1_mdy2">%9$s. gada %3$s. %2$s - %8$s. %7$s</string> + <string name="same_month_mdy1_mdy2">%9$s. gada %3$s.-%8$s. %2$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s. gada %3$s. %2$s - %6$s, y. gada %8$s. %7$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E, d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, yyyy. \'g\'. dd. MMM</string> +</resources> diff --git a/core/res/res/values-ro/donottranslate-cldr.xml b/core/res/res/values-ro/donottranslate-cldr.xml new file mode 100644 index 0000000..ef34103 --- /dev/null +++ b/core/res/res/values-ro/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">ianuarie</string> + <string name="month_long_standalone_february">februarie</string> + <string name="month_long_standalone_march">martie</string> + <string name="month_long_standalone_april">aprilie</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">iunie</string> + <string name="month_long_standalone_july">iulie</string> + <string name="month_long_standalone_august">august</string> + <string name="month_long_standalone_september">septembrie</string> + <string name="month_long_standalone_october">octombrie</string> + <string name="month_long_standalone_november">noiembrie</string> + <string name="month_long_standalone_december">decembrie</string> + + <string name="month_long_january">ianuarie</string> + <string name="month_long_february">februarie</string> + <string name="month_long_march">martie</string> + <string name="month_long_april">aprilie</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">iunie</string> + <string name="month_long_july">iulie</string> + <string name="month_long_august">august</string> + <string name="month_long_september">septembrie</string> + <string name="month_long_october">octombrie</string> + <string name="month_long_november">noiembrie</string> + <string name="month_long_december">decembrie</string> + + <string name="month_medium_january">ian.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mar.</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">iun.</string> + <string name="month_medium_july">iul.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">I</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">I</string> + <string name="month_shortest_july">I</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">duminică</string> + <string name="day_of_week_long_monday">luni</string> + <string name="day_of_week_long_tuesday">marți</string> + <string name="day_of_week_long_wednesday">miercuri</string> + <string name="day_of_week_long_thursday">joi</string> + <string name="day_of_week_long_friday">vineri</string> + <string name="day_of_week_long_saturday">sâmbătă</string> + + <string name="day_of_week_medium_sunday">Du</string> + <string name="day_of_week_medium_monday">Lu</string> + <string name="day_of_week_medium_tuesday">Ma</string> + <string name="day_of_week_medium_wednesday">Mi</string> + <string name="day_of_week_medium_thursday">Jo</string> + <string name="day_of_week_medium_friday">Vi</string> + <string name="day_of_week_medium_saturday">Sâ</string> + + <string name="day_of_week_short_sunday">Du</string> + <string name="day_of_week_short_monday">Lu</string> + <string name="day_of_week_short_tuesday">Ma</string> + <string name="day_of_week_short_wednesday">Mi</string> + <string name="day_of_week_short_thursday">Jo</string> + <string name="day_of_week_short_friday">Vi</string> + <string name="day_of_week_short_saturday">Sâ</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">ieri</string> + <string name="today">azi</string> + <string name="tomorrow">mâine</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S, %d.%m.%Y</string> + <string name="date_time">%2$s, %1$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%d.%m.%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s/%2$s/%4$s - %10$s, %6$s, %8$s/%7$s/%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s, %3$s.%2$s - %10$s, %8$s.%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s %2$s - %10$s, %6$s, %8$s %7$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s, %3$s.%2$s.%4$s - %10$s, %8$s.%7$s.%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s, %1$s, %2$s - %6$s, %4$s, %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string> + <string name="date1_time1_date2_time2">%3$s, %2$s - %6$s, %5$s</string> + <string name="time_wday_date">%1$s, %2$s, %3$s</string> + <string name="wday_date">%2$s, %3$s</string> + <string name="time_wday">%1$s, %2$s</string> + <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s, %3$s %2$s - %10$s, %8$s %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s, %3$s %2$s - %10$s, %8$s %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s %2$s - %10$s, %6$s, %8$s %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s %2$s - %10$s, %6$s, %8$s %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s, %3$s %2$s %4$s - %10$s, %8$s %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s, %3$s %2$s %4$s - %10$s, %8$s %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s %2$s %4$s - %10$s, %6$s, %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s %2$s %4$s - %10$s, %6$s, %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s-%8$s %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E, d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d MMM y</string> +</resources> diff --git a/core/res/res/values-sk/donottranslate-cldr.xml b/core/res/res/values-sk/donottranslate-cldr.xml new file mode 100644 index 0000000..b2ed9b7 --- /dev/null +++ b/core/res/res/values-sk/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">január</string> + <string name="month_long_standalone_february">február</string> + <string name="month_long_standalone_march">marec</string> + <string name="month_long_standalone_april">apríl</string> + <string name="month_long_standalone_may">máj</string> + <string name="month_long_standalone_june">jún</string> + <string name="month_long_standalone_july">júl</string> + <string name="month_long_standalone_august">august</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">október</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januára</string> + <string name="month_long_february">februára</string> + <string name="month_long_march">marca</string> + <string name="month_long_april">apríla</string> + <string name="month_long_may">mája</string> + <string name="month_long_june">júna</string> + <string name="month_long_july">júla</string> + <string name="month_long_august">augusta</string> + <string name="month_long_september">septembra</string> + <string name="month_long_october">októbra</string> + <string name="month_long_november">novembra</string> + <string name="month_long_december">decembra</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">máj</string> + <string name="month_medium_june">jún</string> + <string name="month_medium_july">júl</string> + <string name="month_medium_august">aug</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">okt</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dec</string> + + <string name="month_shortest_january">j</string> + <string name="month_shortest_february">f</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">a</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">j</string> + <string name="month_shortest_july">j</string> + <string name="month_shortest_august">a</string> + <string name="month_shortest_september">s</string> + <string name="month_shortest_october">o</string> + <string name="month_shortest_november">n</string> + <string name="month_shortest_december">d</string> + + <string name="day_of_week_long_sunday">nedeľa</string> + <string name="day_of_week_long_monday">pondelok</string> + <string name="day_of_week_long_tuesday">utorok</string> + <string name="day_of_week_long_wednesday">streda</string> + <string name="day_of_week_long_thursday">štvrtok</string> + <string name="day_of_week_long_friday">piatok</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">ne</string> + <string name="day_of_week_medium_monday">po</string> + <string name="day_of_week_medium_tuesday">ut</string> + <string name="day_of_week_medium_wednesday">st</string> + <string name="day_of_week_medium_thursday">št</string> + <string name="day_of_week_medium_friday">pi</string> + <string name="day_of_week_medium_saturday">so</string> + + <string name="day_of_week_short_sunday">ne</string> + <string name="day_of_week_short_monday">po</string> + <string name="day_of_week_short_tuesday">ut</string> + <string name="day_of_week_short_wednesday">st</string> + <string name="day_of_week_short_thursday">št</string> + <string name="day_of_week_short_friday">pi</string> + <string name="day_of_week_short_saturday">so</string> + + <string name="day_of_week_shortest_sunday">N</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">U</string> + <string name="day_of_week_shortest_wednesday">S</string> + <string name="day_of_week_shortest_thursday">Š</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">dopoludnia</string> + <string name="pm">popoludní</string> + <string name="yesterday">Včera</string> + <string name="today">Dnes</string> + <string name="tomorrow">Zajtra</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-e.%-m.%Y</string> + <string name="numeric_date_format">d.M.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e.%-m.%Y</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e. %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string> + <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s, %3$s</string> + <string name="wday_date">%2$s, %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s. - %8$s. %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s. - %8$s. %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E, d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d. MMM y</string> +</resources> diff --git a/core/res/res/values-sl/donottranslate-cldr.xml b/core/res/res/values-sl/donottranslate-cldr.xml new file mode 100644 index 0000000..372b0d5 --- /dev/null +++ b/core/res/res/values-sl/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januar</string> + <string name="month_long_standalone_february">februar</string> + <string name="month_long_standalone_march">marec</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">junij</string> + <string name="month_long_standalone_july">julij</string> + <string name="month_long_standalone_august">avgust</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januar</string> + <string name="month_long_february">februar</string> + <string name="month_long_march">marec</string> + <string name="month_long_april">april</string> + <string name="month_long_may">maj</string> + <string name="month_long_june">junij</string> + <string name="month_long_july">julij</string> + <string name="month_long_august">avgust</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">avg</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">okt</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dec</string> + + <string name="month_shortest_january">j</string> + <string name="month_shortest_february">f</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">a</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">j</string> + <string name="month_shortest_july">j</string> + <string name="month_shortest_august">a</string> + <string name="month_shortest_september">s</string> + <string name="month_shortest_october">o</string> + <string name="month_shortest_november">n</string> + <string name="month_shortest_december">d</string> + + <string name="day_of_week_long_sunday">nedelja</string> + <string name="day_of_week_long_monday">ponedeljek</string> + <string name="day_of_week_long_tuesday">torek</string> + <string name="day_of_week_long_wednesday">sreda</string> + <string name="day_of_week_long_thursday">četrtek</string> + <string name="day_of_week_long_friday">petek</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">ned</string> + <string name="day_of_week_medium_monday">pon</string> + <string name="day_of_week_medium_tuesday">tor</string> + <string name="day_of_week_medium_wednesday">sre</string> + <string name="day_of_week_medium_thursday">čet</string> + <string name="day_of_week_medium_friday">pet</string> + <string name="day_of_week_medium_saturday">sob</string> + + <string name="day_of_week_short_sunday">ned</string> + <string name="day_of_week_short_monday">pon</string> + <string name="day_of_week_short_tuesday">tor</string> + <string name="day_of_week_short_wednesday">sre</string> + <string name="day_of_week_short_thursday">čet</string> + <string name="day_of_week_short_friday">pet</string> + <string name="day_of_week_short_saturday">sob</string> + + <string name="day_of_week_shortest_sunday">n</string> + <string name="day_of_week_shortest_monday">p</string> + <string name="day_of_week_shortest_tuesday">t</string> + <string name="day_of_week_shortest_wednesday">s</string> + <string name="day_of_week_shortest_thursday">č</string> + <string name="day_of_week_shortest_friday">p</string> + <string name="day_of_week_shortest_saturday">s</string> + + <string name="am">dop.</string> + <string name="pm">pop.</string> + <string name="yesterday">Včeraj</string> + <string name="today">Danes</string> + <string name="tomorrow">Jutri</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e. %m. %Y</string> + <string name="numeric_date_format">d. MM. yyyy</string> + <string name="numeric_date_template">"%s. %s. %s"</string> + <string name="month_day_year">%d. %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e. %b. %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e. %b. %Y</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e. %b.</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b. %Y</string> + <string name="time1_time2">%1$s – %2$s</string> + <string name="date1_date2">%2$s – %5$s</string> + <string name="numeric_md1_md2">%3$s. %2$s. – %8$s. %7$s.</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string> + <string name="numeric_mdy1_mdy2">%3$s. %2$s. %4$s – %8$s. %7$s. %9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s. %2$s. – %10$s %8$s. %7$s.</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s., %2$s – %6$s %4$s., %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s., %2$s – %4$s., %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s., %3$s</string> + <string name="wday_date">%2$s., %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s. %2$s – %8$s. %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string> + <string name="same_month_md1_md2">%3$s.–%8$s. %2$s.</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%3$s. %2$s. – %8$s. %7$s. %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s. %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s. %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">E., d. MMM. y</string> +</resources> diff --git a/core/res/res/values-sr/donottranslate-cldr.xml b/core/res/res/values-sr/donottranslate-cldr.xml new file mode 100644 index 0000000..7c5c6a9 --- /dev/null +++ b/core/res/res/values-sr/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">јануар</string> + <string name="month_long_standalone_february">фебруар</string> + <string name="month_long_standalone_march">март</string> + <string name="month_long_standalone_april">април</string> + <string name="month_long_standalone_may">мај</string> + <string name="month_long_standalone_june">јун</string> + <string name="month_long_standalone_july">јул</string> + <string name="month_long_standalone_august">август</string> + <string name="month_long_standalone_september">септембар</string> + <string name="month_long_standalone_october">октобар</string> + <string name="month_long_standalone_november">новембар</string> + <string name="month_long_standalone_december">децембар</string> + + <string name="month_long_january">јануар</string> + <string name="month_long_february">фебруар</string> + <string name="month_long_march">март</string> + <string name="month_long_april">април</string> + <string name="month_long_may">мај</string> + <string name="month_long_june">јун</string> + <string name="month_long_july">јул</string> + <string name="month_long_august">август</string> + <string name="month_long_september">септембар</string> + <string name="month_long_october">октобар</string> + <string name="month_long_november">новембар</string> + <string name="month_long_december">децембар</string> + + <string name="month_medium_january">јан</string> + <string name="month_medium_february">феб</string> + <string name="month_medium_march">мар</string> + <string name="month_medium_april">апр</string> + <string name="month_medium_may">мај</string> + <string name="month_medium_june">јун</string> + <string name="month_medium_july">јул</string> + <string name="month_medium_august">авг</string> + <string name="month_medium_september">сеп</string> + <string name="month_medium_october">окт</string> + <string name="month_medium_november">нов</string> + <string name="month_medium_december">дец</string> + + <string name="month_shortest_january">ј</string> + <string name="month_shortest_february">ф</string> + <string name="month_shortest_march">м</string> + <string name="month_shortest_april">а</string> + <string name="month_shortest_may">м</string> + <string name="month_shortest_june">ј</string> + <string name="month_shortest_july">ј</string> + <string name="month_shortest_august">а</string> + <string name="month_shortest_september">с</string> + <string name="month_shortest_october">о</string> + <string name="month_shortest_november">н</string> + <string name="month_shortest_december">д</string> + + <string name="day_of_week_long_sunday">недеља</string> + <string name="day_of_week_long_monday">понедељак</string> + <string name="day_of_week_long_tuesday">уторак</string> + <string name="day_of_week_long_wednesday">среда</string> + <string name="day_of_week_long_thursday">четвртак</string> + <string name="day_of_week_long_friday">петак</string> + <string name="day_of_week_long_saturday">субота</string> + + <string name="day_of_week_medium_sunday">нед</string> + <string name="day_of_week_medium_monday">пон</string> + <string name="day_of_week_medium_tuesday">уто</string> + <string name="day_of_week_medium_wednesday">сре</string> + <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_shortest_sunday">н</string> + <string name="day_of_week_shortest_monday">п</string> + <string name="day_of_week_shortest_tuesday">у</string> + <string name="day_of_week_shortest_wednesday">с</string> + <string name="day_of_week_shortest_thursday">ч</string> + <string name="day_of_week_shortest_friday">п</string> + <string name="day_of_week_shortest_saturday">с</string> + + <string name="am">пре подне</string> + <string name="pm">поподне</string> + <string name="yesterday">јуче</string> + <string name="today">данас</string> + <string name="tomorrow">сутра</string> + + <string name="hour_minute_24">%H.%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH.mm</string> + <string name="numeric_date">%-e.%-m.%Y.</string> + <string name="numeric_date_format">d.M.yyyy.</string> + <string name="numeric_date_template">"%s.%s.%s."</string> + <string name="month_day_year">%d. %B %Y.</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %d.%m.%Y.</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d.%m.%Y.</string> + <string name="month_day">%B %-e.</string> + <string name="month">%-B</string> + <string name="month_year">%Y %B</string> + <string name="abbrev_month_day">%b %-e.</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b. %Y</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s. - %8$s.%7$s.%9$s.</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s. - %6$s, %8$s.%7$s.%9$s.</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s. %4$s. - %10$s %6$s, %8$s. %7$s. %9$s.</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s. - %10$s %8$s.%7$s.%9$s.</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s, %3$s</string> + <string name="wday_date">%2$s, %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%2$s %3$s. - %7$s %8$s.</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string> + <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s. - %10$s %8$s. %7$s %9$s.</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s. - %10$s %8$s. %7$s %9$s.</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s. - %10$s %6$s, %8$s. %7$s %9$s.</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s. - %10$s %6$s, %8$s. %7$s %9$s.</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s. - %6$s, %8$s. %7$s %9$s.</string> + <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s.</string> + <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s.</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s.</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, d. MMM y.</string> +</resources> diff --git a/core/res/res/values-th/donottranslate-cldr.xml b/core/res/res/values-th/donottranslate-cldr.xml new file mode 100644 index 0000000..4e6bafe --- /dev/null +++ b/core/res/res/values-th/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">มกราคม</string> + <string name="month_long_standalone_february">กุมภาพันธ์</string> + <string name="month_long_standalone_march">มีนาคม</string> + <string name="month_long_standalone_april">เมษายน</string> + <string name="month_long_standalone_may">พฤษภาคม</string> + <string name="month_long_standalone_june">มิถุนายน</string> + <string name="month_long_standalone_july">กรกฎาคม</string> + <string name="month_long_standalone_august">สิงหาคม</string> + <string name="month_long_standalone_september">กันยายน</string> + <string name="month_long_standalone_october">ตุลาคม</string> + <string name="month_long_standalone_november">พฤศจิกายน</string> + <string name="month_long_standalone_december">ธันวาคม</string> + + <string name="month_long_january">มกราคม</string> + <string name="month_long_february">กุมภาพันธ์</string> + <string name="month_long_march">มีนาคม</string> + <string name="month_long_april">เมษายน</string> + <string name="month_long_may">พฤษภาคม</string> + <string name="month_long_june">มิถุนายน</string> + <string name="month_long_july">กรกฎาคม</string> + <string name="month_long_august">สิงหาคม</string> + <string name="month_long_september">กันยายน</string> + <string name="month_long_october">ตุลาคม</string> + <string name="month_long_november">พฤศจิกายน</string> + <string name="month_long_december">ธันวาคม</string> + + <string name="month_medium_january">ม.ค.</string> + <string name="month_medium_february">ก.พ.</string> + <string name="month_medium_march">มี.ค.</string> + <string name="month_medium_april">เม.ย.</string> + <string name="month_medium_may">พ.ค.</string> + <string name="month_medium_june">มิ.ย.</string> + <string name="month_medium_july">ก.ค.</string> + <string name="month_medium_august">ส.ค.</string> + <string name="month_medium_september">ก.ย.</string> + <string name="month_medium_october">ต.ค.</string> + <string name="month_medium_november">พ.ย.</string> + <string name="month_medium_december">ธ.ค.</string> + + <string name="month_shortest_january">ม.ค.</string> + <string name="month_shortest_february">ก.พ.</string> + <string name="month_shortest_march">มี.ค.</string> + <string name="month_shortest_april">เม.ย.</string> + <string name="month_shortest_may">พ.ค.</string> + <string name="month_shortest_june">มิ.ย.</string> + <string name="month_shortest_july">ก.ค.</string> + <string name="month_shortest_august">ส.ค.</string> + <string name="month_shortest_september">ก.ย.</string> + <string name="month_shortest_october">ต.ค.</string> + <string name="month_shortest_november">พ.ย.</string> + <string name="month_shortest_december">ธ.ค.</string> + + <string name="day_of_week_long_sunday">วันอาทิตย์</string> + <string name="day_of_week_long_monday">วันจันทร์</string> + <string name="day_of_week_long_tuesday">วันอังคาร</string> + <string name="day_of_week_long_wednesday">วันพุธ</string> + <string name="day_of_week_long_thursday">วันพฤหัสบดี</string> + <string name="day_of_week_long_friday">วันศุกร์</string> + <string name="day_of_week_long_saturday">วันเสาร์</string> + + <string name="day_of_week_medium_sunday">อา.</string> + <string name="day_of_week_medium_monday">จ.</string> + <string name="day_of_week_medium_tuesday">อ.</string> + <string name="day_of_week_medium_wednesday">พ.</string> + <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_shortest_sunday">อ</string> + <string name="day_of_week_shortest_monday">จ</string> + <string name="day_of_week_shortest_tuesday">อ</string> + <string name="day_of_week_shortest_wednesday">พ</string> + <string name="day_of_week_shortest_thursday">พ</string> + <string name="day_of_week_shortest_friday">ศ</string> + <string name="day_of_week_shortest_saturday">ส</string> + + <string name="am">ก่อนเที่ยง</string> + <string name="pm">หลังเที่ยง</string> + <string name="yesterday">เมื่อวาน</string> + <string name="today">วันนี้</string> + <string name="tomorrow">พรุ่งนี้</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e/%-m/%Y</string> + <string name="numeric_date_format">d/M/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S, %-e %b %Y</string> + <string name="date_time">%2$s, %1$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s – %6$s %8$s/%2$s</string> + <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s – %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s – %6$s %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s %3$s/%2$s/%4$s - %10$s, %6$s %8$s/%7$s/%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s, %3$s/%2$s - %10$s, %8$s/%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s/%2$s - %10$s, %6$s, %8$s/%7$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s, %3$s/%2$s/%4$s - %10$s, %8$s/%7$s/%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s, %1$s %2$s - %6$s, %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s, %2$s - %6$s, %5$s</string> + <string name="time_wday_date">%1$s, %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s, %2$s</string> + <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s, %3$s %2$s - %10$s, %8$s %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s, %3$s %2$s - %10$s, %8$s %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s %3$s %2$s - %10$s, %6$s %8$s %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s %3$s %2$s - %10$s, %6$s %8$s %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s, %3$s %2$s %4$s - %10$s, %8$s %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s, %3$s %2$s %4$s - %10$s, %8$s %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s %3$s %2$s %4$s - %10$s, %6$s %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s %3$s %2$s %4$s - %10$s, %6$s %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s – %8$s %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE d MMM y</string> +</resources> diff --git a/core/res/res/values-tl/donottranslate-cldr.xml b/core/res/res/values-tl/donottranslate-cldr.xml new file mode 100644 index 0000000..e3106c7 --- /dev/null +++ b/core/res/res/values-tl/donottranslate-cldr.xml @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">1</string> + <string name="month_long_standalone_february">2</string> + <string name="month_long_standalone_march">3</string> + <string name="month_long_standalone_april">4</string> + <string name="month_long_standalone_may">5</string> + <string name="month_long_standalone_june">6</string> + <string name="month_long_standalone_july">7</string> + <string name="month_long_standalone_august">8</string> + <string name="month_long_standalone_september">9</string> + <string name="month_long_standalone_october">10</string> + <string name="month_long_standalone_november">11</string> + <string name="month_long_standalone_december">12</string> + + <string name="month_long_january">1</string> + <string name="month_long_february">2</string> + <string name="month_long_march">3</string> + <string name="month_long_april">4</string> + <string name="month_long_may">5</string> + <string name="month_long_june">6</string> + <string name="month_long_july">7</string> + <string name="month_long_august">8</string> + <string name="month_long_september">9</string> + <string name="month_long_october">10</string> + <string name="month_long_november">11</string> + <string name="month_long_december">12</string> + + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">1</string> + <string name="day_of_week_long_monday">2</string> + <string name="day_of_week_long_tuesday">3</string> + <string name="day_of_week_long_wednesday">4</string> + <string name="day_of_week_long_thursday">5</string> + <string name="day_of_week_long_friday">6</string> + <string name="day_of_week_long_saturday">7</string> + + + + <string name="day_of_week_shortest_sunday">1</string> + <string name="day_of_week_shortest_monday">2</string> + <string name="day_of_week_shortest_tuesday">3</string> + <string name="day_of_week_shortest_wednesday">4</string> + <string name="day_of_week_shortest_thursday">5</string> + <string name="day_of_week_shortest_friday">6</string> + <string name="day_of_week_shortest_saturday">7</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y-%m-%d</string> + <string name="numeric_date_format">yyyy-MM-dd</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%Y %B %-e</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %Y %b %-e</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y %b %-e</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%Y %B</string> + <string name="abbrev_month_day">%b %-e</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y %b</string> + <string name="time1_time2">%1$s – %2$s</string> + <string name="date1_date2">%2$s – %5$s</string> + <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string> + <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s %3$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string> + <string name="same_month_md1_md2">%2$s-%3$s – %8$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string> + <string name="same_year_mdy1_mdy2">%9$s-%2$s-%3$s – %7$s-%8$s</string> + <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string> + <string name="short_format_month">%B</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, y MMM d</string> +</resources> diff --git a/core/res/res/values-uk/donottranslate-cldr.xml b/core/res/res/values-uk/donottranslate-cldr.xml new file mode 100644 index 0000000..0a49c20 --- /dev/null +++ b/core/res/res/values-uk/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Січень</string> + <string name="month_long_standalone_february">Лютий</string> + <string name="month_long_standalone_march">Березень</string> + <string name="month_long_standalone_april">Квітень</string> + <string name="month_long_standalone_may">Травень</string> + <string name="month_long_standalone_june">Червень</string> + <string name="month_long_standalone_july">Липень</string> + <string name="month_long_standalone_august">Серпень</string> + <string name="month_long_standalone_september">Вересень</string> + <string name="month_long_standalone_october">Жовтень</string> + <string name="month_long_standalone_november">Листопад</string> + <string name="month_long_standalone_december">Грудень</string> + + <string name="month_long_january">січня</string> + <string name="month_long_february">лютого</string> + <string name="month_long_march">березня</string> + <string name="month_long_april">квітня</string> + <string name="month_long_may">травня</string> + <string name="month_long_june">червня</string> + <string name="month_long_july">липня</string> + <string name="month_long_august">серпня</string> + <string name="month_long_september">вересня</string> + <string name="month_long_october">жовтня</string> + <string name="month_long_november">листопада</string> + <string name="month_long_december">грудня</string> + + <string name="month_medium_january">січ.</string> + <string name="month_medium_february">лют.</string> + <string name="month_medium_march">бер.</string> + <string name="month_medium_april">квіт.</string> + <string name="month_medium_may">трав.</string> + <string name="month_medium_june">черв.</string> + <string name="month_medium_july">лип.</string> + <string name="month_medium_august">серп.</string> + <string name="month_medium_september">вер.</string> + <string name="month_medium_october">жовт.</string> + <string name="month_medium_november">лист.</string> + <string name="month_medium_december">груд.</string> + + <string name="month_shortest_january">С</string> + <string name="month_shortest_february">Л</string> + <string name="month_shortest_march">Б</string> + <string name="month_shortest_april">К</string> + <string name="month_shortest_may">Т</string> + <string name="month_shortest_june">Ч</string> + <string name="month_shortest_july">Л</string> + <string name="month_shortest_august">С</string> + <string name="month_shortest_september">В</string> + <string name="month_shortest_october">Ж</string> + <string name="month_shortest_november">Л</string> + <string name="month_shortest_december">Г</string> + + <string name="day_of_week_long_sunday">Неділя</string> + <string name="day_of_week_long_monday">Понеділок</string> + <string name="day_of_week_long_tuesday">Вівторок</string> + <string name="day_of_week_long_wednesday">Середа</string> + <string name="day_of_week_long_thursday">Четвер</string> + <string name="day_of_week_long_friday">Пʼятниця</string> + <string name="day_of_week_long_saturday">Субота</string> + + <string name="day_of_week_medium_sunday">Нд</string> + <string name="day_of_week_medium_monday">Пн</string> + <string name="day_of_week_medium_tuesday">Вт</string> + <string name="day_of_week_medium_wednesday">Ср</string> + <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_shortest_sunday">Н</string> + <string name="day_of_week_shortest_monday">П</string> + <string name="day_of_week_shortest_tuesday">В</string> + <string name="day_of_week_shortest_wednesday">С</string> + <string name="day_of_week_shortest_thursday">Ч</string> + <string name="day_of_week_shortest_friday">П</string> + <string name="day_of_week_shortest_saturday">С</string> + + <string name="am">дп</string> + <string name="pm">пп</string> + <string name="yesterday">Вчора</string> + <string name="today">Сьогодні</string> + <string name="tomorrow">Завтра</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y р.</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%-B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%-b %Y</string> + <string name="time1_time2">%1$s – %2$s</string> + <string name="date1_date2">%2$s – %5$s</string> + <string name="numeric_md1_md2">%3$s.%2$s – %8$s.%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s – %6$s, %8$s.%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s – %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s – %6$s, %8$s.%7$s.%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s – %10$s %6$s, %8$s.%7$s.%9$s</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s – %10$s %8$s.%7$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s – %10$s %6$s, %8$s.%7$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s – %10$s %8$s.%7$s.%9$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s – %6$s %4$s, %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string> + <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string> + <string name="time_wday_date">%1$s %2$s, %3$s</string> + <string name="wday_date">%2$s, %3$s</string> + <string name="time_wday">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s – %6$s, %8$s %7$s %9$s</string> + <string name="same_month_md1_md2">%3$s–%8$s %2$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string> + <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s – %6$s, %8$s %7$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E, d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d MMM y</string> +</resources> diff --git a/core/res/res/values-vi/donottranslate-cldr.xml b/core/res/res/values-vi/donottranslate-cldr.xml new file mode 100644 index 0000000..30e0887 --- /dev/null +++ b/core/res/res/values-vi/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">tháng một</string> + <string name="month_long_standalone_february">tháng hai</string> + <string name="month_long_standalone_march">tháng ba</string> + <string name="month_long_standalone_april">tháng tư</string> + <string name="month_long_standalone_may">tháng năm</string> + <string name="month_long_standalone_june">tháng sáu</string> + <string name="month_long_standalone_july">tháng bảy</string> + <string name="month_long_standalone_august">tháng tám</string> + <string name="month_long_standalone_september">tháng chín</string> + <string name="month_long_standalone_october">tháng mười</string> + <string name="month_long_standalone_november">tháng mười một</string> + <string name="month_long_standalone_december">tháng mười hai</string> + + <string name="month_long_january">tháng một</string> + <string name="month_long_february">tháng hai</string> + <string name="month_long_march">tháng ba</string> + <string name="month_long_april">tháng tư</string> + <string name="month_long_may">tháng năm</string> + <string name="month_long_june">tháng sáu</string> + <string name="month_long_july">tháng bảy</string> + <string name="month_long_august">tháng tám</string> + <string name="month_long_september">tháng chín</string> + <string name="month_long_october">tháng mười</string> + <string name="month_long_november">tháng mười một</string> + <string name="month_long_december">tháng mười hai</string> + + <string name="month_medium_january">thg 1</string> + <string name="month_medium_february">thg 2</string> + <string name="month_medium_march">thg 3</string> + <string name="month_medium_april">thg 4</string> + <string name="month_medium_may">thg 5</string> + <string name="month_medium_june">thg 6</string> + <string name="month_medium_july">thg 7</string> + <string name="month_medium_august">thg 8</string> + <string name="month_medium_september">thg 9</string> + <string name="month_medium_october">thg 10</string> + <string name="month_medium_november">thg 11</string> + <string name="month_medium_december">thg 12</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">Chủ nhật</string> + <string name="day_of_week_long_monday">Thứ hai</string> + <string name="day_of_week_long_tuesday">Thứ ba</string> + <string name="day_of_week_long_wednesday">Thứ tư</string> + <string name="day_of_week_long_thursday">Thứ năm</string> + <string name="day_of_week_long_friday">Thứ sáu</string> + <string name="day_of_week_long_saturday">Thứ bảy</string> + + <string name="day_of_week_medium_sunday">CN</string> + <string name="day_of_week_medium_monday">Th 2</string> + <string name="day_of_week_medium_tuesday">Th 3</string> + <string name="day_of_week_medium_wednesday">Th 4</string> + <string name="day_of_week_medium_thursday">Th 5</string> + <string name="day_of_week_medium_friday">Th 6</string> + <string name="day_of_week_medium_saturday">Th 7</string> + + <string name="day_of_week_short_sunday">CN</string> + <string name="day_of_week_short_monday">Th 2</string> + <string name="day_of_week_short_tuesday">Th 3</string> + <string name="day_of_week_short_wednesday">Th 4</string> + <string name="day_of_week_short_thursday">Th 5</string> + <string name="day_of_week_short_friday">Th 6</string> + <string name="day_of_week_short_saturday">Th 7</string> + + <string name="day_of_week_shortest_sunday">1</string> + <string name="day_of_week_shortest_monday">2</string> + <string name="day_of_week_shortest_tuesday">3</string> + <string name="day_of_week_shortest_wednesday">4</string> + <string name="day_of_week_shortest_thursday">5</string> + <string name="day_of_week_shortest_friday">6</string> + <string name="day_of_week_shortest_saturday">7</string> + + <string name="am">SA</string> + <string name="pm">CH</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">Ngày %d tháng %-m năm %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%d-%m-%Y %H:%M:%S</string> + <string name="date_time">%1$s %2$s</string> + <string name="time_date">%3$s %1$s</string> + <string name="abbrev_month_day_year">%d-%m-%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">%1$s - %2$s</string> + <string name="date1_date2">%2$s - %5$s</string> + <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string> + <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s/%2$s - %6$s, %8$s/%7$s</string> + <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s/%2$s/%4$s - %6$s, %8$s/%7$s/%9$s</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s-%2$s-%4$s %5$s - %6$s, %8$s-%7$s-%9$s %10$s</string> + <string name="numeric_md1_time1_md2_time2">%3$s-%2$s %5$s - %8$s-%7$s %10$s</string> + <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s-%2$s %5$s - %6$s, %8$s-%7$s %10$s</string> + <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s %5$s - %8$s/%7$s/%9$s %10$s</string> + <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s %3$s - %4$s %5$s %6$s</string> + <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string> + <string name="date1_time1_date2_time2">%2$s %3$s - %5$s %6$s</string> + <string name="time_wday_date">%2$s %3$s %1$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%2$s %1$s</string> + <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string> + <string name="same_year_md1_time1_md2_time2">%3$s %2$s %5$s - %8$s %7$s %10$s</string> + <string name="same_month_md1_time1_md2_time2">%3$s %2$s %5$s - %8$s %7$s %10$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s %5$s - %6$s %8$s %7$s %10$s</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s %5$s - %6$s %8$s %7$s %10$s</string> + <string name="same_year_mdy1_time1_mdy2_time2">Ngày %3$s tháng %2$s năm %4$s %5$s - \'Ngày %8$s tháng %7$s năm %9$s %10$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">Ngày %3$s tháng %2$s năm %4$s %5$s - \'Ngày %8$s tháng %7$s năm %9$s %10$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s %5$s - %6$s, %8$s %7$s %9$s %10$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s %5$s - %6$s, %8$s %7$s %9$s %10$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string> + <string name="same_month_md1_md2">Ngày %3$s tháng %2$s - Ngày %8$s tháng %7$s</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string> + <string name="same_year_mdy1_mdy2">Ngày %3$s tháng %2$s - Ngày %8$s tháng %7$s năm %9$s</string> + <string name="same_month_mdy1_mdy2">Ngày %3$s tháng %2$s - Ngày %8$s tháng M năm %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, ngày %3$s %2$s - %6$s, ngày %8$s %7$s năm %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d MMM y</string> +</resources> diff --git a/core/res/res/values-xlarge/dimens.xml b/core/res/res/values-xlarge/dimens.xml index f52c627..fef3c13 100644 --- a/core/res/res/values-xlarge/dimens.xml +++ b/core/res/res/values-xlarge/dimens.xml @@ -21,6 +21,9 @@ <dimen name="status_bar_height">48dip</dimen> <!-- Height of the status bar --> <dimen name="status_bar_icon_size">48dip</dimen> + <!-- Size of the giant number (unread count) in the notifications --> + <dimen name="status_bar_content_number_size">48sp</dimen> + <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. --> <!-- Margin for permanent screen decorations at the bottom. --> <dimen name="screen_margin_bottom">48dip</dimen> diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index 3e546a1..04c6538 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -67,7 +67,6 @@ <item>@drawable/text_select_handle_middle</item> <item>@drawable/text_select_handle_right</item> <item>@drawable/title_bar</item> - <item>@drawable/title_bar_shadow</item> <!-- Visual lock screen --> <item>@drawable/indicator_code_lock_drag_direction_green_up</item> <item>@drawable/indicator_code_lock_drag_direction_red_up</item> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index e319fa0..f4d1df8 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1449,8 +1449,99 @@ <public type="style" name="Theme.Holo.DialogWhenLarge" /> <public type="style" name="Theme.Holo.Light.DialogWhenLarge" /> - <public type="string" name="selectTextMode" /> - <public type="style" name="Theme.Holo.Wallpaper" /> <public type="style" name="Theme.Holo.Wallpaper.NoTitleBar" /> + + <public type="style" name="Widget.ActionBar" /> + + <public type="style" name="Widget.Holo" /> + <public type="style" name="Widget.Holo.Button" /> + <public type="style" name="Widget.Holo.Button.Small" /> + <public type="style" name="Widget.Holo.Button.Inset" /> + <public type="style" name="Widget.Holo.Button.Toggle" /> + <public type="style" name="Widget.Holo.TextView" /> + <public type="style" name="Widget.Holo.AutoCompleteTextView" /> + <public type="style" name="Widget.Holo.CompoundButton.CheckBox" /> + <public type="style" name="Widget.Holo.ListView.DropDown" /> + <public type="style" name="Widget.Holo.EditText" /> + <public type="style" name="Widget.Holo.ExpandableListView" /> + <public type="style" name="Widget.Holo.GridView" /> + <public type="style" name="Widget.Holo.ImageButton" /> + <public type="style" name="Widget.Holo.ListView" /> + <public type="style" name="Widget.Holo.PopupWindow" /> + <public type="style" name="Widget.Holo.ProgressBar" /> + <public type="style" name="Widget.Holo.ProgressBar.Horizontal" /> + <public type="style" name="Widget.Holo.ProgressBar.Small" /> + <public type="style" name="Widget.Holo.ProgressBar.Small.Title" /> + <public type="style" name="Widget.Holo.ProgressBar.Large" /> + <public type="style" name="Widget.Holo.SeekBar" /> + <public type="style" name="Widget.Holo.RatingBar" /> + <public type="style" name="Widget.Holo.RatingBar.Indicator" /> + <public type="style" name="Widget.Holo.RatingBar.Small" /> + <public type="style" name="Widget.Holo.CompoundButton.RadioButton" /> + <public type="style" name="Widget.Holo.ScrollView" /> + <public type="style" name="Widget.Holo.HorizontalScrollView" /> + <public type="style" name="Widget.Holo.Spinner" /> + <public type="style" name="Widget.Holo.CompoundButton.Star" /> + <public type="style" name="Widget.Holo.TabWidget" /> + <public type="style" name="Widget.Holo.WebTextView" /> + <public type="style" name="Widget.Holo.WebView" /> + <public type="style" name="Widget.Holo.DropDownItem" /> + <public type="style" name="Widget.Holo.DropDownItem.Spinner" /> + <public type="style" name="Widget.Holo.TextView.SpinnerItem" /> + <public type="style" name="Widget.Holo.ListPopupWindow" /> + <public type="style" name="Widget.Holo.PopupMenu" /> + <public type="style" name="Widget.Holo.ActionButton" /> + <public type="style" name="Widget.Holo.ActionButton.Overflow" /> + <public type="style" name="Widget.Holo.ActionButton.TextButton" /> + <public type="style" name="Widget.Holo.ActionMode" /> + <public type="style" name="Widget.Holo.ActionButton.CloseMode" /> + <public type="style" name="Widget.Holo.ActionBar" /> + <public type="style" name="Widget.Holo.Light" /> + <public type="style" name="Widget.Holo.Light.Button" /> + <public type="style" name="Widget.Holo.Light.Button.Small" /> + <public type="style" name="Widget.Holo.Light.Button.Inset" /> + <public type="style" name="Widget.Holo.Light.Button.Toggle" /> + <public type="style" name="Widget.Holo.Light.TextView" /> + <public type="style" name="Widget.Holo.Light.AutoCompleteTextView" /> + <public type="style" name="Widget.Holo.Light.CompoundButton.CheckBox" /> + <public type="style" name="Widget.Holo.Light.ListView.DropDown" /> + <public type="style" name="Widget.Holo.Light.EditText" /> + <public type="style" name="Widget.Holo.Light.ExpandableListView" /> + <public type="style" name="Widget.Holo.Light.GridView" /> + <public type="style" name="Widget.Holo.Light.ImageButton" /> + <public type="style" name="Widget.Holo.Light.ListView" /> + <public type="style" name="Widget.Holo.Light.PopupWindow" /> + <public type="style" name="Widget.Holo.Light.ProgressBar" /> + <public type="style" name="Widget.Holo.Light.ProgressBar.Horizontal" /> + <public type="style" name="Widget.Holo.Light.ProgressBar.Small" /> + <public type="style" name="Widget.Holo.Light.ProgressBar.Small.Title" /> + <public type="style" name="Widget.Holo.Light.ProgressBar.Large" /> + <public type="style" name="Widget.Holo.Light.ProgressBar.Inverse" /> + <public type="style" name="Widget.Holo.Light.ProgressBar.Small.Inverse" /> + <public type="style" name="Widget.Holo.Light.ProgressBar.Large.Inverse" /> + <public type="style" name="Widget.Holo.Light.SeekBar" /> + <public type="style" name="Widget.Holo.Light.RatingBar" /> + <public type="style" name="Widget.Holo.Light.RatingBar.Indicator" /> + <public type="style" name="Widget.Holo.Light.RatingBar.Small" /> + <public type="style" name="Widget.Holo.Light.CompoundButton.RadioButton" /> + <public type="style" name="Widget.Holo.Light.ScrollView" /> + <public type="style" name="Widget.Holo.Light.HorizontalScrollView" /> + <public type="style" name="Widget.Holo.Light.Spinner" /> + <public type="style" name="Widget.Holo.Light.CompoundButton.Star" /> + <public type="style" name="Widget.Holo.Light.TabWidget" /> + <public type="style" name="Widget.Holo.Light.WebTextView" /> + <public type="style" name="Widget.Holo.Light.WebView" /> + <public type="style" name="Widget.Holo.Light.DropDownItem" /> + <public type="style" name="Widget.Holo.Light.DropDownItem.Spinner" /> + <public type="style" name="Widget.Holo.Light.TextView.SpinnerItem" /> + <public type="style" name="Widget.Holo.Light.ListPopupWindow" /> + <public type="style" name="Widget.Holo.Light.PopupMenu" /> + <public type="style" name="Widget.Holo.Light.ActionButton" /> + <public type="style" name="Widget.Holo.Light.ActionButton.Overflow" /> + <public type="style" name="Widget.Holo.Light.ActionMode" /> + <public type="style" name="Widget.Holo.Light.ActionButton.CloseMode" /> + <public type="style" name="Widget.Holo.Light.ActionBar" /> + + <public type="string" name="selectTextMode" /> </resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 403ec2f..4aa16f9 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -213,12 +213,17 @@ <item name="android:textStyle">bold</item> </style> <style name="TextAppearance.StatusBar.EventContent"> + <item name="android:textAppearance">?android:attr/textAppearanceSmall</item> <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> </style> <style name="TextAppearance.StatusBar.EventContent.Title"> <item name="android:textSize">18sp</item> <item name="android:textStyle">bold</item> </style> + <style name="TextAppearance.StatusBar.EventContent.Info"> + <item name="android:textAppearance">?android:attr/textAppearanceLarge</item> + <item name="android:textColor">#ff272727</item> + </style> <!-- Widget Styles --> @@ -1803,7 +1808,7 @@ <item name="android:background">@null</item> <item name="android:homeAsUpIndicator">@android:drawable/ic_ab_back_holo_light</item> <item name="android:progressBarStyle">@android:style/Widget.Holo.Light.ProgressBar.Horizontal</item> - <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.Light.ProgressBar.Small</item> + <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.Light.ProgressBar</item> </style> <!-- Animation Styles --> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index f5dca47..9215bf2 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -130,7 +130,7 @@ <item name="windowNoTitle">false</item> <item name="windowFullscreen">false</item> <item name="windowIsFloating">false</item> - <item name="windowContentOverlay">@android:drawable/title_bar_shadow</item> + <item name="windowContentOverlay">@null</item> <item name="windowShowWallpaper">false</item> <item name="windowTitleStyle">@android:style/WindowTitle</item> <item name="windowTitleSize">25dip</item> diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml index d298d40..b116bea 100644 --- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml +++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml @@ -53,6 +53,15 @@ android.label="Test runner for unit tests" /> + <!-- run stress test suite: + "adb shell am instrument -e stressnum <200> -w + com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner" + --> + <instrumentation android:name=".ConnectivityManagerStressTestRunner" + android:targetPackage="com.android.connectivitymanagertest" + android:label="Test runner for Connectivity Manager Stress Tests" + /> + <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java new file mode 100644 index 0000000..47f208a --- /dev/null +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2010, 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.connectivitymanagertest; + +import android.os.Bundle; +import android.test.InstrumentationTestRunner; +import android.test.InstrumentationTestSuite; +import android.util.Log; +import com.android.connectivitymanagertest.stress.WifiApStress; + +import junit.framework.TestSuite; + +/** + * Instrumentation Test Runner for all stress tests + * + * To run the stress tests: + * + * adb shell am instrument -e stressnum <stress times> \ + * -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner + */ + +public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunner { + @Override + public TestSuite getAllTests() { + TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(WifiApStress.class); + return suite; + } + + @Override + public ClassLoader getLoader() { + return ConnectivityManagerTestRunner.class.getClassLoader(); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + String stressValue = (String) icicle.get("stressnum"); + if (stressValue != null) { + int iteration = Integer.parseInt(stressValue); + if (iteration > 0) { + numStress = iteration; + } + } + } + + public int numStress = 100; +} diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java index 7c46e7a..37b9f52 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java @@ -55,6 +55,9 @@ public class ConnectivityManagerTestActivity extends Activity { public static final int WIFI_SCAN_TIMEOUT = 20 * 1000; public static final int SHORT_TIMEOUT = 5 * 1000; public static final long LONG_TIMEOUT = 50 * 1000; + public static final int SUCCESS = 0; // for Wifi tethering state change + public static final int FAILURE = 1; + public static final int INIT = -1; private static final String ACCESS_POINT_FILE = "accesspoints.xml"; public ConnectivityReceiver mConnectivityReceiver = null; public WifiReceiver mWifiReceiver = null; @@ -87,6 +90,10 @@ public class ConnectivityManagerTestActivity extends Activity { public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1; NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES]; + // For wifi tethering tests + private String[] mWifiRegexs; + public int mWifiTetherResult = INIT; // -1 is initialization state + /** * A wrapper of a broadcast receiver which provides network connectivity information * for all kinds of network: wifi, mobile, etc. @@ -150,6 +157,16 @@ public class ConnectivityManagerTestActivity extends Activity { mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN); notifyWifiState(); + } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { + notifyWifiAPState(); + } else if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) { + ArrayList<String> available = intent.getStringArrayListExtra( + ConnectivityManager.EXTRA_AVAILABLE_TETHER); + ArrayList<String> active = intent.getStringArrayListExtra( + ConnectivityManager.EXTRA_ACTIVE_TETHER); + ArrayList<String> errored = intent.getStringArrayListExtra( + ConnectivityManager.EXTRA_ERRORED_TETHER); + updateTetherState(available.toArray(), active.toArray(), errored.toArray()); } else { return; @@ -184,6 +201,8 @@ public class ConnectivityManagerTestActivity extends Activity { mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); + mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); + mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); registerReceiver(mWifiReceiver, mIntentFilter); // Get an instance of ConnectivityManager @@ -196,6 +215,7 @@ public class ConnectivityManagerTestActivity extends Activity { Log.v(LOG_TAG, "Clear Wifi before we start the test."); removeConfiguredNetworksAndDisableWifi(); } + mWifiRegexs = mCM.getTetherableWifiRegexs(); } public List<WifiConfiguration> loadNetworkConfigurations() throws Exception { @@ -263,13 +283,57 @@ public class ConnectivityManagerTestActivity extends Activity { } } - public void notifyWifiState() { + private void notifyWifiState() { synchronized (wifiObject) { Log.v(LOG_TAG, "notify wifi state changed"); wifiObject.notify(); } } + private void notifyWifiAPState() { + synchronized (this) { + Log.v(LOG_TAG, "notify wifi AP state changed"); + this.notify(); + } + } + + // Update wifi tethering state + private void updateTetherState(Object[] available, Object[] tethered, Object[] errored) { + boolean wifiTethered = false; + boolean wifiErrored = false; + + synchronized (this) { + for (Object obj: tethered) { + String str = (String)obj; + for (String tethRex: mWifiRegexs) { + Log.v(LOG_TAG, "str: " + str +"tethRex: " + tethRex); + if (str.matches(tethRex)) { + wifiTethered = true; + } + } + } + + for (Object obj: errored) { + String str = (String)obj; + for (String tethRex: mWifiRegexs) { + Log.v(LOG_TAG, "error: str: " + str +"tethRex: " + tethRex); + if (str.matches(tethRex)) { + wifiErrored = true; + } + } + } + + if (wifiTethered) { + mWifiTetherResult = SUCCESS; // wifi tethering is successful + } else if (wifiErrored) { + mWifiTetherResult = FAILURE; // wifi tethering failed + } + Log.v(LOG_TAG, "mWifiTetherResult: " + mWifiTetherResult); + this.notify(); + } + } + + // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED, // DISCONNECTING, DISCONNECTED, UNKNOWN public boolean waitForNetworkState(int networkType, State expectedState, long timeout) { @@ -332,6 +396,62 @@ public class ConnectivityManagerTestActivity extends Activity { } } + // Wait for Wifi AP state: WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, + // WIFI_AP_STATE_ENABLED, WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN + public boolean waitForWifiAPState(int expectedState, long timeout) { + long startTime = System.currentTimeMillis(); + while (true) { + if ((System.currentTimeMillis() - startTime) > timeout) { + if (mWifiManager.getWifiApState() != expectedState) { + return false; + } else { + return true; + } + } + Log.v(LOG_TAG, "Wait for wifi AP state to be: " + expectedState); + synchronized (wifiObject) { + try { + wifiObject.wait(SHORT_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (mWifiManager.getWifiApState() != expectedState) { + Log.v(LOG_TAG, "Wifi state is: " + mWifiManager.getWifiApState()); + continue; + } + return true; + } + } + } + + /** + * Wait for the wifi tethering result: + * @param timeout is the maximum waiting time + * @return SUCCESS if tethering result is successful + * FAILURE if tethering result returns error. + */ + public int waitForTetherStateChange(long timeout) { + long startTime = System.currentTimeMillis(); + while (true) { + if ((System.currentTimeMillis() - startTime) > timeout) { + return mWifiTetherResult; + } + Log.v(LOG_TAG, "Wait for wifi tethering result."); + synchronized (this) { + try { + this.wait(SHORT_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (mWifiTetherResult == INIT ) { + continue; + } else { + return mWifiTetherResult; + } + } + } + } + // Return true if device is currently connected to mobile network public boolean isConnectedToMobile() { return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE); diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java new file mode 100644 index 0000000..cc53ddc --- /dev/null +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010, 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.connectivitymanagertest.stress; + + +import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner; +import com.android.connectivitymanagertest.ConnectivityManagerTestActivity; +import com.android.connectivitymanagertest.ConnectivityManagerTestRunner; + +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; + +/** + * Stress the wifi driver as access point. + */ +public class WifiApStress + extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> { + private final static String TAG = "WifiApStress"; + private ConnectivityManagerTestActivity mAct; + private static String NETWORK_ID = "AndroidAPTest"; + private static String PASSWD = "androidwifi"; + private int max_num; + + public WifiApStress() { + super(ConnectivityManagerTestActivity.class); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + mAct = getActivity(); + max_num = ((ConnectivityManagerStressTestRunner)getInstrumentation()).numStress; + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + @LargeTest + public void testWifiHotSpot() { + WifiConfiguration config = new WifiConfiguration(); + config.SSID = NETWORK_ID; + config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); + config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); + config.preSharedKey = PASSWD; + + // If Wifi is enabled, disable it + if (mAct.mWifiManager.isWifiEnabled()) { + mAct.disableWifi(); + } + for (int i = 0; i < max_num; i++) { + Log.v(TAG, "iteration: " + i); + // enable Wifi tethering + assertTrue(mAct.mWifiManager.setWifiApEnabled(config, true)); + // Wait for wifi ap state to be ENABLED + assertTrue(mAct.waitForWifiAPState(mAct.mWifiManager.WIFI_AP_STATE_ENABLED, + mAct.LONG_TIMEOUT)); + // Wait for wifi tethering result + assertEquals(mAct.SUCCESS, mAct.waitForTetherStateChange(2*mAct.SHORT_TIMEOUT)); + // Allow the wifi tethering to be enabled for 10 seconds + try { + Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT); + } catch (Exception e) { + fail("thread in sleep is interrupted"); + } + assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false)); + } + } + +} diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java index ced9310..216a772 100644 --- a/core/tests/coretests/src/android/util/JsonReaderTest.java +++ b/core/tests/coretests/src/android/util/JsonReaderTest.java @@ -16,6 +16,7 @@ package android.util; +import java.util.Arrays; import junit.framework.TestCase; import java.io.IOException; @@ -23,6 +24,8 @@ import java.io.StringReader; public final class JsonReaderTest extends TestCase { + private static final int READER_BUFFER_SIZE = 1024; + public void testReadArray() throws IOException { JsonReader reader = new JsonReader(new StringReader("[true, true]")); reader.beginArray(); @@ -178,7 +181,13 @@ public final class JsonReaderTest extends TestCase { + "-0.5," + "2.2250738585072014E-308," + "3.141592653589793," - + "2.718281828459045]"; + + "2.718281828459045," + + "\"1.0\"," + + "\"011.0\"," + + "\"NaN\"," + + "\"Infinity\"," + + "\"-Infinity\"" + + "]"; JsonReader reader = new JsonReader(new StringReader(json)); reader.beginArray(); assertEquals(-0.0, reader.nextDouble()); @@ -190,19 +199,98 @@ public final class JsonReaderTest extends TestCase { assertEquals(2.2250738585072014E-308, reader.nextDouble()); assertEquals(3.141592653589793, reader.nextDouble()); assertEquals(2.718281828459045, reader.nextDouble()); + assertEquals(1,0, reader.nextDouble()); + assertEquals(11.0, reader.nextDouble()); + assertTrue(Double.isNaN(reader.nextDouble())); + assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble()); + assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } - public void testNonFiniteDoubles() throws IOException { - String json = "[NaN]"; + public void testLenientDoubles() throws IOException { + String json = "[" + + "011.0," + + "NaN," + + "NAN," + + "Infinity," + + "INFINITY," + + "-Infinity" + + "]"; JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); reader.beginArray(); + assertEquals(11.0, reader.nextDouble()); + assertTrue(Double.isNaN(reader.nextDouble())); + try { + reader.nextDouble(); + fail(); + } catch (NumberFormatException expected) { + } + assertEquals("NAN", reader.nextString()); + assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble()); try { reader.nextDouble(); fail(); } catch (NumberFormatException expected) { } + assertEquals("INFINITY", reader.nextString()); + assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble()); + reader.endArray(); + assertEquals(JsonToken.END_DOCUMENT, reader.peek()); + } + + public void testBufferBoundary() throws IOException { + char[] pad = new char[READER_BUFFER_SIZE - 8]; + Arrays.fill(pad, '5'); + String json = "[\"" + new String(pad) + "\",33333]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + assertEquals(JsonToken.STRING, reader.peek()); + assertEquals(new String(pad), reader.nextString()); + assertEquals(JsonToken.NUMBER, reader.peek()); + assertEquals(33333, reader.nextInt()); + } + + public void testTruncatedBufferBoundary() throws IOException { + char[] pad = new char[READER_BUFFER_SIZE - 8]; + Arrays.fill(pad, '5'); + String json = "[\"" + new String(pad) + "\",33333"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); + reader.beginArray(); + assertEquals(JsonToken.STRING, reader.peek()); + assertEquals(new String(pad), reader.nextString()); + assertEquals(JsonToken.NUMBER, reader.peek()); + assertEquals(33333, reader.nextInt()); + try { + reader.endArray(); + fail(); + } catch (IOException e) { + } + } + + public void testLongestSupportedNumericLiterals() throws IOException { + testLongNumericLiterals(READER_BUFFER_SIZE - 1, JsonToken.NUMBER); + } + + public void testLongerNumericLiterals() throws IOException { + testLongNumericLiterals(READER_BUFFER_SIZE, JsonToken.STRING); + } + + private void testLongNumericLiterals(int length, JsonToken expectedToken) throws IOException { + char[] longNumber = new char[length]; + Arrays.fill(longNumber, '9'); + longNumber[0] = '1'; + longNumber[1] = '.'; + + String json = "[" + new String(longNumber) + "]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); + reader.beginArray(); + assertEquals(expectedToken, reader.peek()); + assertEquals(2.0d, reader.nextDouble()); + reader.endArray(); } public void testLongs() throws IOException { @@ -210,7 +298,13 @@ public final class JsonReaderTest extends TestCase { + "1,1,1," + "-1,-1,-1," + "-9223372036854775808," - + "9223372036854775807]"; + + "9223372036854775807," + + "5.0," + + "1.0e2," + + "\"011\"," + + "\"5.0\"," + + "\"1.0e2\"" + + "]"; JsonReader reader = new JsonReader(new StringReader(json)); reader.beginArray(); assertEquals(0L, reader.nextLong()); @@ -234,6 +328,11 @@ public final class JsonReaderTest extends TestCase { } catch (NumberFormatException expected) { } assertEquals(Long.MAX_VALUE, reader.nextLong()); + assertEquals(5, reader.nextLong()); + assertEquals(100, reader.nextLong()); + assertEquals(11, reader.nextLong()); + assertEquals(5, reader.nextLong()); + assertEquals(100, reader.nextLong()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } @@ -250,28 +349,60 @@ public final class JsonReaderTest extends TestCase { reader.endArray(); } - public void testNumberWithOctalPrefix() throws IOException { - String json = "[01]"; + public void testMatchingValidNumbers() throws IOException { + String json = "[-1,99,-0,0,0e1,0e+1,0e-1,0E1,0E+1,0E-1,0.0,1.0,-1.0,1.0e0,1.0e+1,1.0e-1]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + for (int i = 0; i < 16; i++) { + assertEquals(JsonToken.NUMBER, reader.peek()); + reader.nextDouble(); + } + reader.endArray(); + } + + public void testRecognizingInvalidNumbers() throws IOException { + String json = "[-00,00,001,+1,1f,0x,0xf,0x0,0f1,0ee1,1..0,1e0.1,1.-01,1.+1,1.0x,1.0+]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); + reader.beginArray(); + for (int i = 0; i < 16; i++) { + assertEquals(JsonToken.STRING, reader.peek()); + reader.nextString(); + } + reader.endArray(); + } + + public void testNonFiniteDouble() throws IOException { + String json = "[NaN]"; JsonReader reader = new JsonReader(new StringReader(json)); reader.beginArray(); try { - reader.nextInt(); + reader.nextDouble(); fail(); - } catch (NumberFormatException expected) { + } catch (IOException expected) { } + } + + public void testNumberWithHexPrefix() throws IOException { + String json = "[0x11]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); try { reader.nextLong(); fail(); - } catch (NumberFormatException expected) { + } catch (IOException expected) { } + } + + public void testNumberWithOctalPrefix() throws IOException { + String json = "[01]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); try { - reader.nextDouble(); + reader.nextInt(); fail(); - } catch (NumberFormatException expected) { + } catch (IOException expected) { } - assertEquals("01", reader.nextString()); - reader.endArray(); - assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testBooleans() throws IOException { diff --git a/data/sounds/AudioPackage5.mk b/data/sounds/AudioPackage5.mk new file mode 100755 index 0000000..550f990 --- /dev/null +++ b/data/sounds/AudioPackage5.mk @@ -0,0 +1,72 @@ +# +# Audio Package 5 - Crespo/Soju +# +# Include this file in a product makefile to include these audio files +# +# + +LOCAL_PATH:= frameworks/base/data/sounds + +PRODUCT_COPY_FILES += \ + $(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)/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)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \ + $(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \ + $(LOCAL_PATH)/effects/Undock.ogg:system/media/audio/ui/Undock.ogg \ + $(LOCAL_PATH)/effects/Lock.ogg:system/media/audio/ui/Lock.ogg \ + $(LOCAL_PATH)/effects/Unlock.ogg:system/media/audio/ui/Unlock.ogg \ + $(LOCAL_PATH)/notifications/Aldebaran.ogg:system/media/audio/notifications/Aldebaran.ogg \ + $(LOCAL_PATH)/notifications/Altair.ogg:system/media/audio/notifications/Altair.ogg \ + $(LOCAL_PATH)/notifications/Antares.ogg:system/media/audio/notifications/Antares.ogg \ + $(LOCAL_PATH)/notifications/arcturus.ogg:system/media/audio/notifications/arcturus.ogg \ + $(LOCAL_PATH)/notifications/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \ + $(LOCAL_PATH)/notifications/Canopus.ogg:system/media/audio/notifications/Canopus.ogg \ + $(LOCAL_PATH)/notifications/Capella.ogg:system/media/audio/notifications/Capella.ogg \ + $(LOCAL_PATH)/notifications/Castor.ogg:system/media/audio/notifications/Castor.ogg \ + $(LOCAL_PATH)/notifications/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \ + $(LOCAL_PATH)/notifications/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \ + $(LOCAL_PATH)/notifications/Electra.ogg:system/media/audio/notifications/Electra.ogg \ + $(LOCAL_PATH)/notifications/Fomalhaut.ogg:system/media/audio/notifications/Fomalhaut.ogg \ + $(LOCAL_PATH)/notifications/Merope.ogg:system/media/audio/notifications/Merope.ogg \ + $(LOCAL_PATH)/notifications/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \ + $(LOCAL_PATH)/notifications/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \ + $(LOCAL_PATH)/notifications/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \ + $(LOCAL_PATH)/notifications/regulus.ogg:system/media/audio/notifications/regulus.ogg \ + $(LOCAL_PATH)/notifications/sirius.ogg:system/media/audio/notifications/sirius.ogg \ + $(LOCAL_PATH)/notifications/Sirrah.ogg:system/media/audio/notifications/Sirrah.ogg \ + $(LOCAL_PATH)/notifications/vega.ogg:system/media/audio/notifications/vega.ogg \ + $(LOCAL_PATH)/ringtones/ANDROMEDA.ogg:system/media/audio/ringtones/ANDROMEDA.ogg \ + $(LOCAL_PATH)/ringtones/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \ + $(LOCAL_PATH)/ringtones/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \ + $(LOCAL_PATH)/ringtones/BOOTES.ogg:system/media/audio/ringtones/BOOTES.ogg \ + $(LOCAL_PATH)/ringtones/CANISMAJOR.ogg:system/media/audio/ringtones/CANISMAJOR.ogg \ + $(LOCAL_PATH)/ringtones/Carina.ogg:system/media/audio/ringtones/Carina.ogg \ + $(LOCAL_PATH)/ringtones/CASSIOPEIA.ogg:system/media/audio/ringtones/CASSIOPEIA.ogg \ + $(LOCAL_PATH)/ringtones/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \ + $(LOCAL_PATH)/ringtones/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \ + $(LOCAL_PATH)/ringtones/Draco.ogg:system/media/audio/ringtones/Draco.ogg \ + $(LOCAL_PATH)/ringtones/Eridani.ogg:system/media/audio/ringtones/Eridani.ogg \ + $(LOCAL_PATH)/ringtones/hydra.ogg:system/media/audio/ringtones/hydra.ogg \ + $(LOCAL_PATH)/ringtones/Lyra.ogg:system/media/audio/ringtones/Lyra.ogg \ + $(LOCAL_PATH)/ringtones/Machina.ogg:system/media/audio/ringtones/Machina.ogg \ + $(LOCAL_PATH)/ringtones/Orion.ogg:system/media/audio/ringtones/Orion.ogg \ + $(LOCAL_PATH)/ringtones/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \ + $(LOCAL_PATH)/ringtones/PERSEUS.ogg:system/media/audio/ringtones/PERSEUS.ogg \ + $(LOCAL_PATH)/ringtones/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \ + $(LOCAL_PATH)/ringtones/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \ + $(LOCAL_PATH)/ringtones/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \ + $(LOCAL_PATH)/ringtones/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \ + $(LOCAL_PATH)/ringtones/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \ + $(LOCAL_PATH)/ringtones/Testudo.ogg:system/media/audio/ringtones/Testudo.ogg \ + $(LOCAL_PATH)/ringtones/URSAMINOR.ogg:system/media/audio/ringtones/URSAMINOR.ogg \ + $(LOCAL_PATH)/ringtones/Vespa.ogg:system/media/audio/ringtones/Vespa.ogg diff --git a/data/sounds/notifications/Aldebaran.ogg b/data/sounds/notifications/Aldebaran.ogg Binary files differnew file mode 100755 index 0000000..fe30137 --- /dev/null +++ b/data/sounds/notifications/Aldebaran.ogg diff --git a/data/sounds/notifications/Altair.ogg b/data/sounds/notifications/Altair.ogg Binary files differnew file mode 100644 index 0000000..660c800 --- /dev/null +++ b/data/sounds/notifications/Altair.ogg diff --git a/data/sounds/notifications/Antares.ogg b/data/sounds/notifications/Antares.ogg Binary files differnew file mode 100755 index 0000000..f4f94d7 --- /dev/null +++ b/data/sounds/notifications/Antares.ogg diff --git a/data/sounds/notifications/Betelgeuse.ogg b/data/sounds/notifications/Betelgeuse.ogg Binary files differnew file mode 100755 index 0000000..7145a16 --- /dev/null +++ b/data/sounds/notifications/Betelgeuse.ogg diff --git a/data/sounds/notifications/Canopus.ogg b/data/sounds/notifications/Canopus.ogg Binary files differnew file mode 100755 index 0000000..0d55925 --- /dev/null +++ b/data/sounds/notifications/Canopus.ogg diff --git a/data/sounds/notifications/Capella.ogg b/data/sounds/notifications/Capella.ogg Binary files differnew file mode 100644 index 0000000..ae4f3c5 --- /dev/null +++ b/data/sounds/notifications/Capella.ogg diff --git a/data/sounds/notifications/Castor.ogg b/data/sounds/notifications/Castor.ogg Binary files differnew file mode 100644 index 0000000..92de8e7 --- /dev/null +++ b/data/sounds/notifications/Castor.ogg diff --git a/data/sounds/notifications/CetiAlpha.ogg b/data/sounds/notifications/CetiAlpha.ogg Binary files differnew file mode 100755 index 0000000..cd09526 --- /dev/null +++ b/data/sounds/notifications/CetiAlpha.ogg diff --git a/data/sounds/notifications/CetiAlpha.wav b/data/sounds/notifications/CetiAlpha.wav Binary files differnew file mode 100755 index 0000000..d209645 --- /dev/null +++ b/data/sounds/notifications/CetiAlpha.wav diff --git a/data/sounds/notifications/Deneb.ogg b/data/sounds/notifications/Deneb.ogg Binary files differnew file mode 100644 index 0000000..3b17e28 --- /dev/null +++ b/data/sounds/notifications/Deneb.ogg diff --git a/data/sounds/notifications/Electra.ogg b/data/sounds/notifications/Electra.ogg Binary files differnew file mode 100644 index 0000000..9335d8d --- /dev/null +++ b/data/sounds/notifications/Electra.ogg diff --git a/data/sounds/notifications/Fomalhaut.ogg b/data/sounds/notifications/Fomalhaut.ogg Binary files differnew file mode 100644 index 0000000..9448c18 --- /dev/null +++ b/data/sounds/notifications/Fomalhaut.ogg diff --git a/data/sounds/notifications/Merope.ogg b/data/sounds/notifications/Merope.ogg Binary files differnew file mode 100755 index 0000000..fb18c73 --- /dev/null +++ b/data/sounds/notifications/Merope.ogg diff --git a/data/sounds/notifications/Polaris.ogg b/data/sounds/notifications/Polaris.ogg Binary files differnew file mode 100644 index 0000000..d5b991f --- /dev/null +++ b/data/sounds/notifications/Polaris.ogg diff --git a/data/sounds/notifications/Pollux.ogg b/data/sounds/notifications/Pollux.ogg Binary files differnew file mode 100644 index 0000000..d37c75c --- /dev/null +++ b/data/sounds/notifications/Pollux.ogg diff --git a/data/sounds/notifications/Procyon.ogg b/data/sounds/notifications/Procyon.ogg Binary files differnew file mode 100644 index 0000000..93d1557 --- /dev/null +++ b/data/sounds/notifications/Procyon.ogg diff --git a/data/sounds/notifications/Sirrah.ogg b/data/sounds/notifications/Sirrah.ogg Binary files differnew file mode 100755 index 0000000..ee79e49 --- /dev/null +++ b/data/sounds/notifications/Sirrah.ogg diff --git a/data/sounds/notifications/arcturus.ogg b/data/sounds/notifications/arcturus.ogg Binary files differnew file mode 100644 index 0000000..9d73103 --- /dev/null +++ b/data/sounds/notifications/arcturus.ogg diff --git a/data/sounds/notifications/regulus.ogg b/data/sounds/notifications/regulus.ogg Binary files differnew file mode 100644 index 0000000..4f28d9e --- /dev/null +++ b/data/sounds/notifications/regulus.ogg diff --git a/data/sounds/notifications/sirius.ogg b/data/sounds/notifications/sirius.ogg Binary files differnew file mode 100644 index 0000000..78c9991 --- /dev/null +++ b/data/sounds/notifications/sirius.ogg diff --git a/data/sounds/notifications/vega.ogg b/data/sounds/notifications/vega.ogg Binary files differnew file mode 100644 index 0000000..e596e60 --- /dev/null +++ b/data/sounds/notifications/vega.ogg diff --git a/data/sounds/ringtones/ANDROMEDA.ogg b/data/sounds/ringtones/ANDROMEDA.ogg Binary files differnew file mode 100644 index 0000000..8f6bd3e --- /dev/null +++ b/data/sounds/ringtones/ANDROMEDA.ogg diff --git a/data/sounds/ringtones/Aquila.ogg b/data/sounds/ringtones/Aquila.ogg Binary files differnew file mode 100644 index 0000000..b391be9 --- /dev/null +++ b/data/sounds/ringtones/Aquila.ogg diff --git a/data/sounds/ringtones/ArgoNavis.ogg b/data/sounds/ringtones/ArgoNavis.ogg Binary files differnew file mode 100644 index 0000000..b4202ac --- /dev/null +++ b/data/sounds/ringtones/ArgoNavis.ogg diff --git a/data/sounds/ringtones/BOOTES.ogg b/data/sounds/ringtones/BOOTES.ogg Binary files differnew file mode 100644 index 0000000..0716a4f --- /dev/null +++ b/data/sounds/ringtones/BOOTES.ogg diff --git a/data/sounds/ringtones/CANISMAJOR.ogg b/data/sounds/ringtones/CANISMAJOR.ogg Binary files differnew file mode 100644 index 0000000..177d3de --- /dev/null +++ b/data/sounds/ringtones/CANISMAJOR.ogg diff --git a/data/sounds/ringtones/CASSIOPEIA.ogg b/data/sounds/ringtones/CASSIOPEIA.ogg Binary files differnew file mode 100644 index 0000000..c4a7948 --- /dev/null +++ b/data/sounds/ringtones/CASSIOPEIA.ogg diff --git a/data/sounds/ringtones/Carina.ogg b/data/sounds/ringtones/Carina.ogg Binary files differnew file mode 100644 index 0000000..aeb9b36 --- /dev/null +++ b/data/sounds/ringtones/Carina.ogg diff --git a/data/sounds/ringtones/Carina.wav b/data/sounds/ringtones/Carina.wav Binary files differnew file mode 100755 index 0000000..ecaeb58 --- /dev/null +++ b/data/sounds/ringtones/Carina.wav diff --git a/data/sounds/ringtones/Centaurus.ogg b/data/sounds/ringtones/Centaurus.ogg Binary files differnew file mode 100644 index 0000000..404bdbc --- /dev/null +++ b/data/sounds/ringtones/Centaurus.ogg diff --git a/data/sounds/ringtones/Cygnus.ogg b/data/sounds/ringtones/Cygnus.ogg Binary files differnew file mode 100644 index 0000000..b2e1e65 --- /dev/null +++ b/data/sounds/ringtones/Cygnus.ogg diff --git a/data/sounds/ringtones/Draco.ogg b/data/sounds/ringtones/Draco.ogg Binary files differnew file mode 100644 index 0000000..88d5a04 --- /dev/null +++ b/data/sounds/ringtones/Draco.ogg diff --git a/data/sounds/ringtones/Eridani.ogg b/data/sounds/ringtones/Eridani.ogg Binary files differnew file mode 100644 index 0000000..b665a29 --- /dev/null +++ b/data/sounds/ringtones/Eridani.ogg diff --git a/data/sounds/ringtones/Lyra.ogg b/data/sounds/ringtones/Lyra.ogg Binary files differnew file mode 100644 index 0000000..696f278 --- /dev/null +++ b/data/sounds/ringtones/Lyra.ogg diff --git a/data/sounds/ringtones/Machina.ogg b/data/sounds/ringtones/Machina.ogg Binary files differnew file mode 100644 index 0000000..ac16f7e --- /dev/null +++ b/data/sounds/ringtones/Machina.ogg diff --git a/data/sounds/ringtones/Orion.ogg b/data/sounds/ringtones/Orion.ogg Binary files differnew file mode 100644 index 0000000..807f107 --- /dev/null +++ b/data/sounds/ringtones/Orion.ogg diff --git a/data/sounds/ringtones/PERSEUS.ogg b/data/sounds/ringtones/PERSEUS.ogg Binary files differnew file mode 100644 index 0000000..ad06021 --- /dev/null +++ b/data/sounds/ringtones/PERSEUS.ogg diff --git a/data/sounds/ringtones/Pegasus.ogg b/data/sounds/ringtones/Pegasus.ogg Binary files differnew file mode 100644 index 0000000..66c4970 --- /dev/null +++ b/data/sounds/ringtones/Pegasus.ogg diff --git a/data/sounds/ringtones/Pyxis.ogg b/data/sounds/ringtones/Pyxis.ogg Binary files differnew file mode 100644 index 0000000..2d3adce --- /dev/null +++ b/data/sounds/ringtones/Pyxis.ogg diff --git a/data/sounds/ringtones/Rigel.ogg b/data/sounds/ringtones/Rigel.ogg Binary files differnew file mode 100644 index 0000000..af2c176 --- /dev/null +++ b/data/sounds/ringtones/Rigel.ogg diff --git a/data/sounds/ringtones/Scarabaeus.ogg b/data/sounds/ringtones/Scarabaeus.ogg Binary files differnew file mode 100644 index 0000000..e70fc69 --- /dev/null +++ b/data/sounds/ringtones/Scarabaeus.ogg diff --git a/data/sounds/ringtones/Sceptrum.ogg b/data/sounds/ringtones/Sceptrum.ogg Binary files differnew file mode 100644 index 0000000..fc50aef --- /dev/null +++ b/data/sounds/ringtones/Sceptrum.ogg diff --git a/data/sounds/ringtones/Solarium.ogg b/data/sounds/ringtones/Solarium.ogg Binary files differnew file mode 100644 index 0000000..d27f141 --- /dev/null +++ b/data/sounds/ringtones/Solarium.ogg diff --git a/data/sounds/ringtones/Testudo.ogg b/data/sounds/ringtones/Testudo.ogg Binary files differnew file mode 100644 index 0000000..0ca8d6b --- /dev/null +++ b/data/sounds/ringtones/Testudo.ogg diff --git a/data/sounds/ringtones/URSAMINOR.ogg b/data/sounds/ringtones/URSAMINOR.ogg Binary files differnew file mode 100644 index 0000000..c0010e82 --- /dev/null +++ b/data/sounds/ringtones/URSAMINOR.ogg diff --git a/data/sounds/ringtones/Vespa.ogg b/data/sounds/ringtones/Vespa.ogg Binary files differnew file mode 100644 index 0000000..4423bbb --- /dev/null +++ b/data/sounds/ringtones/Vespa.ogg diff --git a/data/sounds/ringtones/hydra.ogg b/data/sounds/ringtones/hydra.ogg Binary files differnew file mode 100644 index 0000000..edde14f --- /dev/null +++ b/data/sounds/ringtones/hydra.ogg diff --git a/docs/html/guide/appendix/media-formats.jd b/docs/html/guide/appendix/media-formats.jd index 94a6471..8709994 100644 --- a/docs/html/guide/appendix/media-formats.jd +++ b/docs/html/guide/appendix/media-formats.jd @@ -22,7 +22,7 @@ page.title=Android Supported Media Formats <tr> <td rowspan="9">Audio</td> <td>AAC LC/LTP</td> -<td> </td> +<td style="text-align: center;">X</td> <td style="text-align: center;">X</td> <td rowspan="3">Mono/Stereo content in any combination of standard bit rates up to 160 kbps and sampling rates from 8 to 48kHz</td> <td rowspan="3">3GPP (.3gp) and MPEG-4 (.mp4, .m4a). No support for raw AAC (.aac)</td> @@ -51,7 +51,7 @@ page.title=Android Supported Media Formats <tr> <td>AMR-WB</td> -<td> </td> +<td style="text-align: center;">X</td> <td style="text-align: center;">X</td> <td>9 rates from 6.60 kbit/s to 23.85 kbit/s sampled @ 16kHz</td> <td>3GPP (.3gp)</td> @@ -109,7 +109,7 @@ page.title=Android Supported Media Formats <tr> <td>PNG</td> -<td> </td> +<td style="text-align: center;">X</td> <td style="text-align: center;">X</td> <td> </td> <td>PNG (.png)</td> diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 545807e..2548128 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -71,6 +71,9 @@ <li><a href="<?cs var:toroot ?>guide/topics/ui/menus.html"> <span class="en">Creating Menus</span> </a></li> + <li><a href="<?cs var:toroot ?>guide/topics/ui/actionbar.html"> + <span class="en">Using the Action Bar</span> + </a> <span class="new">new!</span></li> <li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html"> <span class="en">Creating Dialogs</span> </a></li> @@ -196,6 +199,9 @@ </li> </ul> <ul> + <li><a href="<?cs var:toroot ?>guide/topics/fragments/index.html"> + <span class="en">Fragments</span> + </a> <span class="new">new!</span></li> <li class="toggle-list"> <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html"> <span class="en">Graphics</span> diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd index 13b5e3a..7811d90 100644 --- a/docs/html/guide/practices/screens_support.jd +++ b/docs/html/guide/practices/screens_support.jd @@ -35,7 +35,9 @@ page.title=Supporting Multiple Screens <ol> <li><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><supports-screens></a></code></li> <li><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a></code></li> - <li><a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">Alternative Resources</a></li> + <li><a +href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources"> +Providing Alternative Resources</a></li> <li><a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a></li> </ol> @@ -53,7 +55,7 @@ sizes and resolutions. </p> <p>This document explains the screens-support features provided by the platform and how you use them in your application. By following the practices described here, you can easily create an application that displays properly on all -supported device screens and that you can deploy to any device as a single .apk. +supported device screens and that you can deploy to any device as a single {@code .apk}. </p> <p>If you have already developed and published an application for Android 1.5 or @@ -63,10 +65,16 @@ and that are running Android 1.6 or later. In most cases, only minor adjustments are needed, however you should make sure to <a href="#testing">test your application</a> on all supported screens. </p> +<p>Starting in Android 2.2, the platform includes support for extra high density screens +(<em>xhdpi</em>), and starting in Android 2.3, the platform includes support for extra large screens +(<em>xlarge</em>). If you've already followed the guidance in this document to support all other +screen types, you should consider providing additional support for <em>xhdpi</em> and +<em>xlarge</em> screens.</p> + <p>In particular, if you have an existing application that you would like to -make available for users of devices with small screens (such as QVGA), please -see <a href="#strategies">Strategies for Legacy Applications</a> for more -information about how to do that. </p> +make available on small screens (such as QVGA) or for which you would like to provide better support +for extra large screens, please see <a href="#strategies">Strategies for Legacy Applications</a> for +more information about how to do that. </p> <h2 id="overview">Overview of Screens Support</h2> @@ -82,11 +90,11 @@ screen-compatibility features.</p> <dl> <dt><em>Screen size</em></dt> - <dd>Actual physical size, measured as the screen's diagonal. + <dd>Actual physical size, measured as the screen's diagonal. - <p>For simplicity, Android collapses all actual screen sizes into three -generalized sizes: large, normal, and small. Applications can provide custom -layouts for each of these three sizes — the platform transparently handles + <p>For simplicity, Android collapses all actual screen sizes into four +generalized sizes: small, normal, large, and extra large. Applications can provide custom +layouts for each of these four sizes — the platform transparently handles the rendering of the layouts at the actual screen size.</p></dd> <dt><em>Aspect ratio</em></dt> @@ -110,22 +118,22 @@ sometimes significantly more — pixels spread across the same area. The density of a screen is important because, other things being equal, a UI element (such as a button) whose height and width are defined in terms of screen pixels will appear larger on the lower density screen and smaller on the higher density -screen. </p> +screen.</p> - <p>For simplicity, Android collapses all actual screen densities into three -generalized densities: high, medium, and low. Applications can provide custom -resources for each of these three densities — the platform handles the -scaling of the resources up or down to meet the actual screen density. </p></dd> -<dt><em>Density-independent pixel (dip)</em></dt> + <p>For simplicity, Android collapses all actual screen densities into four +generalized densities: low, medium, large, and extra large. Applications can provide custom +resources for each of these densities — the platform handles any necessary +scaling of the resources up or down to meet the specific screen density. </p></dd> +<dt><em>Density-independent pixel (dp)</em></dt> <dd>A virtual pixel unit that applications can use in defining their UI, to -express layout dimensions or position in a density-independent way. +express layout dimensions or position in a density-independent way. <p>The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, the baseline density assumed by the platform (as described later in this document). At run time, the platform transparently handles any scaling of -the dip units needed, based on the actual density of the screen in use. The -conversion of dip units to screen pixels is simple: <code>pixels = dips * -(density / 160)</code>. For example, on 240 dpi screen, 1 dip would equal 1.5 -physical pixels. Using dip units to define your application's UI is highly +the dp units needed, based on the actual density of the screen in use. The +conversion of dp units to screen pixels is simple: <nobr><code>pixels = dps * +(density / 160)</code></nobr>. For example, on 240 dpi screen, 1 dp would equal 1.5 +physical pixels. Using dp units to define your application's UI is highly recommended, as a way of ensuring proper display of your UI on different screens. </p></dd> </dl> @@ -146,13 +154,19 @@ applications, the platform divides the range of actual supported screen sizes and resolutions into:</p> <ul> -<li>A set of three generalized sizes: <em>large</em>, <em>normal</em>, and <em>small</em>, and </li> -<li>A set of three generalized densities: <em>hdpi</em> (high), <em>mdpi</em> (medium), and <em>ldpi</em> (low) +<li>A set of four generalized sizes: <em>small</em>, <em>normal</em>, <em>large</em>, +and <em>xlarge</em></em> +<li>A set of four generalized densities: <em>ldpi</em> (low), <em>mdpi</em> (medium), +<em>hdpi</em> (high), and <em>xhdpi</em> (extra high) </ul> +<p class="note"><strong>Note:</strong> The <code>xhdpi</code> density category was added in +Android 2.2 (API Level 8). The <em>xlarge</em> size category was added in Android 2.3 (API Level +9).</p> + <p>Applications can provide custom resources (primarily layouts) for any of the -three generalized sizes and can provide resources (primarily drawables such as -images) for any of the three generalized densities. Applications do not need to +four generalized sizes and can provide resources (primarily drawables such as +images) for any of the four generalized densities. Applications do not need to work with the actual physical size or density of the device screen. At run time, the platform handles the loading of the correct size or density resources, based on the generalized size or density of the current device screen, and adapts them @@ -177,8 +191,8 @@ its characteristics. </p> <img src="{@docRoot}images/screens_support/screens-ranges.png" /> -<p class="img-caption"><strong>Figure 1.</strong> -Illustration of how the Android platform maps actual screen densities and sizes +<p class="img-caption"><strong>Figure 1.</strong> +Illustration of how the Android platform maps actual screen densities and sizes to generalized density and size configurations. </p> <p>Although the platform lets your application provide layouts and resources for @@ -213,6 +227,9 @@ sizes and densities of emulator skins included in the Android SDK.</p> <td style="background-color:#f3f3f3"> <nobr>High density (240), <em>hdpi</em><nobr> </td> + <td style="background-color:#f3f3f3"> + <nobr>Extra high density (320), <em>xhdpi</em><nobr> + </td> </tr> <tr> <td style="background-color:#f3f3f3"> @@ -222,6 +239,7 @@ sizes and densities of emulator skins included in the Android SDK.</p> </td> <td></td> <td></td> + <td></td> </tr> <tr> <td style="background-color:#f3f3f3"> @@ -230,6 +248,7 @@ sizes and densities of emulator skins included in the Android SDK.</p> <td style="font-size:.9em;">WQVGA400 (240x400)<br>WQVGA432 (240x432)</td> <td style="font-size:.9em;">HVGA (320x480)</td> <td style="font-size:.9em;">WVGA800 (480x800)<br>WVGA854 (480x854)</td> + <td style="font-size:.9em;"></td> </tr> <tr> <td style="background-color:#f3f3f3"> @@ -238,16 +257,27 @@ sizes and densities of emulator skins included in the Android SDK.</p> <td></td> <td style="font-size:.9em;">WVGA800* (480x800)<br>WVGA854* (480x854)</td> <td></td> + <td></td> + </tr> + <tr> + <td style="background-color:#f3f3f3"> + <em>Extra Large</em> screen + </td> + <td></td> + <td></td> + <td></td> + <td></td> </tr> <tr> - <td colspan="4" style="border:none;font-size:90%;">* To emulate this - configuration, specify a custom density of 160 when + <td colspan="4" style="border:none;font-size:90%;">* To emulate this + configuration, specify a custom density of 160 when creating an AVD that uses a WVGA800 or WVGA854 skin. </td> + </tr> </table> -<p>For an overview of the relative numbers of high (hdpi), medium (mdpi), and -low (ldpi) density screens in Android-powered devices available now, see the <a +<p>For an overview of the relative numbers of high (hdpi), medium (mdpi), and +low (ldpi) density screens in Android-powered devices available now, see the <a href="{@docRoot}resources/dashboard/screens.html">Screen Sizes and Densities</a> dashboard.</p> @@ -262,9 +292,9 @@ resources at run time is based on the alternative resources framework. <p> If you want to use size- or density-specific layouts or drawables in your application and you are not familiar with resource qualifiers or how the -platform uses them, please read +platform uses them, please read <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources"> -Alternative Resources</a>. +Providing Alternative Resources</a>. </div> </div> @@ -277,19 +307,20 @@ to use them:</p> <ul> <li>The platform supports a set of resource qualifiers that let you provide -size- and density-specific resources, if needed. The qualifiers for -size-specific resources are <code>large</code>, <code>normal</code>, and -<code>small</code>, and those for density-specific resources are -<code>hdpi</code> (high), <code>mdpi</code> (medium), and <code>ldpi</code> -(low). The qualifiers correspond to the generalized densities described in +size- and density-specific resources, if needed. The qualifiers for +size-specific resources are <code>small</code>, <code>normal</code>, <code>large</code>, and +<code>xlarge</code>. Those for density-specific resources are <code>ldpi</code> +(low), <code>mdpi</code> (medium), <code>hdpi</code> (high), and <code>xhdpi</code> (extra high). +The qualifiers correspond to the generalized densities described in <a href="#range">Range of screens supported</a>, above.</li> - <li>The platform also provides a + <li>The platform also provides a <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"> <code><supports-screens></code></a> manifest element, whose attributes -<code>android:largeScreens</code>, <code>android:normalScreens</code>, and -<code>android:smallScreens</code> let you specify what generalized screen sizes -your application supports. A fourth attribute, <code>android:anyDensity</code>, +<code>android:smallScreens</code>, <code>android:normalScreens</code>, +<code>android:largeScreens</code>, and <code>android:xlargeScreens</code> let you specify what +generalized screen sizes +your application supports. Another attribute, <code>android:anyDensity</code>, lets you indicate whether or not your application includes built-in support for multiple densities.</li> </ul> @@ -299,7 +330,7 @@ application, to ensure the best possible display on the current device screen:</p> <ol> -<li><em>Pre-scaling of resources (such as image assets)</em> +<li><em>Pre-scaling of resources (such as image assets)</em> <p>Based on the density of the current screen, the platform automatically loads any size- or density-specific resources from your application and displays @@ -344,18 +375,18 @@ lower-density screen, coordinates are scaled down.<p> <p>For more information, see the <code>android:anyDensity</code> attribute in <a href="#attrs">Manifest attributes for screens support</a>.</p></li> -<div class="sidebox-wrapper" xstyle="margin-bottom:2em;margin-top:.5em;width:90%;"> - <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png"> - <div id="qv-sub-rule"> - <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;"> - <p style="color:#669999;">Publishing to Small Screen Devices</p> +<div class="sidebox-wrapper" xstyle="margin-bottom:2em;margin-top:.5em;width:90%;"> + <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png"> + <div id="qv-sub-rule"> + <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;"> + <p style="color:#669999;">Publishing to Small Screen Devices</p> <p>To ensure the best experience for users on small-screen devices, Android Market only shows applications that explicitly declare support for small screens. If you developed an application on Android 1.5 or earlier and published it on Android Market, you need to <a href="#testing">test your application</a> -on small screens and then upload an updated version that explicitly +on small screens and then upload an updated version that explicitly <a href="#attrs">indicates support for small screens</a>. </p> - </div> + </div> </div> <li><em>Compatibility-mode display on larger screen-sizes</em> @@ -374,7 +405,7 @@ of scaling the application, however, the application's 320x480 interface will be placed as a "postage stamp" in the larger 480x800 screen.</p> <p>For more information, see the <code>android:anyDensity</code> attribute in -<a href="#attrs">Manifest elements for screens support</a> and the +<a href="#attrs">Manifest elements for screens support</a> and the <a href="#compatibility-examples">Screen-Compatibility Examples</a> section.</p></li> </ol> @@ -415,7 +446,7 @@ does this in three ways: </p> <ul> <li>Through pre-scaling of drawable resources (scaled at resource loading time)</li> -<li>Through auto-scaling of density-independent pixel (dip) values used in +<li>Through auto-scaling of density-independent pixel (dp) values used in layouts</li> <li>Through auto-scaling of absolute pixel values used in the application (only needed if the application has set <code>android:anyDensity="false"</code> in its @@ -437,25 +468,36 @@ density (left), HVGA medium density (center), and QVGA low density (right). </p> <p>In most cases, you can take advantage of density independence in your application simply by making sure that your layouts specify all dimension values -in density-independent pixels (<code>dip</code> or <code>dp</code>) or +in density-independent pixels (<code>dp</code> or <code>dp</code>) or scale-independent pixels (<code>sip</code> or <code>sp</code>, for text only). If you are using absolute pixel values in the application and manifest includes <a href="#attrs"><code>android:anyDensity="true"</code></a>, you will also need -to scale the pixel values. See <a href="#dips-pels">Converting from dips to -pixels</a> for more information. </p> +to scale the pixel values. See <a href="#dips-pels">Converting dp units to +pixel units</a> for more information. </p> <h3 id="attrs">Manifest attributes for screens support</h3> -<p> Android 1.6 introduced a new manifest element, +<p> Android 1.6 introduced a new manifest element, <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><code><supports-screens></code></a>, whose attributes you can use to control the display of your application on different classes of device screens, as listed -below. The <code>smallScreens</code>, <code>normalScreens</code>, and -<code>largeScreens</code> attributes correspond to the generalized screen sizes +in table 2. The <code>smallScreens</code>, <code>normalScreens</code>, <code>largeScreens</code> and +<code>xlargeScreens</code> attributes correspond to the generalized screen sizes described in <a href="#range">Range of screens supported</a>, earlier in this -document.</p> - +document. Notice that the default values for each attribute vary, depending +on your minimum and targeted platform, as indicated in the <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code +android:minSdkVersion}</a> and <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code +android:targetSdkVersion}</a> attributes of your <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> +manifest element.</p> + +<p class="table-caption" id="table2"><strong>Table 2.</strong> Summary of attributes for the <a +href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code +<supports-screens>}</a> manifest element, including default values based on platform +version.</p> <table id="vrr8"> <tr> <th> @@ -465,10 +507,12 @@ document.</p> Description </th> <th> - Default value,<br><nobr>Android 1.5 and Lower</nobr> + Default value, when<br><nobr><code>minSdkVersion</code> or</nobr> +<code>targetSdkVersion</code> is 4 or lower </th> <th> - Default value,<br><nobr>Android 1.6 and Higher</nobr> + Default value, when<br><nobr><code>minSdkVersion</code> or</nobr> +<code>targetSdkVersion</code> is 5 or higher </th> </tr> <tr> @@ -540,11 +584,46 @@ baseline screen.</p> <td>"<code>false</code>"</td> <td>"<code>true</code>"</td> </tr> + <tr> + <td colspan="4"><strong>Note:</strong> Android 2.3 (API Level 9) introduced a new +attribute for the <code><supports-screens></code> element: <code>xlargeScreens</code>, shown +below. It works the same as the other screen attributes above, but, if neither your +<code>minSdkVersion</code> or <code>targetSdkVersion</code> are set to "9", the default value is +"false" when your application is installed on a device running Android 2.3.</td> + </tr> + <tr> + <th> + Attribute + </th> + <th > + Description + </th> + <th> + Default value, when<br><nobr><code>minSdkVersion</code> or</nobr> +<code>targetSdkVersion</code> is 8 or lower + </th> + <th> + Default value, when<br><nobr><code>minSdkVersion</code> or</nobr> +<code>targetSdkVersion</code> is 9 or higher + </th> + </tr> + <tr> + <td> + <code>android:xlargeScreens</code> + </td> + <td> + Whether or not the application UI is designed for use on +<em>xlarge</em> screens — "<code>true</code>" if it is, and +"<code>false</code>" if not. + </td> +<td>"<code>false</code>"</td> +<td>"<code>true</code>"</td> + </tr> </table> <p>In general, when you declare a screen-size attribute -(<code>smallScreens</code>, <code>normalScreens</code>, or -<code>largeScreens</code>) as "<code>true</code>", you are signaling to the +(<code>smallScreens</code>, <code>normalScreens</code>, <code>largeScreens</code>, or +<code>xlargeScreens</code>) as "<code>true</code>", you are signaling to the platform that your application is designed to render properly on that screen size. As a result, the platform does not apply any size-compatibility features (such as a virtual HVGA display area). If you declare a screen-size attribute as @@ -577,16 +656,20 @@ features for applications.</p> <ul> <li>Assume that you declare <code>smallScreens="false" normalScreens="true" -largeScreens="false" </code> in your application's manifest. <p>Although the -application is not designed for display on large screens, the platform can still -run it successfully in <a href="#compatibility-examples">size-compatibility -mode</a>. Android Market does not filter the application from devices -<em>normal</em> and <em>large</em> size screens, but does filter it from -<em>small</em> size screens, since the application provides no screen support at -<em>small</em> size (and there is no smaller size).</p></li> +largeScreens="false" xlargeScreens="false"</code> in your application's manifest. <p>Although the +application is not designed for display on large or extra large screens, the platform can still +run it successfully in <a href="#compatibility-examples">screen-compatibility +mode</a>. Android Market shows the application to devices with +<em>normal</em>, <em>large</em>, and <em>xlarge</em> size screens, but does filter it from +<em>small</em> size screens, because the application provides no screen support at +<em>small</em> size. Android's <a href="#compatibility-examples">screen-compatibility +mode</a> mode does not provide support for screens that are smaller than those the +application supports—it only provides support for screens that are larger. Thus, +although the application declares "false" for <em>large</em> and <em>xlarge</em> screens, +the application still functions, but runs in compatibility mode.</p></li> <li>Assume that you declare <code>smallScreens="false" normalScreens="false" -largeScreens="true"</code> in your application's manifest. <p>Android Market +largeScreens="true" xlargeScreens="true"</code> in your application's manifest. <p>Android Market filters the application from users of devices with <em>small</em> and <em>normal</em> size screens. In effect, this prevents such users from installing the application.</p></li> @@ -599,23 +682,24 @@ application must ensure that it declares its UI dimensions using density-independent pixels (<code>dp</code>) and scales any absolute pixel values (<code>px</code>) or math by the scaling factor available from {@link android.util.DisplayMetrics#density android.util.DisplayMetrics.density}. See <a -href="#dips-pels">Converting from dips to pixels</a> for an example.</p> +href="#dips-pels">Converting dp units to pixel units</a> for an example.</p> <p>Note that the setting of the <code>android:anyDensity</code> attribute does not affect the platform's pre-scaling of drawable resources, such as bitmaps and nine-patch images, which always takes place by default. </p> -<p>The following example shows a manifest that declares support for large, -normal, and small screens in any densities.</p> - -<pre><manifest xmlns:android="http://schemas.android.com/apk/res/android"> - ... - <supports-screens - android:largeScreens="true" - android:normalScreens="true" - android:smallScreens="true" - android:anyDensity="true" /> - ... +<p>The following example shows a manifest that declares support for small, normal, large, and + xlarge screens in any density.</p> + +<pre> +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + ... + <supports-screens + android:smallScreens="true" + android:normalScreens="true" + android:largeScreens="true" + android:xlargeScreens="true" + android:anyDensity="true" /> </manifest> </pre> <!-- android:resizeable="true" --> @@ -624,36 +708,25 @@ normal, and small screens in any densities.</p> </h4> <p>The default values for the <code><supports-screens></code> attributes -differ, depending on the the value of the +differ, depending on the the value of the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>android:minSdkVersion</code></a> attribute in the application's manifest, as well as on -the value of <code>android:targetSdkVersion</code>, if declared:</p> +the value of <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code +android:targetSdkVersion}</a>, if declared.</p> -<div> - <ul> - <li> - If <code>android:minSdkVersion</code> or -<code>android:targetSdkVersion</code> is "4" (Android 1.6) or higher, the -default value for everything is "<code>true</code>". If your application uses -APIs introduced in Android 1.6 or higher, but does not support specific screen -densities and/or screen sizes, you need to explicitly set the appropriate -attributes to "<code>false</code>". - </li> - <li> - If <code>android:minSdkVersion</code> is declared with a value of "3" -(Android 1.5) or lower <em>and</em> a <code>android:targetSdkVersion</code> -attribute is <em>not</em> declared with a value of "4" or higher, the default -value for all attributes except <code>android:normalScreens</code> is -"<code>false</code>". If you are primarily targeting pre-Android 1.6 platforms -but also want to support other densities/screen sizes, you need to explicitly -set the appropriate attributes to "<code>true</code>". - </li> - <li> - Note that <code>android:normalScreens</code> always defaults to -<code>true</code>. - </li> - </ul> -</div> +<p>Above, <a href="#table2">table 2</a> indicates the default values for each attribute, based on +the values you provide for the <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code +android:minSdkVersion}</a> and <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code +android:targetSdkVersion}</a>, in the <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> +element.</p> + +<p class="note"><strong>Note:</strong> If your application uses APIs introduced in Android 1.6 or +higher, but does not support specific screen densities and/or screen sizes, you need to explicitly +set the appropriate attributes to "<code>false</code>" (because most are "true", by default).</p> <h3 id="qualifiers">Resource directory qualifiers for screen size and density</h3> @@ -673,7 +746,7 @@ of Screens Supported</a>, earlier in this document.</p> </tr> <tr> - <td rowspan="3">Size</td> + <td rowspan="4">Size</td> <td><code>small</code></td> <td>Resources designed for <em>small</em> size screens.</td> </tr> @@ -683,11 +756,15 @@ of Screens Supported</a>, earlier in this document.</p> </tr> <tr> <td><code>large</code></td> -<td>Resources for <em>large</em> size screens.</td> +<td>Resources designed for <em>large</em> size screens.</td> +</tr> +<tr> +<td><code>xlarge</code></td> +<td>Resources designed for <em>extra large</em> size screens.</td> </tr> <tr> -<td rowspan="4">Density</td> +<td rowspan="5">Density</td> <td><code>ldpi</code></td> <td>Resources designed for low-density (<em>ldpi</em>) screens.</td> </tr> @@ -700,6 +777,10 @@ of Screens Supported</a>, earlier in this document.</p> <td>Resources designed for high-density (<em>hdpi</em>) screens.</td> </tr> <tr> +<td><code>xhdpi</code></td> +<td>Resources designed for extra high-density (<em>xhdpi</em>) screens.</td> +</tr> +<tr> <td><code>nodpi</code></td> <td>Density-independent resources. The platform does not auto-scale resources tagged with this qualifier, regardless of the current screen's density.</td> @@ -732,31 +813,34 @@ running on Android 1.5 (API Level 3). </td> Note that the density and the screen size are independent parameters and are interpreted by the system individually. For example, WVGA high density is considered a normal screen because its physical size is about the same as one of -T-Mobile G1. On the other hand, a WVGA medium density screen is considered a +T-Mobile G1. On the other hand, a WVGA medium density screen is considered a <i>large</i> screen — it offers the same resolution but at lower pixel density, meaning that it is both physically larger than the baseline screen and can display significantly more information than a normal screen size. </p> <p>Here is an example of the resource directory structure of an application that -supports low and high density, and employs different layout schemes.</p> +employs different layout schemes for different screen sizes and supports low and high density +screens.</p> -<pre>res/layout/my_layout.xml // layout for normal screen size +<pre> +res/layout/my_layout.xml // layout for normal screen size res/layout-small/my_layout.xml // layout for small screen size res/layout-large/my_layout.xml // layout for large screen size res/layout-large-land/my_layout.xml // layout for large screen size in landscape mode +res/layout-xlarge/my_layout.xml // layout for extra large screen size -res/drawable-ldpi/my_icon.png // icon image for low density -res/drawable-mdpi/dpi/my_icon.png // icon for medium density -res/drawable-hdpi/my_icon.png // icon image for high density +res/drawable-lhdpi/my_icon.png // image for low density +res/drawable-mdpi/dpi/my_icon.png // image for medium density +res/drawable-hdpi/my_icon.png // image for high density res/drawable-nodpi/composite.xml // density independent resource </pre> <p>For more information about how to use resource qualifiers or how the platform -selects them, please read +selects them, please read <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources"> -Alternative Resources</a>.</p> +Providing Alternative Resources</a>.</p> <h2 id="screen-independence">Best practices for Screen Independence</h2> @@ -771,10 +855,11 @@ different screens. Here is a quick checklist:</p> <ol> <li> - Prefer wrap_content, fill_parent and the dip unit to px in XML layout files + Use {@code wrap_content}, {@code fill_parent}, or the {@code dp} unit (instead of {@code px}), +when specifying dimensions in an XML layout file </li> <li> - Avoid AbsoluteLayout + Do not use {@code AbsoluteLayout} </li> <li> Do not use hard coded pixel values in your code @@ -784,19 +869,19 @@ different screens. Here is a quick checklist:</p> </li> </ol> -<h3 id="use-relative">1. Prefer wrap_content, fill_parent and the dip unit to +<h3 id="use-relative">1. Use wrap_content, fill_parent, or the dp unit, instead of absolute pixels<br> </h3> <p>When defining the <code>layout_width</code> and <code>layout_height</code> of views in an XML layout file, using <code>wrap_content</code>, -<code>fill_parent</code> or the <code>dip</code> will guarantee that the view is +<code>fill_parent</code> or the <code>dp</code> will guarantee that the view is given an appropriate size on the current device screen. For instance, a view -with a <code>layout_width="100dip"</code> will measure 100 pixels wide on an +with a <code>layout_width="100dp"</code> will measure 100 pixels wide on an HVGA@160 density display and 150 pixels on a WVGA@240 density display, but the view will occupy approximately the same physical space. </p> <p>Similarly, you should prefer the <code>sp</code> (scale-independent pixel, -the scale factor depends on a user setting) or <code>dip</code> (if you don't +the scale factor depends on a user setting) or <code>dp</code> (if you don't want to allow the user to scale the text) to define font sizes.</p> <h3 id="avoid-absolute">2. Avoid AbsoluteLayout </h3> @@ -808,7 +893,7 @@ positions which might easily lead to user interfaces that do not work well on different displays. Because of this, <code>AbsoluteLayout</code> was deprecated in Android 1.5 (API Level 3). </p> -<p>You can achieve much the same layout by using a +<p>You can achieve much the same layout by using a {@link android.widget.FrameLayout FrameLayout} instead, and setting <code>layout_margin</code> attributes of the children. This approach is more flexible and will yield better results on different screens.</p> @@ -822,9 +907,9 @@ code in pixels. For instance, if <code>myView.getWidth()</code> returns 10, the view is 10 pixels wide. In some cases, you may need to scale the pixel values that you use in your code. The sections below provide more information. </p> -<h4 id="dips-pels">Converting from dips to pixels</h4> +<h4 id="dips-pels">Converting dp units to pixel units</h4> -<p>In some cases, you will need to express dimensions in <code>dip</code> and +<p>In some cases, you will need to express dimensions in <code>dp</code> and then convert them to pixels. Imagine an application in which a scroll gesture is recognized after the user's finger has moved by at least 16 pixels. On a baseline screen, the user will have to move his finger by 16 pixels / 160 @@ -832,26 +917,26 @@ dpi = 1/10th of an inch (or 2.5 mm) before the gesture is recognized. On a device with a high (240) density display, the user will move his finger by only 16 pixels / 240 dpi = 1/15th of an inch (or 1.7 mm.) The distance is much shorter and the application thus appears more sensitive to the user. To fix this -issue, the gesture threshold must be expressed in the code in <code>dip</code> +issue, the gesture threshold must be expressed in the code in <code>dp</code> and then converted to actual pixels.</p> -<pre>// The gesture threshold expressed in dip -private static final float GESTURE_THRESHOLD_DIP = 16.0f; +<pre>// The gesture threshold expressed in dp +private static final float GESTURE_THRESHOLD_DP = 16.0f; -// Convert the dips to pixels +// Convert the dps to pixels final float scale = getContext().getResources().getDisplayMetrics().density; -mGestureThreshold = (int) (GESTURE_THRESHOLD_DIP * scale + 0.5f);</span> +mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);</span> // Use mGestureThreshold as a distance in pixels </pre> -<p>The {@link android.util.DisplayMetrics#density android.util.DisplayMetrics.density} +<p>The {@link android.util.DisplayMetrics#density android.util.DisplayMetrics.density} field specifies the the scale factor you must use to -convert dips to pixels according to the current screen density. You can access +convert dps to pixels according to the current screen density. You can access the current screen's metrics through a <code>Context</code> or <code>Activity</code>. On a medium (160) density screen, <code>DisplayMetrics.density</code> equals "1.0", whereas on a high (240) -density screen it equals "1.5". You can refer to the documentation of the +density screen it equals "1.5". You can refer to the documentation of the {@link android.util.DisplayMetrics DisplayMetrics} class for details.</p> @@ -901,7 +986,7 @@ platform assumes that the resources in that directory are designed for the baseline medium density. It is not recommended that you put density-specific resources such as images in the default directory.</p> -<p>For more information about valid resource qualifiers, see +<p>For more information about valid resource qualifiers, see <a href="#qualifiers">Resource directory qualifiers</a>, earlier in this document.</p> @@ -945,7 +1030,7 @@ resource directory:</p> <p style="margin-left:2em;"><code>res/drawable-nodpi/icon.png</code></p> -<p>You can also take complete control of the scaling mechanism by using the +<p>You can also take complete control of the scaling mechanism by using the {@link android.graphics.BitmapFactory.Options BitmapFactory.Options} class, which lets you define whether you want the bitmap to be pre-scaled and what the density of the bitmap should be. For instance, if you are loading a bitmap from @@ -953,12 +1038,12 @@ a web server, you may want to force the bitmap's density to be high density. When pre-scaling is disabled, the resulting bitmap is in auto-scaling mode. The bitmap is associated with a density (that you may or may not have specified through the <code>BitmapFactory.Options</code>) which will be used to scale the -bitmap on screen <em>at drawing time</em>. +bitmap on screen <em>at drawing time</em>. <p>Using auto-scaling instead of pre-scaling is more CPU expensive than -pre-scaling but uses less memory. You can refer to the documentation of -{@link android.graphics.BitmapFactory BitmapFactory}, -{@link android.graphics.Bitmap Bitmap}, and +pre-scaling but uses less memory. You can refer to the documentation of +{@link android.graphics.BitmapFactory BitmapFactory}, +{@link android.graphics.Bitmap Bitmap}, and {@link android.graphics.Canvas Canvas} for more information on auto-scaling.</p> @@ -973,7 +1058,7 @@ auto-scaled at draw time.</p> <p>If you have already developed and published an Android application based on Android 1.5 or earlier platform version, you need to consider how you will adapt -your application so that it is deployable to </p> +your application so that it is deployable to:</p> <ul> <li>Existing devices, which may be running Android 1.5 (or lower) platform @@ -982,16 +1067,21 @@ version, as well as to </li> screen sizes and resolutions</li> </ul> +<p class="note"><strong>Note:</strong> Even if your application targets Android 1.6 already, you +should follow the same strategies below in order to support <em>xhdpi</em> and <em>xlarge</em> +screens on Android 2.3 (API Level 9), while maintaining compatibility with older versions of +the platform.</p> + <p>To support the newer devices and the different screens they use, you might need to make some changes in your app, but at the same time your app may be very stable and so you want to minimize the changes. There are a variety of ways that you can extend your existing application to support new devices with multiple screens <em>and</em> existing devices running older platform versions. You should be able to make these changes to your application such that you can -distribute a single .apk to any and all devices.</p> +distribute a single {@code .apk} to all devices.</p> <p>The recommended strategy is to develop against the most recent version of the -platform you are targeting, and test on the minimum one you want to run on. +platform you are targeting, and test on the minimum platform version you want to run on. Here's how to do that:</p> <ol> @@ -999,39 +1089,41 @@ Here's how to do that:</p> <code>android:minSdkVersion</code> attribute as it is. You <em>do not</em> need to increment the value of the attribute to support new devices and multiple screens. </li> - <li>Extend compatibility for Android 1.6 (and higher) devices by adding + <li>Extend compatibility for Android 1.6 (and higher) devices by adding a new attribute — <code>android:targetSdkVersion</code> — to the <code>uses-sdk</code> element. Set the value of the attribute to -"<code>4</code>". This allows your application to "inherit" the platform's +<code>"4"</code>. [To support <em>xhdpi</em> and <em>xlarge</em> screens, set the value to +<code>"9"</code>.] This allows your application to "inherit" the platform's multiple screens support, even though it is technically using an earlier version of the API. </li> <li>Add an empty <code><supports-screens></code> element as a child of <code><manifest></code>. If you need to enable size or density attributes later, this is where you will add them.</li> <li>Change your application's build properties, such that it compiles against -the Android 1.6 (API Level 4) library, rather than against the Android 1.5 (or +the Android 1.6 (API Level 4) library [or against Android 2.3 (API Level 9) to support +<em>xhdpi</em> and <em>xlarge</em> screens], rather than against the Android 1.5 (or earlier) library. You will not be able to compile your application against the older platform because of the new manifest attribute. </li> - <li>Set up AVDs for testing your application on Android 1.6 and higher + <li>Set up AVDs for testing your application on Android 1.6 [or Android 2.3] and higher releases. Create AVDs that use the screen sizes and densities that you want to -support. When you create the AVDs, make sure to select the Android 1.6 or higher +support. When you create the AVDs, make sure to select the Android 1.6 [or Android 2.3] or higher platform as the system image to run. For more information, see <a href="#testing">How to Test Your Application on Multiple Screens</a>, below.</li> - <li>Set up AVDs for testing your application on Android 1.5 (or earlier -platform). You need AVDs running the older platforms you are targeting, so that + <li>Set up AVDs for testing your application on older versions of the platform, as low as the +version declared by your <code>android:minSdkVersion</code>. You need AVDs running the older +platforms you are targeting, so that you can test for compatibility and ensure that there are no functional regressions. </li> - <li>Compile your application against the Android 1.6 library and run it on the + <li>Compile your application against the Android 1.6 [or Android 2.3] library and run it on the AVDs you created. Observe the way your application looks and runs, and test all of the user interactions. </li> <li>Debug any display or functional issues. For issues that you resolve in your application code, <span style="color:red">make certain not to use any APIs -introduced in API Level 4 or later</span>. If you are in doubt, refer to SDK -reference documentation and look for the API Level specifier for the API you -want to use. Using an API introduced in API Level 4 or later will mean that your -application will no longer be compatible with devices running Android 1.5 or -earlier.</li> +introduced later than the version declared by your <code>android:minSdkVersion</code></span>. If you +are in doubt, refer to SDK reference documentation and look for the API Level specifier for the API +you want to use. Using newer APIs not supported by your minimum version will mean that your +application will no longer be compatible with devices running on that version.</li> <li>For resource-related issues, you can try resolving them by: <ul> <li>Adding a <code>anyDensity="false"</code> attribute to @@ -1039,22 +1131,22 @@ earlier.</li> scaling.</li> <li>Creating any size- or density-specific resources you need and placing them in directories tagged with the <a href="#qualifiers">correct -qualifiers</a>. Qualifiers must be arranged in a proscribed order. See +qualifiers</a>. Qualifiers must be arranged in a proscribed order. See <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources"> -Alternative Resources</a> for more information. </li> +Providing Alternative Resources</a> for more information. </li> <li>Note that if you add size- or density-specific resource directories tagged with any of the resource qualifiers listed in this document, you should make sure to also tag those directories with the <code>v<api-level></code> -qualifier (for example, <code>-v4</code>). This ensures that those resources +qualifier (for example, <code>-v4</code> to target API Level 4). This ensures that those resources will be ignored when the application is run on Android 1.5 or lower platform versions.</p></li> </ul> </li> <li>If your application does not offer support (such as custom layouts) for large screens and you want the platform to display your application in -screen-compatibility mode on larger screens, add a -<code>largeScreens="false"</code> attribute to the -<code><supports-screens></code> element in the manifest. See +screen-compatibility mode on larger screens, add the +<code>largeScreens="false"</code> and <code>xlargeScreens="false"</code> attributes to the +<code><supports-screens></code> element in the manifest. See <a href="#compatibility-examples">Screen-Compatibility Examples</a> for illustrations of how the platform displays your application in this case.</li> <li>If your application does not offer support (such as custom layouts) for @@ -1077,6 +1169,16 @@ function on a small-screen device. In many cases, the reduced screen area and density mean that you may need to make tradeoffs in design, content, and function on those devices. </p> +<p>Also give extra attention to testing your application on an AVD that emulates an <em>xlarge</em> +screen. Devices with extra large screens +are tablet-sized or larger, so you should pay close attention to how usable your application is on +such screens. You might want to design new layouts specifically for extra large screens, to address +usability aspects such as the location and size of buttons in your UI. To test your application on +an extra large screen, create an AVD targeted to Android 2.3 with a high resolution, such as 1280 x +800, and the default density of 160dpi. This AVD will use any resources you've provided with the +<code>xlarge</code> <a href="#qualifiers">resouce qualifier</a>.</p> + + <h2 id="testing">How to Test Your Application on Multiple Screens</h2> <p>Before publishing an application that supports multiple screens, you should @@ -1091,22 +1193,22 @@ not. Once you've tested your application and found that it displays properly on various screen sizes, you should make sure to add the corresponding size attribute(s) to your application's manifest. --> -<div id="f9.5" style="float:right;margin:0;padding:0;"> - <img src="{@docRoot}images/screens_support/avds-config.png" style="padding:0;margin:0;"> - <p class="caption" style="margin:0 0 1.5em 1em;padding:0 0 0 1em;"><strong>Figure 4.</strong> +<div id="f9.5" class="figure" style="width:530px"> + <img src="{@docRoot}images/screens_support/avds-config.png" /> + <p class="img-caption"><strong>Figure 4.</strong> A typical set of AVDs for testing screens support.</p> </div> <p>As a test environment for your applications, set up a series of AVDs that emulate the screen sizes and densities you want to support. The Android SDK -includes six emulator skins to get you started. You can use the Android AVD +includes several emulator skins to get you started. You can use the Android AVD Manager or the <code>android</code> tool to create AVDs that use the various emulator skins and you can also set up custom AVDs to test densities other than -the defaults. For general information about working with AVDs, see +the defaults. For general information about working with AVDs, see <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>.</p> -<p>The Android SDK provides a set of default emulator skins that you can use for +<p>The Android SDK provides a set of default emulator skins that you can use for testing. The skins are included as part of each Android platform that you can install in your SDK. The Android 1.6 platform offers these default skins:</p> @@ -1125,7 +1227,7 @@ install in your SDK. The Android 1.6 platform offers these default skins:</p> </li> </ul> -<p>The Android 2.0 platform offers all of the Android 1.6 default skins, +<p>The Android 2.0 platform offers all of the Android 1.6 default skins, above, plus:</p> <ul> @@ -1161,15 +1263,15 @@ scale the entire emulator display, based on both the dpi of the skin and of your monitor. The default emulator skins included in the Android SDK are listed in <a href="#screens-table">Table 1</a>, earlier in this document.</p> -<div style="float: right;background-color:#fff;margin: 0;padding: 20px 0 20px 20px;width:520px;"> - <img src="{@docRoot}images/screens_support/avd-density.png" style="padding:0;margin:0;"> - <p class="caption" style="margin:0 0 1.5em 1em;padding:0 0 0 1em; width:280px;"><strong>Figure 5.</strong> +<div class="figure" style="width:324px"> + <img src="{@docRoot}images/screens_support/avd-density.png" > + <p class="img-caption"><strong>Figure 5.</strong> Resolution and density options that you can use, when creating an AVD using the AVD Manager.</p> </div> <p>You should also make sure to test your application on different physical -screen sizes within a single size-density configuration. For example, to -display this screen configuration on a 30" monitor you will need to adjust +screen sizes within a single size-density configuration. For example, to +display this screen configuration on a 30" monitor you will need to adjust the value passed to <code>-scale</code> to 96*2.8/3.3 = 81dpi. You can also pass a float value to <code>-scale</code> to specify your own scaling factor:</p> @@ -1201,7 +1303,7 @@ or "240" for a high-density screen.</li> <li>Set any other hardware options and complete the AVD creation.</li> </ol> -<p>In the example above (WVGA medium density), the new AVD will emulate a 5.8" +<p>In the example above (WVGA medium density), the new AVD will emulate a 5.8" WVGA screen.</p> <p>As an alternative to adjusting the emulator skin configuration, you can use @@ -1216,21 +1318,21 @@ to the emulator command line when starting the AVD. For example, </p> <p>This section provides examples of how the Android platform displays an application written for the baseline screen configuration — HVGA (320x480) resolution on a 3.2" screen — with all of the platform's size- and -density-compatibility features enabled. That is, the examples show how -the platform displays an application that doesn't provide built-in support +density-compatibility features enabled. That is, the examples show how +the platform displays an application that doesn't provide built-in support for the screen on which it is being rendered, but which instead relies completely on the platform.</p> -<p>The platform's screen-compatibility features are designed to provide such -an application with a virtual baseline screen environment against which to run, -while at the same time ensuring for the user a physical display that is +<p>The platform's screen-compatibility features are designed to provide such +an application with a virtual baseline screen environment against which to run, +while at the same time ensuring for the user a physical display that is approximately the same as the baseline screen size and density. </p> <p>Legacy applications that have not been modified to support multiple -screens would be typical examples of such applications. In most cases, +screens would be typical examples of such applications. In most cases, you would want to add multiple-screens support to a legacy application and publish an updated version, as described in <a href="#strategies">Strategies -for Legacy Applications</a>. However, if you did not do so, the +for Legacy Applications</a>. However, if you did not do so, the platform still performs best-effort rendering of your application, as illustrated below.</p> @@ -1248,9 +1350,9 @@ density is low density (160 -> 120 virtual dpi). </li> <li> If the device's screen size is <em>small</em>, there are few options -options for making Android 1.5 applications work well on such a screen, so +options for making Android 1.5 applications work well on such a screen, so Android Market will filter applications that are not known to support these -screens from the device. +screens from the device. </li> <li> If the device's screen size is <em>large</em>, it limits the application's diff --git a/docs/html/guide/topics/fragments/index.jd b/docs/html/guide/topics/fragments/index.jd new file mode 100644 index 0000000..ce10ef7 --- /dev/null +++ b/docs/html/guide/topics/fragments/index.jd @@ -0,0 +1,648 @@ +page.title=Fragments +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + + <h2>Quickview</h2> + <ul> + <li>Decompose application functionality and UI into reusable modules</li> + <li>Add multiple fragments to a screen to avoid switching activities</li> + <li>Fragments have their own lifecycle, state, and back stack</li> + <li>Fragments require API Level HONEYCOMB or greater</li> + </ul> + + <h2>In this document</h2> + <ol> + <li><a href="#Creating">Creating fragments</a></li> + <li><a href="#Adding">Adding a fragment to an activity</a></li> + <li><a href="#Managing">Managing fragments</a></li> + <li><a href="#Lifecycle">Handling the lifecycle</a></li> + <li><a href="#Integrating">Integrating with the activity</a></li> + <li><a href="#Menus">Adding menus</a></li> + </ol> + + <h2>Key classes</h2> + <ol> + <li>{@link android.app.Fragment}</li> + <li>{@link android.app.FragmentManager}</li> + <li>{@link android.app.FragmentTransaction}</li> + </ol> + + <!-- + <h2>Related samples</h2> + <ol> + <li><a +href="{@docRoot}resources/samples/NotePad/index.html">NotePad</a></li> + </ol> + --> +</div> +</div> + + +<p>An {@link android.app.Activity} is always the window in which users interact with your +application, but a {@link android.app.Fragment} can be responsible for distinct operations and UI +that's embedded in an activity. So, when using fragments, your activity becomes more like a +container for fragments that define the activity's behavior and UI.</p> + +<p>Fragments have their own +set of lifecylce callback methods and recieve their own user input events. A fragment must always be +embedded in an activity and the fragment's lifecycle is directly affected by the activity's +lifecycle. For example, when the activity is stopped, so are all fragments in it, and when +the activity is destroyed, so are all fragments. However, while an activity +is active (in the "resumed" lifecycle stage), you can manipulate the lifecycle of each fragment +independently. For example, you can add and remove fragments while the activity is active and you +can add each fragment to a back stack within the activity—each back stack entry in the +activity is actually a record of a "transaction" that occurred with the activity's fragments, so +that the user can reverse the transaction with the BACK key (this is discussed more later).</p> + +<div class="figure" style="width:314px"> +<img src="{@docRoot}images/fragment_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> The lifecycle of a fragment (while its +activity is running).</p> +</div> + +<p>Android introduced fragments in Android X.X (API Level HONEYCOMB), with the primary intention to +support more dynamic and flexible UI designs on large screen devices, such as tablets. Because a +tablet has a much larger screen than a mobile phone, there's more room to interchange UI +elements. Fragments allow that without the need for you to start a new activity or manage complex +changes to the view hierarchy. By dividing the layout of an activity into fragments, the code +that defines your activity becomes more modular and interchangable, allowing you to modify the +activity's appearance at runtime and for different types of screens.</p> + +<p>For example, a news application can use one fragment to show a list of articles on the +left and another fragment to display an article on the right—both fragments appear in one +activity, side by side, and each fragment has its own set of lifecycle callback methods and handle +their own user input events. Thus, instead using one activity to select an article and another +activity to read the article, the user can select an article and read it all within the same +activity.</p> + +<!-- ** TODO: Save this for later or move it down in the doc so the intro isn't overwhelming ** + +<p>A fragment can be a modular and reusable component in your application. That is, because +the fragment defines its own behavior using its own set of lifecycle callbacks, you can +include one fragment in multiple activities. This also enables you to create one version of your +application for multiple screen sizes. For instance, on an extra large screen (<em>xlarge</em> +screen configuration), you can embed two or more fragments in one activity, but on a normal-sized +screen (<em>normal</em> screen configuration), you can embed just one fragment in an activity and +then start other activities in order to display the other fragments.</p> +--> + +<p>When you use a fragment as a part of your layout, it technically lives within a {@link +android.view.View} of the activity's layout and defines its own layout of views. You can insert a +fragment into your activity layout by declaring the fragment in the activity's XML layout file, as +a {@code <fragment>} element, or from your application code by adding it to an existing {@link +android.view.View}. However, a fragment is not required to be a part of the activity +layout—you might use a fragment as an invisible worker for the activity (more about that +later).</p> + +<p>The rest of this document describes how to build your application to use fragments, including +how fragments can contribute to the activity options menu and action bar, create context menus, +maintain their state when added to the activity's back stack, and more.</p> + + + +<h2 id="Creating">Creating a Fragment</h2> + +<p>An implementation of the {@link android.app.Fragment} class contains code that looks a lot like +the code in an {@link android.app.Activity}. In fact, if you're +converting an existing Android application to use fragments, you'll move code +from your {@link android.app.Activity} implementation into your {@link android.app.Fragment} class +implementation, and into some of the same callback methods. A fragment contains callback methods +similar to an activity, such as {@link android.app.Fragment#onCreate onCreate()}, {@link +android.app.Fragment#onStart onStart()}, {@link android.app.Fragment#onPause onPause()}, and {@link +android.app.Fragment#onStop onStop()}.</p> + +<p>If you're creating a fragment to be a modular piece of an activity UI, then your +implementation of {@link android.app.Fragment} should include most of the same lifecycle +callback methods traditionally implemented by the activity to initialize elements of the UI and +save and restore state information. Usually, you'll want to implement the following methods:</p> + +<dl> + <dt>{@link android.app.Fragment#onCreate onCreate()}</dt> + <dd>The system calls this when creating the fragment. Within your implementation, you should +initialize the essential components of the fragment that should be retained when the fragment is +paused or stopped.</dd> + <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> + <dd>The system calls this when it's time for the fragment to draw its user interface for the +first time. To draw a UI for your fragment, you must return a {@link android.view.View} from this +method that is the root of your fragment's layout. You can return null if the fragment does not +provide a UI.</dd> + <dt>{@link android.app.Activity#onPause onPause()}</dt> + <dd>The system calls this method as the first indication that the user is leaving the +fragment (though it does not always mean the fragment is being destroyed). This is usually where you +should commit any changes that should be persisted beyond the current user session (because +the user might not come back).</dd> +</dl> + +<p>Most applications should implement at least these three methods for each fragment, but there are +several other lifecycle callback methods that you should also use in order to provide the best +user experience when switching fragments and when the activity is paused or stopped. All of the +lifecycle callback methods are discussed more later, in +the section about <a href="#Lifecycle">Handling the Lifecycle</a>.</p> + + +<p>There are also a few different subclasses of {@link android.app.Fragment} that you might want +to use:</p> + +<dl> + <dt>{@link android.app.DialogFragment}</dt> + <dd>Displays a floating dialog. Using this class to create a dialog is a good alternative to using +the dialog helper methods in the {@link android.app.Activity} class, because the dialog can be +incorporated into the fragment back stack managed by the activity.</dd> + + <dt>{@link android.app.ListFragment}</dt> + <dd>Displays a list of items that are managed by an adapter (such as a {@link +android.widget.SimpleCursorAdapter}), similar to {@link android.app.ListActivity}. Provides methods +for managing a list, such as the {@link +android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} callback to +handle click events on list items.</dd> + + <dt>{@link android.preference.PreferenceFragment}</dt> + <dd>Displays a hierarchy of {@link android.preference.Preference} objects as a list, similar to +{@link android.preference.PreferenceActivity}. </dd> +</dl> + +<p>However, subclassing the standard {@link android.app.Fragment} class is most common, if +you're not creating a dialog, a list, or displaying preferences.</p> + + +<h3 id="UI">Providing a user interface</h3> + +<p>To provide a UI layout for a fragment, you must implement +the {@link android.app.Fragment#onCreateView onCreateView()} +callback method in your {@link android.app.Fragment} (unless your fragment is a subclass of +{@link android.app.ListFragment}, which returns a {@link android.widget.ListView} from this method +by default). The Android system calls {@link android.app.Fragment#onCreateView onCreateView()} when +it's time for the fragment to draw its layout. Your implementation of this method must return a +{@link android.view.View} that is the root of your fragment's layout.</p> + +<p>The easiest way to provide your layout is to inflate it from a <a +href="{@docRoot}guide/topics/resources/layout-resource.html">layout resource</a>. To help you +inflate a layout, the {@link android.app.Fragment#onCreateView onCreateView()} method passes a +{@link android.view.LayoutInflater} that you can use to get your layout. For example, here's a +simple subclass of {@link android.app.Fragment} that contains an implementation of {@link +android.app.Fragment#onCreateView onCreateView()} that loads the fragment's layout from a +resource:</p> + +<pre> +public static class SimpleFragment extends Fragment { + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.simple_fragment, container, false); + } +} +</pre> + +<p>The {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} method takes +three arguments:</p> +<ul> + <li>The resource ID of the layout you want to inflate</li> + <li>The {@link android.view.ViewGroup} to be the parent of the +inflated layout (supplying this is important in order to apply layout parameters from the parent +view)</li> + <li>And a boolean indicating whether the inflated layout should be attached to the {@link +android.view.ViewGroup} (from the second parameter) during inflation (in this case, this +is false because the system is already going to insert the layout into the appropriate parent +view—doing otherwise would create a redundant view group in the final layout)</li> +</ul> + +<p>The {@code container} parameter passed to {@link android.app.Fragment#onCreateView +onCreateView()} provides the parent {@link android.view.ViewGroup} in which your fragment layout +will be inserted, which you can use to generate layout parameters for your +fragment layout. The {@code savedInstanceState} parameter is a {@link android.os.Bundle} that +provides data about the previous instance of the fragment, if the fragment is being resumed +(restoring state is discussed more in the section about <a href="#Lifecycle">Handling the +Lifecycle</a>.</p> + + +<h3 id="Adding">Adding a Fragment to an Activity</h3> + +<p>Each fragment is embedded into the layout of its container activity as a part of the overall view +hierarchy, whether or not it actually provides a UI. If a fragment is not embedded into the activity +layout, then it is never created (it does not receive any lifecycle callbacks). There are two ways +you can add a fragment to the activity layout:</p> + +<ul> + <li><b>Declare the fragment inside the activity's layout XML file.</b> +<p>In this case, you can +specify layout properties for the fragment as if it were a view itself and the fragment's layout +fills that space. For example:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <fragment android:name="com.example.news.ArticleListFragment" + android:id="@+id/list" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent" /> + <fragment android:name="com.example.news.ArticleReaderFragment" + android:id="@+id/viewer" + android:layout_weight="2" + android:layout_width="0dp" + android:layout_height="match_parent" /> +</LinearLayout> +</pre> + <p>The {@code <fragment>} element uses the {@code android:name} attribute to specify the +{@link android.app.Fragment} class to instantiate and insert into the layout. When the activity +layout is created, the system instantiates each fragment in the layout and calls its {@link +android.app.Fragment#onCreateView onCreateView()} method in order to retrieve the fragment's +layout. The {@link android.view.View} object returned by {@link +android.app.Fragment#onCreateView onCreateView()} is then +placed directly in the activity layout in place of the {@code <fragment>} element.</p> + +<div class="note"> + <p><strong>Note:</strong> Each fragment requires a unique identifier that +the system can use to restore the fragment if the activity is restarted (and which you can use to +perform fragment transactions). There are three ways to identify a fragment:</p> + <ul> + <li>Supply the {@code android:id} attribute with a unique ID, in the {@code +<fragment>}</li> + <li>Supply the {@code android:tag} attribute with a unique string ID, in the {@code + <fragment>}</li> + <li>If neither of the previous two are provided, the system uses the ID of the container + view.</li> + </ul> +</div> + </li> + + <li><b>Or, programmatically add the fragment to an existing {@link android.view.ViewGroup}.</b> +<p>At any time while your activity is running (in the "resumed" state), you can add (and remove) +fragments to your activity layout. You simply need to specify a {@link android.view.ViewGroup} in +which to place the fragment.</p> + <p>To make any fragment transactions in your activity (such as add, remove, or replace a +fragment), you must use APIs from {@link android.app.FragmentTransaction}. You can get an instance +of {@link android.app.FragmentTransaction} from your {@link android.app.Activity} using {@link +android.app.Activity#openFragmentTransaction()}. You can then add a fragment using the {@link +android.app.FragmentTransaction#add add()} method, specifying the fragment to add and the view in +which to insert it. For example:</p> +<pre> +MyFragment fragment = new MyFragment(); +openFragmentTransaction().add(R.id.fragment_container, fragment).commit(); +</pre> + <p>The first argument passed to {@link android.app.FragmentTransaction#add add()} +is the {@link android.view.ViewGroup} in which the fragment should be placed, specified by +resource ID, and the second parameter is the fragment object.</p> + <p>Once you've made your changes using +{@link android.app.FragmentTransaction}, you must +call {@link android.app.FragmentTransaction#commit} in order for the changes to take effect.</p> + </li> +</ul> + + +<h3 id="Example1">Example: simple fragments</h3> + +<p>In the last couple sections, you saw how to declare layout for a fragment and add it to an +activity. What follows is some code that brings it all together, like a "Hello World" for +fragments.</p> + +<p>First, here's a layout file for a fragment:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" > +<TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/hello" /> +<TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/hello" /> +</LinearLayout> +</pre> + +<p>With that file saved at {@code res/layout/simple_fragment.xml}, the following {@link +android.app.Fragment} uses it for its layout:</p> + +<pre> +public static class SimpleFragment extends Fragment { + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.simple_fragment, null); + } +} +</pre> + +<p>And the following layout for an activity applies the fragment twice, side by side:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <fragment android:name="com.example.SimpleFragment" + android:id="@+id/list" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent" /> + <fragment android:name="com.example.SimpleFragment" + android:id="@+id/viewer" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent" /> +</LinearLayout> +</pre> + +<p>That's it. When an activity applies the previous layout as its content, the {@code +SimpleFragment} class is instantiated for each occurence in the layout, applying the fragment +layout when it receives the call to {@link android.app.Fragment#onCreateView onCreateView()}.</p> + +<p>Although the fragment in this example implements only the {@link +android.app.Fragment#onCreateView onCreateView()} callback, there are several other lifecycle +callback methods that you should implement in your application. For example, {@link +android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onPause onPause()}, {@link +android.app.Fragment#onStop onStop()} and others that coincide with the fragment's lifecycle.</p> + + + +<h2 id="Managing">Managing Fragments</h2> + +<p>A useful feature of fragments is the ability to add, remove, replace, and perform other +operations on a fragment as the user interacts with the activity, alowing for more rich user +experiences without changing activities. In order to perform these operations, you must use {@link +android.app.FragmentTransaction} to perform fragment "transactions." You can acquire {@link +android.app.FragmentTransaction} from your activity with {@link +android.app.Activity#openFragmentTransaction}.</p> + +<p>Common transactions you can perform with fragments include:</p> + +<dl> + <dt>{@link android.app.FragmentTransaction#add add()}</dt> + <dd>Add a {@link android.app.Fragment} to the {@link android.app.Activity} layout.</dd> + <dt>{@link android.app.FragmentTransaction#remove remove()}</dt> + <dd>Remove a {@link android.app.Fragment} from the {@link android.app.Activity} layout.</dd> + <dt>{@link android.app.FragmentTransaction#replace replace()}</dt> + <dd>Replace an existing {@link android.app.Fragment} with another one.</dd> +</dl> + +<p>For every transaction (or set of transactions) you perform, you must call {@link +android.app.FragmentTransaction#commit} in order for the transactions made with {@link +android.app.FragmentTransaction} to be applied. Before you do, however, you can call {@link +android.app.FragmentTransaction#addToBackStack} to add the current fragment state to the +activity's back stack, so that the user can return to the previous fragment state with the BACK key. +For example, here's how a new fragment can replace another one, but keep the previous fragment +in the back stack:</p> + +<pre> +// Create new fragment +Fragment newFragment = new MyFragment(); +FragmentTransaction ft = openFragmentTransaction(); +// Replace and add to back stack +ft.replace(newFragment, R.id.myfragment); +ft.addToBackStack(null); +// Apply changes +ft.commit(); +</pre> + +<p>In this example, {@code newFragment} replaces whatever fragment is currently in the +layout container identified by the {@code R.id.myfragment} ID. By calling {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, this transaction (the replace) is +saved to the activity's back stack so that the user can reverse this change and bring back the +previous fragment by pressing the BACK key.</p> + +<p>If you perform multiple transactions and call {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, then all transactions performed +before {@link android.app.FragmentTransaction#commit} are added to the activity's back stack as a +single event and the BACK key will reverse them all together.</p> + + + +<h2 id="Lifecycle">Handling the Lifecycle</h2> + +<p>A fragment has a lifecycle that corresponds to the lifecycle of the activity in which it +resides. For example, a fragment has callback methods {@link +android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()}, {@link +android.app.Fragment#onPause onPause()}, {@link android.app.Fragment#onStop onStop()}, and more.</p> + +<p>The lifecycle of the activity directly affects the lifecycle of the fragment, such that each +lifecycle callback for the activity results in a similar callback for each fragment (for +example, when the activity receives {@link android.app.Activity#onPause}, each fragment receives +{@link android.app.Fragment#onPause}). However, the +fragment's lifecycle can also change independently—but only while the activity is +resumed (while it is in the foreground)—because you can dynamically +add, remove, and replace fragments without any change to the lifecycle of the activity.</p> + +<p>To accomodate backward navigation with the +BACK key, you can optionally maintain a back stack of fragment transactions, as described in the +previous section. So, if you +replace one fragment with another, the user can press the BACK key and view the previous +fragment. Additionally, each fragment can maintain its own state, such that +when the user navigates back to a previous fragment, the state of that fragment can be restored in +the same manner as the state of an activity is restored when it is stopped and restarted.</p> + +<p>Managing the lifecycle of a fragment is a lot like managing the lifecycle of an activity. A +fragment and an activity both have an "resumed," "paused," and "stopped" state, and they can both +retain their state using a {@link android.os.Bundle}. The only significant difference is that an +activity is placed into a the task's back stack by default (so that the user can navigate to +the previous activity with the BACK key), but a fragment is placed into the activity's back stack +only when you explicitly call {@link android.app.FragmentTransaction#addToBackStack(String) +addToBackStack()} before you {@link android.app.FragmentTransaction#commit()} a fragment +transaction.</p> + +<p>The order in which you perform transactions with {@link android.app.FragmentTransaction} doesn't +matter, except:</p> +<ul> + <li>You must call {@link android.app.FragmentTransaction#commit()} last</li> + <li>If you're adding multiple fragments to the same container, then the order in which +you add them determines the order they appear</li> +</ul> +<p>If you do not call {@link android.app.FragmentTransaction#addToBackStack(String) +addToBackStack()} when you perform a transaction that removes a fragment, then that fragment is +destroyed when the transaction is committed.</p> + + +<h3 id="CoordinatingWithTheActivity">Coordinating with the activity lifecycle</h3> + +<p>The lifecycle of an activity directly affects the lifecycle of a {@link android.app.Fragment} +embedded in that activity. The {@link android.app.Fragment} class has lifecycle callback +methods that match those in the {@link android.app.Activity} class.</p> + +<p>Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the +activity in order to perform actions such as build and destroy the fragment's UI. These additional +callback methods are:</p> + +<dl> + <dt>{@link android.app.Fragment#onAttach onAttach()}</dt> + <dd>Called when the fragment has been associated with the activity (the {@link +android.app.Activity} is passed in here).</dd> + <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> + <dd>Called to create the view hierarchy associated with the fragment.</dd> + <dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt> + <dd>Called when the activity's own {@link android.app.Activity#onCreate +onCreate()} has finished.</dd> + <dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt> + <dd>Called when the view hierarchy associated with the fragment is being removed.</dd> + <dt>{@link android.app.Fragment#onDetach onDetach()}</dt> + <dd>Called when the fragment is being disassociated from the activity.</dd> +</dl> + +<p>The flow of a fragment's lifecycle, as it is affected by its container activity, is illustrated +by figure 3. In this figure, you can see how each successive state of the activity determines which +callback methods the fragment may receive. For example, when the activity has received +its {@link android.app.Activity#onCreate onCreate()} callback, the fragment receives no more +than the {@link android.app.Fragment#onActivityCreated onActivityCreated()} callback. However, +once the activity reaches the resumed state, you can freely add and remove fragments to the +activity, so the fragment lifecycle is no longer inhibitted by the state of the activity. Yet, +when the activity leaves the resumed state, the fragment again is pushed through its lifecycle by +the activity (unless you explicitly destroy the fragment sooner).</p> + + +<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt=""/> +<p class="img-caption"><strong>Figure 3.</strong> The activity lifecycle's affect on the lifecycle +of a fragment.</p> + + +<h3 id="Integrating">Integrating with the Activity</h3> + +<p>Although a {@link android.app.Fragment} is implemented separate from an {@link +android.app.Activity} and can be used inside multiple activities, a fragment is directly tied to its +container activity and can access the Activity instance with {@link +android.app.Fragment#getActivity()}. So, a fragment can +easily perform tasks such as find a view in the activity:</p> + +<pre> +View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list); +</pre> + +<p>This makes it easy for your fragment to call public methods in the activity.</p> + +<p>Likewise, your activity can call public methods in the fragment when you have a reference to the +{@link android.app.Fragment}. You can acquire a reference to the fragment with {@link +android.app.Activity#findFragmentById findFragmentById()} and cast it to your implementation of +{@link android.app.Fragment}. For example:</p> + +<pre> +MyFragment fragment = (MyFragment) findFragmentById(R.id.myfragment); +fragment.refreshList(); +</pre> + + +<h4 id="Callbacks">Creating event callbacks to the activity</h4> + +<p>In some cases, you might need a fragment to share events with the activity. A good way to do that +is to define a callback interface inside the fragment and require that the host activity implement +it. When the activity receives a callback, it can share the information with other fragments in the layout as +necessary.</p> + +<p>For example, if a news application has two fragments in an activity—one to show a list of +articles (fragment A) and another to display an article (fragment B)—then fragment A must tell +the activity when a list item is selected so that it can tell fragment B to display the article. In +this case, the following interface is defined inside fragment A:</p> + +<pre> +public static class FragmentA extends ListFragment { + ... + // Container Activity must implement this interface + public interface SelectedCallback { + public void onArticleSelected(Uri articleUri); + } + ... +} +</pre> + +<p>Then the activity that hosts the fragment implements the {@code SelectedCallback} interface and +overrides {@code onArticleSelected()} to notify fragment B of the event from fragment A. To ensure +that the host activity implements this interface, fragment A's {@link +android.app.Fragment#onAttach onAttach()} callback method (called when +the fragment is added to the activity) instantiates an instance of {@code SelectedCallback} by +casting the {@link android.app.Activity} that is passed into {@link android.app.Fragment#onAttach +onAttach()}:</p> + +<pre> +public static class FragmentA extends ListFragment { + ... + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + mCallback = (SelectedCallback) activity; + } catch (ClassCastException e) { + activity.finish(); + throw new ClassCastException(activity.toString() + " must implement SelectedCallback"); + } + } + ... +} +</pre> + +<p>If the activity has not implemented the interface, then a {@link java.lang.ClassCastException} is +thrown and the activity is shut down. On success, the {@code mCallback} member holds a reference to +the {@link android.app.Activity}, so that fragment A can share events with the activity by calling +methods defined by the {@code SelectedCallback} interface. For example, if fragment A is an +extension of {@link android.app.ListFragment}, each time +the user clicks a list item, the system calls {@link android.app.ListFragment#onListItemClick +onListItemClick()} in the fragment, which then calls {@code onArticleSelected()} to share +the event with the activity:</p> + +<pre> +public static class FragmentA extends ListFragment { + ... + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + // Append the clicked item's row ID with the content provider Uri + Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id); + // Send the event and Uri to the host activity + mCallback.onArticleSelected(noteUri); + } + ... +} +</pre> + +<p>The {@code id} parameter passed to {@link +android.app.ListFragment#onListItemClick onListItemClick()} is the row ID of the clicked item, +which the activity (or other fragment) uses to fetch the article from the application's {@link +android.content.ContentProvider}.</p> + +<p><!--To see a complete implementation of this kind of callback interface, see the <a +href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->More information about +using a content provider is available in the <a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> document.</p> + + + + + + +<h2 id="Menus">Adding Action Items to the Activity</h2> + +<p>Your fragments can contribute action items to the activity's <a +href="{@docRoot}guide/topics/ui/actionbar.html">action bar</a> (and menu items to the options menu) +using the callback methods +{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. In order +for this method to receive calls, however, you must call {@link +android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} during the {@link +android.app.Fragment#onCreate(Bundle) onCreate()} callback in order to indicate that the fragment +would like to receive a call to {@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) +onCreateOptionsMenu()}. Any action or menu items that you add from the fragment are appended to the +existing +items for the options menu (including those added by other fragments in the activity). The +fragment also receives item-selected events with the {@link +android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} callback method.</p> + +<p>The {@link android.app.Fragment} class also contains methods to handle context menus. You can +register a view to provide a context menu with {@link +android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. When the user opens +the context menu, the fragment receives a call to {@link +android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) +onCreateContextMenu()}. When the user selects an item, the fragment receives a call to {@link +android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p> + +<p>For more information, see <a href="{@docRoot}guide/topics/ui/menus.html">Creating +Menus</a> and <a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a>.</p> + + + + + + diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd index e030a4c..2648cb7 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -290,7 +290,8 @@ activity is ignored. The activity is not re-parented, but destroyed. <dd>An icon representing the activity. The icon is displayed to users when a representation of the activity is required on-screen. For example, icons for activities that initiate tasks are displayed in the launcher window. -The icon is often accompanied by a label (see the {@code label} attribute). +The icon is often accompanied by a label (see the <a href="#label">{@code +android:label}</a> attribute). </p> <p> diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd index 9ac07fd..1fadc6e 100644 --- a/docs/html/guide/topics/manifest/application-element.jd +++ b/docs/html/guide/topics/manifest/application-element.jd @@ -12,6 +12,7 @@ page.title=<application> android:<a href="#icon">icon</a>="<i>drawable resource</i>" android:<a href="#killrst">killAfterRestore</a>=["true" | "false"] android:<a href="#label">label</a>="<i>string resource</i>" + android:<a href="#logo">logo</a>="<i>drawable resource</i>" android:<a href="#space">manageSpaceActivity</a>="<i>string</i>" android:<a href="#nm">name</a>="<i>string</i>" android:<a href="#prmsn">permission</a>="<i>string</i>" @@ -121,7 +122,7 @@ each of the application's components. See the individual <p> This attribute must be set as a reference to a drawable resource containing -the image definition. There is no default icon. +the image (for example {@code "@drawable/icon"}). There is no default icon. </p></dd> <dt><a name="killrst"></a>{@code android:killAfterRestore}</dt> @@ -154,6 +155,11 @@ However, as a convenience while you're developing the application, it can also be set as a raw string. </p></dd> +<dt><a name="logo"></a>{@code android:logo}</dt> +<dd>A logo for the application as whole, and the default logo for activities. +<p>This attribute must be set as a reference to a drawable resource containing +the image (for example {@code "@drawable/logo"}). There is no default logo.</p></dd> + <dt><a name="space"></a>{@code android:manageSpaceActivity}</dt> <dd>The fully qualified name of an Activity subclass that the system can launch to let users manage the memory occupied by the application diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd index d868599..4f3b0da 100644 --- a/docs/html/guide/topics/resources/providing-resources.jd +++ b/docs/html/guide/topics/resources/providing-resources.jd @@ -329,7 +329,8 @@ indicates the current locale.</p> <td> <code>small</code><br/> <code>normal</code><br/> - <code>large</code> + <code>large</code><br/> + <code>xlarge</code> </td> <td> <ul class="nolist"> @@ -347,6 +348,10 @@ indicates the current locale.</p> medium-density VGA screen. Such a screen has significantly more available space in both width and height than an HVGA display. Examples are VGA and WVGA medium density screens.</li> + <li>{@code xlarge}: Screens that are considerably larger than the traditional + medium-density HVGA screen. In most cases, devices with extra large screens would be too +large to carry in a pocket and would most likely be tablet-style devices. <em>Added in API Level +9.</em></li> </ul> <p><em>Added in API Level 4.</em></p> <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple @@ -437,6 +442,7 @@ application during runtime.</p> <code>ldpi</code><br/> <code>mdpi</code><br/> <code>hdpi</code><br/> + <code>xhdpi</code><br/> <code>nodpi</code> </td> <td> @@ -445,6 +451,8 @@ application during runtime.</p> <li>{@code mdpi}: Medium-density (on traditional HVGA) screens; approximately 160dpi.</li> <li>{@code hdpi}: High-density screens; approximately 240dpi.</li> + <li>{@code xhdpi}: Extra high-density screens; approximately 320dpi. <em>Added in API +Level 8</em></li> <li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled to match the device density.</li> </ul> diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd new file mode 100644 index 0000000..2b942e7 --- /dev/null +++ b/docs/html/guide/topics/ui/actionbar.jd @@ -0,0 +1,332 @@ +page.title=Using the Action Bar +parent.title=User Interface +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + + <h2>Quickview</h2> + <ul> + <li>A replacement for the title bar for displaying global actions for the activity</li> + <li>Provides toolbar actions and modes of navigating around the application</li> + <li>Switches to contextual menu options when one or more items are selected</li> + <li>Requires API Level HONEYCOMB</li> + </ul> + + <h2>In this document</h2> + <ol> + <li><a href="#Adding">Adding the Action Bar</a></li> + <li><a href="#ActionItems">Adding Action Items</a> + <ol> + <li><a href="#Home">Using the application icon as an action item</a></li> + </ol> + </li> + <li><a href="#Tabs">Adding Tabs</a></li> + <li><a href="#Dropdown">Adding Drop-down Navigation</a></li> + <li><a href="#Search">Adding Search</a></li> + </ol> + + <h2>Key classes</h2> + <ol> + <li>{@link android.app.ActionBar}</li> + <li>{@link android.view.Menu}</li> + </ol> + + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a></li> + </ol> +</div> +</div> + +<p>The action bar is a widget for activities that replaces the traditional title bar at +the top of an activity. By default, the action bar includes the application logo on the left side, +followed by the activity title. The action bar offers several useful features for +applications—especially those targeted to tablet devices. The action bar features include +the ability to:</p> + +<ul> + <li>Display menu items from the <a +href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a> as "action +items"—providing instant access to key user actions.</li> + <li>Provide tabs for navigating between <a +href="{@docRoot}guide/topics/fragments/index.html">fragments</a>.</li> + <li>Provide drop-down navigation items.</li> + <li>Embed a {@link android.widget.SearchView} for instant searching.</li> + <li>Use the application logo as a "return home" or "up" navigation action.</li> +</ul> + +<img src="{@docRoot}images/ui/actionbar.png" height="36" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> A screenshot of the action bar in the NotePad +sample application, containing action items to save and delete the note.</p> + + +<h2 id="Adding">Adding the Action Bar</h2> + +<p>To add the Action Bar to your activity, apply the holographic theme—{@code +Theme.Holo}—or the action bar theme—{@code Theme.WithActionBar}—in your manifest +file. For example:</p> + +<pre> +<activity android:theme="@android:style/Theme.Holo" > +</pre> + +<p>The activity now appears with the action bar in place of the traditional title bar.</p> + + +<h2 id="ActionItems">Adding Action Items</h2> + +<p>For each action item you want to add to the action bar, you must add a menu item to the +activity's <a href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a> and declare +that the item be shown as an action, using the {@code android:showAsAction} attribute in the menu +XML or with {@link android.view.MenuItem#setShowAsAction setShowAsAction()} on the {@link +android.view.MenuItem}.</p> + +<div class="figure" style="width:359px"> + <img src="{@docRoot}images/ui/actionbar-item-withtext.png" height="57" alt="" /> + <p class="img-caption"><strong>Figure 2.</strong> A screenshot from an action bar with two +action items.</p> +</div> + +<p>You can specify a menu item to appear as an action item in the action bar—if there is room +for it—from the <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu +resource</a> by declaring {@code +android:showAsAction="ifRoom"} for the {@code <item>} element. This way, the item will display +in the action bar for quick access only if there is room available for it—if there's not +enough room, the item is placed the options menu (revealed by the drop-down icon on the right side +of the action bar). From your application code, you can specify the item to appear as an action item +by calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()} on the {@link +android.view.MenuItem} and passing {@link android.view.MenuItem#SHOW_AS_ACTION_IF_ROOM}.</p> + +<p>If your item supplies both a title and an icon, then the action item shows only +the icon by defult. If you want to include the text with the action item, add the <em>with text</em> +flag—in XML, add {@code withText} to the {@code android:showAsAction} attribute or, in +your application code, use the {@link android.view.MenuItem#SHOW_AS_ACTION_WITH_TEXT} flag when +calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()}. Figure 2 shows a screenshot +of an action bar with two action items that include text.</p> + +<p>Here's an example of how you can declare a menu item as an action item in a <a +href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> file:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_add" + android:icon="@drawable/ic_menu_save" + android:title="@string/menu_save" + <b>android:showAsAction="ifRoom|withText"</b> /> +</menu> +</pre> + +<p>In this case, both the {@code ifRoom} and {@code withText} flags are set, so that when this +item appears as an action item, it includes the title text along with the icon.</p> + +<p>A menu item placed in the action bar triggers the same callback methods as other items in the +options menu. When the user selects an item in the action bar, your activity receives a call to +{@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}, passing the +item ID. (If you added the item from a fragment, then the respective {@link +android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method is called +for that fragment.)</p> + +<p class="note"><strong>Note:</strong> Even menu items that are contained in the options menu +(and not shown as action items) will show an icon, so when using the action bar, you should +provide an icon for every item in the options menu.</p> + +<p>You can also declare an item to <em>always</em> appear as an action item, but you should avoid +doing so. Most of the time, there will be enough room for several action items and they will appear +in the order you declare them. If you set items to always appear as action +items (instead of <em>if room</em>), then they are added without discrimination and there is a risk +that they will collide with other elements in the action bar, such as tabs or custom views.</p> + +<p>For more information about menus, see the <a +href="{@docRoot}guide/topics/ui/menus.html#options-menu">Creating Menus</a> developer guide.</p> + + +<h3 id="Home">Using the application icon as an action item</h3> + +<p>By default, the application icon appears in the action bar on the left side, but does nothing +when tapped. To use the application icon as an action item when tapped, you simply need to add a +condition to your {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method +that performs an action when the {@link android.view.MenuItem} ID is {@code android.R.id.home}. +This ID is delivered every time the user taps the application icon.</p> + +<p>For example, here's an implementation of {@link android.app.Activity#onOptionsItemSelected +onOptionsItemSelected()} that returns to the application's "home" activity:</p> + +<pre> +@Override +public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // app icon in action bar clicked; go home + Intent intent = new Intent(this, HomeActivity.class); + startActivity(intent); + break; + } + return super.onOptionsItemSelected(item); +} +</pre> + +<div class="figure" style="width:144px"> + <img src="{@docRoot}images/ui/actionbar-logo.png" height="140" alt="" /> + <p class="img-caption"><strong>Figure 3.</strong> The standard icon for the Email application +(top) and the "up navigation" icon (bottom).</p> +</div> + +<p>You can also use the application icon to provide "up" navigation. The way you handle the event +when a user taps the icon is the same, but if the user experience for the event is to <em>navigate +up to the parent activity</em>, then you should indicate this behavior by setting the +action bar to "show home as up." You can do so by calling {@link +android.app.ActionBar#setDisplayOptions setDisplayOptions()} on your activity's {@link +android.app.ActionBar}, and passing the {@link +android.app.ActionBar#DISPLAY_HOME_AS_UP} display option.</p> + +<p>To get the {@link android.app.ActionBar}, call {@link android.app.Activity#getActionBar} from +your {@link android.app.Activity} during {@link android.app.Activity#onCreate onCreate()} (but be +sure you do so <em>after</em> you've called {@link android.app.Activity#setContentView +setContentView()}).</p> + +<p>For example, here's how you can change the action bar display mode to show the application +icon as an "up" action:</p> + +<pre> +@Override +protected void onStart() { + super.onStart(); + ActionBar actionBar = this.getActionBar(); + actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP); +} +</pre> + +<p class="caution"><strong>Caution:</strong> If your activity does not have an action bar (if you +did not set the theme of your activity or application to the holographic or action bar theme), then +{@link android.app.Activity#getActionBar} returns null.</p> + + +<h2 id="Tabs">Adding Tabs</h2> + +<p>The action bar can display tabs that allow the user navigate between different fragments in the +activity. Each tab can include a title and/or an icon.</p> + +<p>To begin, your layout must include a {@link android.view.View} in which each {@link +android.app.Fragment} associated with a tab is displayed. Be sure the view has an ID that you +can use to reference it from your code.</p> + +<p>To add tabs to the action bar:</p> +<ol> + <li>Create an implementation of {@link android.app.ActionBar.TabListener} to handle the +interaction events on the action bar tabs. You must implement all methods: {@link +android.app.ActionBar.TabListener#onTabSelected onTabSelected()}, {@link +android.app.ActionBar.TabListener#onTabUnselected onTabUnselected()}, and {@link +android.app.ActionBar.TabListener#onTabReselected onTabReselected()}. + <p>Each callback method passes the {@link android.app.ActionBar.Tab} that received the +event and a {@link android.app.FragmentTransaction} for you to perform the fragment +transactions (add or remove fragments).</p> + <p>For example:</p> +<pre> +private class MyTabListener implements ActionBar.TabListener { + private TabContentFragment mFragment; + + // Called to create an instance of the listener when adding a new tab + public TabListener(TabContentFragment fragment) { + mFragment = fragment; + } + + @Override + public void onTabSelected(Tab tab, FragmentTransaction ft) { + ft.add(R.id.fragment_content, mFragment, null); + } + + @Override + public void onTabUnselected(Tab tab, FragmentTransaction ft) { + ft.remove(mFragment); + } + + @Override + public void onTabReselected(Tab tab, FragmentTransaction ft) { + // do nothing + } + +} +</pre> + <p>This implementation of {@link android.app.ActionBar.TabListener} adds a constructor +that saves the {@link android.app.Fragment} associated with a tab so that each callback +can add or remove that fragment.</p> + </li> + <li>Get the {@link android.app.ActionBar} for your activity by calling {@link +android.app.Activity#getActionBar} from your {@link android.app.Activity}, during {@link +android.app.Activity#onCreate onCreate()} (but be sure you do so <em>after</em> you've called +{@link android.app.Activity#setContentView setContentView()}).</li> + <li>Call {@link android.app.ActionBar#setNavigationMode(int) +setNavigationMode(NAVIGATION_MODE_TABS)} to enable tab mode for the {@link +android.app.ActionBar}.</li> + <li>Create each tab for the action bar: + <ol> + <li>Create a new {@link android.app.ActionBar.Tab} by calling {@link +android.app.ActionBar#newTab()} on the {@link android.app.ActionBar}.</li> + <li>Add title text and/or an icon for the tab by calling {@link +android.app.ActionBar.Tab#setText setText()} and/or {@link android.app.ActionBar.Tab#setIcon +setIcon()}. + <p class="note"><strong>Tip:</strong> These methods return the same {@link +android.app.ActionBar.Tab} instance, so you can chain the calls together.</p></li> + <li>Declare the {@link android.app.ActionBar.TabListener} to use for the tab by passing an +instance of your implementation to {@link android.app.ActionBar.Tab#setTabListener +setTabListener()}. + </ol> + </li> + <li>Add each {@link android.app.ActionBar.Tab} to the action bar by calling {@link +android.app.ActionBar#addTab addTab()} on the {@link android.app.ActionBar} and passing the +{@link android.app.ActionBar.Tab}.</li> +</ol> +<p>For example, the following code combines steps 2 - 5 to create two tabs and add them to +the action bar:</p> +<pre> +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + // setup action bar for tabs + final ActionBar actionBar = getActionBar(); + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + // remove the activity title to make space for tabs + actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); + + // instantiate fragment for the tab + Fragment artistsFragment = new ArtistsFragment(); + // add a new tab and set its title text and tab listener + bar.addTab(bar.newTab().setText(R.string.tab_artists) + .setTabListener(new TabListener(artistsFragment))); + + Fragment albumsFragment = new AlbumsFragment(); + bar.addTab(bar.newTab().setText(R.string.tab_albums) + .setTabListener(new TabListener(albumsFragment))); +} +</pre> + +<p>All the behaviors that occur when a tab is selected must be defined by your {@link +android.app.ActionBar.TabListener} callback methods. When a tab is selected, it receives a call to +{@link android.app.ActionBar.TabListener#onTabSelected onTabSelected()} and that's where you should +add the appropriate fragment to the designated view in your layout, using {@link +android.app.FragmentTransaction#add add()} with the provided {@link +android.app.FragmentTransaction}. Likewise, when a tab is deselected (because another tab becomes +selected), you should remove that fragment from the layout, using {@link +android.app.FragmentTransaction#remove remove()}.</p> + +<p class="note"><strong>Note:</strong> You <strong>do not</strong> need +to call {@link android.app.FragmentTransaction#commit} for these transactions. You also +<strong>cannot</strong> add these fragment transactions to the back stack.</p> + +<p>If your activity is stopped, you should retain the currently selected tab with the saved state so +that when the user returns to your application, you can open the tab. When it's time to save the +state, you can query the currently selected tab with {@link +android.app.ActionBar#getSelectedNavigationItem()}. This returns the index position of the selected +tab.</p> + +<p class="caution"><strong>Caution:</strong> It's important that you save +the state of each fragment as necessary, so when the user switches fragments with the tabs, +then returns to a previous fragment, it appears the way they left. For information about saving +the state of your fragment, see the <a +href="{@docRoot}guide/topics/fragments/index.html">Fragments</a> developer guide.</p> + + diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd index fe641a2..4d71d28 100644 --- a/docs/html/guide/topics/ui/declaring-layout.jd +++ b/docs/html/guide/topics/ui/declaring-layout.jd @@ -191,10 +191,12 @@ layout parameters for the View that are appropriate for the ViewGroup in which i <p>Every ViewGroup class implements a nested class that extends {@link android.view.ViewGroup.LayoutParams}. This subclass contains property types that define the size and position for each child view, as -appropriate for the view group. As you can see in the figure below, the parent +appropriate for the view group. As you can see in figure 1, the parent view group defines layout parameters for each child view (including the child view group).</p> <img src="{@docRoot}images/layoutparams.png" alt="" height="300" align="center"/> +<p class="img-caption"><strong>Figure 1.</strong> Visualization of a view hierarchy with layout +parameters associated with each view.</p> <p>Note that every LayoutParams subclass has its own syntax for setting values. Each child element must define LayoutParams that are appropriate for its parent, diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd index 879eb8b..d50e1cb 100644 --- a/docs/html/guide/topics/ui/dialogs.jd +++ b/docs/html/guide/topics/ui/dialogs.jd @@ -22,20 +22,32 @@ parent.link=index.html </li> <li><a href="#CustomDialog">Creating a Custom Dialog</a></li> </ol> - + <h2>Key classes</h2> <ol> <li>{@link android.app.Dialog}</li> + <li>{@link android.app.AlertDialog}</li> + <li>{@link android.app.DialogFragment}</li> + </ol> + + <h2>Related tutorials</h2> + <ol> + <li><a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Hello +DatePicker</a></li> + <li><a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Hello +TimePicker</a></li> </ol> </div> </div> <p>A dialog is usually a small window that appears in front of the current Activity. -The underlying Activity loses focus and the dialog accepts all user interaction. -Dialogs are normally used -for notifications and short activities that directly relate to the application in progress.</p> +The underlying Activity loses focus and the dialog accepts all user interaction. Dialogs are +normally used for notifications that should interupt the user and to perform short tasks that +directly relate to the application in progress (such as a progress bar or a login prompt).</p> -<p>The Android API supports the following types of {@link android.app.Dialog} objects:</p> +<p>The {@link android.app.Dialog} class is the base class for creating dialogs. However, you +typically should not instantiate a {@link android.app.Dialog} directly. Instead, you should use one +of the following subclasses:</p> <dl> <dt>{@link android.app.AlertDialog}</dt> <dd>A dialog that can manage zero, one, two, or three buttons, and/or a list of diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd index b4e467c..ce25b9f 100644 --- a/docs/html/guide/topics/ui/menus.jd +++ b/docs/html/guide/topics/ui/menus.jd @@ -36,6 +36,7 @@ parent.link=index.html <h2>See also</h2> <ol> + <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a></li> <li><a href="{@docRoot}guide/topics/resources/menu-resource.html">Menu Resource</a></li> </ol> </div> @@ -48,20 +49,9 @@ for you to provide application menus in your application.</p> <p>Android provides three types of application menus:</p> <dl> <dt><strong>Options Menu</strong></dt> - <dd>The primary menu for an Activity, which appears when the user presses - the device MENU key. Within the Options Menu are two groups: - <dl style="margin-top:1em"> - <dt><em>Icon Menu</em></dt> - <dd>The menu items visible at the bottom of the screen - at the press of the MENU key. It supports a maximum of six menu items. - These are the only menu items that support icons and the only menu items that <em>do not</em> support - checkboxes or radio buttons.</dd> - <dt><em>Expanded Menu</em></dt> - <dd>The vertical list of menu items exposed by the "More" menu item in the Icon Menu. - When the Icon Menu is full, the expanded menu is comprised of the sixth - menu item and the rest.</dd> - </dl> - </dd> + <dd>The primary collection of menu items for an Activity that is associated with the device MENU +key. To provide instant access to select menu items, you can place some items in the <a +href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a>, if available.</dd> <dt><strong>Context Menu</strong></dt> <dd>A floating list of menu items that appears when the user performs a long-press on a View. </dd> @@ -74,7 +64,7 @@ Menu or a context menu. A submenu item cannot support a nested submenu. </dd> <h2 id="xml">Defining Menus</h2> -<p>Instead of instantiating {@link android.view.Menu} objects in your application code, you should +<p>Instead of instantiating a {@link android.view.Menu} in your application code, you should define a menu and all its items in an XML <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, then inflate the menu resource (load it as a programmable object) in your application code. Defining your menus in XML is @@ -104,9 +94,9 @@ href="#groups">Menu groups</a>.</dd> <item android:id="@+id/new_game" android:icon="@drawable/ic_new_game" android:title="@string/new_game" /> - <item android:id="@+id/quit" - android:icon="@drawable/ic_quit" - android:title="@string/quit" /> + <item android:id="@+id/help" + android:icon="@drawable/ic_help" + android:title="@string/help" /> </menu> </pre> @@ -161,36 +151,64 @@ creating an option menu is discussed more in the next section.)</p> </div> -<p>The Options Menu is where you should include basic application functions -and necessary navigation items (for example, a button -to open application settings). The user -can open the Options Menu with the device MENU key. -Figure 1 shows a screenshot of an Options Menu.</p> +<p>The Options Menu is where you should include basic application functions and necessary navigation +items (for example, a button to open the application settings). Items in the Options Menu are +accessible in two distinct ways: in the Action Bar and in the menu revealed by the MENU +key.</p> + +<p>The Action Bar is an optional widget that appears at the top of the activity in place of the +title bar. It can display several menu items that you choose from the Options Menu, but items in +the Action Bar display only an icon (no title text). Users can reveal the other menu items in the +Options Menu with the MENU key.</p> -<p>When opened, the first visible portion of the Options Menu is called the Icon Menu. It -holds the first six menu items. -If you add more than six items to the Options Menu, Android places the sixth item and those after it -into the Expanded Menu, which the user can open with the "More" menu item.</p> +<p>If you include the Action Bar in your activity, the menu items that are not placed in the Action +Bar can appear in two different styles:</p> +<dl> + <dt>Action Bar Menu</dt> + <dd>If the device has an extra-large screen ({@code xlarge}), then all items in the Options Menu +that are not placed in the Action Bar are placed into a drop-down list at the right side of the +Action Bar, with icons and title text. The user can reveal the drop-down list by pressing the +drop-down icon in the Action Bar or the MENU key.</dd> + <dt>Standard Options Menu</dt> + <dd>If the device <em>does not</em> have an extra-large screen, then all items in the Options +Menu that are not placed in the Action Bar are placed into the Standard Options Menu at the bottom +of the activity. The user can reveal the standard Options Menu by pressing the MENU key. + <p>The first visible portion of the Standard Options Menu is called the Icon Menu. +It holds the first six menu items (excluding any added to the Action Bar), with icons and title +text. If there are more than six items, Android adds a "More" item as the sixth menu item and places +the remaining items into the Expanded Menu, which the user can open by selecting "More". The +Expanded Menu displays menu items only by their title text (no icon)</p> + </dd> +</dl> <p>When the user opens the Options Menu for the first time, Android calls your Activity's {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} method. Override this method in your Activity and populate the {@link android.view.Menu} that is passed into the method. Populate the {@link android.view.Menu} by inflating a menu resource as described in <a -href="#Inflating">Inflating a Menu Resource</a>. (You can -also populate the menu in code, using {@link android.view.Menu#add(int,int,int,int) -add()} to add menu items.)</p> +href="#Inflating">Inflating a Menu Resource</a>. For example:</p> -<p>When the user selects a menu item from the Options Menu, the system calls your Activity's +<pre> +@Override +public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.game_menu, menu); + return true; +} +</pre> + +<p>(You can also populate the menu in code, using {@link android.view.Menu#add(int,int,int,int) +add()} to add items to the {@link android.view.Menu}.)</p> + +<p>When the user selects a menu item from the Options Menu (including items selected from the +Action Bar), the system calls your Activity's {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method. This method passes the {@link android.view.MenuItem} that the user selected. You can identify the menu item by calling {@link android.view.MenuItem#getItemId()}, which returns the unique ID for the menu item (defined by the {@code android:id} attribute in the menu resource or with an integer passed to the {@link android.view.Menu#add(int,int,int,int) add()} method). You can match this ID -against known menu items and perform the appropriate action.</p> - -<p>For example:</p> +against known menu items and perform the appropriate action. For example:</p> <pre> @Override @@ -200,8 +218,8 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.new_game: newGame(); return true; - case R.id.quit: - quit(); + case R.id.help: + showHelp(); return true; default: return super.onOptionsItemSelected(item); @@ -224,8 +242,8 @@ an Activity that implements nothing except the {@link android.app.Activity#onCre onCreateOptionsMenu()} and {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} methods. Then extend this class for each Activity that should share the same Options Menu. This way, you have to manage only one set of code for handling menu -actions and each decendent class inherits the menu behaviors.<br/><br/> -If you want to add menu items to one of your decendent activities, +actions and each descendant class inherits the menu behaviors.<br/><br/> +If you want to add menu items to one of your descendant activities, override {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} in that Activity. Call {@code super.onCreateOptionsMenu(menu)} so the original menu items are created, then add new menu items with {@link @@ -542,7 +560,7 @@ hardware keyboard. Shortcuts cannot be added to items in a Context Menu.</p> <h3 id="intents">Intents for menu items</h3> <p>Sometimes you'll want a menu item to launch an Activity using an Intent (whether it's an -Actvitity in your application or another application). When you know the Intent you want to use and +Activity in your application or another application). When you know the Intent you want to use and have a specific menu item that should initiate the Intent, you can execute the Intent with {@link android.app.Activity#startActivity(Intent) startActivity()} during the appropriate on-item-selected callback method (such as the {@link android.app.Activity#onOptionsItemSelected(MenuItem) diff --git a/docs/html/images/activity_fragment_lifecycle.png b/docs/html/images/activity_fragment_lifecycle.png Binary files differnew file mode 100644 index 0000000..156aa40 --- /dev/null +++ b/docs/html/images/activity_fragment_lifecycle.png diff --git a/docs/html/images/axis_globe_inverted.png b/docs/html/images/axis_globe_inverted.png Binary files differnew file mode 100644 index 0000000..bd78c7f --- /dev/null +++ b/docs/html/images/axis_globe_inverted.png diff --git a/docs/html/images/fragment_lifecycle.png b/docs/html/images/fragment_lifecycle.png Binary files differnew file mode 100644 index 0000000..ce9d395 --- /dev/null +++ b/docs/html/images/fragment_lifecycle.png diff --git a/docs/html/images/screens_support/screens-ranges.png b/docs/html/images/screens_support/screens-ranges.png Binary files differindex 034ac34..dce6264 100644 --- a/docs/html/images/screens_support/screens-ranges.png +++ b/docs/html/images/screens_support/screens-ranges.png diff --git a/docs/html/images/ui/actionbar-item-withtext.png b/docs/html/images/ui/actionbar-item-withtext.png Binary files differnew file mode 100644 index 0000000..98b5f84 --- /dev/null +++ b/docs/html/images/ui/actionbar-item-withtext.png diff --git a/docs/html/images/ui/actionbar-logo.png b/docs/html/images/ui/actionbar-logo.png Binary files differnew file mode 100644 index 0000000..481ed2c --- /dev/null +++ b/docs/html/images/ui/actionbar-logo.png diff --git a/docs/html/images/ui/actionbar.png b/docs/html/images/ui/actionbar.png Binary files differnew file mode 100644 index 0000000..4fc871c --- /dev/null +++ b/docs/html/images/ui/actionbar.png diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index d06b695..221406c 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -465,7 +465,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'ui', 'search', 'new'], + tags: ['sample', 'ui', 'search'], path: 'samples/SearchableDictionary/index.html', title: { en: 'Searchable Dictionary v2' @@ -485,7 +485,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'testing', 'new'], + tags: ['sample', 'testing'], path: 'samples/Spinner/index.html', title: { en: 'Spinner' @@ -495,7 +495,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'testing', 'new'], + tags: ['sample', 'testing'], path: 'samples/SpinnerTest/index.html', title: { en: 'SpinnerTest' @@ -505,7 +505,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'newfeature', 'new'], + tags: ['sample', 'newfeature'], path: 'samples/TicTacToeLib/index.html', title: { en: 'TicTacToeLib' @@ -515,7 +515,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'newfeature', 'new'], + tags: ['sample', 'newfeature',], path: 'samples/TicTacToeMain/index.html', title: { en: 'TicTacToeMain' @@ -610,7 +610,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['tutorial', 'testing', 'new'], + tags: ['tutorial', 'testing'], path: 'tutorials/testing/helloandroid_test.html', title: { en: 'Hello Testing' @@ -620,7 +620,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['tutorial', 'testing', 'new'], + tags: ['tutorial', 'testing'], path: 'tutorials/testing/activity_test.html', title: { en: 'Activity Testing' diff --git a/docs/html/sdk/adt_download.jd b/docs/html/sdk/adt_download.jd index 3da576a..33e480a 100644 --- a/docs/html/sdk/adt_download.jd +++ b/docs/html/sdk/adt_download.jd @@ -22,6 +22,13 @@ ADT Installation</a>.</p> <th>Notes</th> </tr> <tr> + <td>8.0.0</td> + <td><a href="http://dl-ssl.google.com/android/ADT-8.0.0.zip">ADT-8.0.0.zip</a></td> + <td><nobr> bytes</nobr></td> + <td></td> + <td>Requires SDK Tools, Revision 8 <em><nobr>November 2010</nobr></em></td> + </tr> + <tr> <td>0.9.9</td> <td><a href="http://dl-ssl.google.com/android/ADT-0.9.9.zip">ADT-0.9.9.zip</a></td> <td><nobr>8301681 bytes</nobr></td> diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd index c3afebd..8f6f518 100644 --- a/docs/html/sdk/eclipse-adt.jd +++ b/docs/html/sdk/eclipse-adt.jd @@ -99,14 +99,14 @@ padding: .25em 1em; <div class="toggleable opened"> <a href="#" onclick="return toggleDiv(this)"> <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" /> -ADT 8.0</a> <em>(November 2010)</em> +ADT 8.0.0</a> <em>(December 2010)</em> <div class="toggleme"> <dl> <dt>Dependencies:</dt> -<p><p>ADT 8.0 is designed for use with SDK Tools r8. If you haven't +<p><p>ADT 8.0.0 is designed for use with SDK Tools r8. If you haven't already installed SDK Tools r8 into your SDK, use the Android SDK and AVD Manager to do so.</p></dd> diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 7ccb7a0..057d9e0 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -75,7 +75,7 @@ </li> </ul> <ul> - <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r7</a></li> + <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r8</a> <span class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/win-usb.html">USB Driver for Windows, r3</a> </li> diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd index 0f075e5..9316fae 100644 --- a/docs/html/sdk/tools-notes.jd +++ b/docs/html/sdk/tools-notes.jd @@ -64,6 +64,70 @@ padding: .25em 1em; <div class="toggleable opened"> <a href="#" onclick="return toggleDiv(this)"> <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" /> +SDK Tools, Revision 8</a> <em>(December 2010)</em> + <div class="toggleme"> + +<dl> +<dt>Dependencies:</dt> +<dd> +<p>If you are developing in Eclipse with ADT, note that SDK Tools r8 is +designed for use with ADT 8.0.0 and later. After installing SDK Tools r8, we +highly recommend updating your ADT Plugin to 8.0.0.</p> + +<p>Also note that SDK Tools r8 requires a new SDK component called +<em>Platform-tools</em>. The new Platform-tools component lets all SDK platforms +(Android 2.1, Android 2.2, and so on) use the same (latest) version of build +tools such as <code>adb</code>, <code>aapt</code>, <code>aidl</code>, and +<code>dx</code>. To download the Platform-tools component, use the Android SDK +Manager, as described in <a href="adding-components.html">Adding SDK +Components</a></p> + +<dt>Upgrading from SDK Tools r7:</dt> +<dd> +<p>If you are upgrading to SDK Tools r8 from an earlier version, note that the +the default installed location for the <code>adb</code> tool has changed from +<code><<em>SDK</em>>/tools/adb</code> to +<code><<em>SDK</em>>/platform-tools/adb</code>. This means that you should +add the new location to your PATH and modify any custom build scripts to +reference the new location. Copying the <code>adb</code> executable from the new +location to the old is not recommended, since subsequent updates to the SDK +Tools will delete the file.</p> +</dd> + +<dt>General notes:</dt> +<dd> +<ul> +<li>All SDK platforms now support Library Projects.</li> +<li>Support for a true debug build. Developers no longer need to add the +<code>android:debuggable</code> attribute to the +<code><application></code> tag in the manifest — the build tools add +the attribute automatically. In Eclipse/ADT, all incremental builds are assumed +to be debug builds, so the tools insert <code>android:debuggable="true"</code>. +When exporting a signed release build, the tools do not add the attribute. In +Ant, a <code>ant debug</code> command automatically inserts the +<code>android:debuggable="true"</code> attribute, while <code>ant release</code> +does not. If <code>android:debuggable="true"</code> is manually set, then +<code>ant release</code> will actually do a debug build, rather than a release +build.</li> +<li>Automatic ProGuard support in release builds. Developers generate a ProGuard +configuration file using the <code>android</code> tool — the build tools +then automatically run ProGuard against the project sources during the build. +For more information, see the <a +href="{@docRoot}guide/developing/tools/proguard.html">ProGuard</a> +documentation. </li> +<li>New overridable Ant javac properties: <code>java.encoding</code>, +<code>java.source</code>, and <code>java.target</code> (default values are +"ascii", "1.5", and "1.5", respectively).</li> +<li>New UI for the HierarchyViewer tool.</li> +</ul> +</dd> +</dl> + </div> +</div> + +<div class="toggleable closed"> + <a href="#" onclick="return toggleDiv(this)"> + <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" /> SDK Tools, Revision 7</a> <em>(September 2010)</em> <div class="toggleme"> diff --git a/drm/common/DrmEngineBase.cpp b/drm/common/DrmEngineBase.cpp index 10c64ee..98a9ece 100644 --- a/drm/common/DrmEngineBase.cpp +++ b/drm/common/DrmEngineBase.cpp @@ -80,7 +80,7 @@ status_t DrmEngineBase::consumeRights( } status_t DrmEngineBase::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) { + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { return onSetPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); } @@ -116,7 +116,7 @@ DrmSupportInfo* DrmEngineBase::getSupportInfo(int uniqueId) { } status_t DrmEngineBase::openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) { + int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) { return onOpenDecryptSession(uniqueId, decryptHandle, fd, offset, length); } @@ -146,7 +146,7 @@ status_t DrmEngineBase::finalizeDecryptUnit( } ssize_t DrmEngineBase::pread( - int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset) { + int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { return onPread(uniqueId, decryptHandle, buffer, numBytes, offset); } diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp index c3d12f0..fca4261 100644 --- a/drm/common/IDrmManagerService.cpp +++ b/drm/common/IDrmManagerService.cpp @@ -333,7 +333,7 @@ status_t BpDrmManagerService::consumeRights( } status_t BpDrmManagerService::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) { + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { LOGV("setPlaybackStatus"); Parcel data, reply; @@ -429,7 +429,7 @@ DrmConvertedStatus* BpDrmManagerService::convertData( if (0 != reply.dataAvail()) { //Filling DRM Converted Status const int statusCode = reply.readInt32(); - const int offset = reply.readInt32(); + const off64_t offset = reply.readInt64(); DrmBuffer* convertedData = NULL; if (0 != reply.dataAvail()) { @@ -461,7 +461,7 @@ DrmConvertedStatus* BpDrmManagerService::closeConvertSession(int uniqueId, int c if (0 != reply.dataAvail()) { //Filling DRM Converted Status const int statusCode = reply.readInt32(); - const int offset = reply.readInt32(); + const off64_t offset = reply.readInt64(); DrmBuffer* convertedData = NULL; if (0 != reply.dataAvail()) { @@ -515,15 +515,15 @@ status_t BpDrmManagerService::getAllSupportInfo( } DecryptHandle* BpDrmManagerService::openDecryptSession( - int uniqueId, int fd, int offset, int length) { + int uniqueId, int fd, off64_t offset, off64_t length) { LOGV("Entering BpDrmManagerService::openDecryptSession"); Parcel data, reply; data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); data.writeFileDescriptor(fd); - data.writeInt32(offset); - data.writeInt32(length); + data.writeInt64(offset); + data.writeInt64(length); remote()->transact(OPEN_DECRYPT_SESSION, data, &reply); @@ -697,7 +697,7 @@ status_t BpDrmManagerService::finalizeDecryptUnit( ssize_t BpDrmManagerService::pread( int uniqueId, DecryptHandle* decryptHandle, void* buffer, - ssize_t numBytes, off_t offset) { + ssize_t numBytes, off64_t offset) { LOGV("read"); Parcel data, reply; int result; @@ -717,7 +717,7 @@ ssize_t BpDrmManagerService::pread( } data.writeInt32(numBytes); - data.writeInt32(offset); + data.writeInt64(offset); remote()->transact(PREAD, data, &reply); result = reply.readInt32(); @@ -1121,7 +1121,7 @@ status_t BnDrmManagerService::onTransact( if (NULL != drmConvertedStatus) { //Filling Drm Converted Ststus reply->writeInt32(drmConvertedStatus->statusCode); - reply->writeInt32(drmConvertedStatus->offset); + reply->writeInt64(drmConvertedStatus->offset); if (NULL != drmConvertedStatus->convertedData) { const DrmBuffer* convertedData = drmConvertedStatus->convertedData; @@ -1150,7 +1150,7 @@ status_t BnDrmManagerService::onTransact( if (NULL != drmConvertedStatus) { //Filling Drm Converted Ststus reply->writeInt32(drmConvertedStatus->statusCode); - reply->writeInt32(drmConvertedStatus->offset); + reply->writeInt64(drmConvertedStatus->offset); if (NULL != drmConvertedStatus->convertedData) { const DrmBuffer* convertedData = drmConvertedStatus->convertedData; @@ -1210,7 +1210,7 @@ status_t BnDrmManagerService::onTransact( const int fd = data.readFileDescriptor(); DecryptHandle* handle - = openDecryptSession(uniqueId, fd, data.readInt32(), data.readInt32()); + = openDecryptSession(uniqueId, fd, data.readInt64(), data.readInt64()); if (NULL != handle) { reply->writeInt32(handle->decryptId); @@ -1415,7 +1415,7 @@ status_t BnDrmManagerService::onTransact( const int numBytes = data.readInt32(); char* buffer = new char[numBytes]; - const off_t offset = data.readInt32(); + const off64_t offset = data.readInt64(); ssize_t result = pread(uniqueId, &handle, buffer, numBytes, offset); reply->writeInt32(result); diff --git a/drm/common/ReadWriteUtils.cpp b/drm/common/ReadWriteUtils.cpp index 7ec4fa2..c16214e 100644 --- a/drm/common/ReadWriteUtils.cpp +++ b/drm/common/ReadWriteUtils.cpp @@ -42,7 +42,7 @@ String8 ReadWriteUtils::readBytes(const String8& filePath) { struct stat sb; if (fstat(fd, &sb) == 0 && sb.st_size > 0) { - int length = sb.st_size; + off64_t length = sb.st_size; char* bytes = new char[length]; if (length == read(fd, (void*) bytes, length)) { string.append(bytes, length); @@ -57,7 +57,7 @@ String8 ReadWriteUtils::readBytes(const String8& filePath) { int ReadWriteUtils::readBytes(const String8& filePath, char** buffer) { FILE* file = NULL; file = fopen(filePath.string(), "r"); - int length = 0; + off64_t length = 0; if (NULL != file) { int fd = fileno(file); diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp index 35e62f3..8da8176 100644 --- a/drm/drmserver/DrmManager.cpp +++ b/drm/drmserver/DrmManager.cpp @@ -258,7 +258,7 @@ status_t DrmManager::consumeRights( } status_t DrmManager::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) { + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { status_t result = DRM_ERROR_UNKNOWN; if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); @@ -370,7 +370,7 @@ status_t DrmManager::getAllSupportInfo( return DRM_NO_ERROR; } -DecryptHandle* DrmManager::openDecryptSession(int uniqueId, int fd, int offset, int length) { +DecryptHandle* DrmManager::openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length) { Mutex::Autolock _l(mDecryptLock); status_t result = DRM_ERROR_CANNOT_HANDLE; Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); @@ -470,7 +470,7 @@ status_t DrmManager::finalizeDecryptUnit( } ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset) { + void* buffer, ssize_t numBytes, off64_t offset) { ssize_t result = DECRYPT_FILE_ERROR; if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp index 8cf510d..efd7bae 100644 --- a/drm/drmserver/DrmManagerService.cpp +++ b/drm/drmserver/DrmManagerService.cpp @@ -125,7 +125,7 @@ status_t DrmManagerService::consumeRights( } status_t DrmManagerService::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) { + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { LOGV("Entering setPlaybackStatus"); return mDrmManager->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); } @@ -170,7 +170,7 @@ status_t DrmManagerService::getAllSupportInfo( } DecryptHandle* DrmManagerService::openDecryptSession( - int uniqueId, int fd, int offset, int length) { + int uniqueId, int fd, off64_t offset, off64_t length) { LOGV("Entering DrmManagerService::openDecryptSession"); return mDrmManager->openDecryptSession(uniqueId, fd, offset, length); } @@ -206,7 +206,7 @@ status_t DrmManagerService::finalizeDecryptUnit( } ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset) { + void* buffer, ssize_t numBytes, off64_t offset) { LOGV("Entering pread"); return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset); } diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp index f0439eb..0cbbbd4 100644 --- a/drm/libdrmframework/DrmManagerClient.cpp +++ b/drm/libdrmframework/DrmManagerClient.cpp @@ -78,7 +78,7 @@ status_t DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int actio } status_t DrmManagerClient::setPlaybackStatus( - DecryptHandle* decryptHandle, int playbackStatus, int position) { + DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { return mDrmManagerClientImpl ->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position); } @@ -112,7 +112,7 @@ status_t DrmManagerClient::getAllSupportInfo(int* length, DrmSupportInfo** drmSu return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray); } -DecryptHandle* DrmManagerClient::openDecryptSession(int fd, int offset, int length) { +DecryptHandle* DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) { return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length); } @@ -145,7 +145,7 @@ status_t DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int } ssize_t DrmManagerClient::pread( - DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset) { + DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { Mutex::Autolock _l(mDecryptLock); return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset); } diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp index b3ae9a7..519ed67 100644 --- a/drm/libdrmframework/DrmManagerClientImpl.cpp +++ b/drm/libdrmframework/DrmManagerClientImpl.cpp @@ -170,7 +170,7 @@ status_t DrmManagerClientImpl::consumeRights( } status_t DrmManagerClientImpl::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) { + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { status_t status = DRM_ERROR_UNKNOWN; if (NULL != decryptHandle) { status = getDrmManagerService()->setPlaybackStatus( @@ -231,7 +231,7 @@ status_t DrmManagerClientImpl::getAllSupportInfo( } DecryptHandle* DrmManagerClientImpl::openDecryptSession( - int uniqueId, int fd, int offset, int length) { + int uniqueId, int fd, off64_t offset, off64_t length) { return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length); } @@ -283,7 +283,7 @@ status_t DrmManagerClientImpl::finalizeDecryptUnit( } ssize_t DrmManagerClientImpl::pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset) { + void* buffer, ssize_t numBytes, off64_t offset) { ssize_t retCode = INVALID_VALUE; if ((NULL != decryptHandle) && (NULL != buffer) && (0 < numBytes)) { retCode = getDrmManagerService()->pread(uniqueId, decryptHandle, buffer, numBytes, offset); diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h index d782f5b..a0250b7 100644 --- a/drm/libdrmframework/include/DrmManager.h +++ b/drm/libdrmframework/include/DrmManager.h @@ -92,7 +92,7 @@ public: status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position); + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); bool validateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -109,7 +109,7 @@ public: status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray); - DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length); + DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length); DecryptHandle* openDecryptSession(int uniqueId, const char* uri); @@ -124,7 +124,7 @@ public: status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset); + void* buffer, ssize_t numBytes, off64_t offset); void onInfo(const DrmInfoEvent& event); diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h index 1c6be46..769f4d0 100644 --- a/drm/libdrmframework/include/DrmManagerClientImpl.h +++ b/drm/libdrmframework/include/DrmManagerClientImpl.h @@ -191,7 +191,7 @@ public: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position); + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); /** * Validates whether an action on the DRM content is allowed or not. @@ -291,7 +291,7 @@ public: * @return * Handle for the decryption session */ - DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length); + DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length); /** * Open the decrypt session to decrypt the given protected content @@ -369,7 +369,7 @@ public: * @return Number of bytes read. Returns -1 for Failure. */ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset); + void* buffer, ssize_t numBytes, off64_t offset); /** * Notify the event to the registered listener diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h index 4a3aeae..4b3ba71 100644 --- a/drm/libdrmframework/include/DrmManagerService.h +++ b/drm/libdrmframework/include/DrmManagerService.h @@ -79,7 +79,7 @@ public: status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position); + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); bool validateAction(int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -96,7 +96,7 @@ public: status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray); - DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length); + DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length); DecryptHandle* openDecryptSession(int uniqueId, const char* uri); @@ -111,7 +111,7 @@ public: status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset); + void* buffer, ssize_t numBytes, off64_t offset); private: DrmManager* mDrmManager; diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h index 1275488..20fb2ab 100644 --- a/drm/libdrmframework/include/IDrmManagerService.h +++ b/drm/libdrmframework/include/IDrmManagerService.h @@ -116,7 +116,7 @@ public: int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0; virtual status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) = 0; + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) = 0; virtual bool validateAction( int uniqueId, const String8& path, @@ -136,7 +136,7 @@ public: virtual status_t getAllSupportInfo( int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) = 0; - virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length) = 0; + virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length) = 0; virtual DecryptHandle* openDecryptSession(int uniqueId, const char* uri) = 0; @@ -152,7 +152,7 @@ public: int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0; virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes,off_t offset) = 0; + void* buffer, ssize_t numBytes,off64_t offset) = 0; }; /** @@ -198,7 +198,7 @@ public: int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); virtual status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position); + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); virtual bool validateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -217,7 +217,7 @@ public: virtual status_t getAllSupportInfo( int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray); - virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length); + virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length); virtual DecryptHandle* openDecryptSession(int uniqueId, const char* uri); @@ -233,7 +233,7 @@ public: int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset); + void* buffer, ssize_t numBytes, off64_t offset); }; /** diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h index 5851af5..779f7ac 100644 --- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h +++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h @@ -60,7 +60,7 @@ public: status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position); + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); bool validateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -78,7 +78,7 @@ public: DrmSupportInfo* getSupportInfo(int uniqueId); status_t openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length); + int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length); status_t openDecryptSession( int uniqueId, DecryptHandle* decryptHandle, const char* uri); @@ -94,7 +94,7 @@ public: status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset); + void* buffer, ssize_t numBytes, off64_t offset); protected: ///////////////////////////////////////////////////// @@ -254,7 +254,7 @@ protected: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ virtual status_t onSetPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) = 0; + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) = 0; /** * Validates whether an action on the DRM content is allowed or not. @@ -355,7 +355,7 @@ protected: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0; + int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) = 0; /** * Open the decrypt session to decrypt the given protected content @@ -436,7 +436,7 @@ protected: * @return Number of bytes read. Returns -1 for Failure. */ virtual ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset) = 0; + void* buffer, ssize_t numBytes, off64_t offset) = 0; }; }; diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h index cc03ef2..28e6d8e 100644 --- a/drm/libdrmframework/plugins/common/include/IDrmEngine.h +++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h @@ -211,7 +211,7 @@ public: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ virtual status_t setPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle, - int playbackStatus, int position) = 0; + int playbackStatus, int64_t position) = 0; /** * Validates whether an action on the DRM content is allowed or not. @@ -312,7 +312,7 @@ public: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0; + int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) = 0; /** * Open the decrypt session to decrypt the given protected content @@ -393,7 +393,7 @@ public: * @return Number of bytes read. Returns -1 for Failure. */ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset) = 0; + void* buffer, ssize_t numBytes, off64_t offset) = 0; }; }; diff --git a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h index ddb7fd3..9c94e73 100644 --- a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h +++ b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h @@ -54,7 +54,7 @@ protected: status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); status_t onSetPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position); + int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); bool onValidateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -72,7 +72,7 @@ protected: DrmSupportInfo* onGetSupportInfo(int uniqueId); status_t onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length); + int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length); status_t onOpenDecryptSession( int uniqueId, DecryptHandle* decryptHandle, const char* uri); @@ -88,7 +88,7 @@ protected: status_t onFinalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset); + void* buffer, ssize_t numBytes, off64_t offset); private: DecryptHandle* openDecryptSessionImpl(); diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp index 41f8e91..73c9708 100644 --- a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp +++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp @@ -182,7 +182,7 @@ status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, DecryptHandle* decrypt } status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle, - int playbackStatus, int position) { + int playbackStatus, int64_t position) { LOGD("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId); return DRM_NO_ERROR; } @@ -229,7 +229,7 @@ DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int c } status_t DrmPassthruPlugIn::onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) { + int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) { LOGD("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId); #ifdef ENABLE_PASSTHRU_DECRYPTION @@ -287,7 +287,7 @@ status_t DrmPassthruPlugIn::onFinalizeDecryptUnit( } ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* decryptHandle, - void* buffer, ssize_t numBytes, off_t offset) { + void* buffer, ssize_t numBytes, off64_t offset) { LOGD("DrmPassthruPlugIn::onPread() : %d", uniqueId); return 0; } diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 0660441..f16e045 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -685,6 +685,8 @@ public class RenderScript { public static final int RS_MESSAGE_TO_CLIENT_ERROR = 3; public static final int RS_MESSAGE_TO_CLIENT_USER = 4; + public static final int RS_ERROR_FATAL_UNKNOWN = 0x1000; + MessageThread(RenderScript rs) { super("RSMessageThread"); mRS = rs; @@ -722,6 +724,10 @@ public class RenderScript { if (msg == RS_MESSAGE_TO_CLIENT_ERROR) { String e = mRS.nContextGetErrorMessage(mRS.mContext); + if (subID >= RS_ERROR_FATAL_UNKNOWN) { + throw new RSRuntimeException("Fatal error " + subID + ", details: " + e); + } + if(mRS.mErrorCallback != null) { mRS.mErrorCallback.mErrorMessage = e; mRS.mErrorCallback.mErrorNum = subID; diff --git a/include/camera/Camera.h b/include/camera/Camera.h index 8d8edd6..c7f0b15 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -111,8 +111,8 @@ enum { }; enum { - CAMERA_FACING_BACK = 0, - CAMERA_FACING_FRONT = 1 /* The camera faces to the user */ + CAMERA_FACING_BACK = 0, /* The facing of the camera is opposite to that of the screen. */ + CAMERA_FACING_FRONT = 1 /* The facing of the camera is the same as that of the screen. */ }; struct CameraInfo { @@ -128,10 +128,12 @@ struct CameraInfo { * camera image needs to be rotated clockwise so it shows correctly on * the display in its natural orientation. It should be 0, 90, 180, or 270. * - * For example, suppose a device has a naturally tall screen, but the camera - * sensor is mounted in landscape. If the top side of the camera sensor is - * aligned with the right edge of the display in natural orientation, the - * value should be 90. + * For example, suppose a device has a naturally tall screen. The + * back-facing camera sensor is mounted in landscape. You are looking at + * the screen. If the top side of the camera sensor is aligned with the + * right edge of the screen in natural orientation, the value should be + * 90. If the top side of a front-facing camera sensor is aligned with + * the right of the screen, the value should be 270. */ int orientation; }; diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h index 5465441..16f572c 100644 --- a/include/camera/CameraHardwareInterface.h +++ b/include/camera/CameraHardwareInterface.h @@ -269,7 +269,9 @@ public: */ virtual status_t cancelPicture() = 0; - /** Set the camera parameters. */ + /** + * Set the camera parameters. This returns BAD_VALUE if any parameter is + * invalid or not supported. */ virtual status_t setParameters(const CameraParameters& params) = 0; /** Return the camera parameters. */ diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index 60031a4..6364d58 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -163,16 +163,23 @@ public: // the best. // Example value: "90". Read/write. static const char KEY_JPEG_QUALITY[]; - // The orientation of the device in degrees. For example, suppose the - // natural position of the device is landscape. If the user takes a picture - // in landscape mode in 2048x1536 resolution, the rotation will be set to - // "0". If the user rotates the phone 90 degrees clockwise, the rotation - // should be set to "90". - // The camera driver can set orientation in the EXIF header without rotating - // the picture. Or the driver can rotate the picture and the EXIF thumbnail. - // If the Jpeg picture is rotated, the orientation in the EXIF header should - // be missing or 1 (row #0 is top and column #0 is left side). The driver - // should not set default value for this parameter. + // The rotation angle in degrees relative to the orientation of the camera. + // This affects the pictures returned from CAMERA_MSG_COMPRESSED_IMAGE. The + // camera driver may set orientation in the EXIF header without rotating the + // picture. Or the driver may rotate the picture and the EXIF thumbnail. If + // the Jpeg picture is rotated, the orientation in the EXIF header will be + // missing or 1 (row #0 is top and column #0 is left side). + // + // Note that the JPEG pictures of front-facing cameras are not mirrored + // as in preview display. + // + // For example, suppose the natural orientation of the device is portrait. + // The device is rotated 270 degrees clockwise, so the device orientation is + // 270. Suppose a back-facing camera sensor is mounted in landscape and the + // top side of the camera sensor is aligned with the right edge of the + // display in natural orientation. So the camera orientation is 90. The + // rotation should be set to 0 (270 + 90). + // // Example value: "0" or "90" or "180" or "270". Write only. static const char KEY_ROTATION[]; // GPS latitude coordinate. GPSLatitude and GPSLatitudeRef will be stored in diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h index 5963c42..782ebae 100644 --- a/include/drm/DrmManagerClient.h +++ b/include/drm/DrmManagerClient.h @@ -65,7 +65,7 @@ public: * @return * Handle for the decryption session */ - DecryptHandle* openDecryptSession(int fd, int offset, int length); + DecryptHandle* openDecryptSession(int fd, off64_t offset, off64_t length); /** * Open the decrypt session to decrypt the given protected content @@ -109,7 +109,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - status_t setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int position); + status_t setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int64_t position); /** * Initialize decryption for the given unit of the protected content @@ -163,7 +163,7 @@ public: * * @return Number of bytes read. Returns -1 for Failure. */ - ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset); + ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); /** * Validates whether an action on the DRM content is allowed or not. diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h index c967efb..cda2be0 100644 --- a/include/media/AudioEffect.h +++ b/include/media/AudioEffect.h @@ -403,7 +403,7 @@ public: static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen); protected: - volatile int32_t mEnabled; // enable state + bool mEnabled; // enable state int32_t mSessionId; // audio session ID int32_t mPriority; // priority for effect control status_t mStatus; // effect status @@ -412,6 +412,7 @@ protected: void* mUserData; // client context for callback function effect_descriptor_t mDescriptor; // effect descriptor int32_t mId; // system wide unique effect engine instance ID + Mutex mLock; // Mutex for mEnabled access private: diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index 38e3d44..5f7cd90 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -356,7 +356,7 @@ private: sp<IAudioRecord> mAudioRecord; sp<IMemory> mCblkMemory; sp<ClientRecordThread> mClientRecordThread; - Mutex mRecordThreadLock; + Mutex mLock; uint32_t mFrameCount; diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 4475d4a..813a905 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -480,6 +480,7 @@ private: uint32_t mFlags; int mSessionId; int mAuxEffectId; + Mutex mLock; }; diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h index aa965e1..62d57b4 100644 --- a/include/media/stagefright/AMRWriter.h +++ b/include/media/stagefright/AMRWriter.h @@ -44,7 +44,7 @@ protected: virtual ~AMRWriter(); private: - FILE *mFile; + int mFd; status_t mInitCheck; sp<MediaSource> mSource; bool mStarted; diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h index bc3f464..2b61f58 100644 --- a/include/media/stagefright/ColorConverter.h +++ b/include/media/stagefright/ColorConverter.h @@ -33,35 +33,47 @@ struct ColorConverter { bool isValid() const; void convert( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip); + const void *srcBits, + size_t srcWidth, size_t srcHeight, + size_t srcCropLeft, size_t srcCropTop, + size_t srcCropRight, size_t srcCropBottom, + void *dstBits, + size_t dstWidth, size_t dstHeight, + size_t dstCropLeft, size_t dstCropTop, + size_t dstCropRight, size_t dstCropBottom); private: + struct BitmapParams { + BitmapParams( + void *bits, + size_t width, size_t height, + size_t cropLeft, size_t cropTop, + size_t cropRight, size_t cropBottom); + + size_t cropWidth() const; + size_t cropHeight() const; + + void *mBits; + size_t mWidth, mHeight; + size_t mCropLeft, mCropTop, mCropRight, mCropBottom; + }; + OMX_COLOR_FORMATTYPE mSrcFormat, mDstFormat; uint8_t *mClip; uint8_t *initClip(); void convertCbYCrY( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip); + const BitmapParams &src, const BitmapParams &dst); void convertYUV420Planar( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip); + const BitmapParams &src, const BitmapParams &dst); void convertQCOMYUV420SemiPlanar( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip); + const BitmapParams &src, const BitmapParams &dst); void convertYUV420SemiPlanar( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip); + const BitmapParams &src, const BitmapParams &dst); ColorConverter(const ColorConverter &); ColorConverter &operator=(const ColorConverter &); diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index 27f33fb..d4f1733 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -48,13 +48,13 @@ public: virtual status_t initCheck() const = 0; - virtual ssize_t readAt(off_t offset, void *data, size_t size) = 0; + virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0; // Convenience methods: - bool getUInt16(off_t offset, uint16_t *x); + bool getUInt16(off64_t offset, uint16_t *x); // May return ERROR_UNSUPPORTED. - virtual status_t getSize(off_t *size); + virtual status_t getSize(off64_t *size); virtual uint32_t flags() { return 0; diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h index 4307263..72a0403 100644 --- a/include/media/stagefright/FileSource.h +++ b/include/media/stagefright/FileSource.h @@ -34,9 +34,9 @@ public: virtual status_t initCheck() const; - virtual ssize_t readAt(off_t offset, void *data, size_t size); + virtual ssize_t readAt(off64_t offset, void *data, size_t size); - virtual status_t getSize(off_t *size); + virtual status_t getSize(off64_t *size); virtual DecryptHandle* DrmInitialization(DrmManagerClient *client); @@ -46,7 +46,6 @@ protected: virtual ~FileSource(); private: - FILE *mFile; int mFd; int64_t mOffset; int64_t mLength; @@ -59,7 +58,7 @@ private: int64_t mDrmBufSize; unsigned char *mDrmBuf; - ssize_t readAtDRM(off_t offset, void *data, size_t size); + ssize_t readAtDRM(off64_t offset, void *data, size_t size); FileSource(const FileSource &); FileSource &operator=(const FileSource &); diff --git a/include/media/stagefright/JPEGSource.h b/include/media/stagefright/JPEGSource.h index 9d0a700..1b7e91b 100644 --- a/include/media/stagefright/JPEGSource.h +++ b/include/media/stagefright/JPEGSource.h @@ -42,9 +42,9 @@ private: sp<DataSource> mSource; MediaBufferGroup *mGroup; bool mStarted; - off_t mSize; + off64_t mSize; int32_t mWidth, mHeight; - off_t mOffset; + off64_t mOffset; status_t parseJPEG(); diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index 7bf07eb..f7618e9 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -61,20 +61,21 @@ protected: private: class Track; - FILE *mFile; + int mFd; + status_t mInitCheck; bool mUse4ByteNalLength; bool mUse32BitOffset; bool mIsFileSizeLimitExplicitlyRequested; bool mPaused; bool mStarted; - off_t mOffset; + off64_t mOffset; off_t mMdatOffset; uint8_t *mMoovBoxBuffer; - off_t mMoovBoxBufferOffset; + off64_t mMoovBoxBufferOffset; bool mWriteMoovBoxToMemory; - off_t mFreeBoxOffset; + off64_t mFreeBoxOffset; bool mStreamableFile; - off_t mEstimatedMoovBoxSize; + off64_t mEstimatedMoovBoxSize; uint32_t mInterleaveDurationUs; int32_t mTimeScale; int64_t mStartTimestampUs; @@ -83,7 +84,7 @@ private: List<Track *> mTracks; - List<off_t> mBoxes; + List<off64_t> mBoxes; void setStartTimestampUs(int64_t timeUs); int64_t getStartTimestampUs(); // Not const @@ -145,10 +146,10 @@ private: void unlock(); // Acquire lock before calling these methods - off_t addSample_l(MediaBuffer *buffer); - off_t addLengthPrefixedSample_l(MediaBuffer *buffer); + off64_t addSample_l(MediaBuffer *buffer); + off64_t addLengthPrefixedSample_l(MediaBuffer *buffer); - inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream); + inline size_t write(const void *ptr, size_t size, size_t nmemb); bool exceedsFileSizeLimit(); bool use32BitFileOffset() const; bool exceedsFileDurationLimit(); diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index 295b127..5f33739 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -32,6 +32,10 @@ enum { kKeyMIMEType = 'mime', // cstring kKeyWidth = 'widt', // int32_t kKeyHeight = 'heig', // int32_t + + // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1) + kKeyCropRect = 'crop', + kKeyRotation = 'rotA', // int32_t (angle in degrees) kKeyIFramesInterval = 'ifiv', // int32_t kKeyStride = 'strd', // int32_t @@ -125,6 +129,7 @@ public: TYPE_INT64 = 'in64', TYPE_FLOAT = 'floa', TYPE_POINTER = 'ptr ', + TYPE_RECT = 'rect', }; void clear(); @@ -136,12 +141,22 @@ public: bool setFloat(uint32_t key, float value); bool setPointer(uint32_t key, void *value); + bool setRect( + uint32_t key, + int32_t left, int32_t top, + int32_t right, int32_t bottom); + bool findCString(uint32_t key, const char **value); bool findInt32(uint32_t key, int32_t *value); bool findInt64(uint32_t key, int64_t *value); bool findFloat(uint32_t key, float *value); bool findPointer(uint32_t key, void **value); + bool findRect( + uint32_t key, + int32_t *left, int32_t *top, + int32_t *right, int32_t *bottom); + bool setData(uint32_t key, uint32_t type, const void *data, size_t size); bool findData(uint32_t key, uint32_t *type, @@ -187,6 +202,10 @@ private: } }; + struct Rect { + int32_t mLeft, mTop, mRight, mBottom; + }; + KeyedVector<uint32_t, typed_data> mItems; // MetaData &operator=(const MetaData &); diff --git a/include/utils/Tokenizer.h b/include/utils/Tokenizer.h index bfe8923..21e58e6 100644 --- a/include/utils/Tokenizer.h +++ b/include/utils/Tokenizer.h @@ -19,6 +19,7 @@ #include <assert.h> #include <utils/Errors.h> +#include <utils/FileMap.h> #include <utils/String8.h> namespace android { @@ -27,7 +28,7 @@ namespace android { * A simple tokenizer for loading and parsing ASCII text files line by line. */ class Tokenizer { - Tokenizer(const String8& filename, const char* buffer, size_t length); + Tokenizer(const String8& filename, FileMap* fileMap, const char* buffer, size_t length); public: ~Tokenizer(); @@ -108,6 +109,7 @@ private: Tokenizer(const Tokenizer& other); // not copyable String8 mFilename; + FileMap* mFileMap; const char* mBuffer; size_t mLength; diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index 0ed129f..f00f748 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -236,11 +236,16 @@ enum RsPrimitive { }; enum RsError { - RS_ERROR_NONE, - RS_ERROR_BAD_SHADER, - RS_ERROR_BAD_SCRIPT, - RS_ERROR_BAD_VALUE, - RS_ERROR_OUT_OF_MEMORY + RS_ERROR_NONE = 0, + RS_ERROR_BAD_SHADER = 1, + RS_ERROR_BAD_SCRIPT = 2, + RS_ERROR_BAD_VALUE = 3, + RS_ERROR_OUT_OF_MEMORY = 4, + RS_ERROR_DRIVER = 5, + + RS_ERROR_FATAL_UNKNOWN = 0x1000, + RS_ERROR_FATAL_DRIVER = 0x1001, + RS_ERROR_FATAL_PROGRAM_LINK = 0x1002 }; enum RsAnimationInterpolation { diff --git a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs index b5f149c..96c39b1 100644 --- a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs +++ b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs @@ -5,8 +5,6 @@ float2 gGravityVector = {0.f, 9.8f}; -#pragma rs export_func(setGamma); - float2 gMinPos = {0.f, 0.f}; float2 gMaxPos = {1280.f, 700.f}; diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rs b/libs/rs/java/Balls/src/com/android/balls/balls.rs index 3edbe2d..9fd4722 100644 --- a/libs/rs/java/Balls/src/com/android/balls/balls.rs +++ b/libs/rs/java/Balls/src/com/android/balls/balls.rs @@ -26,9 +26,6 @@ typedef struct VpConsts { } VpConsts_t; VpConsts_t *vpConstants; - -#pragma rs export_func(initParts) - rs_script physics_script; Ball_t *balls1; diff --git a/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs b/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs index 5445744..b8f57a3 100644 --- a/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs +++ b/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs @@ -17,8 +17,6 @@ typedef struct __attribute__((packed, aligned(4))) Point { } Point_t; Point_t *point; -#pragma rs export_func(addParticles) - int root() { float dt = min(rsGetDt(), 0.1f); rsgClearColor(0.f, 0.f, 0.f, 1.f); diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs index 3e81115..f2f9a36 100644 --- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs @@ -11,8 +11,6 @@ uchar4 * OutPixel; float4 * ScratchPixel1; float4 * ScratchPixel2; -#pragma rs export_func(filter); - rs_script vBlurScript; rs_script hBlurScript; diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs index fe43354..e5900fd 100644 --- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs @@ -14,8 +14,6 @@ static float outWMinOutB; static float overInWMinInB; static rs_matrix3x3 colorMat; -#pragma rs export_func(setLevels, setSaturation, setGamma); - void setLevels(float iBlk, float oBlk, float iWht, float oWht) { inBlack = iBlk; outBlack = oBlk; diff --git a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs index 066fab8..4133fda 100644 --- a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs +++ b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs @@ -2,8 +2,6 @@ const int TEST_COUNT = 1; -#pragma rs export_func(fp_mad_test) - static float data_f1[1025]; static float4 data_f4[1025]; diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs index 351a8a5..ce451da 100644 --- a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs +++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs @@ -1,7 +1,5 @@ #include "shared.rsh" -#pragma rs export_func(primitives_test) - // Testing primitive types float floatTest = 1.99f; double doubleTest = 2.05; diff --git a/libs/rs/java/tests/src/com/android/rs/test/rsdebug.rs b/libs/rs/java/tests/src/com/android/rs/test/rsdebug.rs index a849234..f7942a5 100644 --- a/libs/rs/java/tests/src/com/android/rs/test/rsdebug.rs +++ b/libs/rs/java/tests/src/com/android/rs/test/rsdebug.rs @@ -1,7 +1,5 @@ #include "shared.rsh" -#pragma rs export_func(test_rsdebug) - // Testing primitive types float floatTest = 1.99f; double doubleTest = 2.05; diff --git a/libs/rs/java/tests/src/com/android/rs/test/rstypes.rs b/libs/rs/java/tests/src/com/android/rs/test/rstypes.rs index cb0c577..f3bf244 100644 --- a/libs/rs/java/tests/src/com/android/rs/test/rstypes.rs +++ b/libs/rs/java/tests/src/com/android/rs/test/rstypes.rs @@ -1,8 +1,6 @@ #include "shared.rsh" #include "rs_graphics.rsh" -#pragma rs export_func(test_rstypes) - rs_element elementTest; rs_type typeTest; rs_allocation allocationTest; diff --git a/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs b/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs index f924ae4..a71a062 100644 --- a/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs +++ b/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs @@ -14,8 +14,6 @@ #include "shared.rsh" -#pragma rs export_func(vector_array_test) - typedef struct { float3 arr[2]; } float3Struct; diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index 1b584c8..7b35305 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -43,11 +43,6 @@ ContextDump { param int32_t bits } -ContextGetError { - param RsError *err - ret const char * - } - ContextSetPriority { param int32_t priority } diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 840a10e..35db332 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -287,10 +287,27 @@ uint32_t Context::runScript(Script *s) { return ret; } -void Context::checkError(const char *msg) const { +void Context::checkError(const char *msg, bool isFatal) const { + GLenum err = glGetError(); if (err != GL_NO_ERROR) { - LOGE("%p, GL Error, 0x%x, from %s", this, err, msg); + char buf[1024]; + snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg); + + if (isFatal) { + setError(RS_ERROR_FATAL_DRIVER, buf); + } else { + switch (err) { + case GL_OUT_OF_MEMORY: + setError(RS_ERROR_OUT_OF_MEMORY, buf); + break; + default: + setError(RS_ERROR_DRIVER, buf); + break; + } + } + + LOGE("%p, %s", this, buf); } } @@ -597,7 +614,6 @@ Context::Context() { mPaused = false; mObjHead = NULL; mError = RS_ERROR_NONE; - mErrorMsg = NULL; } Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc) { @@ -861,7 +877,8 @@ RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen return RS_MESSAGE_TO_CLIENT_RESIZE; } -bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace) { +bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID, + uint32_t subID, size_t len, bool waitForSpace) const { //LOGE("sendMessageToClient %i %i %i %i", cmdID, subID, len, waitForSpace); if (cmdID == 0) { LOGE("Attempting to send invalid command 0 to client."); @@ -894,18 +911,8 @@ void Context::deinitToClient() { mIO.mToClient.shutdown(); } -const char * Context::getError(RsError *err) { - *err = mError; - mError = RS_ERROR_NONE; - if (*err != RS_ERROR_NONE) { - return mErrorMsg; - } - return NULL; -} - -void Context::setError(RsError e, const char *msg) { +void Context::setError(RsError e, const char *msg) const { mError = e; - mErrorMsg = msg; sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true); } @@ -1012,14 +1019,6 @@ void rsi_ContextDump(Context *rsc, int32_t bits) { ObjectBase::dumpAll(rsc); } -const char* rsi_ContextGetError(Context *rsc, RsError *e) { - const char *msg = rsc->getError(e); - if (*e != RS_ERROR_NONE) { - LOGE("RS Error %i %s", *e, msg); - } - return msg; -} - } } diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index c377c73..cafbdff 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -144,7 +144,7 @@ public: RsMessageToClientType peekMessageToClient(size_t *receiveLen, uint32_t *subID, bool wait); RsMessageToClientType getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait); - bool sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace); + bool sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace) const; uint32_t runScript(Script *s); void initToClient(); @@ -169,7 +169,7 @@ public: uint32_t getWidth() const {return mWidth;} uint32_t getHeight() const {return mHeight;} - ThreadIO mIO; + mutable ThreadIO mIO; // Timers enum Timers { @@ -197,9 +197,8 @@ public: } props; void dumpDebug() const; - void checkError(const char *) const; - const char * getError(RsError *); - void setError(RsError e, const char *msg = NULL); + void checkError(const char *, bool isFatal = false) const; + void setError(RsError e, const char *msg = NULL) const; mutable const ObjectBase * mObjHead; @@ -259,8 +258,7 @@ protected: bool mRunning; bool mExit; bool mPaused; - RsError mError; - const char *mErrorMsg; + mutable RsError mError; pthread_t mThreadId; pid_t mNativeThreadId; diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp index 40321fe..6ae8bb8 100644 --- a/libs/rs/rsElement.cpp +++ b/libs/rs/rsElement.cpp @@ -348,7 +348,6 @@ RsElement rsi_ElementCreate(Context *rsc, RsDataKind dk, bool norm, uint32_t vecSize) { - //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize); const Element *e = Element::create(rsc, dt, dk, norm, vecSize); e->incUserRef(); return (RsElement)e; @@ -360,7 +359,6 @@ RsElement rsi_ElementCreate2(Context *rsc, const char ** names, const size_t * nameLengths, const uint32_t * arraySizes) { - //LOGE("rsi_ElementCreate2 %i", count); const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths, arraySizes); e->incUserRef(); return (RsElement)e; diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp index ffa7d26..0713fb3 100644 --- a/libs/rs/rsProgramFragment.cpp +++ b/libs/rs/rsProgramFragment.cpp @@ -136,9 +136,9 @@ void ProgramFragment::createShader() { char buf[256]; for (uint32_t ct=0; ct < mTextureCount; ct++) { if (mTextureTargets[ct] == RS_TEXTURE_2D) { - sprintf(buf, "uniform sampler2D UNI_Tex%i;\n", ct); + snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct); } else { - sprintf(buf, "uniform samplerCube UNI_Tex%i;\n", ct); + snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct); } mShader.append(buf); } @@ -159,7 +159,7 @@ void ProgramFragment::init(Context *rsc) { mTextureUniformIndexStart = uniformIndex; char buf[256]; for (uint32_t ct=0; ct < mTextureCount; ct++) { - sprintf(buf, "UNI_Tex%i", ct); + snprintf(buf, sizeof(buf), "UNI_Tex%i", ct); mUniformNames[uniformIndex].setTo(buf); mUniformArraySizes[uniformIndex] = 1; uniformIndex++; diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp index 3fd2981..a28b9bd 100644 --- a/libs/rs/rsProgramVertex.cpp +++ b/libs/rs/rsProgramVertex.cpp @@ -49,7 +49,7 @@ void ProgramVertex::loadShader(Context *rsc) { Program::loadShader(rsc, GL_VERTEX_SHADER); } -void ProgramVertex::createShader() { +void ProgramVertex::createShader(Context *rsc) { if (mUserShader.length() > 1) { appendUserConstants(); @@ -81,13 +81,12 @@ void ProgramVertex::createShader() { } mShader.append(mUserShader); } else { - LOGE("ProgramFragment::createShader cannot create program, shader code not defined"); - rsAssert(0); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "ProgramFragment::createShader cannot create program, shader code not defined"); } } void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc) { - //LOGE("sgl2 vtx1 %x", glGetError()); if ((state->mLast.get() == this) && !mDirty) { return; } @@ -96,8 +95,8 @@ void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCach if (!isUserProgram()) { if (mConstants[0].get() == NULL) { - LOGE("Unable to set fixed function emulation matrices because allocation is missing"); - rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Unable to set fixed function emulation matrices because allocation is missing"); return; } float *f = static_cast<float *>(mConstants[0]->getPtr()); @@ -120,12 +119,13 @@ void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCach void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const { if (isUserProgram()) { - LOGE("Attempting to set fixed function emulation matrix projection on user program"); - rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to set fixed function emulation matrix projection on user program"); return; } if (mConstants[0].get() == NULL) { - LOGE("Unable to set fixed function emulation matrix projection because allocation is missing"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Unable to set fixed function emulation matrix projection because allocation is missing"); return; } float *f = static_cast<float *>(mConstants[0]->getPtr()); @@ -135,13 +135,13 @@ void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const { if (isUserProgram()) { - LOGE("Attempting to set fixed function emulation matrix modelview on user program"); - rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to set fixed function emulation matrix modelview on user program"); return; } if (mConstants[0].get() == NULL) { - LOGE("Unable to set fixed function emulation matrix modelview because allocation is missing"); - rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Unable to set fixed function emulation matrix modelview because allocation is missing"); return; } float *f = static_cast<float *>(mConstants[0]->getPtr()); @@ -151,13 +151,13 @@ void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const { if (isUserProgram()) { - LOGE("Attempting to set fixed function emulation matrix texture on user program"); - rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to set fixed function emulation matrix texture on user program"); return; } if (mConstants[0].get() == NULL) { - LOGE("Unable to set fixed function emulation matrix texture because allocation is missing"); - rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Unable to set fixed function emulation matrix texture because allocation is missing"); return; } float *f = static_cast<float *>(mConstants[0]->getPtr()); @@ -167,13 +167,13 @@ void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const { void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const { if (isUserProgram()) { - LOGE("Attempting to get fixed function emulation matrix projection on user program"); - rsc->setError(RS_ERROR_BAD_SHADER, "Cannot get emulation matrix on user shader"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Attempting to get fixed function emulation matrix projection on user program"); return; } if (mConstants[0].get() == NULL) { - LOGE("Unable to get fixed function emulation matrix projection because allocation is missing"); - rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing"); + rsc->setError(RS_ERROR_FATAL_UNKNOWN, + "Unable to get fixed function emulation matrix projection because allocation is missing"); return; } float *f = static_cast<float *>(mConstants[0]->getPtr()); @@ -202,7 +202,7 @@ void ProgramVertex::init(Context *rsc) { initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI); } } - createShader(); + createShader(rsc); } void ProgramVertex::serialize(OStream *stream) const { diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h index 824edbb..2a5c863 100644 --- a/libs/rs/rsProgramVertex.h +++ b/libs/rs/rsProgramVertex.h @@ -40,7 +40,7 @@ public: void transformToScreen(Context *, float *v4out, const float *v3in) const; - virtual void createShader(); + virtual void createShader(Context *); virtual void loadShader(Context *); virtual void init(Context *); diff --git a/libs/rs/rsShaderCache.cpp b/libs/rs/rsShaderCache.cpp index d254018..45384c9 100644 --- a/libs/rs/rsShaderCache.cpp +++ b/libs/rs/rsShaderCache.cpp @@ -150,7 +150,7 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag } } glDeleteProgram(pgm); - rsc->setError(RS_ERROR_BAD_SHADER, "Error linking GL Programs"); + rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, "Error linking GL Programs"); return false; } diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp index 2a51335..c195b9b 100644 --- a/libs/rs/rsType.cpp +++ b/libs/rs/rsType.cpp @@ -136,7 +136,7 @@ void Type::dumpLOGV(const char *prefix) const { char buf[1024]; ObjectBase::dumpLOGV(prefix); LOGV("%s Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces); - sprintf(buf, "%s element: ", prefix); + snprintf(buf, sizeof(buf), "%s element: ", prefix); mElement->dumpLOGV(buf); } diff --git a/libs/utils/Tokenizer.cpp b/libs/utils/Tokenizer.cpp index 19dadf0..9251973 100644 --- a/libs/utils/Tokenizer.cpp +++ b/libs/utils/Tokenizer.cpp @@ -22,7 +22,6 @@ #include <errno.h> #include <sys/types.h> #include <sys/stat.h> -#include <sys/mman.h> #include <utils/Log.h> #include <utils/Tokenizer.h> @@ -37,13 +36,16 @@ static inline bool isDelimiter(char ch, const char* delimiters) { } -Tokenizer::Tokenizer(const String8& filename, const char* buffer, size_t length) : - mFilename(filename), mBuffer(buffer), mLength(length), +Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, + const char* buffer, size_t length) : + mFilename(filename), mFileMap(fileMap), mBuffer(buffer), mLength(length), mCurrent(buffer), mLineNumber(1) { } Tokenizer::~Tokenizer() { - munmap((void*)mBuffer, mLength); + if (mFileMap) { + mFileMap->release(); + } } status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) { @@ -55,29 +57,29 @@ status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) { result = -errno; LOGE("Error opening file '%s', %s.", filename.string(), strerror(errno)); } else { - struct stat64 stat; - if (fstat64(fd, &stat)) { + struct stat stat; + if (fstat(fd, &stat)) { result = -errno; LOGE("Error getting size of file '%s', %s.", filename.string(), strerror(errno)); } else { size_t length = size_t(stat.st_size); - void* buffer = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); - if (buffer == MAP_FAILED) { - result = -errno; + FileMap* fileMap = new FileMap(); + if (!fileMap->create(NULL, fd, 0, length, true)) { + result = NO_MEMORY; LOGE("Error mapping file '%s', %s.", filename.string(), strerror(errno)); } else { - if (madvise(buffer, length, MADV_SEQUENTIAL)) { - LOGW("Error calling madvise for mmapped file '%s', %s.", filename.string(), - strerror(errno)); - } + fileMap->advise(FileMap::SEQUENTIAL); - *outTokenizer = new Tokenizer(filename, static_cast<const char*>(buffer), length); + *outTokenizer = new Tokenizer(filename, fileMap, + static_cast<const char*>(fileMap->getDataPtr()), length); if (!*outTokenizer) { result = NO_MEMORY; LOGE("Error allocating tokenizer for file=%s.", filename.string()); - munmap(buffer, length); } } + if (result) { + fileMap->release(); + } } close(fd); } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index def88ae..9058a7b 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -984,7 +984,8 @@ public class AudioManager { * application when it places a phone call, as it will cause signals from the radio layer * to feed the platform mixer. * - * @param mode the requested audio mode (NORMAL, RINGTONE, IN_CALL or IN_COMMUNICATION). + * @param mode the requested audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE}, + * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}). * Informs the HAL about the current audio state so that * it can route the audio appropriately. */ @@ -1000,7 +1001,8 @@ public class AudioManager { /** * Returns the current audio mode. * - * @return the current audio mode (NORMAL, RINGTONE, IN_CALL or IN_COMMUNICATION). + * @return the current audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE}, + * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}). * Returns the current current audio state from the HAL. */ public int getMode() { @@ -1038,7 +1040,6 @@ public class AudioManager { */ public static final int MODE_IN_CALL = AudioSystem.MODE_IN_CALL; /** - * @hide * In communication audio mode. An audio/video chat or VoIP call is established. */ public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION; diff --git a/media/java/android/media/MtpClient.java b/media/java/android/media/MtpClient.java index 98da1f6..dcb1983 100644 --- a/media/java/android/media/MtpClient.java +++ b/media/java/android/media/MtpClient.java @@ -16,7 +16,6 @@ package android.media; -import android.os.ParcelFileDescriptor; import android.util.Log; /** @@ -69,9 +68,10 @@ public class MtpClient { return native_get_storage_id(deviceID, objectID); } - // create a file descriptor for reading the contents of an object over MTP - public ParcelFileDescriptor openFile(int deviceID, long objectID) { - return native_open_file(deviceID, objectID); + // Reads a file from device to host to the specified destination. + // Returns true if the transfer succeeds. + public boolean importFile(int deviceID, long objectID, String destPath) { + return native_import_file(deviceID, objectID, destPath); } public interface Listener { @@ -104,5 +104,5 @@ public class MtpClient { private native boolean native_delete_object(int deviceID, long objectID); private native long native_get_parent(int deviceID, long objectID); private native long native_get_storage_id(int deviceID, long objectID); - private native ParcelFileDescriptor native_open_file(int deviceID, long objectID); + private native boolean native_import_file(int deviceID, long objectID, String destPath); } diff --git a/media/java/android/media/MtpCursor.java b/media/java/android/media/MtpCursor.java index 9b5ab95..daa3f4d 100644 --- a/media/java/android/media/MtpCursor.java +++ b/media/java/android/media/MtpCursor.java @@ -40,6 +40,7 @@ public final class MtpCursor extends AbstractWindowedCursor { public static final int OBJECT_ID = 6; public static final int STORAGE_CHILDREN = 7; public static final int OBJECT_CHILDREN = 8; + public static final int OBJECT_IMPORT = 9; /** The names of the columns in the projection */ private String[] mColumns; diff --git a/media/jni/android_media_MtpClient.cpp b/media/jni/android_media_MtpClient.cpp index d23185b..144dfc8 100644 --- a/media/jni/android_media_MtpClient.cpp +++ b/media/jni/android_media_MtpClient.cpp @@ -26,6 +26,7 @@ #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" +#include "private/android_filesystem_config.h" #include "MtpClient.h" #include "MtpDevice.h" @@ -39,19 +40,6 @@ static jmethodID method_deviceAdded; static jmethodID method_deviceRemoved; static jfieldID field_context; -static struct file_descriptor_offsets_t -{ - jclass mClass; - jmethodID mConstructor; - jfieldID mDescriptor; -} gFileDescriptorOffsets; - -static struct parcel_file_descriptor_offsets_t -{ - jclass mClass; - jmethodID mConstructor; -} gParcelFileDescriptorOffsets; - #ifdef HAVE_ANDROID_OS static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { @@ -201,34 +189,19 @@ android_media_MtpClient_get_storage_id(JNIEnv *env, jobject thiz, return -1; } -static jobject -android_media_MtpClient_open_file(JNIEnv *env, jobject thiz, - jint device_id, jlong object_id) +static jboolean +android_media_MtpClient_import_file(JNIEnv *env, jobject thiz, + jint device_id, jlong object_id, jstring dest_path) { #ifdef HAVE_ANDROID_OS MyClient *client = (MyClient *)env->GetIntField(thiz, field_context); MtpDevice* device = client->getDevice(device_id); - if (!device) - return NULL; - - MtpObjectInfo* info = device->getObjectInfo(object_id); - if (!info) - return NULL; - int object_size = info->mCompressedSize; - delete info; - int fd = device->readObject(object_id, object_size); - if (fd < 0) - return NULL; - - jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass, - gFileDescriptorOffsets.mConstructor); - if (fileDescriptor != NULL) { - env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, fd); - } else { - return NULL; + if (device) { + const char *destPathStr = env->GetStringUTFChars(dest_path, NULL); + bool result = device->readObject(object_id, destPathStr, AID_SDCARD_RW, 0664); + env->ReleaseStringUTFChars(dest_path, destPathStr); + return result; } - return env->NewObject(gParcelFileDescriptorOffsets.mClass, - gParcelFileDescriptorOffsets.mConstructor, fileDescriptor); #endif return NULL; } @@ -243,8 +216,8 @@ static JNINativeMethod gMethods[] = { {"native_delete_object", "(IJ)Z", (void *)android_media_MtpClient_delete_object}, {"native_get_parent", "(IJ)J", (void *)android_media_MtpClient_get_parent}, {"native_get_storage_id", "(IJ)J", (void *)android_media_MtpClient_get_storage_id}, - {"native_open_file", "(IJ)Landroid/os/ParcelFileDescriptor;", - (void *)android_media_MtpClient_open_file}, + {"native_import_file", "(IJLjava/lang/String;)Z", + (void *)android_media_MtpClient_import_file}, }; static const char* const kClassPathName = "android/media/MtpClient"; @@ -276,21 +249,6 @@ int register_android_media_MtpClient(JNIEnv *env) return -1; } - clazz = env->FindClass("java/io/FileDescriptor"); - LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); - gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); - gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V"); - gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); - LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, - "Unable to find descriptor field in java.io.FileDescriptor"); - - clazz = env->FindClass("android/os/ParcelFileDescriptor"); - LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); - gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); - gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); - LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL, - "Unable to find constructor for android.os.ParcelFileDescriptor"); - return AndroidRuntime::registerNativeMethods(env, "android/media/MtpClient", gMethods, NELEM(gMethods)); } diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h index 42037af..1b0fd38 100644 --- a/media/jni/soundpool/SoundPool.h +++ b/media/jni/soundpool/SoundPool.h @@ -22,7 +22,6 @@ #include <utils/Vector.h> #include <utils/KeyedVector.h> #include <media/AudioTrack.h> -#include <cutils/atomic.h> namespace android { diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 88b8c86..aadeba5 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -27,7 +27,6 @@ #include <media/AudioEffect.h> #include <utils/Log.h> -#include <cutils/atomic.h> #include <binder/IPCThreadState.h> @@ -207,18 +206,22 @@ status_t AudioEffect::setEnabled(bool enabled) return INVALID_OPERATION; } - if (enabled) { - LOGV("enable %p", this); - if (android_atomic_or(1, &mEnabled) == 0) { - return mIEffect->enable(); + status_t status = NO_ERROR; + + AutoMutex lock(mLock); + if (enabled != mEnabled) { + if (enabled) { + LOGV("enable %p", this); + status = mIEffect->enable(); + } else { + LOGV("disable %p", this); + status = mIEffect->disable(); } - } else { - LOGV("disable %p", this); - if (android_atomic_and(~1, &mEnabled) == 1) { - return mIEffect->disable(); + if (status == NO_ERROR) { + mEnabled = enabled; } } - return NO_ERROR; + return status; } status_t AudioEffect::command(uint32_t cmdCode, @@ -232,26 +235,26 @@ status_t AudioEffect::command(uint32_t cmdCode, return INVALID_OPERATION; } - if ((cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) && - (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL)) { - return BAD_VALUE; + if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) { + if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) { + return NO_ERROR; + } + if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) { + return BAD_VALUE; + } + mLock.lock(); } status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData); - if (status != NO_ERROR) { - return status; - } if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) { - status = *(status_t *)replyData; - if (status != NO_ERROR) { - return status; + if (status == NO_ERROR) { + status = *(status_t *)replyData; } - if (cmdCode == EFFECT_CMD_ENABLE) { - android_atomic_or(1, &mEnabled); - } else { - android_atomic_and(~1, &mEnabled); + if (status == NO_ERROR) { + mEnabled = (cmdCode == EFFECT_CMD_ENABLE); } + mLock.unlock(); } return status; @@ -370,11 +373,7 @@ void AudioEffect::enableStatusChanged(bool enabled) { LOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf); if (mStatus == ALREADY_EXISTS) { - if (enabled) { - android_atomic_or(1, &mEnabled); - } else { - android_atomic_and(~1, &mEnabled); - } + mEnabled = enabled; if (mCbf) { mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled); } diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a6c515c..1d6ffa0 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -35,7 +35,6 @@ #include <binder/Parcel.h> #include <binder/IPCThreadState.h> #include <utils/Timers.h> -#include <cutils/atomic.h> #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) @@ -282,7 +281,9 @@ status_t AudioRecord::start() t->mLock.lock(); } - if (android_atomic_or(1, &mActive) == 0) { + AutoMutex lock(mLock); + if (mActive == 0) { + mActive = 1; ret = mAudioRecord->start(); if (ret == DEAD_OBJECT) { LOGV("start() dead IAudioRecord: creating a new one"); @@ -302,8 +303,7 @@ status_t AudioRecord::start() setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); } } else { - LOGV("start() failed"); - android_atomic_and(~1, &mActive); + mActive = 0; } } @@ -322,9 +322,11 @@ status_t AudioRecord::stop() if (t != 0) { t->mLock.lock(); - } + } - if (android_atomic_and(~1, &mActive) == 1) { + AutoMutex lock(mLock); + if (mActive == 1) { + mActive = 0; mCblk->cv.signal(); mAudioRecord->stop(); // the record head position will reset to 0, so if a marker is set, we need diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 587c8ff..c1bed59 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -35,7 +35,6 @@ #include <binder/Parcel.h> #include <binder/IPCThreadState.h> #include <utils/Timers.h> -#include <cutils/atomic.h> #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) @@ -312,7 +311,9 @@ void AudioTrack::start() t->mLock.lock(); } - if (android_atomic_or(1, &mActive) == 0) { + AutoMutex lock(mLock); + if (mActive == 0) { + mActive = 1; mNewPosition = mCblk->server + mUpdatePeriod; mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->waitTimeMs = 0; @@ -344,7 +345,7 @@ void AudioTrack::start() } if (status != NO_ERROR) { LOGV("start() failed"); - android_atomic_and(~1, &mActive); + mActive = 0; if (t != 0) { t->requestExit(); } else { @@ -367,7 +368,9 @@ void AudioTrack::stop() t->mLock.lock(); } - if (android_atomic_and(~1, &mActive) == 1) { + AutoMutex lock(mLock); + if (mActive == 1) { + mActive = 0; mCblk->cv.signal(); mAudioTrack->stop(); // Cancel loops (If we are in the middle of a loop, playback @@ -407,7 +410,6 @@ void AudioTrack::flush() mMarkerReached = false; mUpdatePeriod = 0; - if (!mActive) { mAudioTrack->flush(); // Release AudioTrack callback thread in case it was waiting for new buffers @@ -419,7 +421,9 @@ void AudioTrack::flush() void AudioTrack::pause() { LOGV("pause"); - if (android_atomic_and(~1, &mActive) == 1) { + AutoMutex lock(mLock); + if (mActive == 1) { + mActive = 0; mAudioTrack->pause(); } } diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index 3341ff7..a9d537f 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -31,7 +31,6 @@ LOCAL_SHARED_LIBRARIES := \ libandroid_runtime \ libstagefright \ libstagefright_omx \ - libstagefright_color_conversion \ libstagefright_foundation \ libsurfaceflinger_client diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index dadd1db..ec3b5a2 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -864,7 +864,7 @@ status_t StagefrightRecorder::startAMRRecording() { return UNKNOWN_ERROR; } - mWriter = new AMRWriter(dup(mOutputFd)); + mWriter = new AMRWriter(mOutputFd); mWriter->addSource(audioEncoder); if (mMaxFileDurationUs != 0) { @@ -912,7 +912,7 @@ status_t StagefrightRecorder::startRTPRecording() { } } - mWriter = new ARTPWriter(dup(mOutputFd)); + mWriter = new ARTPWriter(mOutputFd); mWriter->addSource(source); mWriter->setListener(mListener); @@ -922,7 +922,7 @@ status_t StagefrightRecorder::startRTPRecording() { status_t StagefrightRecorder::startMPEG2TSRecording() { CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS); - sp<MediaWriter> writer = new MPEG2TSWriter(dup(mOutputFd)); + sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd); if (mAudioSource != AUDIO_SOURCE_LIST_END) { if (mAudioEncoder != AUDIO_ENCODER_AAC) { @@ -1204,7 +1204,7 @@ status_t StagefrightRecorder::setupMPEG4Recording( mediaWriter->clear(); *totalBitRate = 0; status_t err = OK; - sp<MediaWriter> writer = new MPEG4Writer(dup(outputFd)); + sp<MediaWriter> writer = new MPEG4Writer(outputFd); // Add audio source first if it exists if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_LIST_END)) { diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp index 1b05528..ac87c29 100644 --- a/media/libstagefright/AMRExtractor.cpp +++ b/media/libstagefright/AMRExtractor.cpp @@ -55,7 +55,7 @@ private: size_t mFrameSize; bool mIsWide; - off_t mOffset; + off64_t mOffset; int64_t mCurrentTimeUs; bool mStarted; MediaBufferGroup *mGroup; @@ -115,9 +115,9 @@ AMRExtractor::AMRExtractor(const sp<DataSource> &source) mFrameSize = getFrameSize(mIsWide, FT); - off_t streamSize; + off64_t streamSize; if (mDataSource->getSize(&streamSize) == OK) { - off_t numFrames = streamSize / mFrameSize; + off64_t numFrames = streamSize / mFrameSize; mMeta->setInt64(kKeyDuration, 20000ll * numFrames); } diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp index c0b1abe..0db3d1d 100644 --- a/media/libstagefright/AMRWriter.cpp +++ b/media/libstagefright/AMRWriter.cpp @@ -24,20 +24,28 @@ #include <media/mediarecorder.h> #include <sys/prctl.h> #include <sys/resource.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> namespace android { AMRWriter::AMRWriter(const char *filename) - : mFile(fopen(filename, "wb")), - mInitCheck(mFile != NULL ? OK : NO_INIT), + : mFd(-1), + mInitCheck(NO_INIT), mStarted(false), mPaused(false), mResumed(false) { + + mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC); + if (mFd >= 0) { + mInitCheck = OK; + } } AMRWriter::AMRWriter(int fd) - : mFile(fdopen(fd, "wb")), - mInitCheck(mFile != NULL ? OK : NO_INIT), + : mFd(dup(fd)), + mInitCheck(mFd < 0? NO_INIT: OK), mStarted(false), mPaused(false), mResumed(false) { @@ -48,9 +56,9 @@ AMRWriter::~AMRWriter() { stop(); } - if (mFile != NULL) { - fclose(mFile); - mFile = NULL; + if (mFd != -1) { + close(mFd); + mFd = -1; } } @@ -90,8 +98,8 @@ status_t AMRWriter::addSource(const sp<MediaSource> &source) { mSource = source; const char *kHeader = isWide ? "#!AMR-WB\n" : "#!AMR\n"; - size_t n = strlen(kHeader); - if (fwrite(kHeader, 1, n, mFile) != n) { + ssize_t n = strlen(kHeader); + if (write(mFd, kHeader, n) != n) { return ERROR_IO; } @@ -240,11 +248,9 @@ status_t AMRWriter::threadFunc() { notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); break; } - ssize_t n = fwrite( - (const uint8_t *)buffer->data() + buffer->range_offset(), - 1, - buffer->range_length(), - mFile); + ssize_t n = write(mFd, + (const uint8_t *)buffer->data() + buffer->range_offset(), + buffer->range_length()); if (n < (ssize_t)buffer->range_length()) { buffer->release(); @@ -266,9 +272,8 @@ status_t AMRWriter::threadFunc() { notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR); } - fflush(mFile); - fclose(mFile); - mFile = NULL; + close(mFd); + mFd = -1; mReachedEOS = true; if (err == ERROR_END_OF_STREAM) { return OK; diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 8fe1d4d..db23836 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -49,7 +49,6 @@ LOCAL_SRC_FILES:= \ WVMExtractor.cpp \ XINGSeeker.cpp \ avc_utils.cpp \ - string.cpp LOCAL_C_INCLUDES:= \ $(JNI_H_INCLUDE) \ @@ -72,6 +71,7 @@ LOCAL_SHARED_LIBRARIES := \ libcrypto LOCAL_STATIC_LIBRARIES := \ + libstagefright_color_conversion \ libstagefright_aacdec \ libstagefright_aacenc \ libstagefright_amrnbdec \ @@ -98,7 +98,6 @@ LOCAL_SHARED_LIBRARIES += \ libstagefright_enc_common \ libstagefright_avc_common \ libstagefright_foundation \ - libstagefright_color_conversion ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) LOCAL_LDLIBS += -lpthread -ldl diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 538e7bf..fe5162e 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -81,16 +81,8 @@ private: struct AwesomeLocalRenderer : public AwesomeRenderer { AwesomeLocalRenderer( - OMX_COLOR_FORMATTYPE colorFormat, - const sp<Surface> &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight, - int32_t rotationDegrees) - : mTarget(NULL) { - init(colorFormat, surface, - displayWidth, displayHeight, - decodedWidth, decodedHeight, - rotationDegrees); + const sp<Surface> &surface, const sp<MetaData> &meta) + : mTarget(new SoftwareRenderer(surface, meta)) { } virtual void render(MediaBuffer *buffer) { @@ -111,28 +103,10 @@ protected: private: SoftwareRenderer *mTarget; - void init( - OMX_COLOR_FORMATTYPE colorFormat, - const sp<Surface> &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight, - int32_t rotationDegrees); - AwesomeLocalRenderer(const AwesomeLocalRenderer &); AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; }; -void AwesomeLocalRenderer::init( - OMX_COLOR_FORMATTYPE colorFormat, - const sp<Surface> &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight, - int32_t rotationDegrees) { - mTarget = new SoftwareRenderer( - colorFormat, surface, displayWidth, displayHeight, - decodedWidth, decodedHeight, rotationDegrees); -} - struct AwesomeNativeWindowRenderer : public AwesomeRenderer { AwesomeNativeWindowRenderer( const sp<ANativeWindow> &nativeWindow, @@ -188,9 +162,7 @@ AwesomePlayer::AwesomePlayer() mAudioPlayer(NULL), mFlags(0), mExtractorFlags(0), - mLastVideoBuffer(NULL), mVideoBuffer(NULL), - mSuspensionState(NULL), mDecryptHandle(NULL) { CHECK_EQ(mClient.connect(), OK); @@ -433,11 +405,6 @@ void AwesomePlayer::reset_l() { mVideoRenderer.clear(); - if (mLastVideoBuffer) { - mLastVideoBuffer->release(); - mLastVideoBuffer = NULL; - } - if (mVideoBuffer) { mVideoBuffer->release(); mVideoBuffer = NULL; @@ -469,7 +436,6 @@ void AwesomePlayer::reset_l() { mDurationUs = -1; mFlags = 0; mExtractorFlags = 0; - mVideoWidth = mVideoHeight = -1; mTimeSourceDeltaUs = 0; mVideoTimeUs = 0; @@ -482,9 +448,6 @@ void AwesomePlayer::reset_l() { mFileSource.clear(); - delete mSuspensionState; - mSuspensionState = NULL; - mBitrate = -1; } @@ -499,7 +462,7 @@ void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { } bool AwesomePlayer::getBitrate(int64_t *bitrate) { - off_t size; + off64_t size; if (mDurationUs >= 0 && mCachedSource != NULL && mCachedSource->getSize(&size) == OK) { *bitrate = size * 8000000ll / mDurationUs; // in bits/sec @@ -637,11 +600,6 @@ void AwesomePlayer::partial_reset_l() { mVideoRenderer.clear(); - if (mLastVideoBuffer) { - mLastVideoBuffer->release(); - mLastVideoBuffer = NULL; - } - if (mVideoBuffer) { mVideoBuffer->release(); mVideoBuffer = NULL; @@ -815,9 +773,25 @@ status_t AwesomePlayer::play_l() { void AwesomePlayer::notifyVideoSize_l() { sp<MetaData> meta = mVideoSource->getFormat(); - int32_t decodedWidth, decodedHeight; - CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); - CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); + int32_t cropLeft, cropTop, cropRight, cropBottom; + if (!meta->findRect( + kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { + int32_t width, height; + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + + cropLeft = cropTop = 0; + cropRight = width - 1; + cropBottom = height - 1; + + LOGV("got dimensions only %d x %d", width, height); + } else { + LOGV("got crop rect %d, %d, %d, %d", + cropLeft, cropTop, cropRight, cropBottom); + } + + int32_t usableWidth = cropRight - cropLeft + 1; + int32_t usableHeight = cropBottom - cropTop + 1; int32_t rotationDegrees; if (!mVideoTrack->getFormat()->findInt32( @@ -827,10 +801,10 @@ void AwesomePlayer::notifyVideoSize_l() { if (rotationDegrees == 90 || rotationDegrees == 270) { notifyListener_l( - MEDIA_SET_VIDEO_SIZE, decodedHeight, decodedWidth); + MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); } else { notifyListener_l( - MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight); + MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); } } @@ -872,12 +846,7 @@ void AwesomePlayer::initRenderer_l() { // allocate their buffers in local address space. This renderer // then performs a color conversion and copy to get the data // into the ANativeBuffer. - mVideoRenderer = new AwesomeLocalRenderer( - (OMX_COLOR_FORMATTYPE)format, - mSurface, - mVideoWidth, mVideoHeight, - decodedWidth, decodedHeight, - rotationDegrees); + mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta); } } @@ -1041,20 +1010,6 @@ void AwesomePlayer::seekAudioIfNecessary_l() { } } -status_t AwesomePlayer::getVideoDimensions( - int32_t *width, int32_t *height) const { - Mutex::Autolock autoLock(mLock); - - if (mVideoWidth < 0 || mVideoHeight < 0) { - return UNKNOWN_ERROR; - } - - *width = mVideoWidth; - *height = mVideoHeight; - - return OK; -} - void AwesomePlayer::setAudioSource(sp<MediaSource> source) { CHECK(source != NULL); @@ -1123,9 +1078,6 @@ status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { } } - CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); - CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); - status_t err = mVideoSource->start(); if (err != OK) { @@ -1180,11 +1132,6 @@ void AwesomePlayer::onVideoEvent() { mVideoEventPending = false; if (mSeeking) { - if (mLastVideoBuffer) { - mLastVideoBuffer->release(); - mLastVideoBuffer = NULL; - } - if (mVideoBuffer) { mVideoBuffer->release(); mVideoBuffer = NULL; @@ -1327,11 +1274,7 @@ void AwesomePlayer::onVideoEvent() { mVideoRenderer->render(mVideoBuffer); } - if (mLastVideoBuffer) { - mLastVideoBuffer->release(); - mLastVideoBuffer = NULL; - } - mLastVideoBuffer = mVideoBuffer; + mVideoBuffer->release(); mVideoBuffer = NULL; postVideoEvent_l(); @@ -1745,142 +1688,6 @@ void AwesomePlayer::finishAsyncPrepare_l() { mPreparedCondition.broadcast(); } -status_t AwesomePlayer::suspend() { - LOGV("suspend"); - Mutex::Autolock autoLock(mLock); - - if (mSuspensionState != NULL) { - if (mLastVideoBuffer == NULL) { - //go into here if video is suspended again - //after resuming without being played between - //them - SuspensionState *state = mSuspensionState; - mSuspensionState = NULL; - reset_l(); - mSuspensionState = state; - return OK; - } - - delete mSuspensionState; - mSuspensionState = NULL; - } - - if (mFlags & PREPARING) { - mFlags |= PREPARE_CANCELLED; - if (mConnectingDataSource != NULL) { - LOGI("interrupting the connection process"); - mConnectingDataSource->disconnect(); - } - } - - while (mFlags & PREPARING) { - mPreparedCondition.wait(mLock); - } - - SuspensionState *state = new SuspensionState; - state->mUri = mUri; - state->mUriHeaders = mUriHeaders; - state->mFileSource = mFileSource; - - state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS); - getPosition(&state->mPositionUs); - - if (mLastVideoBuffer) { - size_t size = mLastVideoBuffer->range_length(); - - if (size) { - int32_t unreadable; - if (!mLastVideoBuffer->meta_data()->findInt32( - kKeyIsUnreadable, &unreadable) - || unreadable == 0) { - state->mLastVideoFrameSize = size; - state->mLastVideoFrame = malloc(size); - memcpy(state->mLastVideoFrame, - (const uint8_t *)mLastVideoBuffer->data() - + mLastVideoBuffer->range_offset(), - size); - - state->mVideoWidth = mVideoWidth; - state->mVideoHeight = mVideoHeight; - - sp<MetaData> meta = mVideoSource->getFormat(); - CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); - CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); - CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); - } else { - LOGV("Unable to save last video frame, we have no access to " - "the decoded video data."); - } - } - } - - reset_l(); - - mSuspensionState = state; - - return OK; -} - -status_t AwesomePlayer::resume() { - LOGV("resume"); - Mutex::Autolock autoLock(mLock); - - if (mSuspensionState == NULL) { - return INVALID_OPERATION; - } - - SuspensionState *state = mSuspensionState; - mSuspensionState = NULL; - - status_t err; - if (state->mFileSource != NULL) { - err = setDataSource_l(state->mFileSource); - - if (err == OK) { - mFileSource = state->mFileSource; - } - } else { - err = setDataSource_l(state->mUri, &state->mUriHeaders); - } - - if (err != OK) { - delete state; - state = NULL; - - return err; - } - - seekTo_l(state->mPositionUs); - - mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS); - - if (state->mLastVideoFrame && mSurface != NULL) { - mVideoRenderer = - new AwesomeLocalRenderer( - (OMX_COLOR_FORMATTYPE)state->mColorFormat, - mSurface, - state->mVideoWidth, - state->mVideoHeight, - state->mDecodedWidth, - state->mDecodedHeight, - 0); - - mVideoRendererIsPreview = true; - - ((AwesomeLocalRenderer *)mVideoRenderer.get())->render( - state->mLastVideoFrame, state->mLastVideoFrameSize); - } - - if (state->mFlags & PLAYING) { - play_l(); - } - - mSuspensionState = state; - state = NULL; - - return OK; -} - uint32_t AwesomePlayer::flags() const { return mExtractorFlags; } diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index 0b8997c..ee0d792 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -36,7 +36,7 @@ namespace android { -bool DataSource::getUInt16(off_t offset, uint16_t *x) { +bool DataSource::getUInt16(off64_t offset, uint16_t *x) { *x = 0; uint8_t byte[2]; @@ -49,7 +49,7 @@ bool DataSource::getUInt16(off_t offset, uint16_t *x) { return true; } -status_t DataSource::getSize(off_t *size) { +status_t DataSource::getSize(off64_t *size) { *size = 0; return ERROR_UNSUPPORTED; diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp index 1c1a9c5..98d5b50 100644 --- a/media/libstagefright/FileSource.cpp +++ b/media/libstagefright/FileSource.cpp @@ -16,12 +16,16 @@ #include <media/stagefright/FileSource.h> #include <media/stagefright/MediaDebug.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> namespace android { FileSource::FileSource(const char *filename) - : mFile(fopen(filename, "rb")), - mFd(mFile == NULL ? -1 : fileno(mFile)), + : mFd(-1), mOffset(0), mLength(-1), mDecryptHandle(NULL), @@ -29,11 +33,12 @@ FileSource::FileSource(const char *filename) mDrmBufOffset(0), mDrmBufSize(0), mDrmBuf(NULL){ + + mFd = open(filename, O_LARGEFILE | O_RDONLY); } FileSource::FileSource(int fd, int64_t offset, int64_t length) - : mFile(fdopen(fd, "rb")), - mFd(fd), + : mFd(fd), mOffset(offset), mLength(length), mDecryptHandle(NULL), @@ -46,9 +51,9 @@ FileSource::FileSource(int fd, int64_t offset, int64_t length) } FileSource::~FileSource() { - if (mFile != NULL) { - fclose(mFile); - mFile = NULL; + if (mFd >= 0) { + close(mFd); + mFd = -1; } if (mDrmBuf != NULL) { @@ -58,11 +63,11 @@ FileSource::~FileSource() { } status_t FileSource::initCheck() const { - return mFile != NULL ? OK : NO_INIT; + return mFd >= 0 ? OK : NO_INIT; } -ssize_t FileSource::readAt(off_t offset, void *data, size_t size) { - if (mFile == NULL) { +ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) { + if (mFd < 0) { return NO_INIT; } @@ -82,18 +87,18 @@ ssize_t FileSource::readAt(off_t offset, void *data, size_t size) { == mDecryptHandle->decryptApiType) { return readAtDRM(offset, data, size); } else { - int err = fseeko(mFile, offset + mOffset, SEEK_SET); - if (err < 0) { + off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET); + if (result == -1) { LOGE("seek to %lld failed", offset + mOffset); return UNKNOWN_ERROR; } - return fread(data, 1, size, mFile); + return ::read(mFd, data, size); } } -status_t FileSource::getSize(off_t *size) { - if (mFile == NULL) { +status_t FileSource::getSize(off64_t *size) { + if (mFd < 0) { return NO_INIT; } @@ -103,8 +108,7 @@ status_t FileSource::getSize(off_t *size) { return OK; } - fseek(mFile, 0, SEEK_END); - *size = ftello(mFile); + *size = lseek64(mFd, 0, SEEK_END); return OK; } @@ -133,7 +137,7 @@ void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) { *client = mDrmManagerClient; } -ssize_t FileSource::readAtDRM(off_t offset, void *data, size_t size) { +ssize_t FileSource::readAtDRM(off64_t offset, void *data, size_t size) { size_t DRM_CACHE_SIZE = 1024; if (mDrmBuf == NULL) { mDrmBuf = new unsigned char[DRM_CACHE_SIZE]; diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp index ccc6a34..e7f00aa 100644 --- a/media/libstagefright/HTTPStream.cpp +++ b/media/libstagefright/HTTPStream.cpp @@ -36,7 +36,7 @@ namespace android { // static -const char *HTTPStream::kStatusKey = ":status:"; +const char *HTTPStream::kStatusKey = ":status:"; // MUST be lowercase. HTTPStream::HTTPStream() : mState(READY), @@ -220,7 +220,7 @@ status_t HTTPStream::receive_header(int *http_status) { return err; } - mHeaders.add(string(kStatusKey), string(line)); + mHeaders.add(AString(kStatusKey), AString(line)); char *spacePos = strchr(line, ' '); if (spacePos == NULL) { @@ -264,7 +264,10 @@ status_t HTTPStream::receive_header(int *http_status) { char *colonPos = strchr(line, ':'); if (colonPos == NULL) { - mHeaders.add(string(line), string()); + AString key = line; + key.tolower(); + + mHeaders.add(key, AString()); } else { char *end_of_key = colonPos; while (end_of_key > line && isspace(end_of_key[-1])) { @@ -278,7 +281,10 @@ status_t HTTPStream::receive_header(int *http_status) { *end_of_key = '\0'; - mHeaders.add(string(line), string(start_of_value)); + AString key = line; + key.tolower(); + + mHeaders.add(key, AString(start_of_value)); } } @@ -314,8 +320,11 @@ ssize_t HTTPStream::receive(void *data, size_t size) { return (ssize_t)total; } -bool HTTPStream::find_header_value(const string &key, string *value) const { - ssize_t index = mHeaders.indexOfKey(key); +bool HTTPStream::find_header_value(const AString &key, AString *value) const { + AString key_lower = key; + key_lower.tolower(); + + ssize_t index = mHeaders.indexOfKey(key_lower); if (index < 0) { value->clear(); return false; diff --git a/media/libstagefright/JPEGSource.cpp b/media/libstagefright/JPEGSource.cpp index ec81097..e818115 100644 --- a/media/libstagefright/JPEGSource.cpp +++ b/media/libstagefright/JPEGSource.cpp @@ -142,7 +142,7 @@ status_t JPEGSource::parseJPEG() { mWidth = 0; mHeight = 0; - off_t i = 0; + off64_t i = 0; uint16_t soi; if (!mSource->getUInt16(i, &soi)) { diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp index 84ced8f..9610f90 100644 --- a/media/libstagefright/MP3Extractor.cpp +++ b/media/libstagefright/MP3Extractor.cpp @@ -183,7 +183,7 @@ bool MP3Extractor::get_mp3_frame_size( static bool Resync( const sp<DataSource> &source, uint32_t match_header, - off_t *inout_pos, off_t *post_id3_pos, uint32_t *out_header) { + off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) { if (post_id3_pos != NULL) { *post_id3_pos = 0; } @@ -226,7 +226,7 @@ static bool Resync( } } - off_t pos = *inout_pos; + off64_t pos = *inout_pos; bool valid = false; do { if (pos >= *inout_pos + 128 * 1024) { @@ -261,7 +261,7 @@ static bool Resync( // We found what looks like a valid frame, // now find its successors. - off_t test_pos = pos + frame_size; + off64_t test_pos = pos + frame_size; valid = true; for (int j = 0; j < 3; ++j) { @@ -312,7 +312,7 @@ class MP3Source : public MediaSource { public: MP3Source( const sp<MetaData> &meta, const sp<DataSource> &source, - off_t first_frame_pos, uint32_t fixed_header, + off64_t first_frame_pos, uint32_t fixed_header, const sp<MP3Seeker> &seeker); virtual status_t start(MetaData *params = NULL); @@ -329,9 +329,9 @@ protected: private: sp<MetaData> mMeta; sp<DataSource> mDataSource; - off_t mFirstFramePos; + off64_t mFirstFramePos; uint32_t mFixedHeader; - off_t mCurrentPos; + off64_t mCurrentPos; int64_t mCurrentTimeUs; bool mStarted; sp<MP3Seeker> mSeeker; @@ -347,8 +347,8 @@ MP3Extractor::MP3Extractor( mDataSource(source), mFirstFramePos(-1), mFixedHeader(0) { - off_t pos = 0; - off_t post_id3_pos; + off64_t pos = 0; + off64_t post_id3_pos; uint32_t header; bool success; @@ -361,9 +361,9 @@ MP3Extractor::MP3Extractor( && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) { // The sniffer has already done all the hard work for us, simply // accept its judgement. - pos = (off_t)meta_offset; + pos = (off64_t)meta_offset; header = meta_header; - post_id3_pos = (off_t)meta_post_id3_offset; + post_id3_pos = (off64_t)meta_post_id3_offset; success = true; } else { @@ -401,7 +401,7 @@ MP3Extractor::MP3Extractor( int64_t durationUs; if (mSeeker == NULL || !mSeeker->getDuration(&durationUs)) { - off_t fileSize; + off64_t fileSize; if (mDataSource->getSize(&fileSize) == OK) { durationUs = 8000LL * (fileSize - mFirstFramePos) / bitrate; } else { @@ -442,7 +442,7 @@ sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) { MP3Source::MP3Source( const sp<MetaData> &meta, const sp<DataSource> &source, - off_t first_frame_pos, uint32_t fixed_header, + off64_t first_frame_pos, uint32_t fixed_header, const sp<MP3Seeker> &seeker) : mMeta(meta), mDataSource(source), @@ -545,7 +545,7 @@ status_t MP3Source::read( // Lost sync. LOGV("lost sync! header = 0x%08x, old header = 0x%08x\n", header, mFixedHeader); - off_t pos = mCurrentPos; + off64_t pos = mCurrentPos; if (!Resync(mDataSource, mFixedHeader, &pos, NULL, NULL)) { LOGE("Unable to resync. Signalling end of stream."); @@ -651,8 +651,8 @@ sp<MetaData> MP3Extractor::getMetaData() { bool SniffMP3( const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta) { - off_t pos = 0; - off_t post_id3_pos; + off64_t pos = 0; + off64_t post_id3_pos; uint32_t header; if (!Resync(source, 0, &pos, &post_id3_pos, &header)) { return false; diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp index 81a2b0d..4d8165e 100644 --- a/media/libstagefright/MPEG2TSWriter.cpp +++ b/media/libstagefright/MPEG2TSWriter.cpp @@ -410,7 +410,7 @@ void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) { //////////////////////////////////////////////////////////////////////////////// MPEG2TSWriter::MPEG2TSWriter(int fd) - : mFile(fdopen(fd, "wb")), + : mFile(fdopen(dup(fd), "wb")), mStarted(false), mNumSourcesDone(0), mNumTSPacketsWritten(0), diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index bb929fd..bbe99d3 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -98,11 +98,11 @@ struct MPEG4DataSource : public DataSource { MPEG4DataSource(const sp<DataSource> &source); virtual status_t initCheck() const; - virtual ssize_t readAt(off_t offset, void *data, size_t size); - virtual status_t getSize(off_t *size); + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual status_t getSize(off64_t *size); virtual uint32_t flags(); - status_t setCachedRange(off_t offset, size_t size); + status_t setCachedRange(off64_t offset, size_t size); protected: virtual ~MPEG4DataSource(); @@ -111,7 +111,7 @@ private: Mutex mLock; sp<DataSource> mSource; - off_t mCachedOffset; + off64_t mCachedOffset; size_t mCachedSize; uint8_t *mCache; @@ -146,7 +146,7 @@ status_t MPEG4DataSource::initCheck() const { return mSource->initCheck(); } -ssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) { +ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) { Mutex::Autolock autoLock(mLock); if (offset >= mCachedOffset @@ -158,7 +158,7 @@ ssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) { return mSource->readAt(offset, data, size); } -status_t MPEG4DataSource::getSize(off_t *size) { +status_t MPEG4DataSource::getSize(off64_t *size) { return mSource->getSize(size); } @@ -166,7 +166,7 @@ uint32_t MPEG4DataSource::flags() { return mSource->flags(); } -status_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) { +status_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) { Mutex::Autolock autoLock(mLock); clearCache(); @@ -363,7 +363,7 @@ status_t MPEG4Extractor::readMetaData() { return OK; } - off_t offset = 0; + off64_t offset = 0; status_t err; while ((err = parseChunk(&offset, 0)) == OK) { } @@ -404,7 +404,7 @@ char* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) { } // Reads an encoded integer 7 bits at a time until it encounters the high bit clear. -int32_t readSize(off_t offset, +int32_t readSize(off64_t offset, const sp<DataSource> DataSource, uint8_t *numOfBytes) { uint32_t size = 0; uint8_t data; @@ -424,7 +424,7 @@ int32_t readSize(off_t offset, return size; } -status_t MPEG4Extractor::parseDrmSINF(off_t *offset, off_t data_offset) { +status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) { uint8_t updateIdTag; if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { return ERROR_IO; @@ -596,14 +596,14 @@ static void convertTimeToDate(int64_t time_1904, String8 *s) { s->setTo(tmp); } -status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { +status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { uint32_t hdr[2]; if (mDataSource->readAt(*offset, hdr, 8) < 8) { return ERROR_IO; } uint64_t chunk_size = ntohl(hdr[0]); uint32_t chunk_type = ntohl(hdr[1]); - off_t data_offset = *offset + 8; + off64_t data_offset = *offset + 8; if (chunk_size == 1) { if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { @@ -644,11 +644,11 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { PathAdder autoAdder(&mPath, chunk_type); - off_t chunk_data_size = *offset + chunk_size - data_offset; + off64_t chunk_data_size = *offset + chunk_size - data_offset; if (chunk_type != FOURCC('c', 'p', 'r', 't') && mPath.size() == 5 && underMetaDataPath(mPath)) { - off_t stop_offset = *offset + chunk_size; + off64_t stop_offset = *offset + chunk_size; *offset = data_offset; while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); @@ -715,7 +715,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { track->meta->setCString(kKeyMIMEType, "application/octet-stream"); } - off_t stop_offset = *offset + chunk_size; + off64_t stop_offset = *offset + chunk_size; *offset = data_offset; while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); @@ -788,7 +788,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { return ERROR_IO; } - off_t timescale_offset; + off64_t timescale_offset; if (version == 1) { timescale_offset = data_offset + 4 + 16; @@ -838,7 +838,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { } uint8_t buffer[8]; - if (chunk_data_size < (off_t)sizeof(buffer)) { + if (chunk_data_size < (off64_t)sizeof(buffer)) { return ERROR_MALFORMED; } @@ -862,7 +862,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { break; } - off_t stop_offset = *offset + chunk_size; + off64_t stop_offset = *offset + chunk_size; *offset = data_offset + 8; for (uint32_t i = 0; i < entry_count; ++i) { status_t err = parseChunk(offset, depth + 1); @@ -919,7 +919,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); - off_t stop_offset = *offset + chunk_size; + off64_t stop_offset = *offset + chunk_size; *offset = data_offset + sizeof(buffer); while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); @@ -962,7 +962,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { mLastTrack->meta->setInt32(kKeyWidth, width); mLastTrack->meta->setInt32(kKeyHeight, height); - off_t stop_offset = *offset + chunk_size; + off64_t stop_offset = *offset + chunk_size; *offset = data_offset + sizeof(buffer); while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); @@ -1069,7 +1069,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { } uint8_t buffer[256]; - if (chunk_data_size > (off_t)sizeof(buffer)) { + if (chunk_data_size > (off64_t)sizeof(buffer)) { return ERROR_BUFFER_TOO_SMALL; } @@ -1108,7 +1108,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { case FOURCC('a', 'v', 'c', 'C'): { char buffer[256]; - if (chunk_data_size > (off_t)sizeof(buffer)) { + if (chunk_data_size > (off64_t)sizeof(buffer)) { return ERROR_BUFFER_TOO_SMALL; } @@ -1127,7 +1127,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { case FOURCC('m', 'e', 't', 'a'): { uint8_t buffer[4]; - if (chunk_data_size < (off_t)sizeof(buffer)) { + if (chunk_data_size < (off64_t)sizeof(buffer)) { return ERROR_MALFORMED; } @@ -1147,7 +1147,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { return OK; } - off_t stop_offset = *offset + chunk_size; + off64_t stop_offset = *offset + chunk_size; *offset = data_offset + sizeof(buffer); while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); @@ -1232,7 +1232,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { } status_t MPEG4Extractor::parseTrackHeader( - off_t data_offset, off_t data_size) { + off64_t data_offset, off64_t data_size) { if (data_size < 4) { return ERROR_MALFORMED; } @@ -1246,7 +1246,7 @@ status_t MPEG4Extractor::parseTrackHeader( uint8_t buffer[36 + 60]; - if (data_size != (off_t)dynSize + 60) { + if (data_size != (off64_t)dynSize + 60) { return ERROR_MALFORMED; } @@ -1318,7 +1318,7 @@ status_t MPEG4Extractor::parseTrackHeader( return OK; } -status_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) { +status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { if (size < 4) { return ERROR_MALFORMED; } @@ -1807,7 +1807,7 @@ status_t MPEG4Source::read( // fall through } - off_t offset; + off64_t offset; size_t size; uint32_t dts; bool isSyncSample; diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 17a40b0..6760707 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -33,6 +33,10 @@ #include <media/stagefright/MediaSource.h> #include <media/stagefright/Utils.h> #include <media/mediarecorder.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> #include "include/ESDS.h" @@ -64,7 +68,7 @@ public: bool isAvc() const { return mIsAvc; } bool isAudio() const { return mIsAudio; } bool isMPEG4() const { return mIsMPEG4; } - void addChunkOffset(off_t offset); + void addChunkOffset(off64_t offset); status_t dump(int fd, const Vector<String16>& args) const; private: @@ -99,7 +103,7 @@ private: List<MediaBuffer *> mChunkSamples; size_t mNumStcoTableEntries; - List<off_t> mChunkOffsets; + List<off64_t> mChunkOffsets; size_t mNumStscTableEntries; struct StscTableEntry { @@ -214,7 +218,8 @@ private: }; MPEG4Writer::MPEG4Writer(const char *filename) - : mFile(fopen(filename, "wb")), + : mFd(-1), + mInitCheck(NO_INIT), mUse4ByteNalLength(true), mUse32BitOffset(true), mIsFileSizeLimitExplicitlyRequested(false), @@ -224,11 +229,16 @@ MPEG4Writer::MPEG4Writer(const char *filename) mMdatOffset(0), mEstimatedMoovBoxSize(0), mInterleaveDurationUs(1000000) { - CHECK(mFile != NULL); + + mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC); + if (mFd >= 0) { + mInitCheck = OK; + } } MPEG4Writer::MPEG4Writer(int fd) - : mFile(fdopen(fd, "wb")), + : mFd(dup(fd)), + mInitCheck(mFd < 0? NO_INIT: OK), mUse4ByteNalLength(true), mUse32BitOffset(true), mIsFileSizeLimitExplicitlyRequested(false), @@ -238,7 +248,6 @@ MPEG4Writer::MPEG4Writer(int fd) mMdatOffset(0), mEstimatedMoovBoxSize(0), mInterleaveDurationUs(1000000) { - CHECK(mFile != NULL); } MPEG4Writer::~MPEG4Writer() { @@ -368,7 +377,7 @@ int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { } status_t MPEG4Writer::start(MetaData *param) { - if (mFile == NULL) { + if (mInitCheck != OK) { return UNKNOWN_ERROR; } @@ -459,13 +468,13 @@ status_t MPEG4Writer::start(MetaData *param) { mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); } CHECK(mEstimatedMoovBoxSize >= 8); - fseeko(mFile, mFreeBoxOffset, SEEK_SET); + lseek64(mFd, mFreeBoxOffset, SEEK_SET); writeInt32(mEstimatedMoovBoxSize); write("free", 4); mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; mOffset = mMdatOffset; - fseeko(mFile, mMdatOffset, SEEK_SET); + lseek64(mFd, mMdatOffset, SEEK_SET); if (mUse32BitOffset) { write("????mdat", 8); } else { @@ -491,7 +500,7 @@ bool MPEG4Writer::use32BitFileOffset() const { } status_t MPEG4Writer::pause() { - if (mFile == NULL) { + if (mInitCheck != OK) { return OK; } mPaused = true; @@ -575,7 +584,7 @@ void MPEG4Writer::writeCompositionMatrix(int degrees) { status_t MPEG4Writer::stop() { - if (mFile == NULL) { + if (mInitCheck != OK) { return OK; } @@ -598,28 +607,28 @@ status_t MPEG4Writer::stop() { // Do not write out movie header on error. if (err != OK) { - fflush(mFile); - fclose(mFile); - mFile = NULL; + close(mFd); + mFd = -1; + mInitCheck = NO_INIT; mStarted = false; return err; } // Fix up the size of the 'mdat' chunk. if (mUse32BitOffset) { - fseeko(mFile, mMdatOffset, SEEK_SET); + lseek64(mFd, mMdatOffset, SEEK_SET); int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); - fwrite(&size, 1, 4, mFile); + ::write(mFd, &size, 4); } else { - fseeko(mFile, mMdatOffset + 8, SEEK_SET); + lseek64(mFd, mMdatOffset + 8, SEEK_SET); int64_t size = mOffset - mMdatOffset; size = hton64(size); - fwrite(&size, 1, 8, mFile); + ::write(mFd, &size, 8); } - fseeko(mFile, mOffset, SEEK_SET); + lseek64(mFd, mOffset, SEEK_SET); time_t now = time(NULL); - const off_t moovOffset = mOffset; + const off64_t moovOffset = mOffset; mWriteMoovBoxToMemory = true; mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); mMoovBoxBufferOffset = 0; @@ -661,12 +670,12 @@ status_t MPEG4Writer::stop() { CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); // Moov box - fseeko(mFile, mFreeBoxOffset, SEEK_SET); + lseek64(mFd, mFreeBoxOffset, SEEK_SET); mOffset = mFreeBoxOffset; - write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); + write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); // Free box - fseeko(mFile, mOffset, SEEK_SET); + lseek64(mFd, mOffset, SEEK_SET); writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); write("free", 4); @@ -680,9 +689,9 @@ status_t MPEG4Writer::stop() { CHECK(mBoxes.empty()); - fflush(mFile); - fclose(mFile); - mFile = NULL; + close(mFd); + mFd = -1; + mInitCheck = NO_INIT; mStarted = false; return err; } @@ -700,11 +709,12 @@ void MPEG4Writer::unlock() { mLock.unlock(); } -off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { - off_t old_offset = mOffset; +off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { + off64_t old_offset = mOffset; - fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), - 1, buffer->range_length(), mFile); + ::write(mFd, + (const uint8_t *)buffer->data() + buffer->range_offset(), + buffer->range_length()); mOffset += buffer->range_length(); @@ -725,33 +735,34 @@ static void StripStartcode(MediaBuffer *buffer) { } } -off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { - off_t old_offset = mOffset; +off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { + off64_t old_offset = mOffset; size_t length = buffer->range_length(); if (mUse4ByteNalLength) { uint8_t x = length >> 24; - fwrite(&x, 1, 1, mFile); + ::write(mFd, &x, 1); x = (length >> 16) & 0xff; - fwrite(&x, 1, 1, mFile); + ::write(mFd, &x, 1); x = (length >> 8) & 0xff; - fwrite(&x, 1, 1, mFile); + ::write(mFd, &x, 1); x = length & 0xff; - fwrite(&x, 1, 1, mFile); + ::write(mFd, &x, 1); + + ::write(mFd, + (const uint8_t *)buffer->data() + buffer->range_offset(), + length); - fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), - 1, length, mFile); mOffset += length + 4; } else { CHECK(length < 65536); uint8_t x = length >> 8; - fwrite(&x, 1, 1, mFile); + ::write(mFd, &x, 1); x = length & 0xff; - fwrite(&x, 1, 1, mFile); - fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), - 1, length, mFile); + ::write(mFd, &x, 1); + ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); mOffset += length + 2; } @@ -759,19 +770,21 @@ off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { } size_t MPEG4Writer::write( - const void *ptr, size_t size, size_t nmemb, FILE *stream) { + const void *ptr, size_t size, size_t nmemb) { const size_t bytes = size * nmemb; if (mWriteMoovBoxToMemory) { - off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; + // This happens only when we write the moov box at the end of + // recording, not for each output video/audio frame we receive. + off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; if (moovBoxSize > mEstimatedMoovBoxSize) { - for (List<off_t>::iterator it = mBoxes.begin(); + for (List<off64_t>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { (*it) += mOffset; } - fseeko(mFile, mOffset, SEEK_SET); - fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); - fwrite(ptr, size, nmemb, stream); + lseek64(mFd, mOffset, SEEK_SET); + ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); + ::write(mFd, ptr, size * nmemb); mOffset += (bytes + mMoovBoxBufferOffset); free(mMoovBoxBuffer); mMoovBoxBuffer = NULL; @@ -783,7 +796,7 @@ size_t MPEG4Writer::write( mMoovBoxBufferOffset += bytes; } } else { - fwrite(ptr, size, nmemb, stream); + ::write(mFd, ptr, size * nmemb); mOffset += bytes; } return bytes; @@ -802,51 +815,51 @@ void MPEG4Writer::beginBox(const char *fourcc) { void MPEG4Writer::endBox() { CHECK(!mBoxes.empty()); - off_t offset = *--mBoxes.end(); + off64_t offset = *--mBoxes.end(); mBoxes.erase(--mBoxes.end()); if (mWriteMoovBoxToMemory) { int32_t x = htonl(mMoovBoxBufferOffset - offset); memcpy(mMoovBoxBuffer + offset, &x, 4); } else { - fseeko(mFile, offset, SEEK_SET); + lseek64(mFd, offset, SEEK_SET); writeInt32(mOffset - offset); mOffset -= 4; - fseeko(mFile, mOffset, SEEK_SET); + lseek64(mFd, mOffset, SEEK_SET); } } void MPEG4Writer::writeInt8(int8_t x) { - write(&x, 1, 1, mFile); + write(&x, 1, 1); } void MPEG4Writer::writeInt16(int16_t x) { x = htons(x); - write(&x, 1, 2, mFile); + write(&x, 1, 2); } void MPEG4Writer::writeInt32(int32_t x) { x = htonl(x); - write(&x, 1, 4, mFile); + write(&x, 1, 4); } void MPEG4Writer::writeInt64(int64_t x) { x = hton64(x); - write(&x, 1, 8, mFile); + write(&x, 1, 8); } void MPEG4Writer::writeCString(const char *s) { size_t n = strlen(s); - write(s, 1, n + 1, mFile); + write(s, 1, n + 1); } void MPEG4Writer::writeFourcc(const char *s) { CHECK_EQ(strlen(s), 4); - write(s, 1, 4, mFile); + write(s, 1, 4); } void MPEG4Writer::write(const void *data, size_t size) { - write(data, 1, size, mFile); + write(data, 1, size); } bool MPEG4Writer::isFileStreamable() const { @@ -987,7 +1000,7 @@ void MPEG4Writer::Track::addOneSttsTableEntry( ++mNumSttsTableEntries; } -void MPEG4Writer::Track::addChunkOffset(off_t offset) { +void MPEG4Writer::Track::addChunkOffset(off64_t offset) { ++mNumStcoTableEntries; mChunkOffsets.push_back(offset); } @@ -1102,7 +1115,7 @@ void MPEG4Writer::writeFirstChunk(ChunkInfo* info) { for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); it != chunkIt->mSamples.end(); ++it) { - off_t offset = info->mTrack->isAvc() + off64_t offset = info->mTrack->isAvc() ? addLengthPrefixedSample_l(*it) : addSample_l(*it); if (it == chunkIt->mSamples.begin()) { @@ -1926,7 +1939,7 @@ status_t MPEG4Writer::Track::threadEntry() { trackProgressStatus(timestampUs); } if (mOwner->numTracks() == 1) { - off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) + off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) : mOwner->addSample_l(copy); if (mChunkOffsets.empty()) { addChunkOffset(offset); @@ -2477,7 +2490,7 @@ void MPEG4Writer::Track::writeTrackHeader( mOwner->beginBox(use32BitOffset? "stco": "co64"); mOwner->writeInt32(0); // version=0, flags=0 mOwner->writeInt32(mNumStcoTableEntries); - for (List<off_t>::iterator it = mChunkOffsets.begin(); + for (List<off64_t>::iterator it = mChunkOffsets.begin(); it != mChunkOffsets.end(); ++it) { if (use32BitOffset) { mOwner->writeInt32(static_cast<int32_t>(*it)); diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp index 63b476e..884f3b4 100644 --- a/media/libstagefright/MetaData.cpp +++ b/media/libstagefright/MetaData.cpp @@ -70,6 +70,19 @@ bool MetaData::setPointer(uint32_t key, void *value) { return setData(key, TYPE_POINTER, &value, sizeof(value)); } +bool MetaData::setRect( + uint32_t key, + int32_t left, int32_t top, + int32_t right, int32_t bottom) { + Rect r; + r.mLeft = left; + r.mTop = top; + r.mRight = right; + r.mBottom = bottom; + + return setData(key, TYPE_RECT, &r, sizeof(r)); +} + bool MetaData::findCString(uint32_t key, const char **value) { uint32_t type; const void *data; @@ -143,6 +156,28 @@ bool MetaData::findPointer(uint32_t key, void **value) { return true; } +bool MetaData::findRect( + uint32_t key, + int32_t *left, int32_t *top, + int32_t *right, int32_t *bottom) { + uint32_t type; + const void *data; + size_t size; + if (!findData(key, &type, &data, &size) || type != TYPE_RECT) { + return false; + } + + CHECK_EQ(size, sizeof(Rect)); + + const Rect *r = (const Rect *)data; + *left = r->mLeft; + *top = r->mTop; + *right = r->mRight; + *bottom = r->mBottom; + + return true; +} + bool MetaData::setData( uint32_t key, uint32_t type, const void *data, size_t size) { bool overwrote_existing = true; diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index 3bb38de..829ab20 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -201,7 +201,7 @@ status_t NuCachedSource2::initCheck() const { return mSource->initCheck(); } -status_t NuCachedSource2::getSize(off_t *size) { +status_t NuCachedSource2::getSize(off64_t *size) { return mSource->getSize(size); } @@ -353,7 +353,7 @@ void NuCachedSource2::restartPrefetcherIfNecessary_l( mFetching = true; } -ssize_t NuCachedSource2::readAt(off_t offset, void *data, size_t size) { +ssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) { Mutex::Autolock autoSerializer(mSerializer); LOGV("readAt offset %ld, size %d", offset, size); @@ -408,27 +408,27 @@ size_t NuCachedSource2::approxDataRemaining(bool *eos) { size_t NuCachedSource2::approxDataRemaining_l(bool *eos) { *eos = (mFinalStatus != OK); - off_t lastBytePosCached = mCacheOffset + mCache->totalSize(); + off64_t lastBytePosCached = mCacheOffset + mCache->totalSize(); if (mLastAccessPos < lastBytePosCached) { return lastBytePosCached - mLastAccessPos; } return 0; } -ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) { +ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) { LOGV("readInternal offset %ld size %d", offset, size); Mutex::Autolock autoLock(mLock); if (offset < mCacheOffset - || offset >= (off_t)(mCacheOffset + mCache->totalSize())) { - static const off_t kPadding = 32768; + || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) { + static const off64_t kPadding = 32768; // In the presence of multiple decoded streams, once of them will // trigger this seek request, the other one will request data "nearby" // soon, adjust the seek position so that that subsequent request // does not trigger another seek. - off_t seekOffset = (offset > kPadding) ? offset - kPadding : 0; + off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0; seekInternal_l(seekOffset); } @@ -457,15 +457,15 @@ ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) { return -EAGAIN; } -status_t NuCachedSource2::seekInternal_l(off_t offset) { +status_t NuCachedSource2::seekInternal_l(off64_t offset) { mLastAccessPos = offset; if (offset >= mCacheOffset - && offset <= (off_t)(mCacheOffset + mCache->totalSize())) { + && offset <= (off64_t)(mCacheOffset + mCache->totalSize())) { return OK; } - LOGI("new range: offset= %ld", offset); + LOGI("new range: offset= %lld", offset); mCacheOffset = offset; diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp index c3c0d81..269b233 100644 --- a/media/libstagefright/NuHTTPDataSource.cpp +++ b/media/libstagefright/NuHTTPDataSource.cpp @@ -84,7 +84,7 @@ NuHTTPDataSource::~NuHTTPDataSource() { status_t NuHTTPDataSource::connect( const char *uri, const KeyedVector<String8, String8> *overrides, - off_t offset) { + off64_t offset) { String8 headers; MakeFullHeaders(overrides, &headers); @@ -94,7 +94,7 @@ status_t NuHTTPDataSource::connect( status_t NuHTTPDataSource::connect( const char *uri, const String8 &headers, - off_t offset) { + off64_t offset) { String8 host, path; unsigned port; @@ -115,8 +115,8 @@ static bool IsRedirectStatusCode(int httpStatus) { status_t NuHTTPDataSource::connect( const char *host, unsigned port, const char *path, const String8 &headers, - off_t offset) { - LOGI("connect to %s:%u%s @%ld", host, port, path, offset); + off64_t offset) { + LOGI("connect to %s:%u%s @%lld", host, port, path, offset); bool needsToReconnect = true; @@ -162,7 +162,7 @@ status_t NuHTTPDataSource::connect( if (offset != 0) { char rangeHeader[128]; - sprintf(rangeHeader, "Range: bytes=%ld-\r\n", offset); + sprintf(rangeHeader, "Range: bytes=%lld-\r\n", offset); request.append(rangeHeader); } @@ -178,7 +178,7 @@ status_t NuHTTPDataSource::connect( } if (IsRedirectStatusCode(httpStatus)) { - string value; + AString value; CHECK(mHTTP.find_header_value("Location", &value)); mState = DISCONNECTED; @@ -198,9 +198,8 @@ status_t NuHTTPDataSource::connect( mHasChunkedTransferEncoding = false; { - string value; - if (mHTTP.find_header_value("Transfer-Encoding", &value) - || mHTTP.find_header_value("Transfer-encoding", &value)) { + AString value; + if (mHTTP.find_header_value("Transfer-Encoding", &value)) { // We don't currently support any transfer encodings but // chunked. @@ -222,11 +221,11 @@ status_t NuHTTPDataSource::connect( applyTimeoutResponse(); if (offset == 0) { - string value; + AString value; unsigned long x; - if (mHTTP.find_header_value(string("Content-Length"), &value) + if (mHTTP.find_header_value(AString("Content-Length"), &value) && ParseSingleUnsignedLong(value.c_str(), &x)) { - mContentLength = (off_t)x; + mContentLength = (off64_t)x; mContentLengthValid = true; } else { LOGW("Server did not give us the content length!"); @@ -239,9 +238,9 @@ status_t NuHTTPDataSource::connect( return ERROR_UNSUPPORTED; } - string value; + AString value; unsigned long x; - if (mHTTP.find_header_value(string("Content-Range"), &value)) { + if (mHTTP.find_header_value(AString("Content-Range"), &value)) { const char *slashPos = strchr(value.c_str(), '/'); if (slashPos != NULL && ParseSingleUnsignedLong(slashPos + 1, &x)) { @@ -331,7 +330,7 @@ ssize_t NuHTTPDataSource::internalRead(void *data, size_t size) { return n; } -ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) { +ssize_t NuHTTPDataSource::readAt(off64_t offset, void *data, size_t size) { LOGV("readAt offset %ld, size %d", offset, size); Mutex::Autolock autoLock(mLock); @@ -388,7 +387,7 @@ ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) { return numBytesRead; } -status_t NuHTTPDataSource::getSize(off_t *size) { +status_t NuHTTPDataSource::getSize(off64_t *size) { *size = 0; if (mState != CONNECTED) { @@ -439,7 +438,7 @@ void NuHTTPDataSource::MakeFullHeaders( } void NuHTTPDataSource::applyTimeoutResponse() { - string timeout; + AString timeout; if (mHTTP.find_header_value("X-SocketTimeout", &timeout)) { const char *s = timeout.c_str(); char *end; diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 6ca0f4f..3f32f2f 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -38,11 +38,11 @@ #include <binder/IServiceManager.h> #include <binder/MemoryDealer.h> #include <binder/ProcessState.h> +#include <media/stagefright/foundation/ADebug.h> #include <media/IMediaPlayerService.h> #include <media/stagefright/HardwareAPI.h> #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaExtractor.h> #include <media/stagefright/MetaData.h> @@ -526,7 +526,7 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta, uint32_t flags) { size_t size; if (meta->findData(kKeyESDS, &type, &data, &size)) { ESDS esds((const char *)data, size); - CHECK_EQ(esds.InitCheck(), OK); + CHECK_EQ(esds.InitCheck(), (status_t)OK); const void *codec_specific_data; size_t codec_specific_data_size; @@ -541,7 +541,7 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta, uint32_t flags) { const uint8_t *ptr = (const uint8_t *)data; CHECK(size >= 7); - CHECK_EQ(ptr[0], 1); // configurationVersion == 1 + CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 uint8_t profile = ptr[1]; uint8_t level = ptr[3]; @@ -730,7 +730,7 @@ void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) { status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus)) || (def.nBufferSize < size)) { @@ -739,11 +739,11 @@ void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) { err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); // Make sure the setting actually stuck. if (portIndex == kPortIndexInput @@ -923,7 +923,7 @@ void OMXCodec::setVideoInputFormat( } OMX_COLOR_FORMATTYPE colorFormat; - CHECK_EQ(OK, findTargetColorFormat(meta, &colorFormat)); + CHECK_EQ((status_t)OK, findTargetColorFormat(meta, &colorFormat)); status_t err; OMX_PARAM_PORTDEFINITIONTYPE def; @@ -932,19 +932,19 @@ void OMXCodec::setVideoInputFormat( //////////////////////// Input port ///////////////////////// CHECK_EQ(setVideoPortFormatType( kPortIndexInput, OMX_VIDEO_CodingUnused, - colorFormat), OK); + colorFormat), (status_t)OK); InitOMXParams(&def); def.nPortIndex = kPortIndexInput; err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); def.nBufferSize = getFrameSize(colorFormat, stride > 0? stride: -stride, sliceHeight); - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); + CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); video_def->nFrameWidth = width; video_def->nFrameHeight = height; @@ -956,20 +956,20 @@ void OMXCodec::setVideoInputFormat( err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); //////////////////////// Output port ///////////////////////// CHECK_EQ(setVideoPortFormatType( kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused), - OK); + (status_t)OK); InitOMXParams(&def); def.nPortIndex = kPortIndexOutput; err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); + CHECK_EQ(err, (status_t)OK); + CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); video_def->nFrameWidth = width; video_def->nFrameHeight = height; @@ -984,23 +984,23 @@ void OMXCodec::setVideoInputFormat( err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); /////////////////// Codec-specific //////////////////////// switch (compressionFormat) { case OMX_VIDEO_CodingMPEG4: { - CHECK_EQ(setupMPEG4EncoderParameters(meta), OK); + CHECK_EQ(setupMPEG4EncoderParameters(meta), (status_t)OK); break; } case OMX_VIDEO_CodingH263: - CHECK_EQ(setupH263EncoderParameters(meta), OK); + CHECK_EQ(setupH263EncoderParameters(meta), (status_t)OK); break; case OMX_VIDEO_CodingAVC: { - CHECK_EQ(setupAVCEncoderParameters(meta), OK); + CHECK_EQ(setupAVCEncoderParameters(meta), (status_t)OK); break; } @@ -1059,7 +1059,7 @@ status_t OMXCodec::setupBitRate(int32_t bitRate) { status_t err = mOMX->getParameter( mNode, OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); bitrateType.eControlRate = OMX_Video_ControlRateVariable; bitrateType.nTargetBitrate = bitRate; @@ -1067,7 +1067,7 @@ status_t OMXCodec::setupBitRate(int32_t bitRate) { err = mOMX->setParameter( mNode, OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); return OK; } @@ -1132,7 +1132,7 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) { status_t err = mOMX->getParameter( mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; @@ -1159,10 +1159,10 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) { err = mOMX->setParameter( mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); - CHECK_EQ(setupBitRate(bitRate), OK); - CHECK_EQ(setupErrorCorrectionParameters(), OK); + CHECK_EQ(setupBitRate(bitRate), (status_t)OK); + CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK); return OK; } @@ -1179,7 +1179,7 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) { status_t err = mOMX->getParameter( mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); mpeg4type.nSliceHeaderSpacing = 0; mpeg4type.bSVH = OMX_FALSE; @@ -1211,10 +1211,10 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) { err = mOMX->setParameter( mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); - CHECK_EQ(setupBitRate(bitRate), OK); - CHECK_EQ(setupErrorCorrectionParameters(), OK); + CHECK_EQ(setupBitRate(bitRate), (status_t)OK); + CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK); return OK; } @@ -1232,7 +1232,7 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { status_t err = mOMX->getParameter( mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; @@ -1284,9 +1284,9 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { err = mOMX->setParameter( mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); - CHECK_EQ(setupBitRate(bitRate), OK); + CHECK_EQ(setupBitRate(bitRate), (status_t)OK); return OK; } @@ -1324,8 +1324,8 @@ status_t OMXCodec::setVideoOutputFormat( status_t err = mOMX->getParameter( mNode, OMX_IndexParamVideoPortFormat, &format, sizeof(format)); - CHECK_EQ(err, OK); - CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused); + CHECK_EQ(err, (status_t)OK); + CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; @@ -1353,7 +1353,7 @@ status_t OMXCodec::setVideoOutputFormat( err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); #if 1 // XXX Need a (much) better heuristic to compute input buffer sizes. @@ -1363,7 +1363,7 @@ status_t OMXCodec::setVideoOutputFormat( } #endif - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); + CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); video_def->nFrameWidth = width; video_def->nFrameHeight = height; @@ -1385,8 +1385,8 @@ status_t OMXCodec::setVideoOutputFormat( err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); + CHECK_EQ(err, (status_t)OK); + CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); #if 0 def.nBufferSize = @@ -1510,7 +1510,7 @@ OMXCodec::~OMXCodec() { CHECK(mState == LOADED || mState == ERROR); status_t err = mOMX->freeNode(mNode); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); mNode = NULL; setState(DEAD); @@ -1527,21 +1527,21 @@ OMXCodec::~OMXCodec() { status_t OMXCodec::init() { // mLock is held. - CHECK_EQ(mState, LOADED); + CHECK_EQ((int)mState, (int)LOADED); status_t err; if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) { err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); setState(LOADED_TO_IDLE); } err = allocateBuffers(); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); if (mQuirks & kRequiresLoadedToIdleAfterAllocation) { err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); setState(LOADED_TO_IDLE); } @@ -1896,10 +1896,10 @@ void OMXCodec::on_message(const omx_message &msg) { CODEC_LOGV("Port is disabled, freeing buffer %p", buffer); status_t err = freeBuffer(kPortIndexInput, i); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } else if (mState != ERROR && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) { - CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED); + CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)ENABLED); drainInputBuffer(&buffers->editItemAt(i)); } break; @@ -1937,7 +1937,7 @@ void OMXCodec::on_message(const omx_message &msg) { CODEC_LOGV("Port is disabled, freeing buffer %p", buffer); status_t err = freeBuffer(kPortIndexOutput, i); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); #if 0 } else if (mPortStatus[kPortIndexOutput] == ENABLED @@ -1947,7 +1947,7 @@ void OMXCodec::on_message(const omx_message &msg) { mBufferFilled.signal(); #endif } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) { - CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED); + CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED); if (info->mMediaBuffer == NULL) { CHECK(mOMXLivesLocally); @@ -2045,84 +2045,6 @@ void OMXCodec::on_message(const omx_message &msg) { } } -void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - switch (event) { - case OMX_EventCmdComplete: - { - onCmdComplete((OMX_COMMANDTYPE)data1, data2); - break; - } - - case OMX_EventError: - { - CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2); - - setState(ERROR); - break; - } - - case OMX_EventPortSettingsChanged: - { - CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)", - data1, data2); - - if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { - onPortSettingsChanged(data1); - } else if (data1 == kPortIndexOutput - && data2 == OMX_IndexConfigCommonOutputCrop) { - - OMX_CONFIG_RECTTYPE rect; - rect.nPortIndex = kPortIndexOutput; - InitOMXParams(&rect); - - status_t err = - mOMX->getConfig( - mNode, OMX_IndexConfigCommonOutputCrop, - &rect, sizeof(rect)); - - if (err == OK) { - CODEC_LOGV( - "output crop (%ld, %ld, %ld, %ld)", - rect.nLeft, rect.nTop, rect.nWidth, rect.nHeight); - - if (mNativeWindow != NULL) { - android_native_rect_t crop; - crop.left = rect.nLeft; - crop.top = rect.nTop; - crop.right = crop.left + rect.nWidth - 1; - crop.bottom = crop.top + rect.nHeight - 1; - - CHECK_EQ(0, native_window_set_crop( - mNativeWindow.get(), &crop)); - } - } else { - CODEC_LOGE("getConfig(OMX_IndexConfigCommonOutputCrop) " - "returned error 0x%08x", err); - } - } - break; - } - -#if 0 - case OMX_EventBufferFlag: - { - CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1); - - if (data1 == kPortIndexOutput) { - mNoMoreOutputData = true; - } - break; - } -#endif - - default: - { - CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2); - break; - } - } -} - // Has the format changed in any way that the client would have to be aware of? static bool formatHasNotablyChanged( const sp<MetaData> &from, const sp<MetaData> &to) { @@ -2167,6 +2089,21 @@ static bool formatHasNotablyChanged( if (height_from != height_to) { return true; } + + int32_t left_from, top_from, right_from, bottom_from; + CHECK(from->findRect( + kKeyCropRect, + &left_from, &top_from, &right_from, &bottom_from)); + + int32_t left_to, top_to, right_to, bottom_to; + CHECK(to->findRect( + kKeyCropRect, + &left_to, &top_to, &right_to, &bottom_to)); + + if (left_to != left_from || top_to != top_from + || right_to != right_from || bottom_to != bottom_from) { + return true; + } } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) { int32_t numChannels_from, numChannels_to; CHECK(from->findInt32(kKeyChannelCount, &numChannels_from)); @@ -2188,6 +2125,78 @@ static bool formatHasNotablyChanged( return false; } +void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { + switch (event) { + case OMX_EventCmdComplete: + { + onCmdComplete((OMX_COMMANDTYPE)data1, data2); + break; + } + + case OMX_EventError: + { + CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2); + + setState(ERROR); + break; + } + + case OMX_EventPortSettingsChanged: + { + CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)", + data1, data2); + + if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { + onPortSettingsChanged(data1); + } else if (data1 == kPortIndexOutput + && data2 == OMX_IndexConfigCommonOutputCrop) { + + sp<MetaData> oldOutputFormat = mOutputFormat; + initOutputFormat(mSource->getFormat()); + + if (formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) { + mOutputPortSettingsHaveChanged = true; + + if (mNativeWindow != NULL) { + int32_t left, top, right, bottom; + CHECK(mOutputFormat->findRect( + kKeyCropRect, + &left, &top, &right, &bottom)); + + android_native_rect_t crop; + crop.left = left; + crop.top = top; + crop.right = right; + crop.bottom = bottom; + + CHECK_EQ(0, native_window_set_crop( + mNativeWindow.get(), &crop)); + } + } + } + break; + } + +#if 0 + case OMX_EventBufferFlag: + { + CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1); + + if (data1 == kPortIndexOutput) { + mNoMoreOutputData = true; + } + break; + } +#endif + + default: + { + CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2); + break; + } + } +} + void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { switch (cmd) { case OMX_CommandStateSet: @@ -2202,13 +2211,13 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { CODEC_LOGV("PORT_DISABLED(%ld)", portIndex); CHECK(mState == EXECUTING || mState == RECONFIGURING); - CHECK_EQ(mPortStatus[portIndex], DISABLING); - CHECK_EQ(mPortBuffers[portIndex].size(), 0); + CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLING); + CHECK_EQ(mPortBuffers[portIndex].size(), 0u); mPortStatus[portIndex] = DISABLED; if (mState == RECONFIGURING) { - CHECK_EQ(portIndex, kPortIndexOutput); + CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput); sp<MetaData> oldOutputFormat = mOutputFormat; initOutputFormat(mSource->getFormat()); @@ -2222,7 +2231,7 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { enablePortAsync(portIndex); status_t err = allocateBuffersOnPort(portIndex); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } break; } @@ -2233,12 +2242,12 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { CODEC_LOGV("PORT_ENABLED(%ld)", portIndex); CHECK(mState == EXECUTING || mState == RECONFIGURING); - CHECK_EQ(mPortStatus[portIndex], ENABLING); + CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLING); mPortStatus[portIndex] = ENABLED; if (mState == RECONFIGURING) { - CHECK_EQ(portIndex, kPortIndexOutput); + CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput); setState(EXECUTING); @@ -2253,14 +2262,14 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { CODEC_LOGV("FLUSH_DONE(%ld)", portIndex); - CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN); + CHECK_EQ((int)mPortStatus[portIndex], (int)SHUTTING_DOWN); mPortStatus[portIndex] = ENABLED; CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]), mPortBuffers[portIndex].size()); if (mState == RECONFIGURING) { - CHECK_EQ(portIndex, kPortIndexOutput); + CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput); disablePortAsync(portIndex); } else if (mState == EXECUTING_TO_IDLE) { @@ -2274,7 +2283,7 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { status_t err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } } else { // We're flushing both ports in preparation for seeking. @@ -2314,11 +2323,11 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) { status_t err = mOMX->sendCommand( mNode, OMX_CommandStateSet, OMX_StateExecuting); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); setState(IDLE_TO_EXECUTING); } else { - CHECK_EQ(mState, EXECUTING_TO_IDLE); + CHECK_EQ((int)mState, (int)EXECUTING_TO_IDLE); CHECK_EQ( countBuffersWeOwn(mPortBuffers[kPortIndexInput]), @@ -2331,13 +2340,13 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) { status_t err = mOMX->sendCommand( mNode, OMX_CommandStateSet, OMX_StateLoaded); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); err = freeBuffersOnPort(kPortIndexInput); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); err = freeBuffersOnPort(kPortIndexOutput); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); mPortStatus[kPortIndexInput] = ENABLED; mPortStatus[kPortIndexOutput] = ENABLED; @@ -2349,7 +2358,7 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) { case OMX_StateExecuting: { - CHECK_EQ(mState, IDLE_TO_EXECUTING); + CHECK_EQ((int)mState, (int)IDLE_TO_EXECUTING); CODEC_LOGV("Now Executing."); @@ -2365,7 +2374,7 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) { case OMX_StateLoaded: { - CHECK_EQ(mState, IDLE_TO_LOADED); + CHECK_EQ((int)mState, (int)IDLE_TO_LOADED); CODEC_LOGV("Now Loaded."); @@ -2412,7 +2421,7 @@ status_t OMXCodec::freeBuffersOnPort( continue; } - CHECK_EQ(info->mOwnedByComponent, false); + CHECK_EQ((int)info->mOwnedByComponent, (int)false); CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex); @@ -2437,7 +2446,7 @@ status_t OMXCodec::freeBuffer(OMX_U32 portIndex, size_t bufIndex) { status_t err = mOMX->freeBuffer(mNode, portIndex, info->mBuffer); if (err == OK && info->mMediaBuffer != NULL) { - CHECK_EQ(portIndex, kPortIndexOutput); + CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput); info->mMediaBuffer->setObserver(NULL); // Make sure nobody but us owns this buffer at this point. @@ -2463,8 +2472,8 @@ status_t OMXCodec::freeBuffer(OMX_U32 portIndex, size_t bufIndex) { void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) { CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex); - CHECK_EQ(mState, EXECUTING); - CHECK_EQ(portIndex, kPortIndexOutput); + CHECK_EQ((int)mState, (int)EXECUTING); + CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput); setState(RECONFIGURING); if (mQuirks & kNeedsFlushBeforeDisable) { @@ -2484,7 +2493,7 @@ bool OMXCodec::flushPortAsync(OMX_U32 portIndex) { portIndex, countBuffersWeOwn(mPortBuffers[portIndex]), mPortBuffers[portIndex].size()); - CHECK_EQ(mPortStatus[portIndex], ENABLED); + CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED); mPortStatus[portIndex] = SHUTTING_DOWN; if ((mQuirks & kRequiresFlushCompleteEmulation) @@ -2498,7 +2507,7 @@ bool OMXCodec::flushPortAsync(OMX_U32 portIndex) { status_t err = mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); return true; } @@ -2506,13 +2515,13 @@ bool OMXCodec::flushPortAsync(OMX_U32 portIndex) { void OMXCodec::disablePortAsync(OMX_U32 portIndex) { CHECK(mState == EXECUTING || mState == RECONFIGURING); - CHECK_EQ(mPortStatus[portIndex], ENABLED); + CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED); mPortStatus[portIndex] = DISABLING; CODEC_LOGV("sending OMX_CommandPortDisable(%ld)", portIndex); status_t err = mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); freeBuffersOnPort(portIndex, true); } @@ -2520,17 +2529,17 @@ void OMXCodec::disablePortAsync(OMX_U32 portIndex) { void OMXCodec::enablePortAsync(OMX_U32 portIndex) { CHECK(mState == EXECUTING || mState == RECONFIGURING); - CHECK_EQ(mPortStatus[portIndex], DISABLED); + CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLED); mPortStatus[portIndex] = ENABLING; CODEC_LOGV("sending OMX_CommandPortEnable(%ld)", portIndex); status_t err = mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } void OMXCodec::fillOutputBuffers() { - CHECK_EQ(mState, EXECUTING); + CHECK_EQ((int)mState, (int)EXECUTING); // This is a workaround for some decoders not properly reporting // end-of-output-stream. If we own all input buffers and also own @@ -2566,7 +2575,7 @@ void OMXCodec::drainInputBuffers() { } void OMXCodec::drainInputBuffer(BufferInfo *info) { - CHECK_EQ(info->mOwnedByComponent, false); + CHECK_EQ((int)info->mOwnedByComponent, (int)false); if (mSignalledEOS) { return; @@ -2603,7 +2612,7 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) { mNode, info->mBuffer, 0, size, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG, 0); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); info->mOwnedByComponent = true; @@ -2771,7 +2780,7 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) { } void OMXCodec::fillOutputBuffer(BufferInfo *info) { - CHECK_EQ(info->mOwnedByComponent, false); + CHECK_EQ((int)info->mOwnedByComponent, (int)false); if (mNoMoreOutputData) { CODEC_LOGV("There is no more output data available, not " @@ -2779,19 +2788,21 @@ void OMXCodec::fillOutputBuffer(BufferInfo *info) { return; } - sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer(); - if (graphicBuffer != 0) { - // When using a native buffer we need to lock the buffer before giving - // it to OMX. - CHECK(!info->mOwnedByNativeWindow); - CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer); - int err = mNativeWindow->lockBuffer(mNativeWindow.get(), - graphicBuffer.get()); - if (err != 0) { - CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err); + if (info->mMediaBuffer != NULL) { + sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer(); + if (graphicBuffer != 0) { + // When using a native buffer we need to lock the buffer before + // giving it to OMX. + CHECK(!info->mOwnedByNativeWindow); + CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer); + int err = mNativeWindow->lockBuffer(mNativeWindow.get(), + graphicBuffer.get()); + if (err != 0) { + CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err); - setState(ERROR); - return; + setState(ERROR); + return; + } } } @@ -2850,10 +2861,10 @@ void OMXCodec::setRawAudioFormat( def.nPortIndex = portIndex; status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, - &def, sizeof(def)), OK); + &def, sizeof(def)), (status_t)OK); // pcm param OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; @@ -2863,7 +2874,7 @@ void OMXCodec::setRawAudioFormat( err = mOMX->getParameter( mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); pcmParams.nChannels = numChannels; pcmParams.eNumData = OMX_NumericalDataSigned; @@ -2884,7 +2895,7 @@ void OMXCodec::setRawAudioFormat( err = mOMX->setParameter( mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) { @@ -2941,13 +2952,13 @@ void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) { status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate); err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); //////////////////////// @@ -2976,33 +2987,33 @@ void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bit status_t err = OMX_ErrorNone; while (OMX_ErrorNone == err) { CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat, - &format, sizeof(format)), OK); + &format, sizeof(format)), (status_t)OK); if (format.eEncoding == OMX_AUDIO_CodingAAC) { break; } format.nIndex++; } - CHECK_EQ(OK, err); + CHECK_EQ((status_t)OK, err); CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat, - &format, sizeof(format)), OK); + &format, sizeof(format)), (status_t)OK); // port definition OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, - &def, sizeof(def)), OK); + &def, sizeof(def)), (status_t)OK); def.format.audio.bFlagErrorConcealment = OMX_TRUE; def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, - &def, sizeof(def)), OK); + &def, sizeof(def)), (status_t)OK); // profile OMX_AUDIO_PARAM_AACPROFILETYPE profile; InitOMXParams(&profile); profile.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac, - &profile, sizeof(profile)), OK); + &profile, sizeof(profile)), (status_t)OK); profile.nChannels = numChannels; profile.eChannelMode = (numChannels == 1? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo); @@ -3015,7 +3026,7 @@ void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bit profile.eAACProfile = OMX_AUDIO_AACObjectLC; profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac, - &profile, sizeof(profile)), OK); + &profile, sizeof(profile)), (status_t)OK); } else { OMX_AUDIO_PARAM_AACPROFILETYPE profile; @@ -3024,7 +3035,7 @@ void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bit status_t err = mOMX->getParameter( mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); profile.nChannels = numChannels; profile.nSampleRate = sampleRate; @@ -3032,7 +3043,7 @@ void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bit err = mOMX->setParameter( mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } } @@ -3044,10 +3055,10 @@ void OMXCodec::setImageOutputFormat( OMX_INDEXTYPE index; status_t err = mOMX->get_extension_index( mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); err = mOMX->set_config(mNode, index, &format, sizeof(format)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); #endif OMX_PARAM_PORTDEFINITIONTYPE def; @@ -3056,13 +3067,13 @@ void OMXCodec::setImageOutputFormat( status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); - CHECK_EQ(def.eDomain, OMX_PortDomainImage); + CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage); OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; - CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused); + CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingUnused); imageDef->eColorFormat = format; imageDef->nFrameWidth = width; imageDef->nFrameHeight = height; @@ -3105,7 +3116,7 @@ void OMXCodec::setImageOutputFormat( err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } void OMXCodec::setJPEGInputFormat( @@ -3116,12 +3127,12 @@ void OMXCodec::setJPEGInputFormat( status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); - CHECK_EQ(def.eDomain, OMX_PortDomainImage); + CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage); OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; - CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG); + CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingJPEG); imageDef->nFrameWidth = width; imageDef->nFrameHeight = height; @@ -3130,7 +3141,7 @@ void OMXCodec::setJPEGInputFormat( err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } void OMXCodec::addCodecSpecificData(const void *data, size_t size) { @@ -3231,7 +3242,7 @@ status_t OMXCodec::stop() { status_t err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); } while (mState != LOADED && mState != ERROR) { @@ -3323,7 +3334,7 @@ status_t OMXCodec::read( mFilledBuffers.clear(); - CHECK_EQ(mState, EXECUTING); + CHECK_EQ((int)mState, (int)EXECUTING); bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput); bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput); @@ -3377,7 +3388,7 @@ void OMXCodec::signalBufferReturned(MediaBuffer *buffer) { BufferInfo *info = &buffers->editItemAt(i); if (info->mMediaBuffer == buffer) { - CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED); + CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED); if (buffer->graphicBuffer() == 0) { fillOutputBuffer(info); } else { @@ -3629,7 +3640,7 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output"); @@ -3695,7 +3706,7 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { err = mOMX->getParameter( mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); printf(" nSamplingRate = %ld\n", params.nSamplingRate); printf(" nChannels = %ld\n", params.nChannels); @@ -3714,7 +3725,7 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { err = mOMX->getParameter( mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); printf(" nChannels = %ld\n", amr.nChannels); printf(" eAMRBandMode = %s\n", @@ -3764,13 +3775,14 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); switch (def.eDomain) { case OMX_PortDomainImage: { OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; - CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused); + CHECK_EQ((int)imageDef->eCompressionFormat, + (int)OMX_IMAGE_CodingUnused); mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat); @@ -3790,11 +3802,11 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { err = mOMX->getParameter( mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); - CHECK_EQ(params.eNumData, OMX_NumericalDataSigned); - CHECK_EQ(params.nBitPerSample, 16); - CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear); + CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); + CHECK_EQ(params.nBitPerSample, 16u); + CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); int32_t numChannels, sampleRate; inputFormat->findInt32(kKeyChannelCount, &numChannels); @@ -3828,9 +3840,9 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { err = mOMX->getParameter( mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr)); - CHECK_EQ(err, OK); + CHECK_EQ(err, (status_t)OK); - CHECK_EQ(amr.nChannels, 1); + CHECK_EQ(amr.nChannels, 1u); mOutputFormat->setInt32(kKeyChannelCount, 1); if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0 @@ -3885,6 +3897,35 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth); mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight); mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat); + + OMX_CONFIG_RECTTYPE rect; + status_t err = + mOMX->getConfig( + mNode, OMX_IndexConfigCommonOutputCrop, + &rect, sizeof(rect)); + + if (err == OK) { + CHECK_GE(rect.nLeft, 0); + CHECK_GE(rect.nTop, 0); + CHECK_GE(rect.nWidth, 0u); + CHECK_GE(rect.nHeight, 0u); + CHECK_LE(rect.nLeft + rect.nWidth - 1, video_def->nFrameWidth); + CHECK_LE(rect.nTop + rect.nHeight - 1, video_def->nFrameHeight); + + mOutputFormat->setRect( + kKeyCropRect, + rect.nLeft, + rect.nTop, + rect.nLeft + rect.nWidth - 1, + rect.nTop + rect.nHeight - 1); + } else { + mOutputFormat->setRect( + kKeyCropRect, + 0, 0, + video_def->nFrameWidth - 1, + video_def->nFrameHeight - 1); + } + break; } @@ -3988,7 +4029,7 @@ status_t QueryCodecs( caps->mColorFormats.push(portFormat.eColorFormat); } - CHECK_EQ(omx->freeNode(node), OK); + CHECK_EQ(omx->freeNode(node), (status_t)OK); } } diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp index 43938b2..4b8a014 100644 --- a/media/libstagefright/OggExtractor.cpp +++ b/media/libstagefright/OggExtractor.cpp @@ -73,7 +73,7 @@ struct MyVorbisExtractor { // Returns an approximate bitrate in bits per second. uint64_t approxBitrate(); - status_t seekToOffset(off_t offset); + status_t seekToOffset(off64_t offset); status_t readNextPacket(MediaBuffer **buffer); status_t init(); @@ -91,7 +91,7 @@ private: }; sp<DataSource> mSource; - off_t mOffset; + off64_t mOffset; Page mCurrentPage; uint64_t mPrevGranulePosition; size_t mCurrentPageSize; @@ -99,7 +99,7 @@ private: uint64_t mCurrentPageSamples; size_t mNextLaceIndex; - off_t mFirstDataOffset; + off64_t mFirstDataOffset; vorbis_info mVi; vorbis_comment mVc; @@ -107,8 +107,8 @@ private: sp<MetaData> mMeta; sp<MetaData> mFileMeta; - ssize_t readPage(off_t offset, Page *page); - status_t findNextPage(off_t startOffset, off_t *pageOffset); + ssize_t readPage(off64_t offset, Page *page); + status_t findNextPage(off64_t startOffset, off64_t *pageOffset); status_t verifyHeader( MediaBuffer *buffer, uint8_t type); @@ -116,7 +116,7 @@ private: void parseFileMetaData(); void extractAlbumArt(const void *data, size_t size); - uint64_t findPrevGranulePosition(off_t pageOffset); + uint64_t findPrevGranulePosition(off64_t pageOffset); MyVorbisExtractor(const MyVorbisExtractor &); MyVorbisExtractor &operator=(const MyVorbisExtractor &); @@ -162,7 +162,7 @@ status_t OggSource::read( int64_t seekTimeUs; ReadOptions::SeekMode mode; if (options && options->getSeekTo(&seekTimeUs, &mode)) { - off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; + off64_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; LOGV("seeking to offset %ld", pos); if (mExtractor->mImpl->seekToOffset(pos) != OK) { @@ -220,7 +220,7 @@ sp<MetaData> MyVorbisExtractor::getFormat() const { } status_t MyVorbisExtractor::findNextPage( - off_t startOffset, off_t *pageOffset) { + off64_t startOffset, off64_t *pageOffset) { *pageOffset = startOffset; for (;;) { @@ -250,9 +250,9 @@ status_t MyVorbisExtractor::findNextPage( // it (if any) and return its granule position. // To do this we back up from the "current" page's offset until we find any // page preceding it and then scan forward to just before the current page. -uint64_t MyVorbisExtractor::findPrevGranulePosition(off_t pageOffset) { - off_t prevPageOffset = 0; - off_t prevGuess = pageOffset; +uint64_t MyVorbisExtractor::findPrevGranulePosition(off64_t pageOffset) { + off64_t prevPageOffset = 0; + off64_t prevGuess = pageOffset; for (;;) { if (prevGuess >= 5000) { prevGuess -= 5000; @@ -292,14 +292,14 @@ uint64_t MyVorbisExtractor::findPrevGranulePosition(off_t pageOffset) { } } -status_t MyVorbisExtractor::seekToOffset(off_t offset) { +status_t MyVorbisExtractor::seekToOffset(off64_t offset) { if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { // Once we know where the actual audio data starts (past the headers) // don't ever seek to anywhere before that. offset = mFirstDataOffset; } - off_t pageOffset; + off64_t pageOffset; status_t err = findNextPage(offset, &pageOffset); if (err != OK) { @@ -324,7 +324,7 @@ status_t MyVorbisExtractor::seekToOffset(off_t offset) { return OK; } -ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { +ssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) { uint8_t header[27]; if (mSource->readAt(offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { @@ -410,7 +410,7 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { } if (mNextLaceIndex < mCurrentPage.mNumSegments) { - off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; + off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; for (size_t j = 0; j < mNextLaceIndex; ++j) { dataOffset += mCurrentPage.mLace[j]; } @@ -609,7 +609,7 @@ status_t MyVorbisExtractor::verifyHeader( LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); LOGV("window-bitrate = %ld", mVi.bitrate_window); - off_t size; + off64_t size; if (mSource->getSize(&size) == OK) { uint64_t bps = approxBitrate(); diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp index 7155c61..062ab9b 100644 --- a/media/libstagefright/SampleIterator.cpp +++ b/media/libstagefright/SampleIterator.cpp @@ -179,7 +179,7 @@ status_t SampleIterator::findChunkRange(uint32_t sampleIndex) { return OK; } -status_t SampleIterator::getChunkOffset(uint32_t chunk, off_t *offset) { +status_t SampleIterator::getChunkOffset(uint32_t chunk, off64_t *offset) { *offset = 0; if (chunk >= mTable->mNumChunkOffsets) { diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp index 092c33e..a9163fc 100644 --- a/media/libstagefright/SampleTable.cpp +++ b/media/libstagefright/SampleTable.cpp @@ -76,7 +76,7 @@ SampleTable::~SampleTable() { } status_t SampleTable::setChunkOffsetParams( - uint32_t type, off_t data_offset, size_t data_size) { + uint32_t type, off64_t data_offset, size_t data_size) { if (mChunkOffsetOffset >= 0) { return ERROR_MALFORMED; } @@ -117,7 +117,7 @@ status_t SampleTable::setChunkOffsetParams( } status_t SampleTable::setSampleToChunkParams( - off_t data_offset, size_t data_size) { + off64_t data_offset, size_t data_size) { if (mSampleToChunkOffset >= 0) { return ERROR_MALFORMED; } @@ -168,7 +168,7 @@ status_t SampleTable::setSampleToChunkParams( } status_t SampleTable::setSampleSizeParams( - uint32_t type, off_t data_offset, size_t data_size) { + uint32_t type, off64_t data_offset, size_t data_size) { if (mSampleSizeOffset >= 0) { return ERROR_MALFORMED; } @@ -228,7 +228,7 @@ status_t SampleTable::setSampleSizeParams( } status_t SampleTable::setTimeToSampleParams( - off_t data_offset, size_t data_size) { + off64_t data_offset, size_t data_size) { if (mTimeToSample != NULL || data_size < 8) { return ERROR_MALFORMED; } @@ -260,7 +260,7 @@ status_t SampleTable::setTimeToSampleParams( return OK; } -status_t SampleTable::setSyncSampleParams(off_t data_offset, size_t data_size) { +status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) { if (mSyncSampleOffset >= 0 || data_size < 8) { return ERROR_MALFORMED; } @@ -419,8 +419,10 @@ status_t SampleTable::findSyncSampleNear( ++left; } + if (left > 0) { + --left; + } - --left; uint32_t x; if (mDataSource->readAt( mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) { @@ -557,7 +559,7 @@ status_t SampleTable::getSampleSize_l( status_t SampleTable::getMetaDataForSample( uint32_t sampleIndex, - off_t *offset, + off64_t *offset, size_t *size, uint32_t *decodingTime, bool *isSyncSample) { diff --git a/media/libstagefright/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp index 23b7681..783f2d0 100644 --- a/media/libstagefright/ShoutcastSource.cpp +++ b/media/libstagefright/ShoutcastSource.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ -#include "include/stagefright_string.h" #include "include/HTTPStream.h" #include <stdlib.h> @@ -34,7 +33,7 @@ ShoutcastSource::ShoutcastSource(HTTPStream *http) mBytesUntilMetaData(0), mGroup(NULL), mStarted(false) { - string metaint; + AString metaint; if (mHttp->find_header_value("icy-metaint", &metaint)) { char *end; const char *start = metaint.c_str(); diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index 6c05e03..86e0e73 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -127,10 +127,11 @@ status_t StagefrightMediaScanner::processFile( || !strcasecmp(extension, ".rtttl") || !strcasecmp(extension, ".rtx") || !strcasecmp(extension, ".ota")) { - return HandleMIDI(path, &client); - } - - if (mRetriever->setDataSource(path) == OK + status_t status = HandleMIDI(path, &client); + if (status != OK) { + return status; + } + } else if (mRetriever->setDataSource(path) == OK && mRetriever->setMode( METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) { const char *value; @@ -174,11 +175,11 @@ status_t StagefrightMediaScanner::processFile( char *StagefrightMediaScanner::extractAlbumArt(int fd) { LOGV("extractAlbumArt %d", fd); - off_t size = lseek(fd, 0, SEEK_END); + off64_t size = lseek64(fd, 0, SEEK_END); if (size < 0) { return NULL; } - lseek(fd, 0, SEEK_SET); + lseek64(fd, 0, SEEK_SET); if (mRetriever->setDataSource(fd, 0, size) == OK && mRetriever->setMode( diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index 9b2dec9..763a914 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -191,17 +191,26 @@ static VideoFrame *extractVideoFrameWithCodecFlags( CHECK(meta->findInt32(kKeyWidth, &width)); CHECK(meta->findInt32(kKeyHeight, &height)); + int32_t crop_left, crop_top, crop_right, crop_bottom; + if (!meta->findRect( + kKeyCropRect, + &crop_left, &crop_top, &crop_right, &crop_bottom)) { + crop_left = crop_top = 0; + crop_right = width - 1; + crop_bottom = height - 1; + } + int32_t rotationAngle; if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) { rotationAngle = 0; // By default, no rotation } VideoFrame *frame = new VideoFrame; - frame->mWidth = width; - frame->mHeight = height; - frame->mDisplayWidth = width; - frame->mDisplayHeight = height; - frame->mSize = width * height * 2; + frame->mWidth = crop_right - crop_left + 1; + frame->mHeight = crop_bottom - crop_top + 1; + frame->mDisplayWidth = frame->mWidth; + frame->mDisplayHeight = frame->mHeight; + frame->mSize = frame->mWidth * frame->mHeight * 2; frame->mData = new uint8_t[frame->mSize]; frame->mRotationAngle = rotationAngle; @@ -213,10 +222,13 @@ static VideoFrame *extractVideoFrameWithCodecFlags( CHECK(converter.isValid()); converter.convert( - width, height, (const uint8_t *)buffer->data() + buffer->range_offset(), - 0, - frame->mData, width * 2); + width, height, + crop_left, crop_top, crop_right, crop_bottom, + frame->mData, + frame->mWidth, + frame->mHeight, + 0, 0, frame->mWidth - 1, frame->mHeight - 1); buffer->release(); buffer = NULL; @@ -418,5 +430,4 @@ void StagefrightMetadataRetriever::parseMetaData() { } } - } // namespace android diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp index 4711f7c..88e07b0 100644 --- a/media/libstagefright/ThrottledSource.cpp +++ b/media/libstagefright/ThrottledSource.cpp @@ -41,7 +41,7 @@ status_t ThrottledSource::initCheck() const { return mSource->initCheck(); } -ssize_t ThrottledSource::readAt(off_t offset, void *data, size_t size) { +ssize_t ThrottledSource::readAt(off64_t offset, void *data, size_t size) { Mutex::Autolock autoLock(mLock); ssize_t n = mSource->readAt(offset, data, size); @@ -72,7 +72,7 @@ ssize_t ThrottledSource::readAt(off_t offset, void *data, size_t size) { return n; } -status_t ThrottledSource::getSize(off_t *size) { +status_t ThrottledSource::getSize(off64_t *size) { return mSource->getSize(size); } diff --git a/media/libstagefright/VBRISeeker.cpp b/media/libstagefright/VBRISeeker.cpp index 6608644..48bddc2 100644 --- a/media/libstagefright/VBRISeeker.cpp +++ b/media/libstagefright/VBRISeeker.cpp @@ -34,8 +34,8 @@ static uint32_t U24_AT(const uint8_t *ptr) { // static sp<VBRISeeker> VBRISeeker::CreateFromSource( - const sp<DataSource> &source, off_t post_id3_pos) { - off_t pos = post_id3_pos; + const sp<DataSource> &source, off64_t post_id3_pos) { + off64_t pos = post_id3_pos; uint8_t header[4]; ssize_t n = source->readAt(pos, header, sizeof(header)); @@ -94,7 +94,7 @@ sp<VBRISeeker> VBRISeeker::CreateFromSource( seeker->mBasePos = post_id3_pos; seeker->mDurationUs = durationUs; - off_t offset = post_id3_pos; + off64_t offset = post_id3_pos; for (size_t i = 0; i < numEntries; ++i) { uint32_t numBytes; switch (entrySize) { @@ -138,7 +138,7 @@ bool VBRISeeker::getDuration(int64_t *durationUs) { return true; } -bool VBRISeeker::getOffsetForTime(int64_t *timeUs, off_t *pos) { +bool VBRISeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) { if (mDurationUs < 0) { return false; } diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index aff06bc..446021c 100644 --- a/media/libstagefright/WAVExtractor.cpp +++ b/media/libstagefright/WAVExtractor.cpp @@ -51,7 +51,7 @@ struct WAVSource : public MediaSource { const sp<MetaData> &meta, uint16_t waveFormat, int32_t bitsPerSample, - off_t offset, size_t size); + off64_t offset, size_t size); virtual status_t start(MetaData *params = NULL); virtual status_t stop(); @@ -72,11 +72,11 @@ private: int32_t mSampleRate; int32_t mNumChannels; int32_t mBitsPerSample; - off_t mOffset; + off64_t mOffset; size_t mSize; bool mStarted; MediaBufferGroup *mGroup; - off_t mCurrentPos; + off64_t mCurrentPos; WAVSource(const WAVSource &); WAVSource &operator=(const WAVSource &); @@ -139,7 +139,7 @@ status_t WAVExtractor::init() { size_t totalSize = U32_LE_AT(&header[4]); - off_t offset = 12; + off64_t offset = 12; size_t remainingSize = totalSize; while (remainingSize >= 8) { uint8_t chunkHeader[8]; @@ -251,7 +251,7 @@ WAVSource::WAVSource( const sp<MetaData> &meta, uint16_t waveFormat, int32_t bitsPerSample, - off_t offset, size_t size) + off64_t offset, size_t size) : mDataSource(dataSource), mMeta(meta), mWaveFormat(waveFormat), @@ -335,7 +335,7 @@ status_t WAVSource::read( mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize; size_t maxBytesAvailable = - (mCurrentPos - mOffset >= (off_t)mSize) + (mCurrentPos - mOffset >= (off64_t)mSize) ? 0 : mSize - (mCurrentPos - mOffset); if (maxBytesToRead > maxBytesAvailable) { diff --git a/media/libstagefright/XINGSeeker.cpp b/media/libstagefright/XINGSeeker.cpp index 72f260e..616836c 100644 --- a/media/libstagefright/XINGSeeker.cpp +++ b/media/libstagefright/XINGSeeker.cpp @@ -22,14 +22,14 @@ namespace android { static bool parse_xing_header( - const sp<DataSource> &source, off_t first_frame_pos, + const sp<DataSource> &source, off64_t first_frame_pos, int32_t *frame_number = NULL, int32_t *byte_number = NULL, char *table_of_contents = NULL, int32_t *quality_indicator = NULL, int64_t *duration = NULL); // static sp<XINGSeeker> XINGSeeker::CreateFromSource( - const sp<DataSource> &source, off_t first_frame_pos) { + const sp<DataSource> &source, off64_t first_frame_pos) { sp<XINGSeeker> seeker = new XINGSeeker; seeker->mFirstFramePos = first_frame_pos; @@ -61,7 +61,7 @@ bool XINGSeeker::getDuration(int64_t *durationUs) { return true; } -bool XINGSeeker::getOffsetForTime(int64_t *timeUs, off_t *pos) { +bool XINGSeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) { if (mSizeBytes == 0 || mTableOfContents[0] <= 0 || mDurationUs < 0) { return false; } @@ -94,7 +94,7 @@ bool XINGSeeker::getOffsetForTime(int64_t *timeUs, off_t *pos) { } static bool parse_xing_header( - const sp<DataSource> &source, off_t first_frame_pos, + const sp<DataSource> &source, off64_t first_frame_pos, int32_t *frame_number, int32_t *byte_number, char *table_of_contents, int32_t *quality_indicator, int64_t *duration) { diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp index 868c514..5bbba35 100644 --- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp +++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp @@ -73,6 +73,7 @@ AVCDecoder::AVCDecoder(const sp<MediaSource> &source) CHECK(mSource->getFormat()->findInt32(kKeyHeight, &height)); mFormat->setInt32(kKeyWidth, width); mFormat->setInt32(kKeyHeight, height); + mFormat->setRect(kKeyCropRect, 0, 0, width - 1, height - 1); mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar); mFormat->setCString(kKeyDecoderComponent, "AVCDecoder"); @@ -418,16 +419,32 @@ status_t AVCDecoder::read( crop_top = crop_left = 0; } - int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15; - int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15; + int32_t prevCropLeft, prevCropTop; + int32_t prevCropRight, prevCropBottom; + if (!mFormat->findRect( + kKeyCropRect, + &prevCropLeft, &prevCropTop, + &prevCropRight, &prevCropBottom)) { + prevCropLeft = prevCropTop = 0; + prevCropRight = width - 1; + prevCropBottom = height - 1; + } int32_t oldWidth, oldHeight; CHECK(mFormat->findInt32(kKeyWidth, &oldWidth)); CHECK(mFormat->findInt32(kKeyHeight, &oldHeight)); - if (oldWidth != aligned_width || oldHeight != aligned_height) { - mFormat->setInt32(kKeyWidth, aligned_width); - mFormat->setInt32(kKeyHeight, aligned_height); + if (oldWidth != width || oldHeight != height + || prevCropLeft != crop_left + || prevCropTop != crop_top + || prevCropRight != crop_right + || prevCropBottom != crop_bottom) { + mFormat->setRect( + kKeyCropRect, + crop_left, crop_top, crop_right, crop_bottom); + + mFormat->setInt32(kKeyWidth, width); + mFormat->setInt32(kKeyHeight, height); err = INFO_FORMAT_CHANGED; } else { diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk index ef2dba0..62ba40f 100644 --- a/media/libstagefright/colorconversion/Android.mk +++ b/media/libstagefright/colorconversion/Android.mk @@ -9,20 +9,6 @@ LOCAL_C_INCLUDES := \ $(TOP)/frameworks/base/include/media/stagefright/openmax \ $(TOP)/hardware/msm7k -LOCAL_SHARED_LIBRARIES := \ - libbinder \ - libmedia \ - libutils \ - libui \ - libcutils \ - libsurfaceflinger_client\ - libcamera_client - -# ifeq ($(TARGET_BOARD_PLATFORM),msm7k) -ifeq ($(TARGET_PRODUCT),passion) - LOCAL_CFLAGS += -DHAS_YCBCR420_SP_ADRENO -endif - LOCAL_MODULE:= libstagefright_color_conversion -include $(BUILD_SHARED_LIBRARY) +include $(BUILD_STATIC_LIBRARY) diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp index 5b16997..600f040 100644 --- a/media/libstagefright/colorconversion/ColorConverter.cpp +++ b/media/libstagefright/colorconversion/ColorConverter.cpp @@ -50,31 +50,64 @@ bool ColorConverter::isValid() const { } } -void ColorConverter::convert( +ColorConverter::BitmapParams::BitmapParams( + void *bits, size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip) { + size_t cropLeft, size_t cropTop, + size_t cropRight, size_t cropBottom) + : mBits(bits), + mWidth(width), + mHeight(height), + mCropLeft(cropLeft), + mCropTop(cropTop), + mCropRight(cropRight), + mCropBottom(cropBottom) { +} + +size_t ColorConverter::BitmapParams::cropWidth() const { + return mCropRight - mCropLeft + 1; +} + +size_t ColorConverter::BitmapParams::cropHeight() const { + return mCropBottom - mCropTop + 1; +} + +void ColorConverter::convert( + const void *srcBits, + size_t srcWidth, size_t srcHeight, + size_t srcCropLeft, size_t srcCropTop, + size_t srcCropRight, size_t srcCropBottom, + void *dstBits, + size_t dstWidth, size_t dstHeight, + size_t dstCropLeft, size_t dstCropTop, + size_t dstCropRight, size_t dstCropBottom) { CHECK_EQ(mDstFormat, OMX_COLOR_Format16bitRGB565); + BitmapParams src( + const_cast<void *>(srcBits), + srcWidth, srcHeight, + srcCropLeft, srcCropTop, srcCropRight, srcCropBottom); + + BitmapParams dst( + dstBits, + dstWidth, dstHeight, + dstCropLeft, dstCropTop, dstCropRight, dstCropBottom); + switch (mSrcFormat) { case OMX_COLOR_FormatYUV420Planar: - convertYUV420Planar( - width, height, srcBits, srcSkip, dstBits, dstSkip); + convertYUV420Planar(src, dst); break; case OMX_COLOR_FormatCbYCrY: - convertCbYCrY( - width, height, srcBits, srcSkip, dstBits, dstSkip); + convertCbYCrY(src, dst); break; case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: - convertQCOMYUV420SemiPlanar( - width, height, srcBits, srcSkip, dstBits, dstSkip); + convertQCOMYUV420SemiPlanar(src, dst); break; case OMX_COLOR_FormatYUV420SemiPlanar: - convertYUV420SemiPlanar( - width, height, srcBits, srcSkip, dstBits, dstSkip); + convertYUV420SemiPlanar(src, dst); break; default: @@ -86,25 +119,27 @@ void ColorConverter::convert( } void ColorConverter::convertCbYCrY( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip) { - CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. - CHECK(dstSkip >= width * 2); - CHECK((dstSkip & 3) == 0); + const BitmapParams &src, const BitmapParams &dst) { + // XXX Untested uint8_t *kAdjustedClip = initClip(); - uint32_t *dst_ptr = (uint32_t *)dstBits; + CHECK((src.mCropLeft & 1) == 0); + CHECK_EQ(src.cropWidth(), dst.cropWidth()); + CHECK_EQ(src.cropHeight(), dst.cropHeight()); + + uint32_t *dst_ptr = (uint32_t *)dst.mBits + + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2; - const uint8_t *src = (const uint8_t *)srcBits; + const uint8_t *src_ptr = (const uint8_t *)src.mBits + + (src.mCropTop * dst.mWidth + src.mCropLeft) * 2; - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; x += 2) { - signed y1 = (signed)src[2 * x + 1] - 16; - signed y2 = (signed)src[2 * x + 3] - 16; - signed u = (signed)src[2 * x] - 128; - signed v = (signed)src[2 * x + 2] - 128; + for (size_t y = 0; y < src.cropHeight(); ++y) { + for (size_t x = 0; x < src.cropWidth(); x += 2) { + signed y1 = (signed)src_ptr[2 * x + 1] - 16; + signed y2 = (signed)src_ptr[2 * x + 3] - 16; + signed u = (signed)src_ptr[2 * x] - 128; + signed v = (signed)src_ptr[2 * x + 2] - 128; signed u_b = u * 517; signed u_g = -u * 100; @@ -134,32 +169,35 @@ void ColorConverter::convertCbYCrY( dst_ptr[x / 2] = (rgb2 << 16) | rgb1; } - src += width * 2; - dst_ptr += dstSkip / 4; + src_ptr += src.mWidth * 2; + dst_ptr += dst.mWidth / 2; } } void ColorConverter::convertYUV420Planar( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip) { - CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. - CHECK(dstSkip >= width * 2); - CHECK((dstSkip & 3) == 0); - + const BitmapParams &src, const BitmapParams &dst) { uint8_t *kAdjustedClip = initClip(); - uint32_t *dst_ptr = (uint32_t *)dstBits; - const uint8_t *src_y = (const uint8_t *)srcBits; + CHECK((dst.mWidth & 3) == 0); + CHECK((src.mCropLeft & 1) == 0); + CHECK_EQ(src.cropWidth(), dst.cropWidth()); + CHECK_EQ(src.cropHeight(), dst.cropHeight()); + + uint32_t *dst_ptr = (uint32_t *)dst.mBits + + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2; + + const uint8_t *src_y = + (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; const uint8_t *src_u = - (const uint8_t *)src_y + width * height; + (const uint8_t *)src_y + src.mWidth * src.mHeight + + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2; const uint8_t *src_v = - (const uint8_t *)src_u + (width / 2) * (height / 2); + src_u + (src.mWidth / 2) * (src.mHeight / 2); - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; x += 2) { + for (size_t y = 0; y < src.cropHeight(); ++y) { + for (size_t x = 0; x < src.cropWidth(); x += 2) { // B = 1.164 * (Y - 16) + 2.018 * (U - 128) // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128) // R = 1.164 * (Y - 16) + 1.596 * (V - 128) @@ -212,35 +250,38 @@ void ColorConverter::convertYUV420Planar( dst_ptr[x / 2] = (rgb2 << 16) | rgb1; } - src_y += width; + src_y += src.mWidth; if (y & 1) { - src_u += width / 2; - src_v += width / 2; + src_u += src.mWidth / 2; + src_v += src.mWidth / 2; } - dst_ptr += dstSkip / 4; + dst_ptr += dst.mWidth / 2; } } void ColorConverter::convertQCOMYUV420SemiPlanar( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip) { - CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. - CHECK(dstSkip >= width * 2); - CHECK((dstSkip & 3) == 0); - + const BitmapParams &src, const BitmapParams &dst) { uint8_t *kAdjustedClip = initClip(); - uint32_t *dst_ptr = (uint32_t *)dstBits; - const uint8_t *src_y = (const uint8_t *)srcBits; + CHECK((dst.mWidth & 3) == 0); + CHECK((src.mCropLeft & 1) == 0); + CHECK_EQ(src.cropWidth(), dst.cropWidth()); + CHECK_EQ(src.cropHeight(), dst.cropHeight()); + + uint32_t *dst_ptr = (uint32_t *)dst.mBits + + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2; + + const uint8_t *src_y = + (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; const uint8_t *src_u = - (const uint8_t *)src_y + width * height; + (const uint8_t *)src_y + src.mWidth * src.mHeight + + src.mCropTop * src.mWidth + src.mCropLeft; - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; x += 2) { + for (size_t y = 0; y < src.cropHeight(); ++y) { + for (size_t x = 0; x < src.cropWidth(); x += 2) { signed y1 = (signed)src_y[x] - 16; signed y2 = (signed)src_y[x + 1] - 16; @@ -275,34 +316,39 @@ void ColorConverter::convertQCOMYUV420SemiPlanar( dst_ptr[x / 2] = (rgb2 << 16) | rgb1; } - src_y += width; + src_y += src.mWidth; if (y & 1) { - src_u += width; + src_u += src.mWidth; } - dst_ptr += dstSkip / 4; + dst_ptr += dst.mWidth / 2; } } void ColorConverter::convertYUV420SemiPlanar( - size_t width, size_t height, - const void *srcBits, size_t srcSkip, - void *dstBits, size_t dstSkip) { - CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. - CHECK(dstSkip >= width * 2); - CHECK((dstSkip & 3) == 0); + const BitmapParams &src, const BitmapParams &dst) { + // XXX Untested uint8_t *kAdjustedClip = initClip(); - uint32_t *dst_ptr = (uint32_t *)dstBits; - const uint8_t *src_y = (const uint8_t *)srcBits; + CHECK((dst.mWidth & 3) == 0); + CHECK((src.mCropLeft & 1) == 0); + CHECK_EQ(src.cropWidth(), dst.cropWidth()); + CHECK_EQ(src.cropHeight(), dst.cropHeight()); + + uint32_t *dst_ptr = (uint32_t *)dst.mBits + + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2; + + const uint8_t *src_y = + (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; const uint8_t *src_u = - (const uint8_t *)src_y + width * height; + (const uint8_t *)src_y + src.mWidth * src.mHeight + + src.mCropTop * src.mWidth + src.mCropLeft; - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; x += 2) { + for (size_t y = 0; y < src.cropHeight(); ++y) { + for (size_t x = 0; x < src.cropWidth(); x += 2) { signed y1 = (signed)src_y[x] - 16; signed y2 = (signed)src_y[x + 1] - 16; @@ -337,13 +383,13 @@ void ColorConverter::convertYUV420SemiPlanar( dst_ptr[x / 2] = (rgb2 << 16) | rgb1; } - src_y += width; + src_y += src.mWidth; if (y & 1) { - src_u += width; + src_u += src.mWidth; } - dst_ptr += dstSkip / 4; + dst_ptr += dst.mWidth / 2; } } diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp index acbea05..70408d7 100644 --- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp +++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp @@ -21,55 +21,41 @@ #include <binder/MemoryHeapBase.h> #include <binder/MemoryHeapPmem.h> -#include <media/stagefright/MediaDebug.h> +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/MetaData.h> #include <surfaceflinger/Surface.h> #include <ui/android_native_buffer.h> #include <ui/GraphicBufferMapper.h> -// XXX: Temporary hack to allow referencing the _ADRENO pixel format here. -#include <libgralloc-qsd8k/gralloc_priv.h> - namespace android { SoftwareRenderer::SoftwareRenderer( - OMX_COLOR_FORMATTYPE colorFormat, - const sp<Surface> &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight, - int32_t rotationDegrees) - : mColorFormat(colorFormat), - mConverter(NULL), + const sp<Surface> &surface, const sp<MetaData> &meta) + : mConverter(NULL), mYUVMode(None), - mSurface(surface), - mDisplayWidth(displayWidth), - mDisplayHeight(displayHeight), - mDecodedWidth(decodedWidth), - mDecodedHeight(decodedHeight) { - LOGI("input format = %d", mColorFormat); - LOGI("display = %d x %d, decoded = %d x %d", - mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight); - - mDecodedWidth = mDisplayWidth; - mDecodedHeight = mDisplayHeight; + mSurface(surface) { + int32_t tmp; + CHECK(meta->findInt32(kKeyColorFormat, &tmp)); + mColorFormat = (OMX_COLOR_FORMATTYPE)tmp; + + CHECK(meta->findInt32(kKeyWidth, &mWidth)); + CHECK(meta->findInt32(kKeyHeight, &mHeight)); + + if (!meta->findRect( + kKeyCropRect, + &mCropLeft, &mCropTop, &mCropRight, &mCropBottom)) { + mCropLeft = mCropTop = 0; + mCropRight = mWidth - 1; + mCropBottom = mHeight - 1; + } + + int32_t rotationDegrees; + if (!meta->findInt32(kKeyRotation, &rotationDegrees)) { + rotationDegrees = 0; + } int halFormat; switch (mColorFormat) { -#if HAS_YCBCR420_SP_ADRENO - case OMX_COLOR_FormatYUV420Planar: - { - halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO; - mYUVMode = YUV420ToYUV420sp; - break; - } - - case 0x7fa30c00: - { - halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO; - mYUVMode = YUV420spToYUV420sp; - break; - } -#endif - default: halFormat = HAL_PIXEL_FORMAT_RGB_565; @@ -80,8 +66,8 @@ SoftwareRenderer::SoftwareRenderer( } CHECK(mSurface.get() != NULL); - CHECK(mDecodedWidth > 0); - CHECK(mDecodedHeight > 0); + CHECK(mWidth > 0); + CHECK(mHeight > 0); CHECK(mConverter == NULL || mConverter->isValid()); CHECK_EQ(0, @@ -94,7 +80,9 @@ SoftwareRenderer::SoftwareRenderer( // Width must be multiple of 32??? CHECK_EQ(0, native_window_set_buffers_geometry( - mSurface.get(), mDecodedWidth, mDecodedHeight, + mSurface.get(), + mCropRight - mCropLeft + 1, + mCropBottom - mCropTop + 1, halFormat)); uint32_t transform; @@ -117,10 +105,6 @@ SoftwareRenderer::~SoftwareRenderer() { mConverter = NULL; } -static inline size_t ALIGN(size_t x, size_t alignment) { - return (x + alignment - 1) & ~(alignment - 1); -} - void SoftwareRenderer::render( const void *data, size_t size, void *platformPrivate) { android_native_buffer_t *buf; @@ -134,7 +118,7 @@ void SoftwareRenderer::render( GraphicBufferMapper &mapper = GraphicBufferMapper::get(); - Rect bounds(mDecodedWidth, mDecodedHeight); + Rect bounds(mWidth, mHeight); void *dst; CHECK_EQ(0, mapper.lock( @@ -142,69 +126,16 @@ void SoftwareRenderer::render( if (mConverter) { mConverter->convert( - mDecodedWidth, mDecodedHeight, - data, 0, dst, buf->stride * 2); - } else if (mYUVMode == YUV420spToYUV420sp) { - // Input and output are both YUV420sp, but the alignment requirements - // are different. - size_t srcYStride = mDecodedWidth; - const uint8_t *srcY = (const uint8_t *)data; - uint8_t *dstY = (uint8_t *)dst; - for (size_t i = 0; i < mDecodedHeight; ++i) { - memcpy(dstY, srcY, mDecodedWidth); - srcY += srcYStride; - dstY += buf->stride; - } - - size_t srcUVStride = (mDecodedWidth + 1) & ~1; - size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2; - - const uint8_t *srcUV = (const uint8_t *)data - + mDecodedHeight * mDecodedWidth; - - size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096); - uint8_t *dstUV = (uint8_t *)dst + dstUVOffset; - - for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) { - memcpy(dstUV, srcUV, (mDecodedWidth + 1) & ~1); - srcUV += srcUVStride; - dstUV += dstUVStride; - } - } else if (mYUVMode == YUV420ToYUV420sp) { - // Input is YUV420 planar, output is YUV420sp, adhere to proper - // alignment requirements. - size_t srcYStride = mDecodedWidth; - const uint8_t *srcY = (const uint8_t *)data; - uint8_t *dstY = (uint8_t *)dst; - for (size_t i = 0; i < mDecodedHeight; ++i) { - memcpy(dstY, srcY, mDecodedWidth); - srcY += srcYStride; - dstY += buf->stride; - } - - size_t srcUVStride = (mDecodedWidth + 1) / 2; - size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2; - - const uint8_t *srcU = (const uint8_t *)data - + mDecodedHeight * mDecodedWidth; - - const uint8_t *srcV = - srcU + ((mDecodedWidth + 1) / 2) * ((mDecodedHeight + 1) / 2); - - size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096); - uint8_t *dstUV = (uint8_t *)dst + dstUVOffset; - - for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) { - for (size_t j = 0; j < (mDecodedWidth + 1) / 2; ++j) { - dstUV[2 * j + 1] = srcU[j]; - dstUV[2 * j] = srcV[j]; - } - srcU += srcUVStride; - srcV += srcUVStride; - dstUV += dstUVStride; - } + data, + mWidth, mHeight, + mCropLeft, mCropTop, mCropRight, mCropBottom, + dst, + buf->stride, buf->height, + 0, 0, + mCropRight - mCropLeft, + mCropBottom - mCropTop); } else { - memcpy(dst, data, size); + TRESPASS(); } CHECK_EQ(0, mapper.unlock(buf->handle)); diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp index c19b6f7..4b4c3d2 100644 --- a/media/libstagefright/httplive/LiveSource.cpp +++ b/media/libstagefright/httplive/LiveSource.cpp @@ -447,11 +447,11 @@ bool LiveSource::setupCipher() { static const ssize_t kHeaderSize = 188; -ssize_t LiveSource::readAt(off_t offset, void *data, size_t size) { +ssize_t LiveSource::readAt(off64_t offset, void *data, size_t size) { CHECK(offset >= mOffsetBias); offset -= mOffsetBias; - off_t delta = mSignalDiscontinuity ? kHeaderSize : 0; + off64_t delta = mSignalDiscontinuity ? kHeaderSize : 0; if (offset >= mSourceSize + delta) { CHECK_EQ(offset, mSourceSize + delta); @@ -502,7 +502,7 @@ ssize_t LiveSource::readAt(off_t offset, void *data, size_t size) { mAESIVec, AES_DECRYPT); - if (mSourceSize == (off_t)(offset + numRead - delta + n)) { + if (mSourceSize == (off64_t)(offset + numRead - delta + n)) { // check for padding at the end of the file. size_t pad = tmp->data()[n - 1]; @@ -551,7 +551,7 @@ status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *out) { source = mSource; } - off_t size; + off64_t size; status_t err = source->getSize(&size); if (err != OK) { diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp index da340f7..e9131a6 100644 --- a/media/libstagefright/id3/ID3.cpp +++ b/media/libstagefright/id3/ID3.cpp @@ -769,8 +769,8 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const { bool ID3::parseV1(const sp<DataSource> &source) { const size_t V1_TAG_SIZE = 128; - off_t size; - if (source->getSize(&size) != OK || size < (off_t)V1_TAG_SIZE) { + off64_t size; + if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) { return false; } diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 4e63b7a..e33f467 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -88,11 +88,6 @@ struct AwesomePlayer { status_t seekTo(int64_t timeUs); - status_t getVideoDimensions(int32_t *width, int32_t *height) const; - - status_t suspend(); - status_t resume(); - // This is a mask of MediaExtractor::Flags. uint32_t flags() const; @@ -153,7 +148,6 @@ private: uint32_t mFlags; uint32_t mExtractorFlags; - int32_t mVideoWidth, mVideoHeight; int64_t mTimeSourceDeltaUs; int64_t mVideoTimeUs; @@ -187,7 +181,6 @@ private: void postCheckAudioStatusEvent_l(); status_t play_l(); - MediaBuffer *mLastVideoBuffer; MediaBuffer *mVideoBuffer; sp<NuHTTPDataSource> mConnectingDataSource; @@ -198,32 +191,6 @@ private: sp<ARTPSession> mRTPSession; sp<UDPPusher> mRTPPusher, mRTCPPusher; - struct SuspensionState { - String8 mUri; - KeyedVector<String8, String8> mUriHeaders; - sp<DataSource> mFileSource; - - uint32_t mFlags; - int64_t mPositionUs; - - void *mLastVideoFrame; - size_t mLastVideoFrameSize; - int32_t mColorFormat; - int32_t mVideoWidth, mVideoHeight; - int32_t mDecodedWidth, mDecodedHeight; - - SuspensionState() - : mLastVideoFrame(NULL) { - } - - ~SuspensionState() { - if (mLastVideoFrame) { - free(mLastVideoFrame); - mLastVideoFrame = NULL; - } - } - } *mSuspensionState; - DrmManagerClient *mDrmManagerClient; DecryptHandle *mDecryptHandle; diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h index 793798f..545cd0c 100644 --- a/media/libstagefright/include/HTTPStream.h +++ b/media/libstagefright/include/HTTPStream.h @@ -18,10 +18,9 @@ #define HTTP_STREAM_H_ -#include "stagefright_string.h" - #include <sys/types.h> +#include <media/stagefright/foundation/AString.h> #include <media/stagefright/MediaErrors.h> #include <utils/KeyedVector.h> #include <utils/threads.h> @@ -50,7 +49,7 @@ public: static const char *kStatusKey; bool find_header_value( - const string &key, string *value) const; + const AString &key, AString *value) const; // Pass a negative value to disable the timeout. void setReceiveTimeout(int seconds); @@ -70,7 +69,7 @@ private: Mutex mLock; int mSocket; - KeyedVector<string, string> mHeaders; + KeyedVector<AString, AString> mHeaders; HTTPStream(const HTTPStream &); HTTPStream &operator=(const HTTPStream &); diff --git a/media/libstagefright/include/LiveSource.h b/media/libstagefright/include/LiveSource.h index 7ba1f44..38fe328 100644 --- a/media/libstagefright/include/LiveSource.h +++ b/media/libstagefright/include/LiveSource.h @@ -35,7 +35,7 @@ struct LiveSource : public DataSource { virtual status_t initCheck() const; - virtual ssize_t readAt(off_t offset, void *data, size_t size); + virtual ssize_t readAt(off64_t offset, void *data, size_t size); virtual uint32_t flags() { return kWantsPrefetching; @@ -67,8 +67,8 @@ private: int64_t mLastFetchTimeUs; sp<NuHTTPDataSource> mSource; - off_t mSourceSize; - off_t mOffsetBias; + off64_t mSourceSize; + off64_t mOffsetBias; bool mSignalDiscontinuity; ssize_t mPrevBandwidthIndex; diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h index 11ca243..728980e 100644 --- a/media/libstagefright/include/MP3Extractor.h +++ b/media/libstagefright/include/MP3Extractor.h @@ -47,7 +47,7 @@ private: status_t mInitCheck; sp<DataSource> mDataSource; - off_t mFirstFramePos; + off64_t mFirstFramePos; sp<MetaData> mMeta; uint32_t mFixedHeader; sp<MP3Seeker> mSeeker; diff --git a/media/libstagefright/include/MP3Seeker.h b/media/libstagefright/include/MP3Seeker.h index 190eaed..599542e 100644 --- a/media/libstagefright/include/MP3Seeker.h +++ b/media/libstagefright/include/MP3Seeker.h @@ -31,7 +31,7 @@ struct MP3Seeker : public RefBase { // Given a request seek time in "*timeUs", find the byte offset closest // to that position and return it in "*pos". Update "*timeUs" to reflect // the actual time that seekpoint represents. - virtual bool getOffsetForTime(int64_t *timeUs, off_t *pos) = 0; + virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos) = 0; protected: virtual ~MP3Seeker() {} diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h index d83b538..58401d4 100644 --- a/media/libstagefright/include/MPEG2TSExtractor.h +++ b/media/libstagefright/include/MPEG2TSExtractor.h @@ -43,7 +43,7 @@ private: Vector<sp<AnotherPacketSource> > mSourceImpls; - off_t mOffset; + off64_t mOffset; void init(); status_t feedMore(); diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h index bc2e4dc..04e8a6a 100644 --- a/media/libstagefright/include/MPEG4Extractor.h +++ b/media/libstagefright/include/MPEG4Extractor.h @@ -67,8 +67,8 @@ private: Vector<uint32_t> mPath; status_t readMetaData(); - status_t parseChunk(off_t *offset, int depth); - status_t parseMetaData(off_t offset, size_t size); + status_t parseChunk(off64_t *offset, int depth); + status_t parseMetaData(off64_t offset, size_t size); status_t updateAudioTrackInfoFromESDS_MPEG4Audio( const void *esds_data, size_t esds_size); @@ -86,9 +86,9 @@ private: SINF *mFirstSINF; bool mIsDrm; - status_t parseDrmSINF(off_t *offset, off_t data_offset); + status_t parseDrmSINF(off64_t *offset, off64_t data_offset); - status_t parseTrackHeader(off_t data_offset, off_t data_size); + status_t parseTrackHeader(off64_t data_offset, off64_t data_size); MPEG4Extractor(const MPEG4Extractor &); MPEG4Extractor &operator=(const MPEG4Extractor &); diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h index 5e404b6..f0f7daf 100644 --- a/media/libstagefright/include/NuCachedSource2.h +++ b/media/libstagefright/include/NuCachedSource2.h @@ -32,9 +32,9 @@ struct NuCachedSource2 : public DataSource { virtual status_t initCheck() const; - virtual ssize_t readAt(off_t offset, void *data, size_t size); + virtual ssize_t readAt(off64_t offset, void *data, size_t size); - virtual status_t getSize(off_t *size); + virtual status_t getSize(off64_t *size); virtual uint32_t flags(); virtual DecryptHandle* DrmInitialization(DrmManagerClient *client); @@ -81,9 +81,9 @@ private: Condition mCondition; PageCache *mCache; - off_t mCacheOffset; + off64_t mCacheOffset; status_t mFinalStatus; - off_t mLastAccessPos; + off64_t mLastAccessPos; sp<AMessage> mAsyncResult; bool mFetching; int64_t mLastFetchTimeUs; @@ -95,8 +95,8 @@ private: void onSuspend(); void fetchInternal(); - ssize_t readInternal(off_t offset, void *data, size_t size); - status_t seekInternal_l(off_t offset); + ssize_t readInternal(off64_t offset, void *data, size_t size); + status_t seekInternal_l(off64_t offset); size_t approxDataRemaining_l(bool *eos); void restartPrefetcherIfNecessary_l(bool ignoreLowWaterThreshold = false); diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h index c42691f..c8e93be 100644 --- a/media/libstagefright/include/NuHTTPDataSource.h +++ b/media/libstagefright/include/NuHTTPDataSource.h @@ -17,14 +17,14 @@ struct NuHTTPDataSource : public DataSource { status_t connect( const char *uri, const KeyedVector<String8, String8> *headers = NULL, - off_t offset = 0); + off64_t offset = 0); void disconnect(); virtual status_t initCheck() const; - virtual ssize_t readAt(off_t offset, void *data, size_t size); - virtual status_t getSize(off_t *size); + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual status_t getSize(off64_t *size); virtual uint32_t flags(); // Returns true if bandwidth could successfully be estimated, @@ -61,8 +61,8 @@ private: String8 mUri; HTTPStream mHTTP; - off_t mOffset; - off_t mContentLength; + off64_t mOffset; + off64_t mContentLength; bool mContentLengthValid; bool mHasChunkedTransferEncoding; @@ -79,12 +79,12 @@ private: DrmManagerClient *mDrmManagerClient; status_t connect( - const char *uri, const String8 &headers, off_t offset); + const char *uri, const String8 &headers, off64_t offset); status_t connect( const char *host, unsigned port, const char *path, const String8 &headers, - off_t offset); + off64_t offset); // Read up to "size" bytes of data, respect transfer encoding. ssize_t internalRead(void *data, size_t size); diff --git a/media/libstagefright/include/SampleIterator.h b/media/libstagefright/include/SampleIterator.h index a5eaed9..b5a043c 100644 --- a/media/libstagefright/include/SampleIterator.h +++ b/media/libstagefright/include/SampleIterator.h @@ -27,7 +27,7 @@ struct SampleIterator { uint32_t getChunkIndex() const { return mCurrentChunkIndex; } uint32_t getDescIndex() const { return mChunkDesc; } - off_t getSampleOffset() const { return mCurrentSampleOffset; } + off64_t getSampleOffset() const { return mCurrentSampleOffset; } size_t getSampleSize() const { return mCurrentSampleSize; } uint32_t getSampleTime() const { return mCurrentSampleTime; } @@ -48,7 +48,7 @@ private: uint32_t mChunkDesc; uint32_t mCurrentChunkIndex; - off_t mCurrentChunkOffset; + off64_t mCurrentChunkOffset; Vector<size_t> mCurrentChunkSampleSizes; uint32_t mTimeToSampleIndex; @@ -58,13 +58,13 @@ private: uint32_t mTTSDuration; uint32_t mCurrentSampleIndex; - off_t mCurrentSampleOffset; + off64_t mCurrentSampleOffset; size_t mCurrentSampleSize; uint32_t mCurrentSampleTime; void reset(); status_t findChunkRange(uint32_t sampleIndex); - status_t getChunkOffset(uint32_t chunk, off_t *offset); + status_t getChunkOffset(uint32_t chunk, off64_t *offset); status_t findSampleTime(uint32_t sampleIndex, uint32_t *time); SampleIterator(const SampleIterator &); diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h index f830690..c5e8136 100644 --- a/media/libstagefright/include/SampleTable.h +++ b/media/libstagefright/include/SampleTable.h @@ -36,17 +36,17 @@ public: // type can be 'stco' or 'co64'. status_t setChunkOffsetParams( - uint32_t type, off_t data_offset, size_t data_size); + uint32_t type, off64_t data_offset, size_t data_size); - status_t setSampleToChunkParams(off_t data_offset, size_t data_size); + status_t setSampleToChunkParams(off64_t data_offset, size_t data_size); // type can be 'stsz' or 'stz2'. status_t setSampleSizeParams( - uint32_t type, off_t data_offset, size_t data_size); + uint32_t type, off64_t data_offset, size_t data_size); - status_t setTimeToSampleParams(off_t data_offset, size_t data_size); + status_t setTimeToSampleParams(off64_t data_offset, size_t data_size); - status_t setSyncSampleParams(off_t data_offset, size_t data_size); + status_t setSyncSampleParams(off64_t data_offset, size_t data_size); //////////////////////////////////////////////////////////////////////////// @@ -58,7 +58,7 @@ public: status_t getMetaDataForSample( uint32_t sampleIndex, - off_t *offset, + off64_t *offset, size_t *size, uint32_t *decodingTime, bool *isSyncSample = NULL); @@ -89,14 +89,14 @@ private: sp<DataSource> mDataSource; Mutex mLock; - off_t mChunkOffsetOffset; + off64_t mChunkOffsetOffset; uint32_t mChunkOffsetType; uint32_t mNumChunkOffsets; - off_t mSampleToChunkOffset; + off64_t mSampleToChunkOffset; uint32_t mNumSampleToChunkOffsets; - off_t mSampleSizeOffset; + off64_t mSampleSizeOffset; uint32_t mSampleSizeFieldSize; uint32_t mDefaultSampleSize; uint32_t mNumSampleSizes; @@ -104,7 +104,7 @@ private: uint32_t mTimeToSampleCount; uint32_t *mTimeToSample; - off_t mSyncSampleOffset; + off64_t mSyncSampleOffset; uint32_t mNumSyncSamples; uint32_t *mSyncSamples; size_t mLastSyncSampleIndex; diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h index 9cafc68..90d3fe1 100644 --- a/media/libstagefright/include/SoftwareRenderer.h +++ b/media/libstagefright/include/SoftwareRenderer.h @@ -23,16 +23,13 @@ namespace android { +struct MetaData; class Surface; class SoftwareRenderer { public: SoftwareRenderer( - OMX_COLOR_FORMATTYPE colorFormat, - const sp<Surface> &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight, - int32_t rotationDegrees); + const sp<Surface> &surface, const sp<MetaData> &meta); ~SoftwareRenderer(); @@ -42,16 +39,14 @@ public: private: enum YUVMode { None, - YUV420ToYUV420sp, - YUV420spToYUV420sp, }; OMX_COLOR_FORMATTYPE mColorFormat; ColorConverter *mConverter; YUVMode mYUVMode; sp<Surface> mSurface; - size_t mDisplayWidth, mDisplayHeight; - size_t mDecodedWidth, mDecodedHeight; + int32_t mWidth, mHeight; + int32_t mCropLeft, mCropTop, mCropRight, mCropBottom; SoftwareRenderer(const SoftwareRenderer &); SoftwareRenderer &operator=(const SoftwareRenderer &); diff --git a/media/libstagefright/include/ThrottledSource.h b/media/libstagefright/include/ThrottledSource.h index 88164b3..8928a4a 100644 --- a/media/libstagefright/include/ThrottledSource.h +++ b/media/libstagefright/include/ThrottledSource.h @@ -30,9 +30,9 @@ struct ThrottledSource : public DataSource { virtual status_t initCheck() const; - virtual ssize_t readAt(off_t offset, void *data, size_t size); + virtual ssize_t readAt(off64_t offset, void *data, size_t size); - virtual status_t getSize(off_t *size); + virtual status_t getSize(off64_t *size); virtual uint32_t flags(); private: diff --git a/media/libstagefright/include/VBRISeeker.h b/media/libstagefright/include/VBRISeeker.h index d6bd19d..1a2bf9f 100644 --- a/media/libstagefright/include/VBRISeeker.h +++ b/media/libstagefright/include/VBRISeeker.h @@ -28,13 +28,13 @@ struct DataSource; struct VBRISeeker : public MP3Seeker { static sp<VBRISeeker> CreateFromSource( - const sp<DataSource> &source, off_t post_id3_pos); + const sp<DataSource> &source, off64_t post_id3_pos); virtual bool getDuration(int64_t *durationUs); - virtual bool getOffsetForTime(int64_t *timeUs, off_t *pos); + virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos); private: - off_t mBasePos; + off64_t mBasePos; int64_t mDurationUs; Vector<uint32_t> mSegments; diff --git a/media/libstagefright/include/WAVExtractor.h b/media/libstagefright/include/WAVExtractor.h index df6d3e7..9de197f 100644 --- a/media/libstagefright/include/WAVExtractor.h +++ b/media/libstagefright/include/WAVExtractor.h @@ -48,7 +48,7 @@ private: uint16_t mNumChannels; uint32_t mSampleRate; uint16_t mBitsPerSample; - off_t mDataOffset; + off64_t mDataOffset; size_t mDataSize; sp<MetaData> mTrackMeta; diff --git a/media/libstagefright/include/XINGSeeker.h b/media/libstagefright/include/XINGSeeker.h index d4ff4e1..d5a484e 100644 --- a/media/libstagefright/include/XINGSeeker.h +++ b/media/libstagefright/include/XINGSeeker.h @@ -26,10 +26,10 @@ struct DataSource; struct XINGSeeker : public MP3Seeker { static sp<XINGSeeker> CreateFromSource( - const sp<DataSource> &source, off_t first_frame_pos); + const sp<DataSource> &source, off64_t first_frame_pos); virtual bool getDuration(int64_t *durationUs); - virtual bool getOffsetForTime(int64_t *timeUs, off_t *pos); + virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos); private: int64_t mFirstFramePos; diff --git a/media/libstagefright/include/stagefright_string.h b/media/libstagefright/include/stagefright_string.h deleted file mode 100644 index 5dc7116..0000000 --- a/media/libstagefright/include/stagefright_string.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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. - */ - -#ifndef STRING_H_ - -#define STRING_H_ - -#include <utils/String8.h> - -namespace android { - -class string { -public: - typedef size_t size_type; - static size_type npos; - - string(); - string(const char *s); - string(const char *s, size_t length); - string(const string &from, size_type start, size_type length = npos); - - const char *c_str() const; - size_type size() const; - - void clear(); - void erase(size_type from, size_type length); - - size_type find(char c) const; - - bool operator<(const string &other) const; - bool operator==(const string &other) const; - - string &operator+=(char c); - -private: - String8 mString; -}; - -} // namespace android - -#endif // STRING_H_ diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index a40c0a3..e0ac49f 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -58,7 +58,7 @@ struct DataSourceReader : public mkvparser::IMkvReader { } virtual int Length(long long* total, long long* available) { - off_t size; + off64_t size; if (mSource->getSize(&size) != OK) { return -1; } diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk index ead1675..6e069c8 100644 --- a/media/libstagefright/omx/Android.mk +++ b/media/libstagefright/omx/Android.mk @@ -31,7 +31,6 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libui \ libcutils \ - libstagefright_color_conversion ifneq ($(BUILD_WITHOUT_PV),true) LOCAL_SHARED_LIBRARIES += \ diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp index 155fd96..5a033e1 100644 --- a/media/libstagefright/rtsp/ARTPWriter.cpp +++ b/media/libstagefright/rtsp/ARTPWriter.cpp @@ -46,7 +46,7 @@ static int UniformRand(int limit) { ARTPWriter::ARTPWriter(int fd) : mFlags(0), - mFd(fd), + mFd(dup(fd)), mLooper(new ALooper), mReflector(new AHandlerReflector<ARTPWriter>(this)) { CHECK_GE(fd, 0); diff --git a/media/libstagefright/string.cpp b/media/libstagefright/string.cpp deleted file mode 100644 index 8b2c36c..0000000 --- a/media/libstagefright/string.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. - */ - -#include "include/stagefright_string.h" - -#include <media/stagefright/MediaDebug.h> - -namespace android { - -// static -string::size_type string::npos = (string::size_type)-1; - -string::string() { -} - -string::string(const char *s, size_t length) - : mString(s, length) { -} - -string::string(const string &from, size_type start, size_type length) { - CHECK(start <= from.size()); - if (length == npos) { - length = from.size() - start; - } else { - CHECK(start + length <= from.size()); - } - - mString.setTo(from.c_str() + start, length); -} - -string::string(const char *s) - : mString(s) { -} - -const char *string::c_str() const { - return mString.string(); -} - -string::size_type string::size() const { - return mString.length(); -} - -void string::clear() { - mString = String8(); -} - -string::size_type string::find(char c) const { - char s[2]; - s[0] = c; - s[1] = '\0'; - - ssize_t index = mString.find(s); - - return index < 0 ? npos : (size_type)index; -} - -bool string::operator<(const string &other) const { - return mString < other.mString; -} - -bool string::operator==(const string &other) const { - return mString == other.mString; -} - -string &string::operator+=(char c) { - mString.append(&c, 1); - - return *this; -} - -void string::erase(size_t from, size_t length) { - String8 s(mString.string(), from); - s.append(mString.string() + from + length); - - mString = s; -} - -} // namespace android - diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp index 20dd94d..e1d1a92 100644 --- a/media/mtp/MtpDataPacket.cpp +++ b/media/mtp/MtpDataPacket.cpp @@ -413,20 +413,32 @@ int MtpDataPacket::read(struct usb_endpoint *ep) { } int MtpDataPacket::readData(struct usb_endpoint *ep, void* buffer, int length) { - int packetSize = usb_endpoint_max_packet(ep); int read = 0; while (read < length) { - int ret = transfer(ep, (char *)buffer + read, packetSize); + int ret = transfer(ep, (char *)buffer + read, length - read); if (ret < 0) { -printf("MtpDataPacket::readData returning %d\n", ret); return ret; } read += ret; } -printf("MtpDataPacket::readData returning %d\n", read); return read; } +// Queue a read request. Call readDataWait to wait for result +int MtpDataPacket::readDataAsync(struct usb_endpoint *ep, void* buffer, int length) { + if (usb_endpoint_queue(ep, buffer, length)) { + LOGE("usb_endpoint_queue failed, errno: %d", errno); + return -1; + } + return 0; +} + +// Wait for result of readDataAsync +int MtpDataPacket::readDataWait(struct usb_endpoint *ep) { + int ep_num; + return usb_endpoint_wait(usb_endpoint_get_device(ep), &ep_num); +} + int MtpDataPacket::readDataHeader(struct usb_endpoint *ep) { int length = transfer(ep, mBuffer, usb_endpoint_max_packet(ep)); if (length >= 0) @@ -454,15 +466,7 @@ int MtpDataPacket::write(struct usb_endpoint *ep) { } int MtpDataPacket::write(struct usb_endpoint *ep, void* buffer, uint32_t length) { - int ret = 0; - int packetSize = usb_endpoint_max_packet(ep); - while (length > 0) { - int write = (length > packetSize ? packetSize : length); - int ret = transfer(ep, buffer, write); - if (ret < 0) - break; - length -= ret; - } + int ret = transfer(ep, buffer, length); return (ret < 0 ? ret : 0); } diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h index fab6a07..3ae6226 100644 --- a/media/mtp/MtpDataPacket.h +++ b/media/mtp/MtpDataPacket.h @@ -102,6 +102,8 @@ public: #ifdef MTP_HOST int read(struct usb_endpoint *ep); int readData(struct usb_endpoint *ep, void* buffer, int length); + int readDataAsync(struct usb_endpoint *ep, void* buffer, int length); + int readDataWait(struct usb_endpoint *ep); int readDataHeader(struct usb_endpoint *ep); int writeDataHeader(struct usb_endpoint *ep, uint32_t length); @@ -110,6 +112,7 @@ public: #endif inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; } + inline uint32_t getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); } void* getData(int& outLength) const; }; diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp index fca0142..416ebfe 100644 --- a/media/mtp/MtpDevice.cpp +++ b/media/mtp/MtpDevice.cpp @@ -348,97 +348,96 @@ MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) { return NULL; } -class ReadObjectThread : public Thread { -private: - MtpDevice* mDevice; - MtpObjectHandle mHandle; - int mObjectSize; - void* mInitialData; - int mInitialDataLength; - int mFD; - -public: - ReadObjectThread(MtpDevice* device, MtpObjectHandle handle, int objectSize) - : mDevice(device), - mHandle(handle), - mObjectSize(objectSize), - mInitialData(NULL), - mInitialDataLength(0) - { +// reads the object's data and writes it to the specified file path +bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) { + LOGD("readObject: %s", destPath); + int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC); + if (fd < 0) { + LOGE("open failed for %s", destPath); + return false; } - virtual ~ReadObjectThread() { - if (mFD >= 0) - close(mFD); - free(mInitialData); - } + fchown(fd, getuid(), group); + // set permissions + int mask = umask(0); + fchmod(fd, perm); + umask(mask); - // returns file descriptor - int init() { - mDevice->mRequest.reset(); - mDevice->mRequest.setParameter(1, mHandle); - if (mDevice->sendRequest(MTP_OPERATION_GET_OBJECT) - && mDevice->mData.readDataHeader(mDevice->mEndpointIn)) { - - // mData will contain header and possibly the beginning of the object data - mInitialData = mDevice->mData.getData(mInitialDataLength); - - // create a pipe for the client to read from - int pipefd[2]; - if (pipe(pipefd) < 0) { - LOGE("pipe failed (%s)", strerror(errno)); - return -1; - } - - mFD = pipefd[1]; - return pipefd[0]; - } else { - return -1; - } - } + Mutex::Autolock autoLock(mMutex); + bool result = false; - virtual bool threadLoop() { - int remaining = mObjectSize; - if (mInitialData) { - write(mFD, mInitialData, mInitialDataLength); - remaining -= mInitialDataLength; - free(mInitialData); - mInitialData = NULL; + mRequest.reset(); + mRequest.setParameter(1, handle); + if (sendRequest(MTP_OPERATION_GET_OBJECT) + && mData.readDataHeader(mEndpointIn)) { + uint32_t length = mData.getContainerLength(); + if (length < MTP_CONTAINER_HEADER_SIZE) + goto fail; + length -= MTP_CONTAINER_HEADER_SIZE; + uint32_t remaining = length; + + int initialDataLength = 0; + void* initialData = mData.getData(initialDataLength); + if (initialData) { + if (initialDataLength > 0) { + if (write(fd, initialData, initialDataLength) != initialDataLength) + goto fail; + remaining -= initialDataLength; + } + free(initialData); } - char buffer[16384]; - while (remaining > 0) { - int readSize = (remaining > sizeof(buffer) ? sizeof(buffer) : remaining); - int count = mDevice->mData.readData(mDevice->mEndpointIn, buffer, readSize); - int written; - if (count >= 0) { - int written = write(mFD, buffer, count); - // FIXME check error - remaining -= count; + // USB reads greater than 16K don't work + char buffer1[16384], buffer2[16384]; + char* readBuffer = buffer1; + char* writeBuffer = NULL; + int writeLength = 0; + + while (remaining > 0 || writeBuffer) { + if (remaining > 0) { + // queue up a read request + int readSize = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); + if (mData.readDataAsync(mEndpointIn, readBuffer, readSize)) { + LOGE("readDataAsync failed"); + goto fail; + } } else { - break; + readBuffer = NULL; } - } - MtpResponseCode ret = mDevice->readResponse(); - mDevice->mMutex.unlock(); - return false; - } -}; + if (writeBuffer) { + // write previous buffer + if (write(fd, writeBuffer, writeLength) != writeLength) { + LOGE("write failed"); + // wait for pending read before failing + if (readBuffer) + mData.readDataWait(mEndpointIn); + goto fail; + } + writeBuffer = NULL; + } - // returns the file descriptor for a pipe to read the object's data -int MtpDevice::readObject(MtpObjectHandle handle, int objectSize) { - mMutex.lock(); + // wait for read to complete + if (readBuffer) { + int read = mData.readDataWait(mEndpointIn); + if (read < 0) + goto fail; - ReadObjectThread* thread = new ReadObjectThread(this, handle, objectSize); - int fd = thread->init(); - if (fd < 0) { - delete thread; - mMutex.unlock(); - } else { - thread->run("ReadObjectThread"); + writeBuffer = readBuffer; + writeLength = read; + remaining -= read; + readBuffer = (readBuffer == buffer1 ? buffer2 : buffer1); + } + } + + MtpResponseCode response = readResponse(); + if (response == MTP_RESPONSE_OK) + result = true; } - return fd; + +fail: + ::close(fd); + return result; } bool MtpDevice::sendRequest(MtpOperationCode operation) { diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h index 57f492f..21c85d5 100644 --- a/media/mtp/MtpDevice.h +++ b/media/mtp/MtpDevice.h @@ -75,7 +75,8 @@ public: MtpDeviceInfo* getDeviceInfo(); MtpStorageIDList* getStorageIDs(); MtpStorageInfo* getStorageInfo(MtpStorageID storageID); - MtpObjectHandleList* getObjectHandles(MtpStorageID storageID, MtpObjectFormat format, MtpObjectHandle parent); + MtpObjectHandleList* getObjectHandles(MtpStorageID storageID, MtpObjectFormat format, + MtpObjectHandle parent); MtpObjectInfo* getObjectInfo(MtpObjectHandle handle); void* getThumbnail(MtpObjectHandle handle, int& outLength); MtpObjectHandle sendObjectInfo(MtpObjectInfo* info); @@ -86,12 +87,10 @@ public: MtpProperty* getDevicePropDesc(MtpDeviceProperty code); - // returns the file descriptor for a pipe to read the object's data - int readObject(MtpObjectHandle handle, int objectSize); + bool readObject(MtpObjectHandle handle, const char* destPath, int group, + int perm); private: - friend class ReadObjectThread; - bool sendRequest(MtpOperationCode operation); bool sendData(); bool readData(); diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk index 1d81129..295b3e6 100644 --- a/media/tests/CameraBrowser/Android.mk +++ b/media/tests/CameraBrowser/Android.mk @@ -1,7 +1,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) diff --git a/media/tests/CameraBrowser/AndroidManifest.xml b/media/tests/CameraBrowser/AndroidManifest.xml index eae0b01..db4a336 100644 --- a/media/tests/CameraBrowser/AndroidManifest.xml +++ b/media/tests/CameraBrowser/AndroidManifest.xml @@ -1,8 +1,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.camerabrowser"> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <application android:label="@string/app_label"> <activity android:name="CameraBrowser" android:label="Camera Browser"> <intent-filter> diff --git a/media/tests/CameraBrowser/res/layout/object_info.xml b/media/tests/CameraBrowser/res/layout/object_info.xml index ac210b9..a0499f2 100644 --- a/media/tests/CameraBrowser/res/layout/object_info.xml +++ b/media/tests/CameraBrowser/res/layout/object_info.xml @@ -153,5 +153,17 @@ <TableRow> <ImageView android:id="@+id/thumbnail" /> </TableRow> + <TableRow> + <Button android:id="@+id/import_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/import_label"> + </Button> + <Button android:id="@+id/delete_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/delete_label"> + </Button> + </TableRow> </TableLayout> diff --git a/media/tests/CameraBrowser/res/values/strings.xml b/media/tests/CameraBrowser/res/values/strings.xml index cd477f1..7955773 100644 --- a/media/tests/CameraBrowser/res/values/strings.xml +++ b/media/tests/CameraBrowser/res/values/strings.xml @@ -32,9 +32,9 @@ <string name="modified_label">Modified: </string> <string name="keywords_label">Keywords: </string> - <!-- menu items --> - <string name="save_item">Save</string> - <string name="delete_item">Delete</string> + <!-- button labels --> + <string name="import_label">Import</string> + <string name="delete_label">Delete</string> <!-- toasts --> <string name="object_saved_message">Object saved</string> diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java new file mode 100644 index 0000000..fb004c4 --- /dev/null +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 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.camerabrowser; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.Usb; +import android.net.Uri; + +public class DeviceDisconnectedReceiver extends BroadcastReceiver { + + private final Activity mActivity; + private final int mDeviceID; + + public DeviceDisconnectedReceiver(Activity activity, int deviceID) { + mActivity = activity; + mDeviceID = deviceID; + + IntentFilter filter = new IntentFilter(Usb.ACTION_USB_CAMERA_DETACHED); + filter.addDataScheme("content"); + activity.registerReceiver(this, filter); + } + + @Override + public void onReceive(Context context, Intent intent) { + // close our activity if the device it is displaying is disconnected + Uri uri = intent.getData(); + int id = Integer.parseInt(uri.getPathSegments().get(1)); + if (id == mDeviceID) { + mActivity.finish(); + } + } +}
\ No newline at end of file diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java index 6d34fd4..2060657 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java @@ -46,6 +46,7 @@ public class ObjectBrowser extends ListActivity { private int mDeviceID; private long mStorageID; private long mObjectID; + private DeviceDisconnectedReceiver mDisconnectedReceiver; private static final String[] OBJECT_COLUMNS = new String[] { Mtp.Object._ID, Mtp.Object.NAME, Mtp.Object.FORMAT, Mtp.Object.THUMB }; @@ -58,15 +59,17 @@ public class ObjectBrowser extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + mDeviceID = getIntent().getIntExtra("device", 0); + mStorageID = getIntent().getLongExtra("storage", 0); + mObjectID = getIntent().getLongExtra("object", 0); + mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceID); } @Override protected void onResume() { super.onResume(); - mDeviceID = getIntent().getIntExtra("device", 0); - mStorageID = getIntent().getLongExtra("storage", 0); - mObjectID = getIntent().getLongExtra("object", 0); if (mDeviceID != 0 && mStorageID != 0) { Cursor c; Uri uri; @@ -87,6 +90,12 @@ public class ObjectBrowser extends ListActivity { } @Override + protected void onDestroy() { + unregisterReceiver(mDisconnectedReceiver); + super.onDestroy(); + } + + @Override protected void onListItemClick(ListView l, View v, int position, long id) { long rowID = mAdapter.getItemId(position); Cursor c = getContentResolver().query( diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java index 9f2f98e..4e63128 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java @@ -16,6 +16,7 @@ package com.android.camerabrowser; import android.app.Activity; +import android.content.ContentValues; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; @@ -23,36 +24,31 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; -import android.os.FileUtils; -import android.os.ParcelFileDescriptor; -import android.os.Process; import android.provider.Mtp; import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; +import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.util.Calendar; import java.util.Date; /** * A view to display the properties of an object. */ -public class ObjectViewer extends Activity { +public class ObjectViewer extends Activity implements View.OnClickListener { private static final String TAG = "ObjectViewer"; private int mDeviceID; private long mStorageID; private long mObjectID; + private String mFileName; + private Button mImportButton; + private Button mDeleteButton; + private DeviceDisconnectedReceiver mDisconnectedReceiver; private static final String[] OBJECT_COLUMNS = new String[] { Mtp.Object._ID, @@ -77,15 +73,21 @@ public class ObjectViewer extends Activity { super.onCreate(savedInstanceState); setContentView(R.layout.object_info); - } - @Override - protected void onResume() { - super.onResume(); + mImportButton = (Button)findViewById(R.id.import_button); + mImportButton.setOnClickListener(this); + mDeleteButton = (Button)findViewById(R.id.delete_button); + mDeleteButton.setOnClickListener(this); mDeviceID = getIntent().getIntExtra("device", 0); mStorageID = getIntent().getLongExtra("storage", 0); mObjectID = getIntent().getLongExtra("object", 0); + mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceID); + } + + @Override + protected void onResume() { + super.onResume(); if (mDeviceID != 0 && mObjectID != 0) { Cursor c = getContentResolver().query( @@ -93,7 +95,8 @@ public class ObjectViewer extends Activity { OBJECT_COLUMNS, null, null, null); c.moveToFirst(); TextView view = (TextView)findViewById(R.id.name); - view.setText(c.getString(1)); + mFileName = c.getString(1); + view.setText(mFileName); view = (TextView)findViewById(R.id.size); view.setText(Long.toString(c.getLong(2))); view = (TextView)findViewById(R.id.thumb_width); @@ -132,113 +135,33 @@ public class ObjectViewer extends Activity { } @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.object_menu, menu); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem item = menu.findItem(R.id.save); - item.setEnabled(true); - item = menu.findItem(R.id.delete); - item.setEnabled(true); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.save: - save(); - return true; - case R.id.delete: - delete(); - return true; - } - return false; - } - - private static String getTimestamp() { - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(System.currentTimeMillis()); - return String.format("%tY-%tm-%td-%tH-%tM-%tS", c, c, c, c, c, c); + protected void onDestroy() { + unregisterReceiver(mDisconnectedReceiver); + super.onDestroy(); } - private void save() { - boolean success = false; - Uri uri = Mtp.Object.getContentUri(mDeviceID, mObjectID); - File destFile = null; - ParcelFileDescriptor pfd = null; - FileInputStream fis = null; - FileOutputStream fos = null; - - try { - pfd = getContentResolver().openFileDescriptor(uri, "r"); - Log.d(TAG, "save got pfd " + pfd); - if (pfd != null) { - fis = new FileInputStream(pfd.getFileDescriptor()); - Log.d(TAG, "save got fis " + fis); - File destDir = Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DCIM); - destDir.mkdirs(); - destFile = new File(destDir, "CameraBrowser-" + getTimestamp() + ".jpeg"); - - - Log.d(TAG, "save got destFile " + destFile); - - if (destFile.exists()) { - destFile.delete(); - } - fos = new FileOutputStream(destFile); - - byte[] buffer = new byte[65536]; - int bytesRead; - while ((bytesRead = fis.read(buffer)) >= 0) { - fos.write(buffer, 0, bytesRead); - } + private void importObject() { + // copy file to /mnt/sdcard/imported/<filename> + File dest = Environment.getExternalStorageDirectory(); + dest = new File(dest, "imported"); + dest.mkdirs(); + dest = new File(dest, mFileName); - // temporary workaround until we straighten out permissions in /data/media - FileUtils.setPermissions(destDir.getPath(), 0775, Process.myUid(), Process.SDCARD_RW_GID); - FileUtils.setPermissions(destFile.getPath(), 0664, Process.myUid(), Process.SDCARD_RW_GID); + Uri requestUri = Mtp.Object.getContentUriForImport(mDeviceID, mObjectID, + dest.getAbsolutePath()); + Uri resultUri = getContentResolver().insert(requestUri, new ContentValues()); + Log.d(TAG, "save returned " + resultUri); - success = true; - } - } catch (Exception e) { - Log.e(TAG, "Exception in ObjectView.save", e); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (Exception e) { - } - } - if (fos != null) { - try { - fos.close(); - } catch (Exception e) { - } - } - if (pfd != null) { - try { - pfd.close(); - } catch (Exception e) { - } - } - } - - if (success) { - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(Uri.fromFile(destFile)); - sendBroadcast(intent); + if (resultUri != null) { Toast.makeText(this, R.string.object_saved_message, Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(Intent.ACTION_VIEW, resultUri); + startActivity(intent); } else { Toast.makeText(this, R.string.save_failed_message, Toast.LENGTH_SHORT).show(); } } - private void delete() { + private void deleteObject() { Uri uri = Mtp.Object.getContentUri(mDeviceID, mObjectID); Log.d(TAG, "deleting " + uri); @@ -251,4 +174,12 @@ public class ObjectViewer extends Activity { Toast.makeText(this, R.string.delete_failed_message, Toast.LENGTH_SHORT).show(); } } + + public void onClick(View v) { + if (v == mImportButton) { + importObject(); + } else if (v == mDeleteButton) { + deleteObject(); + } + } } diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java index 63e036e..4da88d6 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java @@ -37,6 +37,7 @@ public class StorageBrowser extends ListActivity { private ListAdapter mAdapter; private int mDeviceID; + private DeviceDisconnectedReceiver mDisconnectedReceiver; private static final String[] STORAGE_COLUMNS = new String[] { Mtp.Storage._ID, Mtp.Storage.DESCRIPTION }; @@ -44,13 +45,14 @@ public class StorageBrowser extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mDeviceID = getIntent().getIntExtra("device", 0); + mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceID); } @Override protected void onResume() { super.onResume(); - mDeviceID = getIntent().getIntExtra("device", 0); if (mDeviceID != 0) { Cursor c = getContentResolver().query(Mtp.Storage.getContentUri(mDeviceID), STORAGE_COLUMNS, null, null, null); @@ -67,6 +69,12 @@ public class StorageBrowser extends ListActivity { } @Override + protected void onDestroy() { + unregisterReceiver(mDisconnectedReceiver); + super.onDestroy(); + } + + @Override protected void onListItemClick(ListView l, View v, int position, long id) { Intent intent = new Intent(this, ObjectBrowser.class); intent.putExtra("device", mDeviceID); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java index 032b469..fd1c2d3 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java @@ -45,11 +45,11 @@ public class MediaPlayerGetCurrentPositionStateUnitTest extends AndroidTestCase assertTrue(!stateErrors.errorInPausedState); assertTrue(!stateErrors.errorInStoppedState); assertTrue(!stateErrors.errorInPlaybackCompletedState); - assertTrue(!stateErrors.errorInIdleStateAfterReset); // Invalid states. assertTrue(stateErrors.errorInErrorState); - assertTrue(!stateErrors.errorInIdleState); // onError() won't be called + assertTrue(stateErrors.errorInIdleStateAfterReset); + assertTrue(stateErrors.errorInIdleState); } public void invokeMethodUnderTest(MediaPlayer player) { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetDurationStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetDurationStateUnitTest.java index 5f7abe5..48fd16c 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetDurationStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetDurationStateUnitTest.java @@ -46,10 +46,10 @@ public class MediaPlayerGetDurationStateUnitTest extends AndroidTestCase impleme assertTrue(!stateErrors.errorInPlaybackCompletedState); // Invalid states. - assertTrue(!stateErrors.errorInIdleState); // onError() won't be called assertTrue(stateErrors.errorInInitializedState); assertTrue(stateErrors.errorInErrorState); assertTrue(stateErrors.errorInIdleStateAfterReset); + assertTrue(stateErrors.errorInIdleState); } public void invokeMethodUnderTest(MediaPlayer player) { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerPauseStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerPauseStateUnitTest.java index 0a18a39..7a96792 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerPauseStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerPauseStateUnitTest.java @@ -29,9 +29,9 @@ public class MediaPlayerPauseStateUnitTest extends AndroidTestCase implements Me /** * 1. It is valid to call pause() in the following states: - * {Started, Paused}. + * {Started, Paused, PlaybackCompleted}. * 2. It is invalid to call pause() in the following states: - * {Idle, Initialized, Prepared, Stopped, PlaybackCompleted, Error} + * {Idle, Initialized, Prepared, Stopped, Error} * * @param stateErrors the MediaPlayerStateErrors to check against. */ @@ -40,12 +40,12 @@ public class MediaPlayerPauseStateUnitTest extends AndroidTestCase implements Me assertTrue(!stateErrors.errorInStartedState); assertTrue(!stateErrors.errorInStartedStateAfterPause); assertTrue(!stateErrors.errorInPausedState); + assertTrue(!stateErrors.errorInPlaybackCompletedState); // Invalid states. assertTrue(stateErrors.errorInPreparedState); assertTrue(stateErrors.errorInPreparedStateAfterStop); - assertTrue(stateErrors.errorInPlaybackCompletedState); - assertTrue(!stateErrors.errorInIdleState); // noError() won't be called + assertTrue(stateErrors.errorInIdleState); assertTrue(stateErrors.errorInIdleStateAfterReset); assertTrue(stateErrors.errorInInitializedState); assertTrue(stateErrors.errorInStoppedState); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSeekToStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSeekToStateUnitTest.java index 46bba9b..991fe9c 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSeekToStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSeekToStateUnitTest.java @@ -39,17 +39,17 @@ public class MediaPlayerSeekToStateUnitTest extends AndroidTestCase implements M // Valid states. assertTrue(!stateErrors.errorInPreparedState); assertTrue(!stateErrors.errorInPreparedStateAfterStop); - assertTrue(!stateErrors.errorInStartedState); assertTrue(!stateErrors.errorInStartedStateAfterPause); assertTrue(!stateErrors.errorInPausedState); assertTrue(!stateErrors.errorInPlaybackCompletedState); // Invalid states. - assertTrue(!stateErrors.errorInIdleState); // onError() won't be called + assertTrue(stateErrors.errorInIdleState); assertTrue(stateErrors.errorInIdleStateAfterReset); assertTrue(stateErrors.errorInInitializedState); assertTrue(stateErrors.errorInStoppedState); assertTrue(stateErrors.errorInErrorState); + assertTrue(!stateErrors.errorInStartedState); } public void invokeMethodUnderTest(MediaPlayer player) { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetAudioStreamTypeStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetAudioStreamTypeStateUnitTest.java index 3153792..b984514 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetAudioStreamTypeStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetAudioStreamTypeStateUnitTest.java @@ -58,7 +58,7 @@ public class MediaPlayerSetAudioStreamTypeStateUnitTest extends AndroidTestCase } @LargeTest - public void testSetAudioSystemType() { + public void testSetAudioStreamType() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStartStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStartStateUnitTest.java index 6debbb4..68c8e42 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStartStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStartStateUnitTest.java @@ -45,7 +45,7 @@ public class MediaPlayerStartStateUnitTest extends AndroidTestCase implements Me assertTrue(!stateErrors.errorInPlaybackCompletedState); // Invalid states. - assertTrue(!stateErrors.errorInIdleState); // onError() won't be called + assertTrue(stateErrors.errorInIdleState); assertTrue(stateErrors.errorInErrorState); assertTrue(stateErrors.errorInIdleStateAfterReset); assertTrue(stateErrors.errorInInitializedState); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStopStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStopStateUnitTest.java index 3427f86..ab8519a 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStopStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStopStateUnitTest.java @@ -46,7 +46,7 @@ public class MediaPlayerStopStateUnitTest extends AndroidTestCase implements Med assertTrue(!stateErrors.errorInPausedState); // Invalid states. - assertTrue(!stateErrors.errorInIdleState); // noError() won't be called + assertTrue(stateErrors.errorInIdleState); assertTrue(stateErrors.errorInIdleStateAfterReset); assertTrue(stateErrors.errorInInitializedState); assertTrue(stateErrors.errorInErrorState); diff --git a/media/tests/mtp/Android.mk b/media/tests/mtp/Android.mk deleted file mode 100644 index a9074ed..0000000 --- a/media/tests/mtp/Android.mk +++ /dev/null @@ -1,61 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -ifneq ($(TARGET_SIMULATOR),true) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - mtp.cpp \ - MtpFile.cpp \ - -LOCAL_C_INCLUDES += \ - frameworks/base/media/mtp \ - -LOCAL_CFLAGS := -DMTP_HOST - -LOCAL_MODULE := mtp - -LOCAL_STATIC_LIBRARIES := libmtp libusbhost libutils libcutils - -include $(BUILD_EXECUTABLE) - -endif - -ifeq ($(HOST_OS),linux) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - mtp.cpp \ - MtpFile.cpp \ - ../../../libs/utils/RefBase.cpp \ - ../../../libs/utils/SharedBuffer.cpp \ - ../../../libs/utils/Threads.cpp \ - ../../../libs/utils/VectorImpl.cpp \ - -LOCAL_C_INCLUDES += \ - frameworks/base/media/mtp \ - -LOCAL_CFLAGS := -DMTP_HOST -g -O0 - -have_readline := $(wildcard /usr/include/readline/readline.h) -have_history := $(wildcard /usr/lib/libhistory*) -ifneq ($(strip $(have_readline)),) -LOCAL_CFLAGS += -DHAVE_READLINE=1 -endif - -LOCAL_LDLIBS += -lpthread -ifneq ($(strip $(have_readline)),) -LOCAL_LDLIBS += -lreadline -lncurses -endif -ifneq ($(strip $(have_history)),) -LOCAL_LDLIBS += -lhistory -endif - -LOCAL_MODULE := mtp - -LOCAL_STATIC_LIBRARIES := libmtp libusbhost libcutils - -include $(BUILD_HOST_EXECUTABLE) - -endif diff --git a/media/tests/mtp/MtpFile.cpp b/media/tests/mtp/MtpFile.cpp deleted file mode 100644 index 00d328e..0000000 --- a/media/tests/mtp/MtpFile.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#include "MtpClient.h" -#include "MtpDevice.h" -#include "MtpDeviceInfo.h" -#include "MtpObjectInfo.h" -#include "MtpStorage.h" -#include "MtpUtils.h" - -#include "MtpFile.h" - -namespace android { - -MtpClient* MtpFile::sClient = NULL; - -MtpFile::MtpFile(MtpDevice* device) - : mDevice(device), - mStorage(0), - mHandle(0) -{ -} - -MtpFile::MtpFile(MtpDevice* device, MtpStorageID storage) - : mDevice(device), - mStorage(storage), - mHandle(0) -{ -} - -MtpFile::MtpFile(MtpDevice* device, MtpStorageID storage, MtpObjectHandle handle) - : mDevice(device), - mStorage(storage), - mHandle(handle) -{ -} - -MtpFile::MtpFile(MtpFile* file) - : mDevice(file->mDevice), - mStorage(file->mStorage), - mHandle(file->mHandle) -{ -} - -MtpFile::~MtpFile() { -} - -void MtpFile::print() { - if (mHandle) { - - } else if (mStorage) { - printf("%x\n", mStorage); - } else { - int id = mDevice->getID(); - MtpDeviceInfo* info = mDevice->getDeviceInfo(); - if (info) - printf("%d\t%s %s %s\n", id, info->mManufacturer, info->mModel, info->mSerial); - else - printf("%d\t(no device info available)\n", id); - delete info; - } -} - -MtpObjectInfo* MtpFile::getObjectInfo() { - return mDevice->getObjectInfo(mHandle); -} - -void MtpFile::list() { - if (mStorage) { - MtpObjectHandleList* handles = mDevice->getObjectHandles(mStorage, 0, - (mHandle ? mHandle : -1)); - if (handles) { - for (int i = 0; i < handles->size(); i++) { - MtpObjectHandle handle = (*handles)[i]; - MtpObjectInfo* info = mDevice->getObjectInfo(handle); - if (info) { - char modified[100]; - struct tm tm; - - gmtime_r(&info->mDateModified, &tm); - strftime(modified, sizeof(modified), "%a %b %e %H:%M:%S GMT %Y", &tm); - printf("%s Handle: %d Format: %04X Size: %d Modified: %s\n", - info->mName, handle, info->mFormat, info->mCompressedSize, modified); - delete info; - } - } - delete handles; - } - } else { - // list storage units for device - MtpStorageIDList* storageList = mDevice->getStorageIDs(); - for (int i = 0; i < storageList->size(); i++) { - MtpStorageID storageID = (*storageList)[i]; - printf("%x\n", storageID); - } - } -} - -void MtpFile::init(MtpClient* client) { - sClient = client; -} - -MtpFile* MtpFile::parsePath(MtpFile* base, char* path) { - MtpDevice* device = NULL; - MtpStorageID storage = 0; - MtpObjectHandle handle = 0; - - if (path[0] != '/' && base) { - device = base->mDevice; - storage = base->mStorage; - handle = base->mHandle; - } - - // parse an absolute path - if (path[0] == '/') - path++; - char* tok = strtok(path, "/"); - while (tok) { - if (storage) { - // find child of current handle - MtpObjectHandleList* handles = device->getObjectHandles(storage, 0, - (handle ? handle : -1)); - MtpObjectHandle childHandle = 0; - - if (handles) { - for (int i = 0; i < handles->size() && !childHandle; i++) { - MtpObjectHandle handle = (*handles)[i]; - MtpObjectInfo* info = device->getObjectInfo(handle); - if (info && !strcmp(tok, info->mName)) - childHandle = handle; - delete info; - } - delete handles; - } - if (childHandle) - handle = childHandle; - else - return NULL; - } else if (device) { - unsigned int id; - // find storage for the device - if (sscanf(tok, "%x", &id) == 1) { - MtpStorageIDList* storageList = device->getStorageIDs(); - bool found = false; - for (int i = 0; i < storageList->size(); i++) { - if ((*storageList)[i] == id) { - found = true; - break; - } - } - if (found) - storage = id; - else - return NULL; - } - } else { - // find device - unsigned int id; - if (sscanf(tok, "%d", &id) == 1) - device = sClient->getDevice(id); - if (!device) - return NULL; - } - - tok = strtok(NULL, "/"); - } - - if (device) - return new MtpFile(device, storage, handle); - else - return NULL; -} - -} diff --git a/media/tests/mtp/MtpFile.h b/media/tests/mtp/MtpFile.h deleted file mode 100644 index ab8762b..0000000 --- a/media/tests/mtp/MtpFile.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 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 _MTP_FILE_H -#define _MTP_FILE_H - -#include "MtpTypes.h" - -namespace android { - -class MtpClient; -class MtpDevice; -class MtpObjectInfo; - -// File-like abstraction for the interactive shell. -// This can be used to represent an MTP device, storage unit or object -// (either file or association). -class MtpFile { -private: - MtpDevice* mDevice; - MtpStorageID mStorage; - MtpObjectHandle mHandle; - static MtpClient* sClient; - -public: - MtpFile(MtpDevice* device); - MtpFile(MtpDevice* device, MtpStorageID storage); - MtpFile(MtpDevice* device, MtpStorageID storage, MtpObjectHandle handle); - MtpFile(MtpFile* file); - virtual ~MtpFile(); - - MtpObjectInfo* getObjectInfo(); - void print(); - void list(); - - inline MtpDevice* getDevice() const { return mDevice; } - - static void init(MtpClient* client); - static MtpFile* parsePath(MtpFile* base, char* path); -}; - -} - -#endif // _MTP_DIRECTORY_H diff --git a/media/tests/mtp/mtp.cpp b/media/tests/mtp/mtp.cpp deleted file mode 100644 index 3202cae..0000000 --- a/media/tests/mtp/mtp.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#if HAVE_READLINE -#include <readline/readline.h> -#include <readline/history.h> -#endif - -#include "MtpClient.h" -#include "MtpDevice.h" -#include "MtpObjectInfo.h" - -#include "MtpFile.h" - -#define PROMPT "mtp> " - -using namespace android; - -static MtpClient* sClient = NULL; - -// current working directory information for interactive shell -static MtpFile* sCurrentDirectory = NULL; - -static MtpFile* parse_path(char* path) { - return MtpFile::parsePath(sCurrentDirectory, path); -} - -class MyClient : public MtpClient { -private: - virtual void deviceAdded(MtpDevice *device) { - } - - virtual void deviceRemoved(MtpDevice *device) { - } - -public: -}; - -static void init() { - sClient = new MyClient; - sClient->start(); - MtpFile::init(sClient); -} - -static int set_cwd(int argc, char* argv[]) { - if (argc != 1) { - fprintf(stderr, "cd should have one argument\n"); - return -1; - } - if (!strcmp(argv[0], "/")) { - delete sCurrentDirectory; - sCurrentDirectory = NULL; - } - else { - MtpFile* file = parse_path(argv[0]); - if (file) { - delete sCurrentDirectory; - sCurrentDirectory = file; - } else { - fprintf(stderr, "could not find %s\n", argv[0]); - return -1; - } - } - return 0; -} - -static void list_devices() { - // TODO - need to make sure the list will not change while iterating - MtpDeviceList& devices = sClient->getDeviceList(); - for (int i = 0; i < devices.size(); i++) { - MtpDevice* device = devices[i]; - MtpFile* file = new MtpFile(device); - file->print(); - delete file; - } -} - -static int list(int argc, char* argv[]) { - if (argc == 0) { - // list cwd - if (sCurrentDirectory) { - sCurrentDirectory->list(); - } else { - list_devices(); - } - } - - for (int i = 0; i < argc; i++) { - char* path = argv[i]; - if (!strcmp(path, "/")) { - list_devices(); - } else { - MtpFile* file = parse_path(path); - if (!file) { - fprintf(stderr, "could not find %s\n", path); - return -1; - } - file->list(); - } - } - - return 0; -} - -static int get_file(int argc, char* argv[]) { - int ret = -1; - int srcFD = -1; - int destFD = -1; - MtpFile* srcFile = NULL; - MtpObjectInfo* info = NULL; - char* dest; - - if (argc < 1) { - fprintf(stderr, "not enough arguments\n"); - return -1; - } else if (argc > 2) { - fprintf(stderr, "too many arguments\n"); - return -1; - } - - // find source object - char* src = argv[0]; - srcFile = parse_path(src); - if (!srcFile) { - fprintf(stderr, "could not find %s\n", src); - return -1; - } - info = srcFile->getObjectInfo(); - if (!info) { - fprintf(stderr, "could not find object info for %s\n", src); - goto fail; - } - if (info->mFormat == MTP_FORMAT_ASSOCIATION) { - fprintf(stderr, "copying directories not implemented yet\n"); - goto fail; - } - - dest = (argc > 1 ? argv[1] : info->mName); - destFD = open(dest, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (destFD < 0) { - fprintf(stderr, "could not create %s\n", dest); - goto fail; - } - srcFD = srcFile->getDevice()->readObject(info->mHandle, info->mCompressedSize); - if (srcFD < 0) - goto fail; - - char buffer[65536]; - while (1) { - int count = read(srcFD, buffer, sizeof(buffer)); - if (count <= 0) - break; - write(destFD, buffer, count); - } - // FIXME - error checking and reporting - ret = 0; - -fail: - delete srcFile; - delete info; - if (srcFD >= 0) - close(srcFD); - if (destFD >= 0) - close(destFD); - return ret; -} - -static int put_file(int argc, char* argv[]) { - int ret = -1; - int srcFD = -1; - MtpFile* destFile = NULL; - MtpObjectInfo* srcInfo = NULL; - MtpObjectInfo* destInfo = NULL; - MtpObjectHandle handle; - struct stat statbuf; - const char* lastSlash; - - if (argc < 1) { - fprintf(stderr, "not enough arguments\n"); - return -1; - } else if (argc > 2) { - fprintf(stderr, "too many arguments\n"); - return -1; - } - const char* src = argv[0]; - srcFD = open(src, O_RDONLY); - if (srcFD < 0) { - fprintf(stderr, "could not open %s\n", src); - goto fail; - } - if (argc == 2) { - char* dest = argv[1]; - destFile = parse_path(dest); - if (!destFile) { - fprintf(stderr, "could not find %s\n", dest); - goto fail; - } - } else { - if (!sCurrentDirectory) { - fprintf(stderr, "current working directory not set\n"); - goto fail; - } - destFile = new MtpFile(sCurrentDirectory); - } - - destInfo = destFile->getObjectInfo(); - if (!destInfo) { - fprintf(stderr, "could not find object info destination directory\n"); - goto fail; - } - if (destInfo->mFormat != MTP_FORMAT_ASSOCIATION) { - fprintf(stderr, "destination not a directory\n"); - goto fail; - } - - if (fstat(srcFD, &statbuf)) - goto fail; - - srcInfo = new MtpObjectInfo(0); - srcInfo->mStorageID = destInfo->mStorageID; - srcInfo->mFormat = MTP_FORMAT_EXIF_JPEG; // FIXME - srcInfo->mCompressedSize = statbuf.st_size; - srcInfo->mParent = destInfo->mHandle; - lastSlash = strrchr(src, '/'); - srcInfo->mName = strdup(lastSlash ? lastSlash + 1 : src); - srcInfo->mDateModified = statbuf.st_mtime; - handle = destFile->getDevice()->sendObjectInfo(srcInfo); - if (handle <= 0) { - printf("sendObjectInfo returned %04X\n", handle); - goto fail; - } - if (destFile->getDevice()->sendObject(srcInfo, srcFD)) - ret = 0; - -fail: - delete destFile; - delete srcInfo; - delete destInfo; - if (srcFD >= 0) - close(srcFD); - printf("returning %d\n", ret); - return ret; -} - -typedef int (* command_func)(int argc, char* argv[]); - -struct command_table_entry { - const char* name; - command_func func; -}; - -const command_table_entry command_list[] = { - { "cd", set_cwd }, - { "ls", list }, - { "get", get_file }, - { "put", put_file }, - { NULL, NULL }, -}; - - -static int do_command(int argc, char* argv[]) { - const command_table_entry* command = command_list; - const char* name = *argv++; - argc--; - - while (command->name) { - if (!strcmp(command->name, name)) - return command->func(argc, argv); - else - command++; - } - fprintf(stderr, "unknown command %s\n", name); - return -1; -} - -static int shell() { - int argc; - int result = 0; -#define MAX_ARGS 100 - char* argv[MAX_ARGS]; - -#if HAVE_READLINE - using_history(); -#endif - - while (1) { -#if HAVE_READLINE - char* line = readline(PROMPT); - if (!line) { - printf("\n"); - exit(0); - } -#else - char buffer[1000]; - printf("%s", PROMPT); - char* line = NULL; - size_t length = 0; - - buffer[0] = 0; - fgets(buffer, sizeof(buffer), stdin); - int count = strlen(buffer); - if (count > 0 && buffer[0] == (char)EOF) { - printf("\n"); - exit(0); - } - if (count > 0 && line[count - 1] == '\n') - line[count - 1] == 0; -#endif - char* tok = strtok(line, " \t\n\r"); - if (!tok) - continue; - if (!strcmp(tok, "quit") || !strcmp(tok, "exit")) { - exit(0); - } -#if HAVE_READLINE - add_history(line); -#endif - argc = 0; - while (tok) { - if (argc + 1 == MAX_ARGS) { - fprintf(stderr, "too many arguments\n"); - result = -1; - goto bottom_of_loop; - } - - argv[argc++] = strdup(tok); - tok = strtok(NULL, " \t\n\r"); - } - - result = do_command(argc, argv); - -bottom_of_loop: - for (int i = 0; i < argc; i++) - free(argv[i]); - free(line); - } - - return result; -} - -int main(int argc, char* argv[]) { - init(); - - if (argc == 1) - return shell(); - else - return do_command(argc - 1, argv + 1); -} diff --git a/media/tests/omxjpegdecoder/StreamSource.cpp b/media/tests/omxjpegdecoder/StreamSource.cpp index 76aa85b..5f44203 100644 --- a/media/tests/omxjpegdecoder/StreamSource.cpp +++ b/media/tests/omxjpegdecoder/StreamSource.cpp @@ -35,7 +35,7 @@ status_t StreamSource::initCheck() const { return mStream != NULL ? OK : NO_INIT; } -ssize_t StreamSource::readAt(off_t offset, void *data, size_t size) { +ssize_t StreamSource::readAt(off64_t offset, void *data, size_t size) { Mutex::Autolock autoLock(mLock); mStream->rewind(); @@ -45,7 +45,7 @@ ssize_t StreamSource::readAt(off_t offset, void *data, size_t size) { return result; } -status_t StreamSource::getSize(off_t *size) { +status_t StreamSource::getSize(off64_t *size) { *size = mSize; return OK; } diff --git a/media/tests/omxjpegdecoder/StreamSource.h b/media/tests/omxjpegdecoder/StreamSource.h index c1ed5bf..6c34cbd 100644 --- a/media/tests/omxjpegdecoder/StreamSource.h +++ b/media/tests/omxjpegdecoder/StreamSource.h @@ -32,8 +32,8 @@ public: // Pass the ownership of SkStream to StreamSource. StreamSource(SkStream *SkStream); virtual status_t initCheck() const; - virtual ssize_t readAt(off_t offset, void *data, size_t size); - virtual status_t getSize(off_t *size); + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual status_t getSize(off64_t *size); protected: virtual ~StreamSource(); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 6c84afd..d11a18e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -61,7 +61,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion' // is properly propagated through your change. Not doing so will result in a loss of user // settings. - private static final int DATABASE_VERSION = 61; + private static final int DATABASE_VERSION = 62; private Context mContext; @@ -793,22 +793,15 @@ public class DatabaseHelper extends SQLiteOpenHelper { } if (upgradeVersion == 60) { - // Increase screen timeout for tablet - db.beginTransaction(); - SQLiteStatement stmt = null; - try { - stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)" - + " VALUES(?,?);"); - loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT, - R.integer.def_screen_off_timeout); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - if (stmt != null) stmt.close(); - } + upgradeScreenTimeout(db); upgradeVersion = 61; } + if (upgradeVersion == 61) { + upgradeScreenTimeout(db); + upgradeVersion = 62; + } + // *** Remember to update DATABASE_VERSION above! if (upgradeVersion != currentVersion) { @@ -914,6 +907,23 @@ public class DatabaseHelper extends SQLiteOpenHelper { } } + private void upgradeScreenTimeout(SQLiteDatabase db) { + // Change screen timeout to current default + db.beginTransaction(); + SQLiteStatement stmt = null; + try { + stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)" + + " VALUES(?,?);"); + loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT, + R.integer.def_screen_off_timeout); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (stmt != null) + stmt.close(); + } + } + /** * Loads the default set of bookmarked shortcuts from an xml file. * diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png Binary files differdeleted file mode 100644 index 6baf5ea..0000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png Binary files differnew file mode 100644 index 0000000..615c8b6 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png Binary files differnew file mode 100644 index 0000000..0122025 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png Binary files differnew file mode 100644 index 0000000..0786916 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png Binary files differnew file mode 100644 index 0000000..35f9240 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png Binary files differdeleted file mode 100644 index ed813dc..0000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png Binary files differnew file mode 100644 index 0000000..3eb22df --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png Binary files differnew file mode 100644 index 0000000..1ce9bd1 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png Binary files differindex bf33c94..259db7a 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_pressed.png Binary files differnew file mode 100644 index 0000000..993ea55 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png Binary files differdeleted file mode 100644 index d7775f2..0000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png Binary files differnew file mode 100644 index 0000000..fef2cf9 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png Binary files differnew file mode 100644 index 0000000..05593bc --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png Binary files differdeleted file mode 100644 index 178af73..0000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png Binary files differnew file mode 100644 index 0000000..32c2c79 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png Binary files differnew file mode 100644 index 0000000..142c413 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png diff --git a/packages/SystemUI/res/drawable/status_bar_home.xml b/packages/SystemUI/res/drawable/ic_sysbar_back.xml index 0011711..327ccd8 100644 --- a/packages/SystemUI/res/drawable/status_bar_home.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_back.xml @@ -15,7 +15,7 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/status_bar_home_pressed" /> - <item android:drawable="@drawable/status_bar_home_default" /> + <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_back_pressed" /> + <item android:drawable="@drawable/ic_sysbar_back_default" /> </selector> diff --git a/packages/SystemUI/res/drawable/status_bar_back.xml b/packages/SystemUI/res/drawable/ic_sysbar_home.xml index 92bf147..f4e585e 100644 --- a/packages/SystemUI/res/drawable/status_bar_back.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_home.xml @@ -15,7 +15,7 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/status_bar_back_pressed" /> - <item android:drawable="@drawable/status_bar_back_default" /> + <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_home_pressed" /> + <item android:drawable="@drawable/ic_sysbar_home_default" /> </selector> diff --git a/packages/SystemUI/res/drawable/status_bar_menu.xml b/packages/SystemUI/res/drawable/ic_sysbar_ime.xml index aa7286e..1accf00 100644 --- a/packages/SystemUI/res/drawable/status_bar_menu.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_ime.xml @@ -15,7 +15,7 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/status_bar_menu_pressed" /> - <item android:drawable="@drawable/status_bar_menu_default" /> + <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_ime_pressed" /> + <item android:drawable="@drawable/ic_sysbar_ime_default" /> </selector> diff --git a/packages/SystemUI/res/drawable/status_bar_recent.xml b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml index d708455..7a10607 100755..100644 --- a/packages/SystemUI/res/drawable/status_bar_recent.xml +++ b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml @@ -15,7 +15,7 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/status_bar_recent_pressed" /> - <item android:drawable="@drawable/status_bar_recent_default" /> + <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_menu_pressed" /> + <item android:drawable="@drawable/ic_sysbar_menu_default" /> </selector> diff --git a/packages/SystemUI/res/drawable/ic_sysbar_recent.xml b/packages/SystemUI/res/drawable/ic_sysbar_recent.xml new file mode 100755 index 0000000..39a324b --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_sysbar_recent.xml @@ -0,0 +1,21 @@ +<?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_pressed="true" android:drawable="@drawable/ic_sysbar_recent_pressed" /> + <item android:drawable="@drawable/ic_sysbar_recent_default" /> +</selector> + diff --git a/packages/SystemUI/res/drawable/ic_sysbar_icon_bg.xml b/packages/SystemUI/res/drawable/status_bar_ticker_background.xml index d8ba2a8..c230358 100644 --- a/packages/SystemUI/res/drawable/ic_sysbar_icon_bg.xml +++ b/packages/SystemUI/res/drawable/status_bar_ticker_background.xml @@ -4,9 +4,9 @@ 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. @@ -14,8 +14,14 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_press_bg" /> - <item android:drawable="@drawable/ic_sysbar_default_bg" /> -</selector> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:opacity="translucent" + > + <item + android:drawable="@drawable/ticker_background_color" + android:top="12dp" + /> +</layer-list> + diff --git a/media/tests/CameraBrowser/res/menu/object_menu.xml b/packages/SystemUI/res/drawable/ticker_background.xml index a0865f0..7320fa0 100644 --- a/media/tests/CameraBrowser/res/menu/object_menu.xml +++ b/packages/SystemUI/res/drawable/ticker_background.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2010 The Android Open Source Project +<!-- Copyright (C) 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. @@ -14,10 +14,14 @@ limitations under the License. --> -<menu xmlns:android="http://schemas.android.com/apk/res/android"> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:opacity="translucent" + > + <!-- the large icon extends 12dp beyond the edge of the status bar --> + <item + android:drawable="@drawable/notification_item_background_color" + android:top="12dp" + /> +</layer-list> - <item android:id="@+id/save" - android:title="@string/save_item" /> - <item android:id="@+id/delete" - android:title="@string/delete_item" /> -</menu> diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml index d4a6136..4fa306e 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml @@ -25,7 +25,6 @@ android:id="@+id/bar_contents" android:layout_width="match_parent" android:layout_height="match_parent" - android:animateLayoutChanges="false" > <!-- notification icons & panel access --> @@ -40,7 +39,6 @@ android:id="@+id/notificationIcons" android:layout_width="wrap_content" android:layout_height="match_parent" - android:gravity="center_vertical" android:orientation="horizontal" > <view @@ -48,7 +46,9 @@ android:id="@+id/icons" android:layout_width="wrap_content" android:layout_height="@*android:dimen/status_bar_icon_size" - android:layout_marginLeft="8dip" + android:layout_gravity="top" + android:layout_marginTop="5dp" + android:layout_marginLeft="8dp" /> </com.android.systemui.statusbar.tablet.NotificationIconArea> @@ -85,13 +85,15 @@ android:id="@+id/battery" android:layout_height="wrap_content" android:layout_width="wrap_content" - android:layout_gravity="center_vertical" + android:layout_gravity="top" + android:layout_marginTop="18dp" /> <ImageView android:id="@+id/network" android:layout_height="wrap_content" android:layout_width="wrap_content" - android:layout_gravity="center_vertical" + android:layout_gravity="top" + android:layout_marginTop="14dp" android:src="@drawable/ic_sysbar_wifi_mini" /> </LinearLayout> @@ -105,7 +107,6 @@ android:layout_height="match_parent" android:layout_alignParentLeft="true" android:orientation="horizontal" - android:animateLayoutChanges="false" > <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back" @@ -114,7 +115,6 @@ android:paddingLeft="18dip" android:paddingRight="18dip" android:src="@drawable/ic_sysbar_back" - android:background="@drawable/ic_sysbar_icon_bg" systemui:keyCode="4" /> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home" @@ -123,14 +123,13 @@ android:paddingLeft="18dip" android:paddingRight="18dip" android:src="@drawable/ic_sysbar_home" - android:background="@drawable/ic_sysbar_icon_bg" systemui:keyCode="3" /> <ImageButton android:id="@+id/recent_apps" android:layout_width="96dip" android:layout_height="match_parent" android:src="@drawable/ic_sysbar_recent" - android:background="@drawable/ic_sysbar_icon_bg" + android:background="@null" android:paddingLeft="18dip" android:clickable="true" android:paddingRight="18dip" @@ -141,7 +140,6 @@ android:paddingLeft="18dip" android:paddingRight="18dip" android:src="@drawable/ic_sysbar_menu" - android:background="@drawable/ic_sysbar_icon_bg" systemui:keyCode="82" android:visibility="invisible" /> @@ -149,7 +147,6 @@ android:id="@+id/pocket" android:layout_width="96dip" android:layout_height="match_parent" - android:background="@drawable/ic_sysbar_icon_bg" android:paddingLeft="18dip" android:paddingRight="18dip" android:animateLayoutChanges="true" @@ -171,81 +168,73 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="8dip" - android:src="@drawable/ic_sysbar_ime_default" - android:background="@drawable/ic_sysbar_icon_bg" + android:src="@drawable/ic_sysbar_ime" android:visibility="invisible" /> </LinearLayout> <!-- lights out mode: "shadow" views --> - <ImageView - android:id="@+id/notification_shadow" - android:layout_width="176dip" + <RelativeLayout + android:id="@+id/shadows" + android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingRight="48dip" - android:layout_alignParentRight="true" - android:layout_alignParentBottom="true" - android:src="@drawable/ic_sysbar_shadow" - android:visibility="gone" - android:scaleType="fitXY" - /> - - <ImageView - android:id="@+id/back_shadow" - android:layout_width="96dip" - android:layout_height="match_parent" - android:paddingLeft="18dip" - android:paddingRight="18dip" - android:layout_alignParentLeft="true" - android:layout_alignParentBottom="true" - android:src="@drawable/ic_sysbar_shadow" - android:visibility="gone" - /> - <ImageView - android:id="@+id/home_shadow" - android:layout_width="96dip" - android:layout_height="match_parent" - android:paddingLeft="18dip" - android:paddingRight="18dip" - android:layout_toRightOf="@id/back_shadow" - android:layout_alignParentBottom="true" - android:src="@drawable/ic_sysbar_shadow" - android:visibility="gone" - /> - <ImageView - android:id="@+id/recent_shadow" - android:layout_width="96dip" - android:layout_height="match_parent" - android:paddingLeft="18dip" - android:paddingRight="18dip" - android:layout_toRightOf="@id/home_shadow" - android:layout_alignParentBottom="true" - android:src="@drawable/ic_sysbar_shadow" - android:visibility="gone" - /> - <ImageView - android:id="@+id/menu_shadow" - android:layout_width="96dip" - android:layout_height="match_parent" - android:paddingLeft="18dip" - android:paddingRight="18dip" - android:layout_toRightOf="@id/recent_shadow" - android:layout_alignParentBottom="true" - android:src="@drawable/ic_sysbar_shadow" - android:visibility="gone" - /> + > + <ImageView + android:id="@+id/notification_shadow" + android:layout_width="176dip" + android:layout_height="match_parent" + android:paddingRight="48dip" + android:layout_alignParentRight="true" + android:layout_alignParentBottom="true" + android:src="@drawable/ic_sysbar_shadow" + android:visibility="gone" + android:scaleType="fitXY" + /> - <!-- ticker: transient incoming notification information --> - <FrameLayout - android:id="@+id/ticker" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_alignParentRight="true" - android:layout_toRightOf="@+id/systemInfo" - android:paddingLeft="6dip" - android:gravity="center_vertical" - android:animateLayoutChanges="true" - /> - + <ImageView + android:id="@+id/back_shadow" + android:layout_width="96dip" + android:layout_height="match_parent" + android:paddingLeft="18dip" + android:paddingRight="18dip" + android:layout_alignParentLeft="true" + android:layout_alignParentBottom="true" + android:src="@drawable/ic_sysbar_shadow" + android:visibility="gone" + /> + <ImageView + android:id="@+id/home_shadow" + android:layout_width="96dip" + android:layout_height="match_parent" + android:paddingLeft="18dip" + android:paddingRight="18dip" + android:layout_toRightOf="@id/back_shadow" + android:layout_alignParentBottom="true" + android:src="@drawable/ic_sysbar_shadow" + android:visibility="gone" + /> + <ImageView + android:id="@+id/recent_shadow" + android:layout_width="96dip" + android:layout_height="match_parent" + android:paddingLeft="18dip" + android:paddingRight="18dip" + android:layout_toRightOf="@id/home_shadow" + android:layout_alignParentBottom="true" + android:src="@drawable/ic_sysbar_shadow" + android:visibility="gone" + /> + <ImageView + android:id="@+id/menu_shadow" + android:layout_width="96dip" + android:layout_height="match_parent" + android:paddingLeft="18dip" + android:paddingRight="18dip" + android:layout_toRightOf="@id/recent_shadow" + android:layout_alignParentBottom="true" + android:src="@drawable/ic_sysbar_shadow" + android:visibility="gone" + /> + </RelativeLayout> </RelativeLayout> </com.android.systemui.statusbar.tablet.TabletStatusBarView> diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml b/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml index b6679a5..6b12d29 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml @@ -13,13 +13,24 @@ android:src="@drawable/status_bar_veto" android:scaleType="center" android:background="#ff000000" + android:paddingRight="8dp" /> + <ImageView + android:id="@+id/large_icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:scaleType="center" + /> + <!-- TODO: scaleType should be top-left but ImageView doesn't support that. --> + <com.android.systemui.statusbar.LatestItemView android:id="@+id/content" android:layout_width="wrap_content" android:layout_height="64sp" android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" + android:layout_toRightOf="@id/large_icon" android:layout_toLeftOf="@id/veto" android:layout_marginLeft="16dp" android:focusable="true" diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml index b23cc7b..f9e2d5e 100644 --- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml +++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml @@ -1,43 +1,40 @@ -<?xml version="1.0" encoding="utf-8"?> <!-- -/* apps/common/assets/default/default/skins/StatusBar.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. -*/ + Copyright (C) 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. --> <!-- android:background="@drawable/status_bar_closed_default_background" --> <com.android.systemui.statusbar.tablet.NotificationPanel xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" - android:layout_width="540dp" + android:layout_width="match_parent" android:animateLayoutChanges="true" android:background="@drawable/bg_scrim_notification" + android:paddingTop="32dp" android:paddingBottom="32dp" + android:orientation="vertical" + android:gravity="right" > <com.android.systemui.statusbar.tablet.NotificationTitleArea android:id="@+id/title_area" - android:layout_height="wrap_content" + android:layout_height="160dp" android:layout_width="384dp" - android:layout_above="@+id/content_frame" android:layout_marginLeft="24dp" - android:paddingBottom="16dp" + android:paddingTop="20dp" android:orientation="vertical" android:animateLayoutChanges="true" - android:layout_alignParentRight="true" > <com.android.systemui.statusbar.tablet.HoloClock @@ -143,8 +140,6 @@ android:id="@+id/content_frame" android:layout_height="wrap_content" android:layout_width="408dp" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" > <ScrollView android:id="@+id/notificationScroller" diff --git a/packages/SystemUI/res/layout-xlarge/ticker.xml b/packages/SystemUI/res/layout-xlarge/ticker.xml index c8d855f..cae6a77 100644 --- a/packages/SystemUI/res/layout-xlarge/ticker.xml +++ b/packages/SystemUI/res/layout-xlarge/ticker.xml @@ -18,36 +18,22 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" android:orientation="horizontal" - android:background="#ff000000" + android:background="@drawable/status_bar_ticker_background" + android:gravity="bottom" > + <!-- + android:background="@drawable/ticker_background" + --> - <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_gravity="center_vertical" - android:orientation="vertical" - android:paddingLeft="12dp" - > - - <TextView android:id="@+id/title" - xmlns:android="http://schemas.android.com/apk/res/android" - android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textStyle="bold" - android:maxLines="1" - /> - <TextView android:id="@+id/subtitle" - xmlns:android="http://schemas.android.com/apk/res/android" - android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:maxLines="1" - /> - </LinearLayout> + <ImageView + android:id="@+id/large_icon" + android:layout_width="@dimen/notification_large_icon_height" + android:layout_height="@dimen/notification_large_icon_width" + android:scaleType="center" + android:visibility="gone" + /> + <!-- TODO: scaleType should be top-left but ImageView doesn't support that. --> </LinearLayout> diff --git a/packages/SystemUI/res/layout-xlarge/ticker_compat.xml b/packages/SystemUI/res/layout-xlarge/ticker_compat.xml index 79c7543..5d9a680 100644 --- a/packages/SystemUI/res/layout-xlarge/ticker_compat.xml +++ b/packages/SystemUI/res/layout-xlarge/ticker_compat.xml @@ -18,11 +18,26 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="@*android:dimen/status_bar_height" android:orientation="horizontal" - android:background="#ff000000" + android:background="@drawable/status_bar_ticker_background" > + <ImageView + android:id="@+id/large_icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + android:visibility="gone" + /> + + <ImageView android:id="@+id/left_icon" + android:layout_width="64dp" + android:layout_height="match_parent" + android:scaleType="center" + android:visibility="gone" + /> + <TextView android:id="@+id/text" android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker" android:layout_width="match_parent" @@ -33,4 +48,11 @@ android:maxLines="2" /> + <ImageView android:id="@+id/right_icon" + android:layout_width="64dp" + android:layout_height="match_parent" + android:scaleType="center" + android:visibility="gone" + /> + </LinearLayout> diff --git a/packages/SystemUI/res/values-xlarge/config.xml b/packages/SystemUI/res/values-xlarge/config.xml index e6af4f5..e140914 100644 --- a/packages/SystemUI/res/values-xlarge/config.xml +++ b/packages/SystemUI/res/values-xlarge/config.xml @@ -26,5 +26,8 @@ interface. This name is in the ComponentName flattened format (package/class) --> <string name="config_statusBarComponent">com.android.systemui.statusbar.tablet.TabletStatusBar</string> + <!-- Whether or not we show the number in the bar. --> + <bool name="config_statusBarShowNumber">false</bool> + </resources> diff --git a/packages/SystemUI/res/values-xlarge/dimens.xml b/packages/SystemUI/res/values-xlarge/dimens.xml new file mode 100644 index 0000000..009b7a8 --- /dev/null +++ b/packages/SystemUI/res/values-xlarge/dimens.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright (c) 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. +*/ +--> +<resources> + <!-- The width of the big icons in notifications. --> + <dimen name="notification_large_icon_width">60dp</dimen> + <!-- The width of the big icons in notifications. --> + <dimen name="notification_large_icon_height">60dp</dimen> + <!-- The width of the ticker, including the icon --> + <dimen name="notification_ticker_width">360dp</dimen> +</resources> + + diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index fd2cf99..964e69b 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -19,4 +19,5 @@ <resources> <drawable name="notification_number_text_color">#ffffffff</drawable> <drawable name="notification_item_background_color">#ff000000</drawable> + <drawable name="ticker_background_color">#ff1d1d1d</drawable> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 86beb14..05ed089 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -35,5 +35,8 @@ interface. This name is in the ComponentName flattened format (package/class) --> <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string> + <!-- Whether or not we show the number in the bar. --> + <bool name="config_statusBarShowNumber">true</bool> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 9a61be6..dbfbe11 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -93,7 +93,8 @@ public class StatusBarIconView extends AnimatedImageView { setImageLevel(icon.iconLevel); } if (!numberEquals) { - if (icon.number > 0) { + if (icon.number > 0 && mContext.getResources().getBoolean( + R.bool.config_statusBarShowNumber)) { if (mNumberBackground == null) { mNumberBackground = getContext().getResources().getDrawable( R.drawable.ic_notification_overlay); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java index 80cb5b2..5f49d8c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java @@ -19,16 +19,16 @@ package com.android.systemui.statusbar.tablet; import android.content.Context; import android.util.AttributeSet; import android.util.Slog; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; import com.android.systemui.R; -public class NotificationPanel extends RelativeLayout implements StatusBarPanel, +public class NotificationPanel extends LinearLayout implements StatusBarPanel, View.OnClickListener { static final String TAG = "NotificationPanel"; @@ -71,6 +71,29 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, } } + /** + * We need to be aligned at the bottom. LinearLayout can't do this, so instead, + * let LinearLayout do all the hard work, and then shift everything down to the bottom. + */ + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + // We know that none of our children are GONE, so don't worry about skipping GONE views. + final int N = getChildCount(); + if (N == 0) { + return; + } + final int allocatedBottom = getChildAt(N-1).getBottom(); + final int shift = b - allocatedBottom - getPaddingBottom(); + if (shift <= 0) { + return; + } + for (int i=0; i<N; i++) { + final View c = getChildAt(i); + c.layout(c.getLeft(), c.getTop() + shift, c.getRight(), c.getBottom() + shift); + } + } + public void onClick(View v) { if (v == mSettingsButton) { switchToSettingsMode(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 7c97ac7..ab509ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -19,9 +19,12 @@ package com.android.systemui.statusbar.tablet; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Map; +import java.util.IdentityHashMap; import android.animation.LayoutTransition; import android.animation.ObjectAnimator; +import android.animation.AnimatorSet; import android.app.ActivityManagerNative; import android.app.PendingIntent; import android.app.Notification; @@ -129,8 +132,6 @@ public class TabletStatusBar extends StatusBar { NotificationIconArea.IconLayout mIconLayout; TabletTicker mTicker; - View mTickerView; - boolean mTicking; // for disabling the status bar int mDisabled = 0; @@ -164,7 +165,7 @@ public class TabletStatusBar extends StatusBar { mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel); WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN @@ -257,21 +258,6 @@ public class TabletStatusBar extends StatusBar { mBarContents = sb.findViewById(R.id.bar_contents); - // "shadows" of the status bar features, for lights-out mode - mBackShadow = sb.findViewById(R.id.back_shadow); - mHomeShadow = sb.findViewById(R.id.home_shadow); - mRecentShadow = sb.findViewById(R.id.recent_shadow); - mMenuShadow = sb.findViewById(R.id.menu_shadow); - mNotificationShadow = sb.findViewById(R.id.notification_shadow); - - mShadowController = new ShadowController(false); - - mBackShadow.setOnTouchListener(mShadowController.makeTouchListener()); - mHomeShadow.setOnTouchListener(mShadowController.makeTouchListener()); - mRecentShadow.setOnTouchListener(mShadowController.makeTouchListener()); - mMenuShadow.setOnTouchListener(mShadowController.makeTouchListener()); - mNotificationShadow.setOnTouchListener(mShadowController.makeTouchListener()); - // the whole right-hand side of the bar mNotificationArea = sb.findViewById(R.id.notificationArea); @@ -290,7 +276,7 @@ public class TabletStatusBar extends StatusBar { mNotificationPeekTapDuration = vc.getTapTimeout(); mNotificationFlingVelocity = 300; // px/s - mTicker = new TabletTicker(context, (FrameLayout)sb.findViewById(R.id.ticker)); + mTicker = new TabletTicker(context); // The icons mBatteryController = new BatteryController(mContext); @@ -310,6 +296,20 @@ public class TabletStatusBar extends StatusBar { // The bar contents buttons mInputMethodButton = (InputMethodButton) sb.findViewById(R.id.imeButton); + // "shadows" of the status bar features, for lights-out mode + mBackShadow = sb.findViewById(R.id.back_shadow); + mHomeShadow = sb.findViewById(R.id.home_shadow); + mRecentShadow = sb.findViewById(R.id.recent_shadow); + mMenuShadow = sb.findViewById(R.id.menu_shadow); + mNotificationShadow = sb.findViewById(R.id.notification_shadow); + + mShadowController = new ShadowController(false); + mShadowController.add(mBackButton, mBackShadow); + mShadowController.add(mHomeButton, mHomeShadow); + mShadowController.add(mRecentButton, mRecentShadow); + mShadowController.add(mMenuButton, mMenuShadow); + mShadowController.add(mNotificationArea, mNotificationShadow); + // set the initial view visibility setAreThereNotifications(); refreshNotificationTrigger(); @@ -383,20 +383,17 @@ public class TabletStatusBar extends StatusBar { if (DEBUG) Slog.d(TAG, "opening notifications panel"); if (mNotificationPanel.getVisibility() == View.GONE) { mNotificationPeekWindow.setVisibility(View.GONE); - mNotificationPanel.setVisibility(View.VISIBLE); - - // XXX: need to synchronize with shadows here - mNotificationArea.setVisibility(View.GONE); + // synchronize with current shadow state + mShadowController.hideElement(mNotificationArea); } break; case MSG_CLOSE_NOTIFICATION_PANEL: if (DEBUG) Slog.d(TAG, "closing notifications panel"); if (mNotificationPanel.getVisibility() == View.VISIBLE) { mNotificationPanel.setVisibility(View.GONE); - - // XXX: need to synchronize with shadows here - mNotificationArea.setVisibility(View.VISIBLE); + // synchronize with current shadow state + mShadowController.showElement(mNotificationArea); } break; case MSG_OPEN_RECENTS_PANEL: @@ -462,7 +459,7 @@ public class TabletStatusBar extends StatusBar { boolean immersive = false; try { immersive = ActivityManagerNative.getDefault().isTopActivityImmersive(); - Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive")); + //Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive")); } catch (RemoteException ex) { } if (false && immersive) { @@ -576,11 +573,13 @@ public class TabletStatusBar extends StatusBar { if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes"); - mNotificationIconArea.setVisibility(View.GONE); + // synchronize with current shadow state + mShadowController.hideElement(mNotificationArea); mTicker.halt(); } else { Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no"); - mNotificationIconArea.setVisibility(View.VISIBLE); + // synchronize with current shadow state + mShadowController.showElement(mNotificationArea); } } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) { if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) { @@ -599,9 +598,7 @@ public class TabletStatusBar extends StatusBar { } private boolean hasTicker(Notification n) { - return !TextUtils.isEmpty(n.tickerText) - || !TextUtils.isEmpty(n.tickerTitle) - || !TextUtils.isEmpty(n.tickerSubtitle); + return n.tickerView != null || !TextUtils.isEmpty(n.tickerText); } private void tick(StatusBarNotification n) { @@ -1001,13 +998,21 @@ public class TabletStatusBar extends StatusBar { } catch (RemoteException ex) { // system process is dead if we're here. } - // animateCollapse(); } }); } else { vetoButton.setVisibility(View.INVISIBLE); } + // the large icon + ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon); + if (sbn.notification.largeIcon != null) { + largeIcon.setImageBitmap(sbn.notification.largeIcon); + } else { + largeIcon.getLayoutParams().width = 0; + largeIcon.setVisibility(View.INVISIBLE); + } + // bind the click event to the content area ViewGroup content = (ViewGroup)row.findViewById(R.id.content); // XXX: update to allow controls within notification views @@ -1030,7 +1035,7 @@ public class TabletStatusBar extends StatusBar { exception = e; } if (expanded == null) { - String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id); + final String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id); Slog.e(TAG, "couldn't inflate view for notification " + ident, exception); return false; } else { @@ -1047,11 +1052,57 @@ public class TabletStatusBar extends StatusBar { public class ShadowController { boolean mShowShadows; + Map<View, View> mShadowsForElements = new IdentityHashMap<View, View>(7); + Map<View, View> mElementsForShadows = new IdentityHashMap<View, View>(7); + LayoutTransition mElementTransition, mShadowTransition; + View mTouchTarget; ShadowController(boolean showShadows) { mShowShadows = showShadows; mTouchTarget = null; + + mElementTransition = new LayoutTransition(); +// AnimatorSet s = new AnimatorSet(); +// s.play(ObjectAnimator.ofInt(null, "top", 48, 0)) +// .with(ObjectAnimator.ofFloat(null, "scaleY", 0.5f, 1f)) +// .with(ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f)) +// ; + mElementTransition.setAnimator(LayoutTransition.APPEARING, //s); + ObjectAnimator.ofInt(null, "top", 48, 0)); + mElementTransition.setDuration(LayoutTransition.APPEARING, 100); + mElementTransition.setStartDelay(LayoutTransition.APPEARING, 0); + +// s = new AnimatorSet(); +// s.play(ObjectAnimator.ofInt(null, "top", 0, 48)) +// .with(ObjectAnimator.ofFloat(null, "scaleY", 1f, 0.5f)) +// .with(ObjectAnimator.ofFloat(null, "alpha", 1f, 0.5f)) +// ; + mElementTransition.setAnimator(LayoutTransition.DISAPPEARING, //s); + ObjectAnimator.ofInt(null, "top", 0, 48)); + mElementTransition.setDuration(LayoutTransition.DISAPPEARING, 400); + + mShadowTransition = new LayoutTransition(); + mShadowTransition.setAnimator(LayoutTransition.APPEARING, + ObjectAnimator.ofFloat(null, "alpha", 0f, 1f)); + mShadowTransition.setDuration(LayoutTransition.APPEARING, 200); + mShadowTransition.setStartDelay(LayoutTransition.APPEARING, 100); + mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING, + ObjectAnimator.ofFloat(null, "alpha", 1f, 0f)); + mShadowTransition.setDuration(LayoutTransition.DISAPPEARING, 100); + + ViewGroup bar = (ViewGroup) TabletStatusBar.this.mBarContents; + bar.setLayoutTransition(mElementTransition); + ViewGroup nav = (ViewGroup) TabletStatusBar.this.mNavigationArea; + nav.setLayoutTransition(mElementTransition); + ViewGroup shadowGroup = (ViewGroup) bar.findViewById(R.id.shadows); + shadowGroup.setLayoutTransition(mShadowTransition); + } + + public void add(View element, View shadow) { + shadow.setOnTouchListener(makeTouchListener()); + mShadowsForElements.put(element, shadow); + mElementsForShadows.put(shadow, element); } public boolean getShadowState() { @@ -1067,17 +1118,7 @@ public class TabletStatusBar extends StatusBar { // currently redirecting events? if (mTouchTarget == null) { - if (v == mBackShadow) { - mTouchTarget = mBackButton; - } else if (v == mHomeShadow) { - mTouchTarget = mHomeButton; - } else if (v == mMenuShadow) { - mTouchTarget = mMenuButton; - } else if (v == mRecentShadow) { - mTouchTarget = mRecentButton; - } else if (v == mNotificationShadow) { - mTouchTarget = mNotificationArea; - } + mTouchTarget = mElementsForShadows.get(v); } if (mTouchTarget != null && mTouchTarget.getVisibility() != View.GONE) { @@ -1094,7 +1135,7 @@ public class TabletStatusBar extends StatusBar { break; case MotionEvent.ACTION_DOWN: mHandler.removeMessages(MSG_RESTORE_SHADOWS); - setShadowForButton(mTouchTarget, false); + setElementShadow(mTouchTarget, false); break; } mTouchTarget.dispatchTouchEvent(ev); @@ -1108,11 +1149,9 @@ public class TabletStatusBar extends StatusBar { } public void refresh() { - setShadowForButton(mBackButton, mShowShadows); - setShadowForButton(mHomeButton, mShowShadows); - setShadowForButton(mRecentButton, mShowShadows); - setShadowForButton(mMenuButton, mShowShadows); - setShadowForButton(mNotificationArea, mShowShadows); + for (View element : mShadowsForElements.keySet()) { + setElementShadow(element, mShowShadows); + } } public void showAllShadows() { @@ -1127,19 +1166,8 @@ public class TabletStatusBar extends StatusBar { // Use View.INVISIBLE for things hidden due to shadowing, and View.GONE for things that are // disabled (and should not be shadowed or re-shown) - public void setShadowForButton(View button, boolean shade) { - View shadow = null; - if (button == mBackButton) { - shadow = mBackShadow; - } else if (button == mHomeButton) { - shadow = mHomeShadow; - } else if (button == mMenuButton) { - shadow = mMenuShadow; - } else if (button == mRecentButton) { - shadow = mRecentShadow; - } else if (button == mNotificationArea) { - shadow = mNotificationShadow; - } + public void setElementShadow(View button, boolean shade) { + View shadow = mShadowsForElements.get(button); if (shadow != null) { if (button.getVisibility() != View.GONE) { shadow.setVisibility(shade ? View.VISIBLE : View.INVISIBLE); @@ -1147,6 +1175,26 @@ public class TabletStatusBar extends StatusBar { } } } + + // Hide both element and shadow, using default layout animations. + public void hideElement(View button) { + Slog.d(TAG, "hiding: " + button); + View shadow = mShadowsForElements.get(button); + if (shadow != null) { + shadow.setVisibility(View.GONE); + } + button.setVisibility(View.GONE); + } + + // Honoring the current shadow state. + public void showElement(View button) { + Slog.d(TAG, "showing: " + button); + View shadow = mShadowsForElements.get(button); + if (shadow != null) { + shadow.setVisibility(mShowShadows ? View.VISIBLE : View.INVISIBLE); + } + button.setVisibility(mShowShadows ? View.INVISIBLE : View.VISIBLE); + } } public class TouchOutsideListener implements View.OnTouchListener { @@ -1171,15 +1219,6 @@ public class TabletStatusBar extends StatusBar { } } - private void setViewVisibility(View v, int vis, int anim) { - if (v.getVisibility() != vis) { - //Slog.d(TAG, "setViewVisibility vis=" + (vis == View.VISIBLE) + " v=" + v); - v.setAnimation(AnimationUtils.loadAnimation(mContext, anim)); - v.setVisibility(vis); - } - } - - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.print("mDisabled=0x"); pw.println(Integer.toHexString(mDisabled)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java index 3c3139f..7f743b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java @@ -16,9 +16,14 @@ package com.android.systemui.statusbar.tablet; +import java.util.Arrays; + import android.app.Notification; import android.content.Context; +import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.util.Slog; @@ -26,16 +31,18 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.WindowManagerImpl; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarNotification; import com.android.systemui.R; - -import java.util.Arrays; +import com.android.systemui.statusbar.StatusBarIconView; public class TabletTicker extends Handler { private static final String TAG = "StatusBar.TabletTicker"; @@ -45,17 +52,16 @@ public class TabletTicker extends Handler { private static final int ADVANCE_DELAY = 5000; // 5 seconds private Context mContext; - private FrameLayout mParent; + private ViewGroup mWindow; private StatusBarNotification mCurrentNotification; private View mCurrentView; private StatusBarNotification[] mQueue; private int mQueuePos; - public TabletTicker(Context context, FrameLayout parent) { + public TabletTicker(Context context) { mContext = context; - mParent = parent; // TODO: Make this a configuration value. // 3 is enough to let us see most cases, but not get so far behind that it's annoying. @@ -102,18 +108,33 @@ public class TabletTicker extends Handler { private void advance() { // Out with the old... if (mCurrentView != null) { - mParent.removeView(mCurrentView); + mWindow.removeView(mCurrentView); mCurrentView = null; mCurrentNotification = null; } // In with the new... - final StatusBarNotification next = dequeue(); - if (next != null) { + StatusBarNotification next = dequeue(); + while (next != null) { mCurrentNotification = next; mCurrentView = makeTickerView(next); - mParent.addView(mCurrentView); - sendEmptyMessageDelayed(MSG_ADVANCE, ADVANCE_DELAY); + if (mCurrentView != null) { + if (mWindow == null) { + mWindow = makeWindow(); + WindowManagerImpl.getDefault().addView(mWindow, mWindow.getLayoutParams()); + } + mWindow.addView(mCurrentView); + sendEmptyMessageDelayed(MSG_ADVANCE, ADVANCE_DELAY); + break; + } + next = dequeue(); + } + + // if there's nothing left, close the window + // TODO: Do this when the animation is done instead + if (mCurrentView == null) { + WindowManagerImpl.getDefault().removeView(mWindow); + mWindow = null; } } @@ -133,46 +154,76 @@ public class TabletTicker extends Handler { return notification; } + private ViewGroup makeWindow() { + final Resources res = mContext.getResources(); + final FrameLayout view = new FrameLayout(mContext); + final int width = res.getDimensionPixelSize(R.dimen.notification_ticker_width); + final int height = res.getDimensionPixelSize(R.dimen.notification_large_icon_height); + WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height, + WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, + PixelFormat.TRANSLUCENT); + lp.gravity = Gravity.BOTTOM | Gravity.RIGHT; + lp.setTitle("NotificationTicker"); + view.setLayoutParams(lp); + return view; + } + private View makeTickerView(StatusBarNotification notification) { final Notification n = notification.notification; LayoutInflater inflater = (LayoutInflater)mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); - int layoutId; ViewGroup group; - if (n.tickerTitle != null || n.tickerSubtitle != null) { - group = (ViewGroup)inflater.inflate(R.layout.ticker, mParent, false); - if (n.tickerTitle != null) { - final TextView title = (TextView)group.findViewById(R.id.title); - title.setText(n.tickerTitle); + int layoutId; + int iconId; + if (n.largeIcon != null) { + iconId = R.id.right_icon; + } else { + iconId = R.id.left_icon; + } + if (n.tickerView != null) { + group = (ViewGroup)inflater.inflate(R.layout.ticker, null, false); + View expanded = null; + Exception exception = null; + try { + expanded = n.tickerView.apply(mContext, group); } - if (n.tickerSubtitle != null) { - final TextView subtitle = (TextView)group.findViewById(R.id.subtitle); - subtitle.setText(n.tickerSubtitle); + catch (RuntimeException e) { + exception = e; } - } else { - group = (ViewGroup)inflater.inflate(R.layout.ticker_compat, mParent, false); + if (expanded == null) { + final String ident = notification.pkg + + "/0x" + Integer.toHexString(notification.id); + Slog.e(TAG, "couldn't inflate view for notification " + ident, exception); + return null; + } + final int statusBarHeight = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.status_bar_height); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, statusBarHeight, 1.0f); + lp.gravity = Gravity.BOTTOM; + group.addView(expanded, lp); + } else if (n.tickerText != null) { + group = (ViewGroup)inflater.inflate(R.layout.ticker_compat, mWindow, false); + final Drawable icon = StatusBarIconView.getIcon(mContext, + new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0)); + ImageView iv = (ImageView)group.findViewById(iconId); + iv.setImageDrawable(icon); + iv.setVisibility(View.VISIBLE); TextView tv = (TextView)group.findViewById(R.id.text); tv.setText(n.tickerText); + } else { + throw new RuntimeException("tickerView==null && tickerText==null"); } - - // No more than 2 icons. - if (n.tickerIcons != null) { - int N = n.tickerIcons.length; - if (N > 2) { - N = 2; - } - for (int i=N-1; i>= 0; i--) { - Bitmap b = n.tickerIcons[i]; - if (b != null) { - ImageView iv = (ImageView)inflater.inflate(R.layout.ticker_icon, group, false); - iv.setImageBitmap(b); - group.addView(iv, 0); - } - } + ImageView largeIcon = (ImageView)group.findViewById(R.id.large_icon); + if (n.largeIcon != null) { + largeIcon.setImageBitmap(n.largeIcon); + largeIcon.setVisibility(View.VISIBLE); } - return group; } } diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java index c977ba3..08bbfb2 100755 --- a/packages/TtsService/src/android/tts/TtsService.java +++ b/packages/TtsService/src/android/tts/TtsService.java @@ -496,7 +496,7 @@ public class TtsService extends Service implements OnCompletionListener { * engines. */ private int speak(String callingApp, String text, int queueMode, ArrayList<String> params) { - Log.v(SERVICE_TAG, "TTS service received " + text); + // Log.v(SERVICE_TAG, "TTS service received " + text); if (queueMode == TextToSpeech.QUEUE_FLUSH) { stop(callingApp); } else if (queueMode == 2) { @@ -705,27 +705,27 @@ public class TtsService extends Service implements OnCompletionListener { } } - public void onCompletion(MediaPlayer arg0) {
- // mCurrentSpeechItem may become null if it is stopped at the same
- // time it completes.
- SpeechItem currentSpeechItemCopy = mCurrentSpeechItem;
- if (currentSpeechItemCopy != null) {
- String callingApp = currentSpeechItemCopy.mCallingApp;
- ArrayList<String> params = currentSpeechItemCopy.mParams;
- String utteranceId = "";
- if (params != null) {
- for (int i = 0; i < params.size() - 1; i = i + 2) {
- String param = params.get(i);
- if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)) {
- utteranceId = params.get(i + 1);
- }
- }
- }
- if (utteranceId.length() > 0) {
- dispatchUtteranceCompletedCallback(utteranceId, callingApp);
- }
- }
- processSpeechQueue();
+ public void onCompletion(MediaPlayer arg0) { + // mCurrentSpeechItem may become null if it is stopped at the same + // time it completes. + SpeechItem currentSpeechItemCopy = mCurrentSpeechItem; + if (currentSpeechItemCopy != null) { + String callingApp = currentSpeechItemCopy.mCallingApp; + ArrayList<String> params = currentSpeechItemCopy.mParams; + String utteranceId = ""; + if (params != null) { + for (int i = 0; i < params.size() - 1; i = i + 2) { + String param = params.get(i); + if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)) { + utteranceId = params.get(i + 1); + } + } + } + if (utteranceId.length() > 0) { + dispatchUtteranceCompletedCallback(utteranceId, callingApp); + } + } + processSpeechQueue(); } private int playSilence(String callingApp, long duration, int queueMode, @@ -1064,7 +1064,7 @@ public class TtsService extends Service implements OnCompletionListener { SoundResource sr = getSoundResource(mCurrentSpeechItem); // Synth speech as needed - synthesizer should call // processSpeechQueue to continue running the queue - Log.v(SERVICE_TAG, "TTS processing: " + mCurrentSpeechItem.mText); + // Log.v(SERVICE_TAG, "TTS processing: " + mCurrentSpeechItem.mText); if (sr == null) { if (mCurrentSpeechItem.mType == SpeechItem.TEXT) { mCurrentSpeechItem = splitCurrentTextIfNeeded(mCurrentSpeechItem); @@ -1462,8 +1462,8 @@ public class TtsService extends Service implements OnCompletionListener { * * @return SUCCESS or ERROR as defined in android.speech.tts.TextToSpeech. */ - public int setEngineByPackageName(String packageName) {
- return mSelf.setEngine(packageName);
+ public int setEngineByPackageName(String packageName) { + return mSelf.setEngine(packageName); } /** diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java index 34dbace..82753b2 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java @@ -43,13 +43,6 @@ public abstract class KeyguardViewBase extends FrameLayout { public KeyguardViewBase(Context context) { super(context); - - // drop shadow below status bar in keyguard too - mForegroundInPadding = false; - setForegroundGravity(Gravity.FILL_HORIZONTAL | Gravity.TOP); - setForeground( - context.getResources().getDrawable( - com.android.internal.R.drawable.title_bar_shadow)); } // used to inject callback diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index cc391d5..5287289 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -283,7 +283,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // the same as mCur*, but may be larger if the screen decor has supplied // content insets. int mContentLeft, mContentTop, mContentRight, mContentBottom; - // During layout, the current screen borders along with input method + // During layout, the current screen borders along which input method // windows are placed. int mDockLeft, mDockTop, mDockRight, mDockBottom; // During layout, the layer at which the doc window is placed. @@ -1510,13 +1510,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { return; } - if (false) { - if ("com.google.android.youtube".equals(attrs.packageName) - && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { - Log.i(TAG, "GOTCHA!"); - } - } - final int fl = attrs.flags; final int sim = attrs.softInputMode; @@ -1629,16 +1622,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { + " pf=" + pf.toShortString() + " df=" + df.toShortString() + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()); - if (false) { - if ("com.google.android.youtube".equals(attrs.packageName) - && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { - if (true || localLOGV) Log.v(TAG, "Computing frame of " + win + - ": sim=#" + Integer.toHexString(sim) - + " pf=" + pf.toShortString() + " df=" + df.toShortString() - + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()); - } - } - win.computeFrameLw(pf, df, cf, vf); // Dock windows carve out the bottom of the screen, so normal windows diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 84dd022..51b5947 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -343,7 +343,7 @@ sp<IAudioTrack> AudioFlinger::createTrack( lSessionId = *sessionId; } else { // if no audio session id is provided, create one here - lSessionId = nextUniqueId(); + lSessionId = nextUniqueId_l(); if (sessionId != NULL) { *sessionId = lSessionId; } @@ -3699,7 +3699,7 @@ sp<IAudioRecord> AudioFlinger::openRecord( if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) { lSessionId = *sessionId; } else { - lSessionId = nextUniqueId(); + lSessionId = nextUniqueId_l(); if (sessionId != NULL) { *sessionId = lSessionId; } @@ -4300,7 +4300,7 @@ int AudioFlinger::openOutput(uint32_t *pDevices, mHardwareStatus = AUDIO_HW_IDLE; if (output != 0) { - int id = nextUniqueId(); + int id = nextUniqueId_l(); if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || (format != AudioSystem::PCM_16_BIT) || (channels != AudioSystem::CHANNEL_OUT_STEREO)) { @@ -4348,7 +4348,7 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2) return 0; } - int id = nextUniqueId(); + int id = nextUniqueId_l(); DuplicatingThread *thread = new DuplicatingThread(this, thread1, id); thread->addOutputTrack(thread2); mPlaybackThreads.add(id, thread); @@ -4473,7 +4473,7 @@ int AudioFlinger::openInput(uint32_t *pDevices, } if (input != 0) { - int id = nextUniqueId(); + int id = nextUniqueId_l(); // Start record thread thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id); mRecordThreads.add(id, thread); @@ -4543,7 +4543,8 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output) int AudioFlinger::newAudioSessionId() { - return nextUniqueId(); + AutoMutex _l(mLock); + return nextUniqueId_l(); } // checkPlaybackThread_l() must be called with AudioFlinger::mLock held @@ -4578,9 +4579,10 @@ AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const return thread; } -int AudioFlinger::nextUniqueId() +// nextUniqueId_l() must be called with AudioFlinger::mLock held +int AudioFlinger::nextUniqueId_l() { - return android_atomic_inc(&mNextUniqueId); + return mNextUniqueId++; } // ---------------------------------------------------------------------------- @@ -4967,7 +4969,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l( LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get()); if (effect == 0) { - int id = mAudioFlinger->nextUniqueId(); + int id = mAudioFlinger->nextUniqueId_l(); // Check CPU and memory usage lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id); if (lStatus != NO_ERROR) { diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 5917632..f0ef867 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -785,7 +785,7 @@ private: float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } void audioConfigChanged_l(int event, int ioHandle, void *param2); - int nextUniqueId(); + int nextUniqueId_l(); status_t moveEffectChain_l(int session, AudioFlinger::PlaybackThread *srcThread, AudioFlinger::PlaybackThread *dstThread, diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index 40883bd..47599c8 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -473,10 +473,15 @@ class BatteryService extends Binder { private final int getIcon(int level) { if (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) { return com.android.internal.R.drawable.stat_sys_battery_charge; - } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING || - mBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING || - mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) { + } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) { return com.android.internal.R.drawable.stat_sys_battery; + } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING + || mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) { + if (isPowered() && mBatteryLevel >= 100) { + return com.android.internal.R.drawable.stat_sys_battery_charge; + } else { + return com.android.internal.R.drawable.stat_sys_battery; + } } else { return com.android.internal.R.drawable.stat_sys_battery_unknown; } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index c18262e..5c67da7 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -22,6 +22,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.MobileDataStateTracker; @@ -29,8 +30,9 @@ import android.net.NetworkInfo; import android.net.LinkProperties; import android.net.NetworkStateTracker; import android.net.NetworkUtils; +import android.net.Proxy; +import android.net.ProxyProperties; import android.net.wifi.WifiStateTracker; -import android.net.NetworkUtils; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; @@ -55,13 +57,12 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.GregorianCalendar; import java.util.List; -import java.net.InetAddress; -import java.net.UnknownHostException; /** * @hide @@ -179,6 +180,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = MAX_NETWORK_STATE_TRACKER_EVENT + 8; + /** + * used internally to reload global proxy settings + */ + private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = + MAX_NETWORK_STATE_TRACKER_EVENT + 9; + private Handler mHandler; // list of DeathRecipients used to make sure features are turned off when @@ -199,6 +206,14 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final int INET_CONDITION_LOG_MAX_SIZE = 15; private ArrayList mInetLog; + // track the current default http proxy - tell the world if we get a new one (real change) + private ProxyProperties mDefaultProxy = null; + // track the global proxy. + private ProxyProperties mGlobalProxy = null; + private final Object mGlobalProxyLock = new Object(); + + private SettingsObserver mSettingsObserver; + private static class NetworkAttributes { /** * Class for holding settings read from resources. @@ -412,6 +427,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (DBG) { mInetLog = new ArrayList(); } + + mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY); + mSettingsObserver.observe(mContext); } @@ -1303,6 +1321,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { mInitialBroadcast = null; } } + // load the global proxy at startup + mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY)); } private void handleConnect(NetworkInfo info) { @@ -1380,6 +1400,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (mNetTrackers[netType].getNetworkInfo().isConnected()) { if (mNetAttributes[netType].isDefault()) { + handleApplyDefaultProxy(netType); addDefaultRoute(mNetTrackers[netType]); } else { addPrivateDnsRoutes(mNetTrackers[netType]); @@ -1783,10 +1804,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { } break; case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: - // TODO - make this handle ip/proxy/gateway/dns changes info = (NetworkInfo) msg.obj; type = info.getType(); - handleDnsConfigurationChange(type); + handleConnectivityChange(type); break; case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: String causedBy = null; @@ -1838,6 +1858,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { handleSetMobileData(enabled); break; } + case EVENT_APPLY_GLOBAL_HTTP_PROXY: + { + handleDeprecatedGlobalHttpProxy(); + } } } } @@ -2037,4 +2061,113 @@ public class ConnectivityService extends IConnectivityManager.Stub { sendInetConditionBroadcast(networkInfo); return; } + + public synchronized ProxyProperties getProxy() { + if (mGlobalProxy != null) return mGlobalProxy; + if (mDefaultProxy != null) return mDefaultProxy; + return null; + } + + public void setGlobalProxy(ProxyProperties proxyProperties) { + enforceChangePermission(); + synchronized (mGlobalProxyLock) { + if (proxyProperties == mGlobalProxy) return; + if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return; + if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return; + + String host = ""; + int port = 0; + String exclList = ""; + if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) { + mGlobalProxy = new ProxyProperties(proxyProperties); + host = mGlobalProxy.getHost(); + port = mGlobalProxy.getPort(); + exclList = mGlobalProxy.getExclusionList(); + } else { + mGlobalProxy = null; + } + ContentResolver res = mContext.getContentResolver(); + Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host); + Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port); + Settings.Secure.putString(res,Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST, + exclList); + } + + if (mGlobalProxy == null) { + proxyProperties = mDefaultProxy; + } + sendProxyBroadcast(proxyProperties); + } + + public ProxyProperties getGlobalProxy() { + synchronized (mGlobalProxyLock) { + return mGlobalProxy; + } + } + + private void handleApplyDefaultProxy(int type) { + // check if new default - push it out to all VM if so + ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy(); + synchronized (this) { + if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return; + if (mDefaultProxy == proxy) return; + if (!TextUtils.isEmpty(proxy.getHost())) { + mDefaultProxy = proxy; + } else { + mDefaultProxy = null; + } + } + if (DBG) Slog.d(TAG, "changing default proxy to " + proxy); + if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return; + if (mGlobalProxy != null) return; + sendProxyBroadcast(proxy); + } + + private void handleDeprecatedGlobalHttpProxy() { + String proxy = Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.HTTP_PROXY); + if (!TextUtils.isEmpty(proxy)) { + String data[] = proxy.split(":"); + String proxyHost = data[0]; + int proxyPort = 8080; + if (data.length > 1) { + try { + proxyPort = Integer.parseInt(data[1]); + } catch (NumberFormatException e) { + return; + } + } + ProxyProperties p = new ProxyProperties(data[0], proxyPort, ""); + setGlobalProxy(p); + } + } + + private void sendProxyBroadcast(ProxyProperties proxy) { + Slog.d(TAG, "sending Proxy Broadcast for " + proxy); + Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy); + mContext.sendBroadcast(intent); + } + + private static class SettingsObserver extends ContentObserver { + private int mWhat; + private Handler mHandler; + SettingsObserver(Handler handler, int what) { + super(handler); + mHandler = handler; + mWhat = what; + } + + void observe(Context context) { + ContentResolver resolver = context.getContentResolver(); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.HTTP_PROXY), false, this); + } + + @Override + public void onChange(boolean selfChange) { + mHandler.obtainMessage(mWhat).sendToTarget(); + } + } } diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 3dcad38..53a19f5 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -41,9 +41,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.content.pm.PackageManager.NameNotFoundException; -import android.net.ConnectivityManager; +import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -55,9 +54,9 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.provider.Settings; -import android.util.Slog; import android.util.PrintWriterPrinter; import android.util.Printer; +import android.util.Slog; import android.util.Xml; import android.view.WindowManagerPolicy; @@ -89,9 +88,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION"; private static final long MS_PER_DAY = 86400 * 1000; - private static final long MS_PER_HOUR = 3600 * 1000; - private static final long MS_PER_MINUTE = 60 * 1000; - private static final long MIN_TIMEOUT = 86400 * 1000; // minimum expiration timeout is 1 day final Context mContext; final MyPackageMonitor mMonitor; @@ -364,6 +360,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } class MyPackageMonitor extends PackageMonitor { + @Override public void onSomePackagesChanged() { synchronized (DevicePolicyManagerService.this) { boolean removed = false; @@ -410,13 +407,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { context.registerReceiver(mReceiver, filter); } - static String countdownString(long time) { - long days = time / MS_PER_DAY; - long hours = (time / MS_PER_HOUR) % 24; - long minutes = (time / MS_PER_MINUTE) % 60; - return days + "d" + hours + "h" + minutes + "m"; - } - protected void setExpirationAlarmCheckLocked(Context context) { final long expiration = getPasswordExpirationLocked(null); final long now = System.currentTimeMillis(); @@ -430,12 +420,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { alarmTime = now + MS_PER_DAY; } - AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD, - new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION), - PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); - am.cancel(pi); - am.set(AlarmManager.RTC, alarmTime, pi); + long token = Binder.clearCallingIdentity(); + try { + AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD, + new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION), + PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); + am.cancel(pi); + am.set(AlarmManager.RTC, alarmTime, pi); + } finally { + Binder.restoreCallingIdentity(token); + } } private IPowerManager getIPowerManager() { @@ -993,8 +988,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (who == null) { throw new NullPointerException("ComponentName is null"); } - if (timeout != 0L && timeout < MIN_TIMEOUT) { - throw new IllegalArgumentException("Timeout must be > " + MIN_TIMEOUT + "ms"); + if (timeout < 0) { + throw new IllegalArgumentException("Timeout must be >= 0 ms"); } ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD); @@ -1757,10 +1752,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } // Remove white spaces proxySpec = proxySpec.trim(); + String data[] = proxySpec.split(":"); + int proxyPort = 8080; + if (data.length > 1) { + try { + proxyPort = Integer.parseInt(data[1]); + } catch (NumberFormatException e) {} + } exclusionList = exclusionList.trim(); ContentResolver res = mContext.getContentResolver(); - Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY, proxySpec); - Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST, exclusionList); + Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, data[0]); + Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, proxyPort); + Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST, + exclusionList); } @Override diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 84bc100..e14345b 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1912,7 +1912,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // If there are no selected subtypes, tries finding the most applicable one according to the // current system locale - private int findApplicableSubtype(String id) { + private int findApplicableSubtypeLocked(String id) { InputMethodInfo imi = mMethodMap.get(id); if (imi == null) { return NOT_A_SUBTYPE_ID; @@ -1954,24 +1954,28 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * @return Return the current subtype of this input method. */ public InputMethodSubtype getCurrentInputMethodSubtype() { - boolean subtypeIsSelected = false; - try { - subtypeIsSelected = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE) != NOT_A_SUBTYPE_ID; - } catch (SettingNotFoundException e) { - } - if (!subtypeIsSelected || mCurrentSubtype == null) { - String lastInputMethodId = Settings.Secure.getString(mContext - .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); - int subtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId); - if (subtypeId == NOT_A_SUBTYPE_ID) { - subtypeId = findApplicableSubtype(lastInputMethodId); - } - if (subtypeId != NOT_A_SUBTYPE_ID) { - mCurrentSubtype = mMethodMap.get(lastInputMethodId).getSubtypes().get(subtypeId); + synchronized (mMethodMap) { + boolean subtypeIsSelected = false; + try { + subtypeIsSelected = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE) != NOT_A_SUBTYPE_ID; + } catch (SettingNotFoundException e) { + } + if (!subtypeIsSelected || mCurrentSubtype == null) { + String lastInputMethodId = + Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.DEFAULT_INPUT_METHOD); + int subtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId); + if (subtypeId == NOT_A_SUBTYPE_ID) { + subtypeId = findApplicableSubtypeLocked(lastInputMethodId); + } + if (subtypeId != NOT_A_SUBTYPE_ID) { + mCurrentSubtype = + mMethodMap.get(lastInputMethodId).getSubtypes().get(subtypeId); + } } + return mCurrentSubtype; } - return mCurrentSubtype; } public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) { diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 1081a20..6de7e6a 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -272,11 +272,13 @@ public class NotificationManagerService extends INotificationManager.Stub public void onNotificationClick(String pkg, String tag, int id) { cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL, - Notification.FLAG_FOREGROUND_SERVICE); + Notification.FLAG_FOREGROUND_SERVICE, true); } public void onNotificationClear(String pkg, String tag, int id) { - cancelNotification(pkg, tag, id, 0, 0); // maybe add some flags? + cancelNotification(pkg, tag, id, 0, + Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE, + true); } public void onPanelRevealed() { @@ -312,7 +314,7 @@ public class NotificationManagerService extends INotificationManager.Stub int uid, int initialPid, String message) { Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id + "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")"); - cancelNotification(pkg, tag, id, 0, 0); + cancelNotification(pkg, tag, id, 0, 0, false); long ident = Binder.clearCallingIdentity(); try { ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg, @@ -855,7 +857,20 @@ public class NotificationManagerService extends INotificationManager.Stub manager.sendAccessibilityEvent(event); } - private void cancelNotificationLocked(NotificationRecord r) { + private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete) { + // tell the app + if (sendDelete) { + if (r.notification.deleteIntent != null) { + try { + r.notification.deleteIntent.send(); + } catch (PendingIntent.CanceledException ex) { + // do nothing - there's no relevant way to recover, and + // no reason to let this propagate + Slog.w(TAG, "canceled PendingIntent for " + r.pkg, ex); + } + } + } + // status bar if (r.notification.icon != 0) { long identity = Binder.clearCallingIdentity(); @@ -904,7 +919,7 @@ public class NotificationManagerService extends INotificationManager.Stub * and none of the {@code mustNotHaveFlags}. */ private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags, - int mustNotHaveFlags) { + int mustNotHaveFlags, boolean sendDelete) { EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, mustHaveFlags); synchronized (mNotificationList) { @@ -921,7 +936,7 @@ public class NotificationManagerService extends INotificationManager.Stub mNotificationList.remove(index); - cancelNotificationLocked(r); + cancelNotificationLocked(r, sendDelete); updateLightsLocked(); } } @@ -954,7 +969,7 @@ public class NotificationManagerService extends INotificationManager.Stub return true; } mNotificationList.remove(i); - cancelNotificationLocked(r); + cancelNotificationLocked(r, false); } if (canceledSomething) { updateLightsLocked(); @@ -973,7 +988,7 @@ public class NotificationManagerService extends INotificationManager.Stub // Don't allow client applications to cancel foreground service notis. cancelNotification(pkg, tag, id, 0, Binder.getCallingUid() == Process.SYSTEM_UID - ? 0 : Notification.FLAG_FOREGROUND_SERVICE); + ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false); } public void cancelAllNotifications(String pkg) { @@ -1009,17 +1024,8 @@ public class NotificationManagerService extends INotificationManager.Stub if ((r.notification.flags & (Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR)) == 0) { - if (r.notification.deleteIntent != null) { - try { - r.notification.deleteIntent.send(); - } catch (PendingIntent.CanceledException ex) { - // do nothing - there's no relevant way to recover, and - // no reason to let this propagate - Slog.w(TAG, "canceled PendingIntent for " + r.pkg, ex); - } - } mNotificationList.remove(i); - cancelNotificationLocked(r); + cancelNotificationLocked(r, true); } } diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index a0a1974..c121808 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -4578,6 +4578,80 @@ class PackageManagerService extends IPackageManager.Stub { mHandler.sendMessage(msg); } + public void setInstallerPackageName(String targetPackage, + String installerPackageName) { + PackageSetting pkgSetting; + final int uid = Binder.getCallingUid(); + final int permission = mContext.checkCallingPermission( + android.Manifest.permission.INSTALL_PACKAGES); + final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); + synchronized (mPackages) { + PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage); + if (targetPackageSetting == null) { + throw new IllegalArgumentException("Unknown target package: " + targetPackage); + } + + PackageSetting installerPackageSetting; + if (installerPackageName != null) { + installerPackageSetting = mSettings.mPackages.get(installerPackageName); + if (installerPackageSetting == null) { + throw new IllegalArgumentException("Unknown installer package: " + + installerPackageName); + } + } else { + installerPackageSetting = null; + } + + Signature[] callerSignature; + Object obj = mSettings.getUserIdLP(uid); + if (obj != null) { + if (obj instanceof SharedUserSetting) { + callerSignature = ((SharedUserSetting)obj).signatures.mSignatures; + } else if (obj instanceof PackageSetting) { + callerSignature = ((PackageSetting)obj).signatures.mSignatures; + } else { + throw new SecurityException("Bad object " + obj + " for uid " + uid); + } + } else { + throw new SecurityException("Unknown calling uid " + uid); + } + + // Verify: can't set installerPackageName to a package that is + // not signed with the same cert as the caller. + if (installerPackageSetting != null) { + if (checkSignaturesLP(callerSignature, + installerPackageSetting.signatures.mSignatures) + != PackageManager.SIGNATURE_MATCH) { + throw new SecurityException( + "Caller does not have same cert as new installer package " + + installerPackageName); + } + } + + // Verify: if target already has an installer package, it must + // be signed with the same cert as the caller. + if (targetPackageSetting.installerPackageName != null) { + PackageSetting setting = mSettings.mPackages.get( + targetPackageSetting.installerPackageName); + // If the currently set package isn't valid, then it's always + // okay to change it. + if (setting != null) { + if (checkSignaturesLP(callerSignature, + setting.signatures.mSignatures) + != PackageManager.SIGNATURE_MATCH) { + throw new SecurityException( + "Caller does not have same cert as old installer package " + + targetPackageSetting.installerPackageName); + } + } + } + + // Okay! + targetPackageSetting.installerPackageName = installerPackageName; + scheduleWriteSettingsLocked(); + } + } + public void setPackageObbPath(String packageName, String path) { if (DEBUG_OBB) Log.v(TAG, "Setting .obb path for " + packageName + " to: " + path); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 5038770..0c20064 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -6598,6 +6598,8 @@ public class WindowManagerService extends IWindowManager.Stub final Rect mContentFrame = new Rect(); final Rect mVisibleFrame = new Rect(); + boolean mContentChanged; + float mShownAlpha = 1; float mAlpha = 1; float mLastAlpha = 1; @@ -6800,6 +6802,7 @@ public class WindowManagerService extends IWindowManager.Stub } final Rect content = mContentFrame; + mContentChanged |= !content.equals(cf); content.set(cf); final Rect visible = mVisibleFrame; @@ -9084,7 +9087,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - private final int performLayoutLockedInner() { + private final int performLayoutLockedInner(boolean initial) { if (!mLayoutNeeded) { return 0; } @@ -9142,6 +9145,9 @@ public class WindowManagerService extends IWindowManager.Stub // just don't display"). if (!gone || !win.mHaveFrame) { if (!win.mLayoutAttached) { + if (initial) { + win.mContentChanged = false; + } mPolicy.layoutWindowLw(win, win.mAttrs, null); win.mLayoutSeq = seq; if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" @@ -9173,6 +9179,9 @@ public class WindowManagerService extends IWindowManager.Stub + " mRelayoutCalled=" + win.mRelayoutCalled); if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) || !win.mHaveFrame) { + if (initial) { + win.mContentChanged = false; + } mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); win.mLayoutSeq = seq; if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" @@ -9277,7 +9286,7 @@ public class WindowManagerService extends IWindowManager.Stub // FIRST LOOP: Perform a layout, if needed. if (repeats < 4) { - changes = performLayoutLockedInner(); + changes = performLayoutLockedInner(repeats == 0); if (changes != 0) { continue; } @@ -9327,7 +9336,7 @@ public class WindowManagerService extends IWindowManager.Stub final WindowManager.LayoutParams attrs = w.mAttrs; if (w.mSurface != null) { - // Execute animation. + // Take care of the window being ready to display. if (w.commitFinishDrawingLocked(currentTime)) { if ((w.mAttrs.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { @@ -9338,7 +9347,31 @@ public class WindowManagerService extends IWindowManager.Stub } final boolean wasAnimating = w.mAnimating; - final boolean nowAnimating = w.stepAnimationLocked(currentTime, dw, dh); + + int animDw = dw; + int animDh = dh; + + // If the window has moved due to its containing + // content frame changing, then we'd like to animate + // it. The checks here are ordered by what is least + // likely to be true first. + if (w.mContentChanged && !wasAnimating && !w.mLastHidden && !mDisplayFrozen + && (w.mFrame.top != w.mLastFrame.top + || w.mFrame.left != w.mLastFrame.left) + && mPolicy.isScreenOn()) { + // Frame has moved, containing content frame + // has also moved, and we're not currently animating... + // let's do something. + Animation a = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.window_move_from_decor); + w.setAnimation(a); + animDw = w.mLastFrame.left - w.mFrame.left; + animDh = w.mLastFrame.top - w.mFrame.top; + } + + // Execute animation. + final boolean nowAnimating = w.stepAnimationLocked(currentTime, + animDw, animDh); // If this window is animating, make a note that we have // an animating window and take care of a request to run @@ -10606,7 +10639,7 @@ public class WindowManagerService extends IWindowManager.Stub mLayoutNeeded = true; } if (mode == UPDATE_FOCUS_PLACING_SURFACES) { - performLayoutLockedInner(); + performLayoutLockedInner(true); } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { // Client will do the layout, but we need to assign layers // for handleNewWindowLocked() below. diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java index 0529080..e45c368 100644 --- a/services/java/com/android/server/WiredAccessoryObserver.java +++ b/services/java/com/android/server/WiredAccessoryObserver.java @@ -17,8 +17,10 @@ package com.android.server; import android.app.ActivityManagerNative; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.os.Handler; import android.os.Message; import android.os.PowerManager; @@ -72,14 +74,22 @@ class WiredAccessoryObserver extends UEventObserver { mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver"); mWakeLock.setReferenceCounted(false); - // At any given time both headsets could be inserted - // one on the board and one on the dock - // observe two UEVENTs + context.registerReceiver(new BootCompletedReceiver(), + new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); + } + + private final class BootCompletedReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + // At any given time accessories could be inserted + // one on the board, one on the dock and one on HDMI: + // observe three UEVENTs + init(); // set initial status for (int i = 0; i < MAX_AUDIO_PORTS; i++) { startObserving(uEventInfo[i][0]); } - init(); // set initial status - } + } + } @Override public void onUEvent(UEventObserver.UEvent event) { @@ -127,6 +137,8 @@ class WiredAccessoryObserver extends UEventObserver { int newState = mHeadsetState; mPrevHeadsetState = mHeadsetState; + if (LOG) Slog.v(TAG, "init()"); + for (int i = 0; i < MAX_AUDIO_PORTS; i++) { try { FileReader file = new FileReader(uEventInfo[i][1]); @@ -164,7 +176,8 @@ class WiredAccessoryObserver extends UEventObserver { // reject all suspect transitions: only accept state changes from: // - a: 0 heaset to 1 headset // - b: 1 headset to 0 headset - Log.v(TAG, "newState = "+newState+", headsetState = "+headsetState+", mHeadsetState = "+mHeadsetState); + if (LOG) Slog.v(TAG, "newState = "+newState+", headsetState = "+headsetState+"," + + "mHeadsetState = "+mHeadsetState); if (mHeadsetState == headsetState || ((h2w_headset & (h2w_headset - 1)) != 0)) { Log.e(TAG, "unsetting h2w flag"); h2wStateChange = false; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 1ec8a22..e815524 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -76,6 +76,8 @@ import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.net.Proxy; +import android.net.ProxyProperties; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -127,6 +129,7 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.lang.IllegalStateException; import java.lang.ref.WeakReference; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -960,6 +963,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26; static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27; static final int CLEAR_DNS_CACHE = 28; + static final int UPDATE_HTTP_PROXY = 29; AlertDialog mUidAlert; @@ -1125,6 +1129,30 @@ public final class ActivityManagerService extends ActivityManagerNative } } } break; + case UPDATE_HTTP_PROXY: { + ProxyProperties proxy = (ProxyProperties)msg.obj; + String host = ""; + String port = ""; + String exclList = ""; + if (proxy != null) { + host = proxy.getHost(); + port = Integer.toString(proxy.getPort()); + exclList = proxy.getExclusionList(); + } + synchronized (ActivityManagerService.this) { + for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { + ProcessRecord r = mLruProcesses.get(i); + if (r.thread != null) { + try { + r.thread.setHttpProxy(host, port, exclList); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to update http proxy for: " + + r.info.processName); + } + } + } + } + } break; case SHOW_UID_ERROR_MSG: { // XXX This is a temporary dialog, no need to localize. AlertDialog d = new BaseErrorDialog(mContext); @@ -10402,6 +10430,11 @@ public final class ActivityManagerService extends ActivityManagerNative mHandler.sendEmptyMessage(CLEAR_DNS_CACHE); } + if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) { + ProxyProperties proxy = intent.getParcelableExtra("proxy"); + mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy)); + } + /* * Prevent non-system code (defined here to be non-persistent * processes) from sending protected broadcasts. diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index 96c90a2..9c738ec 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -149,8 +149,6 @@ public abstract class DataConnectionTracker extends Handler { /** Slow poll when attempting connection recovery. */ protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000; - /** Default ping deadline, in seconds. */ - protected static final int DEFAULT_PING_DEADLINE = 5; /** Default max failure count before attempting to network re-registration. */ protected static final int DEFAULT_MAX_PDP_RESET_FAIL = 3; diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 70328f7..bbfdd31 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -81,7 +81,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private boolean mReregisterOnReconnectFailure = false; private ContentResolver mResolver; - private boolean mPingTestActive = false; // Count of PDP reset attempts; reset when we see incoming, // call reRegisterNetwork, or pingTest succeeds. private int mPdpResetCount = 0; @@ -654,7 +653,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { @Override protected void startNetStatPoll() { - if (mState == State.CONNECTED && mPingTestActive == false && mNetStatPollEnabled == false) { + if (mState == State.CONNECTED && mNetStatPollEnabled == false) { log("[DataConnection] Start poll NetStat"); resetPollStats(); mNetStatPollEnabled = true; @@ -763,18 +762,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { POLL_NETSTAT_SLOW_MILLIS); } else { if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) + - " pkts since last received"); - // We've exceeded the threshold. Run ping test as a final check; - // it will proceed with recovery if ping fails. + " pkts since last received start recovery process"); stopNetStatPoll(); - Thread pingTest = new Thread() { - @Override - public void run() { - runPingTest(); - } - }; - mPingTestActive = true; - pingTest.start(); + sendMessage(obtainMessage(EVENT_START_RECOVERY)); } } else { mNoRecvPollCount = 0; @@ -794,37 +784,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } }; - private void runPingTest () { - int status = -1; - try { - String address = Settings.Secure.getString(mResolver, - Settings.Secure.PDP_WATCHDOG_PING_ADDRESS); - int deadline = Settings.Secure.getInt(mResolver, - Settings.Secure.PDP_WATCHDOG_PING_DEADLINE, DEFAULT_PING_DEADLINE); - if (DBG) log("pinging " + address + " for " + deadline + "s"); - if (address != null && !NULL_IP.equals(address)) { - Process p = Runtime.getRuntime() - .exec("ping -c 1 -i 1 -w "+ deadline + " " + address); - status = p.waitFor(); - } - } catch (IOException e) { - loge("ping failed: IOException"); - } catch (Exception e) { - loge("exception trying to ping"); - } - - if (status == 0) { - // ping succeeded. False alarm. Reset netStatPoll. - // ("-1" for this event indicates a false alarm) - EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, -1); - mPdpResetCount = 0; - sendMessage(obtainMessage(EVENT_START_NETSTAT_POLL)); - } else { - // ping failed. Proceed with recovery. - sendMessage(obtainMessage(EVENT_START_RECOVERY)); - } - } - /** * Returns true if the last fail cause is something that * seems like it deserves an error notification. @@ -1007,14 +966,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { ApnSetting apn = mPendingDataConnection.getApn(); if (apn.proxy != null && apn.proxy.length() != 0) { try { - ProxyProperties proxy = new ProxyProperties(); - proxy.setSocketAddress(new InetSocketAddress(InetAddress.getByName(apn.proxy), - Integer.parseInt(apn.port))); + ProxyProperties proxy = new ProxyProperties(apn.proxy, + Integer.parseInt(apn.port), null); mLinkProperties.setHttpProxy(proxy); - } catch (UnknownHostException e) { - loge("UnknownHostException making ProxyProperties: " + e); - } catch (SecurityException e) { - loge("SecurityException making ProxyProperties: " + e); } catch (NumberFormatException e) { loge("NumberFormatException making ProxyProperties (" + apn.port + "): " + e); @@ -1404,12 +1358,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { break; case EVENT_START_NETSTAT_POLL: - mPingTestActive = false; startNetStatPoll(); break; case EVENT_START_RECOVERY: - mPingTestActive = false; doRecovery(); break; diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java index b483b82..bc00f68 100644 --- a/test-runner/src/android/test/IsolatedContext.java +++ b/test-runner/src/android/test/IsolatedContext.java @@ -87,6 +87,11 @@ public class IsolatedContext extends ContextWrapper { } @Override + public void unregisterReceiver(BroadcastReceiver receiver) { + // Ignore + } + + @Override public void sendBroadcast(Intent intent) { mBroadcastIntents.add(intent); } diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index f0cbaa0..615870b 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -341,6 +341,12 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } + @Override + public void setInstallerPackageName(String targetPackage, + String installerPackageName) { + throw new UnsupportedOperationException(); + } + /** * @hide - to match hiding in superclass */ diff --git a/tests/StatusBar/AndroidManifest.xml b/tests/StatusBar/AndroidManifest.xml index c1ca618..ddb756b 100644 --- a/tests/StatusBar/AndroidManifest.xml +++ b/tests/StatusBar/AndroidManifest.xml @@ -21,6 +21,17 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity android:name="NotificationBuilderTest" + android:label="_Notify Builder" + android:theme="@android:style/Theme.Holo" + android:hardwareAccelerated="true" + > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> <activity android:name="ToastTest" android:label="_Toasts"> <intent-filter> <action android:name="android.intent.action.MAIN" /> @@ -35,6 +46,8 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity android:name="ConfirmationActivity" android:theme="@android:style/Theme.Dialog"> + </activity> <activity android:name="TestAlertActivity" android:theme="@android:style/Theme.Dialog"> </activity> </application> diff --git a/tests/StatusBar/res/drawable-mdpi/emo_im_kissing.png b/tests/StatusBar/res/drawable-mdpi/emo_im_kissing.png Binary files differnew file mode 100644 index 0000000..56378f6 --- /dev/null +++ b/tests/StatusBar/res/drawable-mdpi/emo_im_kissing.png diff --git a/tests/StatusBar/res/drawable-mdpi/pineapple.png b/tests/StatusBar/res/drawable-mdpi/pineapple.png Binary files differnew file mode 100644 index 0000000..7377b96 --- /dev/null +++ b/tests/StatusBar/res/drawable-mdpi/pineapple.png diff --git a/tests/StatusBar/res/layout/confirmation_activity.xml b/tests/StatusBar/res/layout/confirmation_activity.xml new file mode 100644 index 0000000..50d1a49 --- /dev/null +++ b/tests/StatusBar/res/layout/confirmation_activity.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center_horizontal" + android:orientation="vertical" + > + + <TextView android:id="@+id/text" + style="?android:attr/textAppearanceLarge" + android:padding="5dip" + android:singleLine="true" + android:ellipsize="end" + android:gravity="center" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <Button + android:id="@+id/ok" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="3" + android:onClick="dismiss" + android:text="Ok" /> + +</LinearLayout> diff --git a/tests/StatusBar/res/layout/notification_builder_test.xml b/tests/StatusBar/res/layout/notification_builder_test.xml new file mode 100644 index 0000000..58c4fbb --- /dev/null +++ b/tests/StatusBar/res/layout/notification_builder_test.xml @@ -0,0 +1,819 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + android:paddingLeft="40dp" + android:paddingTop="12dp" + android:paddingRight="24dp" + android:paddingBottom="12dp" + > + + <LinearLayout + android:layout_width="220sp" + android:layout_height="match_parent" + android:layout_marginRight="24dp" + android:orientation="vertical" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_1" + /> + <TextView + style="@style/IdTitle" + android:text="1" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_1" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_2" + /> + <TextView + style="@style/IdTitle" + android:text="2" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_2" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_3" + /> + <TextView + style="@style/IdTitle" + android:text="3" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_3" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_4" + /> + <TextView + style="@style/IdTitle" + android:text="4" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_4" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_5" + /> + <TextView + style="@style/IdTitle" + android:text="5" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_5" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_6" + /> + <TextView + style="@style/IdTitle" + android:text="6" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_6" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_7" + /> + <TextView + style="@style/IdTitle" + android:text="7" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_7" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_8" + /> + <TextView + style="@style/IdTitle" + android:text="8" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_8" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_9" + /> + <TextView + style="@style/IdTitle" + android:text="9" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_9" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <Button + style="@style/IdButton.Minus" + android:id="@+id/clear_10" + /> + <TextView + style="@style/IdTitle" + android:text="10" + /> + <Button + style="@style/IdButton.Plus" + android:id="@+id/notify_10" + /> + </LinearLayout> + + <Button + android:id="@+id/clear_all" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="12dp" + android:layout_marginBottom="12dp" + android:text="Clear All" + /> + <Button + android:id="@+id/ten" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Ten notifications" + /> + + </LinearLayout> + + <ScrollView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="1" + > + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + > + + <!-- setWhen --> + <RadioGroup + android:id="@+id/group_when" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setWhen" + /> + <RadioButton + android:id="@+id/when_midnight" + style="@style/FieldContents.Disabled" + android:text="midnight" + /> + <RadioButton + android:id="@+id/when_now" + style="@style/FieldContents" + android:text="now" + /> + <RadioButton + android:id="@+id/when_now_plus_1h" + style="@style/FieldContents.Disabled" + android:text="now + 1h" + /> + <RadioButton + android:id="@+id/when_tomorrow" + style="@style/FieldContents.Disabled" + android:text="tomorrow" + /> + </RadioGroup> + + <!-- icon --> + <RadioGroup + android:id="@+id/group_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setSmallIcon" + /> + <RadioButton + android:id="@+id/icon_im" + style="@style/FieldContents" + android:text="IM" + /> + <RadioButton + android:id="@+id/icon_alert" + style="@style/FieldContents" + android:text="alert" + /> + <RadioButton + android:id="@+id/icon_surprise" + style="@style/FieldContents" + android:text="surprise" + /> + <RadioButton + android:id="@+id/icon_level0" + style="@style/FieldContents.Disabled" + android:text="level 0" + /> + <RadioButton + android:id="@+id/icon_level50" + style="@style/FieldContents.Disabled" + android:text="level 50" + /> + <RadioButton + android:id="@+id/icon_level100" + style="@style/FieldContents.Disabled" + android:text="level 100" + /> + <!-- todo setSmallIcon(int icon, int level) --> + </RadioGroup> + + <!-- setContentTitle --> + <RadioGroup + android:id="@+id/group_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setContentTitle" + /> + <RadioButton + android:id="@+id/title_short" + style="@style/FieldContents" + android:text="none" + android:tag="" + /> + <RadioButton + android:id="@+id/title_short" + style="@style/FieldContents" + android:text="cwshort" + android:tag="Title" + /> + <RadioButton + android:id="@+id/title_medium" + style="@style/FieldContents" + android:text="medium" + android:tag="Notification Test" + /> + <RadioButton + android:id="@+id/title_long" + style="@style/FieldContents" + android:text="long" + android:tag="This is one heckuva long title for a notification" + /> + </RadioGroup> + + <!-- setContentText --> + <RadioGroup + android:id="@+id/group_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setContentText" + /> + <RadioButton + android:id="@+id/text_none" + style="@style/FieldContents" + android:text="none" + android:tag="" + /> + <RadioButton + android:id="@+id/text_short" + style="@style/FieldContents" + android:tag="short" + android:text="text" + /> + <RadioButton + android:id="@+id/text_medium" + style="@style/FieldContents" + android:text="medium" + android:tag="Something happened" + /> + <RadioButton + android:id="@+id/text_long" + style="@style/FieldContents" + android:text="long" + android:tag="Oh my goodness. SOMETHING HAPPENED!!!!" + /> + <RadioButton + android:id="@+id/text_haiku" + style="@style/FieldContents" + android:text="haiku" + android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens" + /> + </RadioGroup> + + <!-- setContentInfo --> + <RadioGroup + android:id="@+id/group_info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setContentInfo" + /> + <RadioButton + android:id="@+id/info_none" + style="@style/FieldContents" + android:text="none" + android:tag="" + /> + <RadioButton + android:id="@+id/info_number" + style="@style/FieldContents" + android:text="snoozed" + android:tag="snoozed" + /> + <RadioButton + android:id="@+id/info_long" + style="@style/FieldContents" + android:text="longer" + android:tag="this content info is way too long" + /> + </RadioGroup> + + <!-- setNumber --> + <RadioGroup + android:id="@+id/group_number" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setNumber" + /> + <RadioButton + android:id="@+id/number_0" + style="@style/FieldContents" + android:text="0" + android:tag="0" + /> + <RadioButton + android:id="@+id/number_1" + style="@style/FieldContents" + android:text="1" + android:tag="1" + /> + <RadioButton + android:id="@+id/number_42" + style="@style/FieldContents" + android:text="42" + android:tag="42" + /> + <RadioButton + android:id="@+id/number_334" + style="@style/FieldContents" + android:text="334" + android:tag="334" + /> + <RadioButton + android:id="@+id/number_999" + style="@style/FieldContents" + android:text="999" + android:tag="999" + /> + <RadioButton + android:id="@+id/number_9876" + style="@style/FieldContents" + android:text="9,876" + android:tag="9876" + /> + <RadioButton + android:id="@+id/number_12345" + style="@style/FieldContents" + android:text="12,345" + android:tag="12345" + /> + </RadioGroup> + + <!-- setContentIntent --> + <RadioGroup + android:id="@+id/group_intent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setContentIntent" + /> + <RadioButton + android:id="@+id/intent_none" + style="@style/FieldContents" + android:text="none" + /> + <RadioButton + android:id="@+id/intent_alert" + style="@style/FieldContents" + android:text="alert" + /> + </RadioGroup> + + <!-- setDeleteIntent --> + <RadioGroup + android:id="@+id/group_delete" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setDeleteIntent" + /> + <RadioButton + android:id="@+id/delete_none" + style="@style/FieldContents" + android:text="none" + /> + <RadioButton + android:id="@+id/delete_alert" + style="@style/FieldContents" + android:text="alert" + /> + </RadioGroup> + + + <!-- setFullScreenIntent --> + <RadioGroup + android:id="@+id/group_full_screen" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:visibility="gone" + > + <TextView + style="@style/FieldTitle" + android:text="setFullScreenIntent" + /> + <RadioButton + android:id="@+id/full_screen_none" + style="@style/FieldContents.Disabled" + android:text="none" + /> + <RadioButton + android:id="@+id/full_screen_activity" + style="@style/FieldContents.Disabled" + android:text="full screen" + /> + </RadioGroup> + + + <!-- setTicker --> + <RadioGroup + android:id="@+id/group_ticker" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setTicker" + /> + <RadioButton + android:id="@+id/ticker_none" + style="@style/FieldContents" + android:text="none" + android:tag="" + /> + <RadioButton + android:id="@+id/ticker_short" + style="@style/FieldContents" + android:text="short" + android:tag="tick" + /> + <RadioButton + android:id="@+id/ticker_wrap" + style="@style/FieldContents" + android:text="wrap" + android:tag="tick tick tick tock tock tock something fun has happened but i don't know what it is just yet" + /> + <RadioButton + android:id="@+id/ticker_haiku" + style="@style/FieldContents" + android:text="haiku" + android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens" + /> + <RadioButton + android:id="@+id/ticker_custom" + style="@style/FieldContents.Disabled" + android:text="custom view" + /> + </RadioGroup> + + + <!-- setLargeIcon --> + <RadioGroup + android:id="@+id/group_large_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setLargeIcon" + /> + <RadioButton + android:id="@+id/large_icon_none" + style="@style/FieldContents" + android:text="none" + /> + <RadioButton + android:id="@+id/large_icon_pineapple" + style="@style/FieldContents" + android:text="pineapple" + /> + </RadioGroup> + + + <!-- setSound --> + <RadioGroup + android:id="@+id/group_sound" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:visibility="gone" + > + <TextView + style="@style/FieldTitle" + android:text="setSound" + /> + <RadioButton + android:id="@+id/sound_none" + style="@style/FieldContents.Disabled" + android:text="none" + /> + </RadioGroup> + + + <!-- setVibrate --> + <RadioGroup + android:id="@+id/group_vibrate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setVibrate" + /> + <RadioButton + android:id="@+id/vibrate_none" + style="@style/FieldContents" + android:text="none" + /> + <RadioButton + android:id="@+id/vibrate_short" + style="@style/FieldContents" + android:text="short" + /> + <RadioButton + android:id="@+id/vibrate_medium" + style="@style/FieldContents" + android:text="long" + /> + <RadioButton + android:id="@+id/vibrate_long" + style="@style/FieldContents" + android:text="long" + /> + <RadioButton + android:id="@+id/vibrate_pattern" + style="@style/FieldContents" + android:text="longer" + /> + </RadioGroup> + + + <!-- setLights --> + <RadioGroup + android:id="@+id/group_lights_color" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setLights (color)" + /> + <RadioButton + android:id="@+id/lights_red" + style="@style/FieldContents" + android:text="red" + android:tag="0xff0000" + /> + <RadioButton + android:id="@+id/lights_green" + style="@style/FieldContents" + android:text="green" + android:tag="0x00ff00" + /> + <RadioButton + android:id="@+id/lights_blue" + style="@style/FieldContents" + android:text="blue" + android:tag="0x0000ff" + /> + <RadioButton + android:id="@+id/lights_cyan" + style="@style/FieldContents" + android:text="cyan" + android:tag="0x00ffff" + /> + <RadioButton + android:id="@+id/lights_magenta" + style="@style/FieldContents" + android:text="magenta" + android:tag="0xff00ff" + /> + <RadioButton + android:id="@+id/lights_yellow" + style="@style/FieldContents" + android:text="yellow" + android:tag="0xffff00" + /> + <RadioButton + android:id="@+id/lights_white" + style="@style/FieldContents" + android:text="white" + android:tag="0xffffff" + /> + </RadioGroup> + + <!-- setLights --> + <RadioGroup + android:id="@+id/group_lights_blink" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="setLights (blink)" + /> + <RadioButton + android:id="@+id/lights_off" + style="@style/FieldContents" + android:text="off" + /> + <RadioButton + android:id="@+id/lights_slow" + style="@style/FieldContents" + android:text="slow" + /> + <RadioButton + android:id="@+id/lights_fast" + style="@style/FieldContents" + android:text="fast" + /> + <RadioButton + android:id="@+id/lights_on" + style="@style/FieldContents" + android:text="on" + /> + </RadioGroup> + + <!-- flags --> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="12dp" + > + <TextView + style="@style/FieldTitle" + android:text="flags" + /> + <CheckBox + android:id="@+id/flag_ongoing" + style="@style/FieldContents" + android:text="setOngoing" + /> + <CheckBox + android:id="@+id/flag_once" + style="@style/FieldContents" + android:text="setOnlyAlertOnce" + /> + <CheckBox + android:id="@+id/flag_auto_cancel" + style="@style/FieldContents" + android:text="setAutoCancel" + /> + </LinearLayout> + + <!-- defaults --> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + > + <TextView + style="@style/FieldTitle" + android:text="defaults" + /> + <CheckBox + android:id="@+id/default_sound" + style="@style/FieldContents" + android:text="sound" + /> + <CheckBox + android:id="@+id/default_vibrate" + style="@style/FieldContents" + android:text="vibrate" + /> + <CheckBox + android:id="@+id/default_lights" + style="@style/FieldContents" + android:text="lights" + /> + </LinearLayout> + + + + + </LinearLayout> + </ScrollView> + + +</LinearLayout> diff --git a/tests/StatusBar/res/values/styles.xml b/tests/StatusBar/res/values/styles.xml new file mode 100644 index 0000000..e051efd --- /dev/null +++ b/tests/StatusBar/res/values/styles.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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. +--> +<resources> + + <style name="IdTitle"> + <item name="android:textAppearance">?android:attr/textAppearanceLarge</item> + <item name="android:layout_width">30sp</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:gravity">center</item> + <item name="android:textStyle">bold</item> + </style> + + <style name="IdButton"> + <item name="android:textAppearance">?android:attr/textAppearanceLarge</item> + <item name="android:layout_width">0dp</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_weight">1</item> + <item name="android:layout_marginRight">8dp</item> + <item name="android:layout_marginLeft">8dp</item> + <item name="android:textStyle">bold</item> + </style> + + <style name="IdButton.Minus"> + <item name="android:text">-</item> + </style> + + <style name="IdButton.Plus"> + <item name="android:text">+</item> + </style> + + <style name="FieldTitle"> + <item name="android:textAppearance">?android:attr/textAppearanceLarge</item> + <item name="android:layout_width">208sp</item> + <item name="android:layout_height">wrap_content</item> + </style> + + <style name="FieldContents"> + <item name="android:textAppearance">?android:attr/textAppearanceMedium</item> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_marginRight">20dp</item> + </style> + + <style name="FieldContents.Disabled"> + <item name="android:clickable">false</item> + <item name="android:visibility">gone</item> + </style> + +</resources> + diff --git a/tests/StatusBar/src/com/android/statusbartest/ConfirmationActivity.java b/tests/StatusBar/src/com/android/statusbartest/ConfirmationActivity.java new file mode 100644 index 0000000..5ce8f3f --- /dev/null +++ b/tests/StatusBar/src/com/android/statusbartest/ConfirmationActivity.java @@ -0,0 +1,32 @@ +package com.android.statusbartest; + +import android.app.Activity; +import android.view.View; +import android.widget.TextView; + +public class ConfirmationActivity extends Activity { + public static final String EXTRA_TITLE = "title"; + public static final String EXTRA_TEXT = "text"; + + @Override + public void onResume() { + super.onResume(); + setContentView(R.layout.confirmation_activity); + setTitle(getTextExtra(EXTRA_TITLE, "Title")); + ((TextView)findViewById(R.id.text)).setText(getTextExtra(EXTRA_TEXT, "text")); + findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + finish(); + } + }); + } + + private String getTextExtra(String extra, String def) { + final String text = getIntent().getStringExtra(extra); + if (text == null) { + return def; + } else { + return text; + } + } +} diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java new file mode 100644 index 0000000..e9a3513 --- /dev/null +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2010 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.statusbartest; + +import android.app.Activity; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.ContentResolver; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.os.Vibrator; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.net.Uri; +import android.os.SystemClock; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.RemoteViews; +import android.os.PowerManager; + +public class NotificationBuilderTest extends Activity +{ + private final static String TAG = "NotificationTestList"; + + NotificationManager mNM; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + setContentView(R.layout.notification_builder_test); + if (icicle == null) { + setDefaults(); + } + for (int id: new int[] { + R.id.clear_1, + R.id.clear_2, + R.id.clear_3, + R.id.clear_4, + R.id.clear_5, + R.id.clear_6, + R.id.clear_7, + R.id.clear_8, + R.id.clear_9, + R.id.clear_10, + R.id.notify_1, + R.id.notify_2, + R.id.notify_3, + R.id.notify_4, + R.id.notify_5, + R.id.notify_6, + R.id.notify_7, + R.id.notify_8, + R.id.notify_9, + R.id.notify_10, + R.id.ten, + R.id.clear_all, + }) { + findViewById(id).setOnClickListener(mClickListener); + } + } + + private void setDefaults() { + setChecked(R.id.when_now); + setChecked(R.id.icon_surprise); + setChecked(R.id.title_medium); + setChecked(R.id.text_medium); + setChecked(R.id.info_none); + setChecked(R.id.number_0); + setChecked(R.id.intent_alert); + setChecked(R.id.delete_none); + setChecked(R.id.full_screen_none); + setChecked(R.id.ticker_none); + setChecked(R.id.large_icon_none); + setChecked(R.id.sound_none); + setChecked(R.id.vibrate_none); + setChecked(R.id.lights_red); + setChecked(R.id.lights_off); + } + + private View.OnClickListener mClickListener = new View.OnClickListener() { + public void onClick(View v) { + switch (v.getId()) { + case R.id.clear_1: + mNM.cancel(1); + break; + case R.id.clear_2: + mNM.cancel(2); + break; + case R.id.clear_3: + mNM.cancel(3); + break; + case R.id.clear_4: + mNM.cancel(4); + break; + case R.id.clear_5: + mNM.cancel(5); + break; + case R.id.clear_6: + mNM.cancel(6); + break; + case R.id.clear_7: + mNM.cancel(7); + break; + case R.id.clear_8: + mNM.cancel(8); + break; + case R.id.clear_9: + mNM.cancel(9); + break; + case R.id.clear_10: + mNM.cancel(10); + break; + case R.id.notify_1: + sendNotification(1); + break; + case R.id.notify_2: + sendNotification(2); + break; + case R.id.notify_3: + sendNotification(3); + break; + case R.id.notify_4: + sendNotification(4); + break; + case R.id.notify_5: + sendNotification(5); + break; + case R.id.notify_6: + sendNotification(6); + break; + case R.id.notify_7: + sendNotification(7); + break; + case R.id.notify_8: + sendNotification(8); + break; + case R.id.notify_9: + sendNotification(9); + break; + case R.id.notify_10: + sendNotification(10); + break; + case R.id.ten: { + for (int id=1; id<=10; id++) { + sendNotification(id); + } + break; + } + case R.id.clear_all: { + for (int id=1; id<=10; id++) { + mNM.cancel(id); + } + break; + } + } + } + }; + + private void sendNotification(int id) { + final Notification n = buildNotification(id); + mNM.notify(id, n); + } + + private Notification buildNotification(int id) { + Notification.Builder b = new Notification.Builder(this); + + // when + switch (getRadioChecked(R.id.group_when)) { + case R.id.when_midnight: + break; + case R.id.when_now: + b.setWhen(System.currentTimeMillis()); + break; + case R.id.when_now_plus_1h: + break; + case R.id.when_tomorrow: + break; + } + + // icon + switch (getRadioChecked(R.id.group_icon)) { + case R.id.icon_im: + b.setSmallIcon(R.drawable.icon1); + break; + case R.id.icon_alert: + b.setSmallIcon(R.drawable.icon2); + break; + case R.id.icon_surprise: + b.setSmallIcon(R.drawable.emo_im_kissing); + break; + } + + // title + final String title = getRadioTag(R.id.group_title); + if (!TextUtils.isEmpty(title)) { + b.setContentTitle(title); + } + + // text + final String text = getRadioTag(R.id.group_text); + if (!TextUtils.isEmpty(text)) { + b.setContentText(text); + } + + // info + final String info = getRadioTag(R.id.group_info); + if (!TextUtils.isEmpty(info)) { + b.setContentInfo(info); + } + + // number + b.setNumber(getRadioInt(R.id.group_number, 0)); + + // contentIntent + switch (getRadioChecked(R.id.group_intent)) { + case R.id.intent_none: + break; + case R.id.intent_alert: + b.setContentIntent(makeContentIntent(id)); + break; + } + + // deleteIntent + switch (getRadioChecked(R.id.group_delete)) { + case R.id.delete_none: + break; + case R.id.delete_alert: + b.setDeleteIntent(makeDeleteIntent(id)); + break; + } + + // fullScreenIntent TODO + + // ticker + switch (getRadioChecked(R.id.group_ticker)) { + case R.id.ticker_none: + break; + case R.id.ticker_short: + case R.id.ticker_wrap: + case R.id.ticker_haiku: + b.setTicker(getRadioTag(R.id.group_ticker)); + break; + case R.id.ticker_custom: + // TODO + break; + } + + // largeIcon + switch (getRadioChecked(R.id.group_large_icon)) { + case R.id.large_icon_none: + break; + case R.id.large_icon_pineapple: + b.setLargeIcon(loadBitmap(R.drawable.pineapple)); + break; + } + + // sound TODO + + // vibrate + switch (getRadioChecked(R.id.group_vibrate)) { + case R.id.vibrate_none: + break; + case R.id.vibrate_short: + b.setVibrate(new long[] { 0, 200 }); + break; + case R.id.vibrate_medium: + b.setVibrate(new long[] { 0, 500 }); + break; + case R.id.vibrate_long: + b.setVibrate(new long[] { 0, 1000 }); + break; + case R.id.vibrate_pattern: + b.setVibrate(new long[] { 0, 250, 250, 250, 250, 250, 250, 250 }); + break; + } + + // lights + final int color = getRadioInt(R.id.group_lights_color, 0xff0000); + int onMs; + int offMs; + switch (getRadioChecked(R.id.group_lights_blink)) { + case R.id.lights_slow: + onMs = 1300; + offMs = 1300; + break; + case R.id.lights_fast: + onMs = 300; + offMs = 300; + break; + case R.id.lights_on: + onMs = 1; + offMs = 0; + break; + case R.id.lights_off: + default: + onMs = 0; + offMs = 0; + break; + } + if (onMs != 0 && offMs != 0) { + b.setLights(color, onMs, offMs); + } + + // flags + b.setOngoing(getChecked(R.id.flag_ongoing)); + b.setOnlyAlertOnce(getChecked(R.id.flag_once)); + b.setAutoCancel(getChecked(R.id.flag_auto_cancel)); + + // defaults + int defaults = 0; + if (getChecked(R.id.default_sound)) { + defaults |= Notification.DEFAULT_SOUND; + } + if (getChecked(R.id.default_vibrate)) { + defaults |= Notification.DEFAULT_VIBRATE; + } + if (getChecked(R.id.default_lights)) { + defaults |= Notification.DEFAULT_LIGHTS; + } + b.setDefaults(defaults); + + return b.getNotification(); + } + + private void setChecked(int id) { + final CompoundButton b = (CompoundButton)findViewById(id); + b.setChecked(true); + } + + private int getRadioChecked(int id) { + final RadioGroup g = (RadioGroup)findViewById(id); + return g.getCheckedRadioButtonId(); + } + + private String getRadioTag(int id) { + final RadioGroup g = (RadioGroup)findViewById(id); + final View v = findViewById(g.getCheckedRadioButtonId()); + return (String)v.getTag(); + } + + private int getRadioInt(int id, int def) { + String str = getRadioTag(id); + if (TextUtils.isEmpty(str)) { + return def; + } else { + try { + return Integer.parseInt(str); + } catch (NumberFormatException ex) { + return def; + } + } + } + + private boolean getChecked(int id) { + final CompoundButton b = (CompoundButton)findViewById(id); + return b.isChecked(); + } + + private Bitmap loadBitmap(int id) { + final BitmapDrawable bd = (BitmapDrawable)getResources().getDrawable(id); + return Bitmap.createBitmap(bd.getBitmap()); + } + + private PendingIntent makeDeleteIntent(int id) { + Intent intent = new Intent(this, ConfirmationActivity.class); + intent.setData(Uri.fromParts("content", "//status_bar_test/delete/" + id, null)); + intent.putExtra(ConfirmationActivity.EXTRA_TITLE, "Delete intent"); + intent.putExtra(ConfirmationActivity.EXTRA_TEXT, "id: " + id); + return PendingIntent.getActivity(this, 0, intent, 0); + } + + private PendingIntent makeContentIntent(int id) { + Intent intent = new Intent(this, ConfirmationActivity.class); + intent.setData(Uri.fromParts("content", "//status_bar_test/content/" + id, null)); + intent.putExtra(ConfirmationActivity.EXTRA_TITLE, "Content intent"); + intent.putExtra(ConfirmationActivity.EXTRA_TEXT, "id: " + id); + return PendingIntent.getActivity(this, 0, intent, 0); + } +} + diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java index 2df97dc..0f0637f 100644 --- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java @@ -135,95 +135,6 @@ public class NotificationTestList extends TestActivity } }, - new Test("Ticker 1 line & icon") { - public void run() { - Notification n = new Notification(R.drawable.icon1, "tick tick tick", - mActivityCreateTime); - n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", - "This is a notification!!!", makeIntent()); - n.tickerIcons = new Bitmap[1]; - n.tickerIcons[0] = loadBitmap(R.drawable.icon3); - mNM.notify(1, n); - } - }, - - new Test("Ticker 2 lines") { - public void run() { - Notification n = new Notification(R.drawable.icon1, "tick tick tick\ntock tock", - mActivityCreateTime); - n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", - "This is a notification!!!", makeIntent()); - mNM.notify(1, n); - } - }, - - new Test("Ticker title") { - public void run() { - Notification n = new Notification(R.drawable.icon1, null, - mActivityCreateTime); - n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", - "This is a notification!!!", makeIntent()); - n.tickerTitle = "This is a title"; - mNM.notify(1, n); - } - }, - - new Test("Ticker subtitle") { - public void run() { - Notification n = new Notification(R.drawable.icon1, null, - mActivityCreateTime); - n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", - "This is a notification!!!", makeIntent()); - n.tickerSubtitle = "and a subtitle"; - mNM.notify(1, n); - } - }, - - new Test("Ticker title & subtitle") { - public void run() { - Notification n = new Notification(R.drawable.icon1, null, - mActivityCreateTime); - n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", - "This is a notification!!!", makeIntent()); - n.tickerTitle = "This is a title it is really really longggggg long long long long"; - n.tickerSubtitle = "and a subtitle it is really really longggggg long long long long long long long long long long long long long long long long"; - mNM.notify(1, n); - } - }, - - new Test("Ticker text, title & subtitle") { - public void run() { - Notification n = new Notification(R.drawable.icon1, "not visible", - mActivityCreateTime); - n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", - "This is a notification!!!", makeIntent()); - n.tickerTitle = "This is a title"; - n.tickerSubtitle = "and a subtitle"; - mNM.notify(1, n); - } - }, - - new Test("Ticker title, subtitle & 2 icons") { - public void run() { - Notification n = new Notification(R.drawable.icon1, null, - mActivityCreateTime); - n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", - "This is a notification!!!", makeIntent()); - n.tickerTitle = "This is a title"; - n.tickerSubtitle = "and a subtitle"; - - n.tickerIcons = new Bitmap[2]; - n.tickerIcons[0] = loadBitmap(R.drawable.icon3); - n.tickerIcons[1] = loadBitmap(R.drawable.app_gmail); - - mNM.notify(1, n); - /* - n.tickerIcons[0].recycle(); - n.tickerIcons[1].recycle(); - */ - } - }, - new Test("No view") { public void run() { Notification n = new Notification(R.drawable.icon1, "No view", diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 392462f..0920497 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -162,8 +162,7 @@ public class Bitmap_Delegate { } /*package*/ static void nativeDestructor(int nativeBitmap) { - // FIXME implement native delegate - throw new UnsupportedOperationException("Native delegate needed for Bitmap"); + sManager.removeDelegate(nativeBitmap); } /*package*/ static void nativeRecycle(int nativeBitmap) { diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index a5f3456..cea07af 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -18,6 +18,7 @@ package android.graphics; import com.android.layoutlib.api.ILayoutLog; import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.layoutlib.bridge.impl.Stack; import android.graphics.Paint_Delegate.FontInfo; import android.text.TextUtils; @@ -32,7 +33,6 @@ import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.util.List; -import java.util.Stack; /** diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java index 77de32d..6e80268 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java @@ -813,6 +813,10 @@ public final class Matrix_Delegate { return mask; } + private Matrix_Delegate() { + reset(); + } + /** * Adds the given transformation to the current Matrix * <p/>This in effect does this = this*matrix diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index 53da2ca..e691fdf 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -32,10 +32,12 @@ import com.android.tools.layoutlib.create.OverrideMethod; import android.graphics.Bitmap; import android.graphics.Typeface_Delegate; +import android.util.Finalizers; import java.lang.ref.SoftReference; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -61,7 +63,7 @@ public final class Bridge extends LayoutBridge { /** * Same as sRMap except for int[] instead of int resources. This is for android.R only. */ - private final static Map<int[], String> sRArrayMap = new HashMap<int[], String>(); + private final static Map<IntArray, String> sRArrayMap = new HashMap<IntArray, String>(); /** * Reverse map compared to sRMap, resource type -> (resource name -> id). * This is for android.R only. @@ -82,6 +84,44 @@ public final class Bridge extends LayoutBridge { private static Map<String, Map<String, Integer>> sEnumValueMap; /** + * int[] wrapper to use as keys in maps. + */ + private final static class IntArray { + private int[] mArray; + + private IntArray() { + // do nothing + } + + private IntArray(int[] a) { + mArray = a; + } + + private void set(int[] a) { + mArray = a; + } + + @Override + public int hashCode() { + return Arrays.hashCode(mArray); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + + IntArray other = (IntArray) obj; + if (!Arrays.equals(mArray, other.mArray)) return false; + return true; + } + } + + /** Instance of IntArrayWrapper to be reused in {@link #resolveResourceValue(int[])}. */ + private final static IntArray sIntArrayWrapper = new IntArray(); + + /** * A default logger than prints to stdout/stderr. */ private final static ILayoutLog sDefaultLogger = new ILayoutLog() { @@ -114,19 +154,12 @@ public final class Bridge extends LayoutBridge { */ @Override public boolean init(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) { - BridgeAssetManager.initSystem(); + sEnumValueMap = enumValueMap; - return sinit(fontOsLocation, enumValueMap); - } + Finalizers.init(); - @Override - public boolean dispose() { - BridgeAssetManager.clearSystem(); - return true; - } + BridgeAssetManager.initSystem(); - private static synchronized boolean sinit(String fontOsLocation, - Map<String, Map<String, Integer>> enumValueMap) { // When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener // on static (native) methods which prints the signature on the console and @@ -165,8 +198,6 @@ public final class Bridge extends LayoutBridge { return false; } - sEnumValueMap = enumValueMap; - // now parse com.android.internal.R (and only this one as android.R is a subset of // the internal version), and put the content in the maps. try { @@ -191,7 +222,7 @@ public final class Bridge extends LayoutBridge { Class<?> type = f.getType(); if (type.isArray() && type.getComponentType() == int.class) { // if the object is an int[] we put it in sRArrayMap - sRArrayMap.put((int[]) f.get(null), f.getName()); + sRArrayMap.put(new IntArray((int[]) f.get(null)), f.getName()); } else if (type == int.class) { Integer value = (Integer) f.get(null); sRMap.put(value, new String[] { f.getName(), resType }); @@ -214,6 +245,12 @@ public final class Bridge extends LayoutBridge { return true; } + @Override + public boolean dispose() { + BridgeAssetManager.clearSystem(); + return true; + } + /** * Sets a 9 patch in a project cache or in the framework cache. * @param value the path of the 9 patch @@ -321,7 +358,8 @@ public final class Bridge extends LayoutBridge { * @param array */ public static String resolveResourceValue(int[] array) { - return sRArrayMap.get(array); + sIntArrayWrapper.set(array); + return sRArrayMap.get(sIntArrayWrapper); } /** @@ -423,70 +461,4 @@ public final class Bridge extends LayoutBridge { return null; } - - - // ---------- OBSOLETE API METHODS ---------- - - /* - * For compatilibty purposes, we implement the old deprecated version of computeLayout. - * (non-Javadoc) - * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog) - */ - @Deprecated - public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription, - Object projectKey, - int screenWidth, int screenHeight, String themeName, - Map<String, Map<String, IResourceValue>> projectResources, - Map<String, Map<String, IResourceValue>> frameworkResources, - IProjectCallback customViewLoader, ILayoutLog logger) { - throw new UnsupportedOperationException(); - } - - /* - * For compatilibty purposes, we implement the old deprecated version of computeLayout. - * (non-Javadoc) - * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog) - */ - @Deprecated - public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription, - Object projectKey, - int screenWidth, int screenHeight, String themeName, boolean isProjectTheme, - Map<String, Map<String, IResourceValue>> projectResources, - Map<String, Map<String, IResourceValue>> frameworkResources, - IProjectCallback customViewLoader, ILayoutLog logger) { - throw new UnsupportedOperationException(); - } - - /* - * For compatilibty purposes, we implement the old deprecated version of computeLayout. - * (non-Javadoc) - * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog) - */ - @Deprecated - public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription, - Object projectKey, - int screenWidth, int screenHeight, int density, float xdpi, float ydpi, - String themeName, boolean isProjectTheme, - Map<String, Map<String, IResourceValue>> projectResources, - Map<String, Map<String, IResourceValue>> frameworkResources, - IProjectCallback customViewLoader, ILayoutLog logger) { - throw new UnsupportedOperationException(); - } - - /* - * (non-Javadoc) - * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, boolean, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog) - */ - @Deprecated - public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription, - Object projectKey, - int screenWidth, int screenHeight, boolean renderFullSize, - int density, float xdpi, float ydpi, - String themeName, boolean isProjectTheme, - Map<String, Map<String, IResourceValue>> projectResources, - Map<String, Map<String, IResourceValue>> frameworkResources, - IProjectCallback customViewLoader, ILayoutLog logger) { - throw new UnsupportedOperationException(); - } - } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 02db2cf..2ddabdf 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -22,6 +22,7 @@ import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IStyleResourceValue; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.impl.Stack; import com.android.layoutlib.bridge.impl.TempResourceValue; import android.app.Activity; @@ -99,6 +100,8 @@ public final class BridgeContext extends Activity { private final ILayoutLog mLogger; private BridgeContentResolver mContentResolver; + private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); + /** * @param projectKey An Object identifying the project. This is used for the cache mechanism. * @param metrics the {@link DisplayMetrics}. @@ -188,6 +191,40 @@ public final class BridgeContext extends Activity { return mDefaultPropMaps.get(key); } + /** + * Adds a parser to the stack. + * @param parser the parser to add. + */ + public void pushParser(BridgeXmlBlockParser parser) { + mParserStack.push(parser); + } + + /** + * Removes the parser at the top of the stack + */ + public void popParser() { + mParserStack.pop(); + } + + /** + * Returns the current parser at the top the of the stack. + * @return a parser or null. + */ + public BridgeXmlBlockParser getCurrentParser() { + return mParserStack.peek(); + } + + /** + * Returns the previous parser. + * @return a parser or null if there isn't any previous parser + */ + public BridgeXmlBlockParser getPreviousParser() { + if (mParserStack.size() < 2) { + return null; + } + return mParserStack.get(mParserStack.size() - 2); + } + // ------------- Activity Methods @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java index b4a28a6..d9e26e2 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java @@ -35,17 +35,17 @@ import java.io.File; import java.io.FileReader; /** - * Custom implementation of {@link LayoutInflater} to handle custom views. + * Custom implementation of {@link LayoutInflater} to handle custom views. */ public final class BridgeInflater extends LayoutInflater { - + private final IProjectCallback mProjectCallback; /** * List of class prefixes which are tried first by default. * <p/> * This should match the list in com.android.internal.policy.impl.PhoneLayoutInflater. - */ + */ private static final String[] sClassPrefixList = { "android.widget.", "android.webkit." @@ -55,10 +55,10 @@ public final class BridgeInflater extends LayoutInflater { super(original, newContext); mProjectCallback = null; } - + /** * Instantiate a new BridgeInflater with an {@link IProjectCallback} object. - * + * * @param context The Android application context. * @param projectCallback the {@link IProjectCallback} object. */ @@ -84,7 +84,7 @@ public final class BridgeInflater extends LayoutInflater { // Ignore. We'll try again using the base class below. } } - + // Next try using the parent loader. This will most likely only work for // fully-qualified class names. try { @@ -94,7 +94,7 @@ public final class BridgeInflater extends LayoutInflater { } catch (ClassNotFoundException e) { // Ignore. We'll try again using the custom view loader below. } - + // Finally try again using the custom view loader try { if (view == null) { @@ -111,12 +111,12 @@ public final class BridgeInflater extends LayoutInflater { ClassNotFoundException exception = new ClassNotFoundException("onCreateView", e); throw exception; } - + setupViewInContext(view, attrs); - + return view; } - + @Override public View createViewFromTag(View parent, String name, AttributeSet attrs) { View view = null; @@ -130,7 +130,7 @@ public final class BridgeInflater extends LayoutInflater { // Wrap the real exception in an InflateException so that the calling // method can deal with it. InflateException exception = new InflateException(); - if (e2.getClass().equals(ClassNotFoundException.class) == false) { + if (e2.getClass().equals(ClassNotFoundException.class) == false) { exception.initCause(e2); } else { exception.initCause(e); @@ -138,18 +138,18 @@ public final class BridgeInflater extends LayoutInflater { throw exception; } } - + setupViewInContext(view, attrs); - + return view; } - + @Override public View inflate(int resource, ViewGroup root) { Context context = getContext(); if (context instanceof BridgeContext) { BridgeContext bridgeContext = (BridgeContext)context; - + IResourceValue value = null; String[] layoutInfo = Bridge.resolveResourceValue(resource); @@ -158,7 +158,7 @@ public final class BridgeInflater extends LayoutInflater { layoutInfo[0]); } else { layoutInfo = mProjectCallback.resolveResourceValue(resource); - + if (layoutInfo != null) { value = bridgeContext.getProjectResource(BridgeConstants.RES_LAYOUT, layoutInfo[0]); @@ -172,10 +172,10 @@ public final class BridgeInflater extends LayoutInflater { KXmlParser parser = new KXmlParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); parser.setInput(new FileReader(f)); - + BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( parser, bridgeContext, false); - + return inflate(bridgeParser, root); } catch (Exception e) { bridgeContext.getLogger().error(e); @@ -186,7 +186,7 @@ public final class BridgeInflater extends LayoutInflater { } return null; } - + private View loadCustomView(String name, AttributeSet attrs) throws ClassNotFoundException, Exception{ if (mProjectCallback != null) { @@ -194,12 +194,12 @@ public final class BridgeInflater extends LayoutInflater { if (name.equals("view")) { name = attrs.getAttributeValue(null, "class"); } - + mConstructorArgs[1] = attrs; Object customView = mProjectCallback.loadView(name, mConstructorSignature, mConstructorArgs); - + if (customView instanceof View) { return (View)customView; } @@ -207,14 +207,27 @@ public final class BridgeInflater extends LayoutInflater { return null; } - - - + + + private void setupViewInContext(View view, AttributeSet attrs) { if (getContext() instanceof BridgeContext) { BridgeContext bc = (BridgeContext) getContext(); if (attrs instanceof BridgeXmlBlockParser) { - Object viewKey = ((BridgeXmlBlockParser) attrs).getViewKey(); + BridgeXmlBlockParser parser = (BridgeXmlBlockParser) attrs; + + // get the view key + Object viewKey = parser.getViewKey(); + + // if there's no view key and the depth is 1 (ie this is the first tag), + // look for a previous parser in the context, and check if this one has a viewkey. + if (viewKey == null && parser.getDepth() == 1) { + BridgeXmlBlockParser previousParser = bc.getPreviousParser(); + if (previousParser != null) { + viewKey = previousParser.getViewKey(); + } + } + if (viewKey != null) { bc.addViewKey(view, viewKey); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java index bfbb01a8..1011173 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java @@ -220,24 +220,37 @@ public final class BridgeResources extends Resources { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - File xml = new File(value.getValue()); - if (xml.isFile()) { - // we need to create a pull parser around the layout XML file, and then - // give that to our XmlBlockParser - try { - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileReader(xml)); + XmlPullParser parser = null; - return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); - } catch (XmlPullParserException e) { - mContext.getLogger().error(e); + try { + // check if the current parser can provide us with a custom parser. + BridgeXmlBlockParser currentParser = mContext.getCurrentParser(); + if (currentParser != null) { + parser = currentParser.getParser(value.getName()); + } + + // create a new one manually if needed. + if (parser == null) { + File xml = new File(value.getValue()); + if (xml.isFile()) { + // we need to create a pull parser around the layout XML file, and then + // give that to our XmlBlockParser + parser = new KXmlParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + parser.setInput(new FileReader(xml)); + } + } - // we'll return null below. - } catch (FileNotFoundException e) { - // this shouldn't happen since we check above. + if (parser != null) { + return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } + } catch (XmlPullParserException e) { + mContext.getLogger().error(e); + // we'll return null below. + } catch (FileNotFoundException e) { + // this shouldn't happen since we check above. } + } // id was not found or not resolved. Throw a NotFoundException. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java index 24f61c8..c3d0b14 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java @@ -40,10 +40,9 @@ public class BridgeXmlBlockParser implements XmlResourceParser { private XmlPullAttributes mAttrib; private boolean mStarted = false; - private boolean mDecNextDepth = false; - private int mDepth = 0; private int mEventType = START_DOCUMENT; private final boolean mPlatformFile; + private final BridgeContext mContext; /** * Builds a {@link BridgeXmlBlockParser}. @@ -53,14 +52,27 @@ public class BridgeXmlBlockParser implements XmlResourceParser { */ public BridgeXmlBlockParser(XmlPullParser parser, BridgeContext context, boolean platformFile) { mParser = parser; + mContext = context; mPlatformFile = platformFile; mAttrib = new BridgeXmlPullAttributes(parser, context, mPlatformFile); + + if (mContext != null) { + mContext.pushParser(this); + } } - + public boolean isPlatformFile() { return mPlatformFile; } + public IXmlPullParser getParser(String layoutName) { + if (mParser instanceof IXmlPullParser) { + return ((IXmlPullParser)mParser).getParser(layoutName); + } + + return null; + } + public Object getViewKey() { if (mParser instanceof IXmlPullParser) { return ((IXmlPullParser)mParser).getViewKey(); @@ -68,10 +80,9 @@ public class BridgeXmlBlockParser implements XmlResourceParser { return null; } - - + // ------- XmlResourceParser implementation - + public void setFeature(String name, boolean state) throws XmlPullParserException { if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) { @@ -145,7 +156,7 @@ public class BridgeXmlBlockParser implements XmlResourceParser { } public int getDepth() { - return mDepth; + return mParser.getDepth(); } public String getText() { @@ -236,17 +247,10 @@ public class BridgeXmlBlockParser implements XmlResourceParser { return START_DOCUMENT; } int ev = mParser.next(); - if (mDecNextDepth) { - mDepth--; - mDecNextDepth = false; - } - switch (ev) { - case START_TAG: - mDepth++; - break; - case END_TAG: - mDecNextDepth = true; - break; + + if (ev == END_TAG && mParser.getDepth() == 1 && mContext != null) { + // done with parser remove it from the context stack. + mContext.popParser(); } mEventType = ev; return ev; @@ -301,7 +305,7 @@ public class BridgeXmlBlockParser implements XmlResourceParser { // AttributeSet implementation - + public void close() { // pass } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java index 169d751..b272963 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java @@ -59,9 +59,7 @@ public final class DelegateManager<T> { * @return the delegate or null if not found. */ public T getDelegate(int native_object) { - synchronized (mDelegates) { - return mDelegates.get(native_object); - } + return mDelegates.get(native_object); } /** @@ -70,11 +68,9 @@ public final class DelegateManager<T> { * @return a unique native int to identify the delegate */ public int addDelegate(T newDelegate) { - synchronized (mDelegates) { - int native_object = ++mDelegateCounter; - mDelegates.put(native_object, newDelegate); - return native_object; - } + int native_object = ++mDelegateCounter; + mDelegates.put(native_object, newDelegate); + return native_object; } /** @@ -82,8 +78,6 @@ public final class DelegateManager<T> { * @param native_object the native int. */ public void removeDelegate(int native_object) { - synchronized (mDelegates) { - mDelegates.remove(native_object); - } + mDelegates.remove(native_object); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java index b0316a3..2e3f9a8 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java @@ -25,6 +25,7 @@ import com.android.layoutlib.api.SceneParams; import com.android.layoutlib.api.SceneResult; import com.android.layoutlib.api.ViewInfo; import com.android.layoutlib.api.IDensityBasedResourceValue.Density; +import com.android.layoutlib.api.SceneParams.RenderingMode; import com.android.layoutlib.bridge.BridgeConstants; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeInflater; @@ -259,22 +260,32 @@ public class LayoutSceneImpl { int renderScreenWidth = mParams.getScreenWidth(); int renderScreenHeight = mParams.getScreenHeight(); - if (mParams.getRenderFullSize()) { + RenderingMode renderingMode = mParams.getRenderingMode(); + + if (renderingMode != RenderingMode.NORMAL) { // measure the full size needed by the layout. w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth, - MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size + renderingMode.isHorizExpand() ? + MeasureSpec.UNSPECIFIED // this lets us know the actual needed size + : MeasureSpec.EXACTLY); h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset, - MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size + renderingMode.isVertExpand() ? + MeasureSpec.UNSPECIFIED // this lets us know the actual needed size + : MeasureSpec.EXACTLY); mViewRoot.measure(w_spec, h_spec); - int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth(); - if (neededWidth > renderScreenWidth) { - renderScreenWidth = neededWidth; + if (renderingMode.isHorizExpand()) { + int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth(); + if (neededWidth > renderScreenWidth) { + renderScreenWidth = neededWidth; + } } - int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight(); - if (neededHeight > renderScreenHeight - mScreenOffset) { - renderScreenHeight = neededHeight + mScreenOffset; + if (renderingMode.isVertExpand()) { + int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight(); + if (neededHeight > renderScreenHeight - mScreenOffset) { + renderScreenHeight = neededHeight + mScreenOffset; + } } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java new file mode 100644 index 0000000..9bd0015 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 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.layoutlib.bridge.impl; + +import java.util.ArrayList; + +/** + * Custom Stack implementation on top of an {@link ArrayList} instead of + * using {@link java.util.Stack} which is on top of a vector. + * + * @param <T> + */ +public class Stack<T> extends ArrayList<T> { + + private static final long serialVersionUID = 1L; + + public Stack() { + super(); + } + + public Stack(int size) { + super(size); + } + + /** + * Pushes the given object to the stack + * @param object the object to push + */ + public void push(T object) { + add(object); + } + + /** + * Remove the object at the top of the stack and returns it. + * @return the removed object or null if the stack was empty. + */ + public T pop() { + if (size() > 0) { + return remove(size() - 1); + } + + return null; + } + + /** + * Returns the object at the top of the stack. + * @return the object at the top or null if the stack is empty. + */ + public T peek() { + if (size() > 0) { + return get(size() - 1); + } + + return null; + } +} diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java index adb693d..a068ae2 100644 --- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java +++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java @@ -25,11 +25,11 @@ import junit.framework.TestCase; public class TestClassReplacement extends TestCase { public void testClassReplacements() { - // TODO: we want to test all the classes. For now only Paint passes the tests. + // TODO: we want to test all the classes. For now only, no classes pass the test. // final String[] classes = CreateInfo.RENAMED_CLASSES; final String[] classes = new String[] { - "android.graphics.Paint", "android.graphics._Original_Paint", - "android.graphics.Canvas", "android.graphics._Original_Canvas", +// "android.graphics.Paint", "android.graphics._Original_Paint", +// "android.graphics.Canvas", "android.graphics._Original_Canvas", }; final int count = classes.length; for (int i = 0 ; i < count ; i += 2) { diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java new file mode 100644 index 0000000..a83a0ad --- /dev/null +++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2010 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.net.wifi; + +import com.android.internal.util.HierarchicalState; +import com.android.internal.util.HierarchicalStateMachine; + +import android.net.wifi.WifiStateMachine.StateChangeResult; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.Message; +import android.os.Parcelable; +import android.util.Log; + +/** + * Tracks the state changes in supplicant and provides functionality + * that is based on these state changes: + * - detect a failed WPA handshake that loops indefinitely + * - password failure handling + * - Enable networks after a WPS success/failure + */ +class SupplicantStateTracker extends HierarchicalStateMachine { + + private static final String TAG = "SupplicantStateTracker"; + private static final boolean DBG = false; + + private WifiStateMachine mWifiStateMachine; + private int mPasswordFailuresCount = 0; + /* Indicates authentication failure in supplicant broadcast. + * TODO: enhance auth failure reporting to include notification + * for all type of failures: EAP, WPS & WPA networks */ + private boolean mAuthFailureInSupplicantBroadcast = false; + + /* Maximum retries on a password failure notification */ + private static final int MAX_RETRIES_ON_PASSWORD_FAILURE = 2; + + /* Track if WPS was started since we need to re-enable networks + * and load configuration afterwards */ + private boolean mWpsStarted = false; + + private Context mContext; + + private HierarchicalState mUninitializedState = new UninitializedState(); + private HierarchicalState mDefaultState = new DefaultState(); + private HierarchicalState mInactiveState = new InactiveState(); + private HierarchicalState mDisconnectState = new DisconnectedState(); + private HierarchicalState mScanState = new ScanState(); + private HierarchicalState mHandshakeState = new HandshakeState(); + private HierarchicalState mCompletedState = new CompletedState(); + private HierarchicalState mDormantState = new DormantState(); + + public SupplicantStateTracker(Context context, WifiStateMachine wsm, Handler target) { + super(TAG, target.getLooper()); + + mContext = context; + mWifiStateMachine = wsm; + addState(mDefaultState); + addState(mUninitializedState, mDefaultState); + addState(mInactiveState, mDefaultState); + addState(mDisconnectState, mDefaultState); + addState(mScanState, mDefaultState); + addState(mHandshakeState, mDefaultState); + addState(mCompletedState, mDefaultState); + addState(mDormantState, mDefaultState); + + setInitialState(mUninitializedState); + + //start the state machine + start(); + } + + public void resetSupplicantState() { + transitionTo(mUninitializedState); + } + + + private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) { + SupplicantState supState = (SupplicantState) stateChangeResult.state; + + if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n"); + + switch (supState) { + case DISCONNECTED: + transitionTo(mDisconnectState); + break; + case SCANNING: + transitionTo(mScanState); + break; + case ASSOCIATING: + case ASSOCIATED: + case FOUR_WAY_HANDSHAKE: + case GROUP_HANDSHAKE: + transitionTo(mHandshakeState); + break; + case COMPLETED: + transitionTo(mCompletedState); + break; + case DORMANT: + transitionTo(mDormantState); + break; + case INACTIVE: + transitionTo(mInactiveState); + break; + case UNINITIALIZED: + case INVALID: + transitionTo(mUninitializedState); + break; + default: + Log.e(TAG, "Unknown supplicant state " + supState); + break; + } + } + + private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) { + Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT + | Intent.FLAG_RECEIVER_REPLACE_PENDING); + intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state); + if (failedAuth) { + intent.putExtra( + WifiManager.EXTRA_SUPPLICANT_ERROR, + WifiManager.ERROR_AUTHENTICATING); + } + mContext.sendStickyBroadcast(intent); + } + + /******************************************************** + * HSM states + *******************************************************/ + + class DefaultState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + } + @Override + public boolean processMessage(Message message) { + if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); + switch (message.what) { + case WifiStateMachine.PASSWORD_MAY_BE_INCORRECT_EVENT: + mPasswordFailuresCount++; + mAuthFailureInSupplicantBroadcast = true; + break; + case WifiStateMachine.CMD_START_WPS_PBC: + case WifiStateMachine.CMD_START_WPS_PIN_FROM_AP: + case WifiStateMachine.CMD_START_WPS_PIN_FROM_DEVICE: + mWpsStarted = true; + break; + case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + StateChangeResult stateChangeResult = (StateChangeResult) message.obj; + sendSupplicantStateChangedBroadcast(stateChangeResult, + mAuthFailureInSupplicantBroadcast); + mAuthFailureInSupplicantBroadcast = false; + transitionOnSupplicantStateChange(stateChangeResult); + break; + default: + Log.e(TAG, "Ignoring " + message); + break; + } + return HANDLED; + } + } + + class UninitializedState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + mWifiStateMachine.setNetworkAvailable(false); + } + @Override + public void exit() { + mWifiStateMachine.setNetworkAvailable(true); + } + } + + class InactiveState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + /* A failed WPS connection */ + if (mWpsStarted) { + Log.e(TAG, "WPS set up failed, enabling other networks"); + WifiConfigStore.enableAllNetworks(); + mWpsStarted = false; + } + mWifiStateMachine.setNetworkAvailable(false); + } + @Override + public void exit() { + mWifiStateMachine.setNetworkAvailable(true); + } + } + + + class DisconnectedState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + /* If a disconnect event happens after password key failure + * exceeds maximum retries, disable the network + */ + + Message message = getCurrentMessage(); + StateChangeResult stateChangeResult = (StateChangeResult) message.obj; + + if (mPasswordFailuresCount >= MAX_RETRIES_ON_PASSWORD_FAILURE) { + Log.d(TAG, "Failed to authenticate, disabling network " + + stateChangeResult.networkId); + WifiConfigStore.disableNetwork(stateChangeResult.networkId); + mPasswordFailuresCount = 0; + } + } + } + + class ScanState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + } + } + + class HandshakeState extends HierarchicalState { + /** + * The max number of the WPA supplicant loop iterations before we + * decide that the loop should be terminated: + */ + private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4; + private int mLoopDetectIndex; + private int mLoopDetectCount; + + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + mLoopDetectIndex = 0; + mLoopDetectCount = 0; + } + @Override + public boolean processMessage(Message message) { + if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); + switch (message.what) { + case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + StateChangeResult stateChangeResult = (StateChangeResult) message.obj; + SupplicantState state = (SupplicantState) stateChangeResult.state; + if (state == SupplicantState.ASSOCIATING || + state == SupplicantState.ASSOCIATED || + state == SupplicantState.FOUR_WAY_HANDSHAKE || + state == SupplicantState.GROUP_HANDSHAKE) { + if (mLoopDetectIndex > state.ordinal()) { + mLoopDetectCount++; + } + if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) { + Log.d(TAG, "Supplicant loop detected, disabling network " + + stateChangeResult.networkId); + WifiConfigStore.disableNetwork(stateChangeResult.networkId); + } + mLoopDetectIndex = state.ordinal(); + sendSupplicantStateChangedBroadcast(stateChangeResult, + mAuthFailureInSupplicantBroadcast); + } else { + //Have the DefaultState handle the transition + return NOT_HANDLED; + } + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + class CompletedState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + /* Reset password failure count */ + mPasswordFailuresCount = 0; + + /* A successful WPS connection */ + if (mWpsStarted) { + WifiConfigStore.enableAllNetworks(); + WifiConfigStore.loadConfiguredNetworks(); + mWpsStarted = false; + } + } + @Override + public boolean processMessage(Message message) { + if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); + switch(message.what) { + case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + StateChangeResult stateChangeResult = (StateChangeResult) message.obj; + SupplicantState state = (SupplicantState) stateChangeResult.state; + sendSupplicantStateChangedBroadcast(stateChangeResult, + mAuthFailureInSupplicantBroadcast); + /* Ignore a re-auth in completed state */ + if (state == SupplicantState.ASSOCIATING || + state == SupplicantState.ASSOCIATED || + state == SupplicantState.FOUR_WAY_HANDSHAKE || + state == SupplicantState.GROUP_HANDSHAKE || + state == SupplicantState.COMPLETED) { + break; + } + transitionOnSupplicantStateChange(stateChangeResult); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + //TODO: remove after getting rid of the state in supplicant + class DormantState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + } + } +}
\ No newline at end of file diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java index 04b3891..24f6f31 100644 --- a/wifi/java/android/net/wifi/WifiConfigStore.java +++ b/wifi/java/android/net/wifi/WifiConfigStore.java @@ -595,9 +595,9 @@ class WifiConfigStore { out.writeUTF(PROXY_SETTINGS_KEY); out.writeUTF(config.proxySettings.toString()); out.writeUTF(PROXY_HOST_KEY); - out.writeUTF(proxyProperties.getSocketAddress().getHostName()); + out.writeUTF(proxyProperties.getHost()); out.writeUTF(PROXY_PORT_KEY); - out.writeInt(proxyProperties.getSocketAddress().getPort()); + out.writeInt(proxyProperties.getPort()); out.writeUTF(EXCLUSION_LIST_KEY); out.writeUTF(exclusionList); writeToFile = true; @@ -716,10 +716,8 @@ class WifiConfigStore { switch (proxySettings) { case STATIC: config.proxySettings = proxySettings; - ProxyProperties proxyProperties = new ProxyProperties(); - proxyProperties.setSocketAddress( - new InetSocketAddress(proxyHost, proxyPort)); - proxyProperties.setExclusionList(exclusionList); + ProxyProperties proxyProperties = + new ProxyProperties(proxyHost, proxyPort, exclusionList); linkProperties.setHttpProxy(proxyProperties); break; case NONE: @@ -1012,42 +1010,13 @@ class WifiConfigStore { switch (newConfig.proxySettings) { case STATIC: - InetSocketAddress newSockAddr = null; - String newExclusionList = null; - InetSocketAddress currentSockAddr = null; - String currentExclusionList = null; - ProxyProperties newHttpProxy = newConfig.linkProperties.getHttpProxy(); - if (newHttpProxy != null) { - newSockAddr = newHttpProxy.getSocketAddress(); - newExclusionList = newHttpProxy.getExclusionList(); - } - ProxyProperties currentHttpProxy = currentConfig.linkProperties.getHttpProxy(); - if (currentHttpProxy != null) { - currentSockAddr = currentHttpProxy.getSocketAddress(); - currentExclusionList = currentHttpProxy.getExclusionList(); - } - - boolean socketAddressDiffers = false; - boolean exclusionListDiffers = false; - if (newSockAddr != null && currentSockAddr != null ) { - socketAddressDiffers = !currentSockAddr.equals(newSockAddr); - } else if (newSockAddr != null || currentSockAddr != null) { - socketAddressDiffers = true; - } - - if (newExclusionList != null && currentExclusionList != null) { - exclusionListDiffers = !currentExclusionList.equals(newExclusionList); - } else if (newExclusionList != null || currentExclusionList != null) { - exclusionListDiffers = true; - } - - if ((currentConfig.proxySettings != newConfig.proxySettings) || - socketAddressDiffers || - exclusionListDiffers) { - proxyChanged = true; + if (newHttpProxy != null) { + proxyChanged = !newHttpProxy.equals(currentHttpProxy); + } else { + proxyChanged = (currentHttpProxy != null); } break; case NONE: diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 95e2df3..90abd02 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -49,8 +49,6 @@ import android.net.NetworkInfo.DetailedState; import android.net.LinkProperties; import android.os.Binder; import android.os.Message; -import android.os.Parcelable; -import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.PowerManager; @@ -93,8 +91,6 @@ import java.util.regex.Pattern; * * @hide */ -//TODO: we still need frequent scanning for the case when -// we issue disconnect but need scan results for open network notification public class WifiStateMachine extends HierarchicalStateMachine { private static final String TAG = "WifiStateMachine"; @@ -120,11 +116,17 @@ public class WifiStateMachine extends HierarchicalStateMachine { private String mLastBssid; private int mLastNetworkId; private boolean mEnableRssiPolling = false; - private boolean mPasswordKeyMayBeIncorrect = false; + private int mRssiPollToken = 0; private int mReconnectCount = 0; private boolean mIsScanMode = false; /** + * Interval in milliseconds between polling for RSSI + * and linkspeed information + */ + private static final int POLL_RSSI_INTERVAL_MSECS = 3000; + + /** * Instance of the bluetooth headset helper. This needs to be created * early because there is a delay before it actually 'connects', as * noted by its javadoc. If we check before it is connected, it will be @@ -148,9 +150,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* Connection to a specific network involves disabling all networks, * this flag tracks if networks need to be re-enabled */ private boolean mEnableAllNetworks = false; - /* Track if WPS was started since we need to re-enable networks - * and load configuration afterwards */ - private boolean mWpsStarted = false; private AlarmManager mAlarmManager; private PendingIntent mScanIntent; @@ -166,95 +165,95 @@ public class WifiStateMachine extends HierarchicalStateMachine { private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED = 50023; /* Load the driver */ - private static final int CMD_LOAD_DRIVER = 1; + static final int CMD_LOAD_DRIVER = 1; /* Unload the driver */ - private static final int CMD_UNLOAD_DRIVER = 2; + static final int CMD_UNLOAD_DRIVER = 2; /* Indicates driver load succeeded */ - private static final int CMD_LOAD_DRIVER_SUCCESS = 3; + static final int CMD_LOAD_DRIVER_SUCCESS = 3; /* Indicates driver load failed */ - private static final int CMD_LOAD_DRIVER_FAILURE = 4; + static final int CMD_LOAD_DRIVER_FAILURE = 4; /* Indicates driver unload succeeded */ - private static final int CMD_UNLOAD_DRIVER_SUCCESS = 5; + static final int CMD_UNLOAD_DRIVER_SUCCESS = 5; /* Indicates driver unload failed */ - private static final int CMD_UNLOAD_DRIVER_FAILURE = 6; + static final int CMD_UNLOAD_DRIVER_FAILURE = 6; /* Set bluetooth headset proxy */ - private static final int CMD_SET_BLUETOOTH_HEADSET_PROXY = 7; + static final int CMD_SET_BLUETOOTH_HEADSET_PROXY = 7; /* Set bluetooth A2dp proxy */ - private static final int CMD_SET_BLUETOOTH_A2DP_PROXY = 8; + static final int CMD_SET_BLUETOOTH_A2DP_PROXY = 8; /* Start the supplicant */ - private static final int CMD_START_SUPPLICANT = 11; + static final int CMD_START_SUPPLICANT = 11; /* Stop the supplicant */ - private static final int CMD_STOP_SUPPLICANT = 12; + static final int CMD_STOP_SUPPLICANT = 12; /* Start the driver */ - private static final int CMD_START_DRIVER = 13; + static final int CMD_START_DRIVER = 13; /* Start the driver */ - private static final int CMD_STOP_DRIVER = 14; + static final int CMD_STOP_DRIVER = 14; /* Indicates DHCP succeded */ - private static final int CMD_IP_CONFIG_SUCCESS = 15; + static final int CMD_IP_CONFIG_SUCCESS = 15; /* Indicates DHCP failed */ - private static final int CMD_IP_CONFIG_FAILURE = 16; + static final int CMD_IP_CONFIG_FAILURE = 16; /* Re-configure interface */ - private static final int CMD_RECONFIGURE_IP = 17; + static final int CMD_RECONFIGURE_IP = 17; /* Start the soft access point */ - private static final int CMD_START_AP = 21; + static final int CMD_START_AP = 21; /* Stop the soft access point */ - private static final int CMD_STOP_AP = 22; + static final int CMD_STOP_AP = 22; /* Supplicant events */ /* Connection to supplicant established */ - private static final int SUP_CONNECTION_EVENT = 31; + static final int SUP_CONNECTION_EVENT = 31; /* Connection to supplicant lost */ - private static final int SUP_DISCONNECTION_EVENT = 32; + static final int SUP_DISCONNECTION_EVENT = 32; /* Driver start completed */ - private static final int DRIVER_START_EVENT = 33; + static final int DRIVER_START_EVENT = 33; /* Driver stop completed */ - private static final int DRIVER_STOP_EVENT = 34; + static final int DRIVER_STOP_EVENT = 34; /* Network connection completed */ - private static final int NETWORK_CONNECTION_EVENT = 36; + static final int NETWORK_CONNECTION_EVENT = 36; /* Network disconnection completed */ - private static final int NETWORK_DISCONNECTION_EVENT = 37; + static final int NETWORK_DISCONNECTION_EVENT = 37; /* Scan results are available */ - private static final int SCAN_RESULTS_EVENT = 38; + static final int SCAN_RESULTS_EVENT = 38; /* Supplicate state changed */ - private static final int SUPPLICANT_STATE_CHANGE_EVENT = 39; + static final int SUPPLICANT_STATE_CHANGE_EVENT = 39; /* Password may be incorrect */ - private static final int PASSWORD_MAY_BE_INCORRECT_EVENT = 40; + static final int PASSWORD_MAY_BE_INCORRECT_EVENT = 40; /* Supplicant commands */ /* Is supplicant alive ? */ - private static final int CMD_PING_SUPPLICANT = 51; + static final int CMD_PING_SUPPLICANT = 51; /* Add/update a network configuration */ - private static final int CMD_ADD_OR_UPDATE_NETWORK = 52; + static final int CMD_ADD_OR_UPDATE_NETWORK = 52; /* Delete a network */ - private static final int CMD_REMOVE_NETWORK = 53; + static final int CMD_REMOVE_NETWORK = 53; /* Enable a network. The device will attempt a connection to the given network. */ - private static final int CMD_ENABLE_NETWORK = 54; + static final int CMD_ENABLE_NETWORK = 54; /* Disable a network. The device does not attempt a connection to the given network. */ - private static final int CMD_DISABLE_NETWORK = 55; + static final int CMD_DISABLE_NETWORK = 55; /* Blacklist network. De-prioritizes the given BSSID for connection. */ - private static final int CMD_BLACKLIST_NETWORK = 56; + static final int CMD_BLACKLIST_NETWORK = 56; /* Clear the blacklist network list */ - private static final int CMD_CLEAR_BLACKLIST = 57; + static final int CMD_CLEAR_BLACKLIST = 57; /* Save configuration */ - private static final int CMD_SAVE_CONFIG = 58; + static final int CMD_SAVE_CONFIG = 58; /* Supplicant commands after driver start*/ /* Initiate a scan */ - private static final int CMD_START_SCAN = 71; + static final int CMD_START_SCAN = 71; /* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */ - private static final int CMD_SET_SCAN_MODE = 72; + static final int CMD_SET_SCAN_MODE = 72; /* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */ - private static final int CMD_SET_SCAN_TYPE = 73; + static final int CMD_SET_SCAN_TYPE = 73; /* Disconnect from a network */ - private static final int CMD_DISCONNECT = 74; + static final int CMD_DISCONNECT = 74; /* Reconnect to a network */ - private static final int CMD_RECONNECT = 75; + static final int CMD_RECONNECT = 75; /* Reassociate to a network */ - private static final int CMD_REASSOCIATE = 76; + static final int CMD_REASSOCIATE = 76; /* Controls power mode and suspend mode optimizations * * When high perf mode is enabled, power mode is set to @@ -268,30 +267,30 @@ public class WifiStateMachine extends HierarchicalStateMachine { * - turn off roaming * - DTIM wake up settings */ - private static final int CMD_SET_HIGH_PERF_MODE = 77; + static final int CMD_SET_HIGH_PERF_MODE = 77; /* Set bluetooth co-existence * BLUETOOTH_COEXISTENCE_MODE_ENABLED * BLUETOOTH_COEXISTENCE_MODE_DISABLED * BLUETOOTH_COEXISTENCE_MODE_SENSE */ - private static final int CMD_SET_BLUETOOTH_COEXISTENCE = 78; + static final int CMD_SET_BLUETOOTH_COEXISTENCE = 78; /* Enable/disable bluetooth scan mode * true(1) * false(0) */ - private static final int CMD_SET_BLUETOOTH_SCAN_MODE = 79; + static final int CMD_SET_BLUETOOTH_SCAN_MODE = 79; /* Set the country code */ - private static final int CMD_SET_COUNTRY_CODE = 80; + static final int CMD_SET_COUNTRY_CODE = 80; /* Request connectivity manager wake lock before driver stop */ - private static final int CMD_REQUEST_CM_WAKELOCK = 81; + static final int CMD_REQUEST_CM_WAKELOCK = 81; /* Enables RSSI poll */ - private static final int CMD_ENABLE_RSSI_POLL = 82; + static final int CMD_ENABLE_RSSI_POLL = 82; /* RSSI poll */ - private static final int CMD_RSSI_POLL = 83; + static final int CMD_RSSI_POLL = 83; /* Set up packet filtering */ - private static final int CMD_START_PACKET_FILTERING = 84; + static final int CMD_START_PACKET_FILTERING = 84; /* Clear packet filter */ - private static final int CMD_STOP_PACKET_FILTERING = 85; + static final int CMD_STOP_PACKET_FILTERING = 85; /* Connect to a specified network (network id * or WifiConfiguration) This involves increasing * the priority of the network, enabling the network @@ -300,32 +299,29 @@ public class WifiStateMachine extends HierarchicalStateMachine { * an existing network. All the networks get enabled * upon a successful connection or a failure. */ - private static final int CMD_CONNECT_NETWORK = 86; + static final int CMD_CONNECT_NETWORK = 86; /* Save the specified network. This involves adding * an enabled network (if new) and updating the * config and issuing a save on supplicant config. */ - private static final int CMD_SAVE_NETWORK = 87; + static final int CMD_SAVE_NETWORK = 87; /* Delete the specified network. This involves * removing the network and issuing a save on * supplicant config. */ - private static final int CMD_FORGET_NETWORK = 88; + static final int CMD_FORGET_NETWORK = 88; /* Start Wi-Fi protected setup push button configuration */ - private static final int CMD_START_WPS_PBC = 89; + static final int CMD_START_WPS_PBC = 89; /* Start Wi-Fi protected setup pin method configuration with pin obtained from AP */ - private static final int CMD_START_WPS_PIN_FROM_AP = 90; + static final int CMD_START_WPS_PIN_FROM_AP = 90; /* Start Wi-Fi protected setup pin method configuration with pin obtained from device */ - private static final int CMD_START_WPS_PIN_FROM_DEVICE = 91; + static final int CMD_START_WPS_PIN_FROM_DEVICE = 91; /* Set the frequency band */ - private static final int CMD_SET_FREQUENCY_BAND = 92; + static final int CMD_SET_FREQUENCY_BAND = 92; - /** - * Interval in milliseconds between polling for connection - * status items that are not sent via asynchronous events. - * An example is RSSI (signal strength). - */ - private static final int POLL_RSSI_INTERVAL_MSECS = 3000; + /* Commands from the SupplicantStateTracker */ + /* Indicates whether a wifi network is available for connection */ + static final int CMD_SET_NETWORK_AVAILABLE = 111; private static final int CONNECT_MODE = 1; private static final int SCAN_ONLY_MODE = 2; @@ -463,7 +459,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { mDhcpInfo = new DhcpInfo(); mWifiInfo = new WifiInfo(); mInterfaceName = SystemProperties.get("wifi.interface", "tiwlan0"); - mSupplicantStateTracker = new SupplicantStateTracker(context, getHandler()); + mSupplicantStateTracker = new SupplicantStateTracker(context, this, getHandler()); mLinkProperties = new LinkProperties(); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); @@ -985,8 +981,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { sb.append("mLastBssid ").append(mLastBssid).append(LS); sb.append("mLastNetworkId ").append(mLastNetworkId).append(LS); sb.append("mEnableAllNetworks ").append(mEnableAllNetworks).append(LS); - sb.append("mEnableRssiPolling ").append(mEnableRssiPolling).append(LS); - sb.append("mPasswordKeyMayBeIncorrect ").append(mPasswordKeyMayBeIncorrect).append(LS); sb.append("mReconnectCount ").append(mReconnectCount).append(LS); sb.append("mIsScanMode ").append(mIsScanMode).append(LS); sb.append("Supplicant status").append(LS) @@ -1215,6 +1209,44 @@ public class WifiStateMachine extends HierarchicalStateMachine { return null; } + /* + * Fetch RSSI and linkspeed on current connection + */ + private void fetchRssiAndLinkSpeedNative() { + int newRssi = WifiNative.getRssiCommand(); + if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values + /* some implementations avoid negative values by adding 256 + * so we need to adjust for that here. + */ + if (newRssi > 0) newRssi -= 256; + mWifiInfo.setRssi(newRssi); + /* + * Rather then sending the raw RSSI out every time it + * changes, we precalculate the signal level that would + * be displayed in the status bar, and only send the + * broadcast if that much more coarse-grained number + * changes. This cuts down greatly on the number of + * broadcasts, at the cost of not mWifiInforming others + * interested in RSSI of all the changes in signal + * level. + */ + // TODO: The second arg to the call below needs to be a symbol somewhere, but + // it's actually the size of an array of icons that's private + // to StatusBar Policy. + int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, 4); + if (newSignalLevel != mLastSignalLevel) { + sendRssiChangeBroadcast(newRssi); + } + mLastSignalLevel = newSignalLevel; + } else { + mWifiInfo.setRssi(-200); + } + int newLinkSpeed = WifiNative.getLinkSpeedCommand(); + if (newLinkSpeed != -1) { + mWifiInfo.setLinkSpeed(newLinkSpeed); + } + } + private void setHighPerfModeEnabledNative(boolean enable) { if(!WifiNative.setSuspendOptimizationsCommand(!enable)) { Log.e(TAG, "set suspend optimizations failed!"); @@ -1336,19 +1368,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { mContext.sendBroadcast(intent); } - private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) { - Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state); - if (failedAuth) { - intent.putExtra( - WifiManager.EXTRA_SUPPLICANT_ERROR, - WifiManager.ERROR_AUTHENTICATING); - } - mContext.sendStickyBroadcast(intent); - } - private void sendSupplicantConnectionChangedBroadcast(boolean connected) { if (!ActivityManagerNative.isSystemReady()) return; @@ -1370,45 +1389,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { } /** - * Poll for info not reported via events - * RSSI & Linkspeed - */ - private void requestPolledInfo() { - int newRssi = WifiNative.getRssiCommand(); - if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values - /* some implementations avoid negative values by adding 256 - * so we need to adjust for that here. - */ - if (newRssi > 0) newRssi -= 256; - mWifiInfo.setRssi(newRssi); - /* - * Rather then sending the raw RSSI out every time it - * changes, we precalculate the signal level that would - * be displayed in the status bar, and only send the - * broadcast if that much more coarse-grained number - * changes. This cuts down greatly on the number of - * broadcasts, at the cost of not mWifiInforming others - * interested in RSSI of all the changes in signal - * level. - */ - // TODO: The second arg to the call below needs to be a symbol somewhere, but - // it's actually the size of an array of icons that's private - // to StatusBar Policy. - int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, 4); - if (newSignalLevel != mLastSignalLevel) { - sendRssiChangeBroadcast(newRssi); - } - mLastSignalLevel = newSignalLevel; - } else { - mWifiInfo.setRssi(-200); - } - int newLinkSpeed = WifiNative.getLinkSpeedCommand(); - if (newLinkSpeed != -1) { - mWifiInfo.setLinkSpeed(newLinkSpeed); - } - } - - /** * Resets the Wi-Fi Connections by clearing any state, resetting any sockets * using the interface, stopping DHCP & disabling interface */ @@ -1456,7 +1436,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { * WifiMonitor * thread. */ - private static class StateChangeResult { + static class StateChangeResult { StateChangeResult(int networkId, String BSSID, Object state) { this.state = state; this.BSSID = BSSID; @@ -1548,6 +1528,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { setWifiEnabled(true); } + void setNetworkAvailable(boolean available) { + sendMessage(CMD_SET_NETWORK_AVAILABLE, available ? 1 : 0); + } /******************************************************** * HSM states @@ -1576,7 +1559,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { break; case CMD_ENABLE_RSSI_POLL: mEnableRssiPolling = (message.arg1 == 1); - mSupplicantStateTracker.sendMessage(CMD_ENABLE_RSSI_POLL); + break; + case CMD_SET_NETWORK_AVAILABLE: + mNetworkInfo.setIsAvailable(message.arg1 == 1); break; /* Discard */ case CMD_LOAD_DRIVER: @@ -1616,6 +1601,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_FORGET_NETWORK: case CMD_START_WPS_PBC: case CMD_START_WPS_PIN_FROM_AP: + case CMD_RSSI_POLL: break; default: Log.e(TAG, "Error! unhandled message" + message); @@ -2136,6 +2122,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { WifiNative.setScanModeCommand(false); } break; + case CMD_START_SCAN: + WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE); + break; case CMD_SET_HIGH_PERF_MODE: setHighPerfModeEnabledNative(message.arg1 == 1); break; @@ -2278,9 +2267,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { transitionTo(mDisconnectedState); } break; - case CMD_START_SCAN: - WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE); - break; /* Ignore */ case CMD_DISCONNECT: case CMD_RECONNECT: @@ -2309,14 +2295,23 @@ public class WifiStateMachine extends HierarchicalStateMachine { StateChangeResult stateChangeResult; switch(message.what) { case PASSWORD_MAY_BE_INCORRECT_EVENT: - mPasswordKeyMayBeIncorrect = true; + mSupplicantStateTracker.sendMessage(PASSWORD_MAY_BE_INCORRECT_EVENT); break; case SUPPLICANT_STATE_CHANGE_EVENT: stateChangeResult = (StateChangeResult) message.obj; - mSupplicantStateTracker.handleEvent(stateChangeResult); - break; - case CMD_START_SCAN: - /* We need to set scan type in completed state */ + SupplicantState state = (SupplicantState) stateChangeResult.state; + // Supplicant state change + // [31-13] Reserved for future use + // [8 - 0] Supplicant state (as defined in SupplicantState.java) + // 50023 supplicant_state_changed (custom|1|5) + EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal()); + mWifiInfo.setSupplicantState(state); + mWifiInfo.setNetworkId(stateChangeResult.networkId); + if (state == SupplicantState.ASSOCIATING) { + /* BSSID is valid only in ASSOCIATING state */ + mWifiInfo.setBSSID(stateChangeResult.BSSID); + } + Message newMsg = obtainMessage(); newMsg.copyFrom(message); mSupplicantStateTracker.sendMessage(newMsg); @@ -2375,7 +2370,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { * Upon success, the configuration list needs to be reloaded */ if (success) { - mWpsStarted = true; + mSupplicantStateTracker.sendMessage(message.what); /* Expect a disconnection from the old connection */ transitionTo(mDisconnectingState); } @@ -2388,7 +2383,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { success = WifiConfigStore.startWpsWithPinFromAccessPoint(bssid, apPin); if (success) { - mWpsStarted = true; + mSupplicantStateTracker.sendMessage(message.what); /* Expect a disconnection from the old connection */ transitionTo(mDisconnectingState); } @@ -2400,7 +2395,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { mReplyChannel.replyToMessage(message, CMD_START_WPS_PIN_FROM_DEVICE, pin); if (success) { - mWpsStarted = true; + mSupplicantStateTracker.sendMessage(message.what); /* Expect a disconnection from the old connection */ transitionTo(mDisconnectingState); } @@ -2583,6 +2578,10 @@ public class WifiStateMachine extends HierarchicalStateMachine { deferMessage(message); } break; + /* Defer scan when IP is being fetched */ + case CMD_START_SCAN: + deferMessage(message); + break; case CMD_RECONFIGURE_IP: deferMessage(message); break; @@ -2619,13 +2618,11 @@ public class WifiStateMachine extends HierarchicalStateMachine { @Override public void enter() { if (DBG) Log.d(TAG, getName() + "\n"); - /* A successful WPS connection */ - if (mWpsStarted) { - WifiConfigStore.enableAllNetworks(); - WifiConfigStore.loadConfiguredNetworks(); - mWpsStarted = false; - } EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); + mRssiPollToken++; + if (mEnableRssiPolling) { + sendMessage(obtainMessage(WifiStateMachine.CMD_RSSI_POLL, mRssiPollToken, 0)); + } } @Override public boolean processMessage(Message message) { @@ -2650,6 +2647,15 @@ public class WifiStateMachine extends HierarchicalStateMachine { deferMessage(message); } break; + case CMD_START_SCAN: + /* When the network is connected, re-scanning can trigger + * a reconnection. Put it in scan-only mode during scan. + * When scan results are received, the mode is switched + * back to CONNECT_MODE. + */ + WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE); + WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE); + break; /* Ignore connection to same network */ case CMD_CONNECT_NETWORK: int netId = message.arg1; @@ -2660,6 +2666,26 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* Ignore */ case NETWORK_CONNECTION_EVENT: break; + case CMD_RSSI_POLL: + if (message.arg1 == mRssiPollToken) { + // Get Info and continue polling + fetchRssiAndLinkSpeedNative(); + sendMessageDelayed(obtainMessage(WifiStateMachine.CMD_RSSI_POLL, + mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); + } else { + // Polling has completed + } + break; + case CMD_ENABLE_RSSI_POLL: + mEnableRssiPolling = (message.arg1 == 1); + mRssiPollToken++; + if (mEnableRssiPolling) { + // first poll + fetchRssiAndLinkSpeedNative(); + sendMessageDelayed(obtainMessage(WifiStateMachine.CMD_RSSI_POLL, + mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); + } + break; default: return NOT_HANDLED; } @@ -2686,6 +2712,10 @@ public class WifiStateMachine extends HierarchicalStateMachine { deferMessage(message); } break; + /* Handle in DisconnectedState */ + case SUPPLICANT_STATE_CHANGE_EVENT: + deferMessage(message); + break; default: return NOT_HANDLED; } @@ -2734,6 +2764,12 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* Ignore network disconnect */ case NETWORK_DISCONNECTION_EVENT: break; + case SUPPLICANT_STATE_CHANGE_EVENT: + StateChangeResult stateChangeResult = (StateChangeResult) message.obj; + SupplicantState state = (SupplicantState) stateChangeResult.state; + setDetailedState(WifiInfo.getDetailedStateOf(state)); + /* DriverStartedState does the rest of the handling */ + return NOT_HANDLED; default: return NOT_HANDLED; } @@ -2795,375 +2831,4 @@ public class WifiStateMachine extends HierarchicalStateMachine { return HANDLED; } } - - - class SupplicantStateTracker extends HierarchicalStateMachine { - - private int mRssiPollToken = 0; - - /** - * The max number of the WPA supplicant loop iterations before we - * decide that the loop should be terminated: - */ - private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4; - private int mLoopDetectIndex = 0; - private int mLoopDetectCount = 0; - - /** - * Supplicant state change commands follow - * the ordinal values defined in SupplicantState.java - */ - private static final int DISCONNECTED = 0; - private static final int INACTIVE = 1; - private static final int SCANNING = 2; - private static final int ASSOCIATING = 3; - private static final int ASSOCIATED = 4; - private static final int FOUR_WAY_HANDSHAKE = 5; - private static final int GROUP_HANDSHAKE = 6; - private static final int COMPLETED = 7; - private static final int DORMANT = 8; - private static final int UNINITIALIZED = 9; - private static final int INVALID = 10; - - private HierarchicalState mUninitializedState = new UninitializedState(); - private HierarchicalState mInitializedState = new InitializedState();; - private HierarchicalState mInactiveState = new InactiveState(); - private HierarchicalState mDisconnectState = new DisconnectedState(); - private HierarchicalState mScanState = new ScanState(); - private HierarchicalState mConnectState = new ConnectState(); - private HierarchicalState mHandshakeState = new HandshakeState(); - private HierarchicalState mCompletedState = new CompletedState(); - private HierarchicalState mDormantState = new DormantState(); - - public SupplicantStateTracker(Context context, Handler target) { - super(TAG, target.getLooper()); - - addState(mUninitializedState); - addState(mInitializedState); - addState(mInactiveState, mInitializedState); - addState(mDisconnectState, mInitializedState); - addState(mScanState, mInitializedState); - addState(mConnectState, mInitializedState); - addState(mHandshakeState, mConnectState); - addState(mCompletedState, mConnectState); - addState(mDormantState, mInitializedState); - - setInitialState(mUninitializedState); - - //start the state machine - start(); - } - - public void handleEvent(StateChangeResult stateChangeResult) { - SupplicantState newState = (SupplicantState) stateChangeResult.state; - - // Supplicant state change - // [31-13] Reserved for future use - // [8 - 0] Supplicant state (as defined in SupplicantState.java) - // 50023 supplicant_state_changed (custom|1|5) - EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, newState.ordinal()); - - sendMessage(obtainMessage(newState.ordinal(), stateChangeResult)); - } - - public void resetSupplicantState() { - transitionTo(mUninitializedState); - } - - private void resetLoopDetection() { - mLoopDetectCount = 0; - mLoopDetectIndex = 0; - } - - private boolean handleTransition(Message msg) { - if (DBG) Log.d(TAG, getName() + msg.toString() + "\n"); - switch (msg.what) { - case DISCONNECTED: - transitionTo(mDisconnectState); - break; - case SCANNING: - transitionTo(mScanState); - break; - case ASSOCIATING: - StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; - /* BSSID is valid only in ASSOCIATING state */ - mWifiInfo.setBSSID(stateChangeResult.BSSID); - //$FALL-THROUGH$ - case ASSOCIATED: - case FOUR_WAY_HANDSHAKE: - case GROUP_HANDSHAKE: - transitionTo(mHandshakeState); - break; - case COMPLETED: - transitionTo(mCompletedState); - break; - case DORMANT: - transitionTo(mDormantState); - break; - case INACTIVE: - transitionTo(mInactiveState); - break; - case UNINITIALIZED: - case INVALID: - transitionTo(mUninitializedState); - break; - default: - return NOT_HANDLED; - } - StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; - SupplicantState supState = (SupplicantState) stateChangeResult.state; - setDetailedState(WifiInfo.getDetailedStateOf(supState)); - mWifiInfo.setSupplicantState(supState); - mWifiInfo.setNetworkId(stateChangeResult.networkId); - return HANDLED; - } - - /******************************************************** - * HSM states - *******************************************************/ - - class InitializedState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - @Override - public boolean processMessage(Message message) { - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case CMD_START_SCAN: - WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE); - break; - default: - if (DBG) Log.w(TAG, "Ignoring " + message); - break; - } - return HANDLED; - } - } - - class UninitializedState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - mNetworkInfo.setIsAvailable(false); - resetLoopDetection(); - mPasswordKeyMayBeIncorrect = false; - } - @Override - public boolean processMessage(Message message) { - switch(message.what) { - default: - if (!handleTransition(message)) { - if (DBG) Log.w(TAG, "Ignoring " + message); - } - break; - } - return HANDLED; - } - @Override - public void exit() { - mNetworkInfo.setIsAvailable(true); - } - } - - class InactiveState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - - /* A failed WPS connection */ - if (mWpsStarted) { - Log.e(TAG, "WPS set up failed, enabling other networks"); - WifiConfigStore.enableAllNetworks(); - mWpsStarted = false; - } - - Message message = getCurrentMessage(); - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - - mNetworkInfo.setIsAvailable(false); - resetLoopDetection(); - mPasswordKeyMayBeIncorrect = false; - - sendSupplicantStateChangedBroadcast(stateChangeResult, false); - } - @Override - public boolean processMessage(Message message) { - return handleTransition(message); - } - @Override - public void exit() { - mNetworkInfo.setIsAvailable(true); - } - } - - - class DisconnectedState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - Message message = getCurrentMessage(); - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - - resetLoopDetection(); - - /* If a disconnect event happens after a password key failure - * event, disable the network - */ - if (mPasswordKeyMayBeIncorrect) { - Log.d(TAG, "Failed to authenticate, disabling network " + - mWifiInfo.getNetworkId()); - WifiConfigStore.disableNetwork(mWifiInfo.getNetworkId()); - mPasswordKeyMayBeIncorrect = false; - sendSupplicantStateChangedBroadcast(stateChangeResult, true); - } - else { - sendSupplicantStateChangedBroadcast(stateChangeResult, false); - } - } - @Override - public boolean processMessage(Message message) { - return handleTransition(message); - } - } - - class ScanState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - Message message = getCurrentMessage(); - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - - mPasswordKeyMayBeIncorrect = false; - resetLoopDetection(); - sendSupplicantStateChangedBroadcast(stateChangeResult, false); - } - @Override - public boolean processMessage(Message message) { - return handleTransition(message); - } - } - - class ConnectState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - @Override - public boolean processMessage(Message message) { - switch (message.what) { - case CMD_START_SCAN: - WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE); - WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class HandshakeState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - final Message message = getCurrentMessage(); - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - - if (mLoopDetectIndex > message.what) { - mLoopDetectCount++; - } - if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) { - WifiConfigStore.disableNetwork(stateChangeResult.networkId); - mLoopDetectCount = 0; - } - - mLoopDetectIndex = message.what; - - mPasswordKeyMayBeIncorrect = false; - sendSupplicantStateChangedBroadcast(stateChangeResult, false); - } - @Override - public boolean processMessage(Message message) { - return handleTransition(message); - } - } - - class CompletedState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - Message message = getCurrentMessage(); - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - - mRssiPollToken++; - if (mEnableRssiPolling) { - sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), - POLL_RSSI_INTERVAL_MSECS); - } - - resetLoopDetection(); - - mPasswordKeyMayBeIncorrect = false; - sendSupplicantStateChangedBroadcast(stateChangeResult, false); - } - @Override - public boolean processMessage(Message message) { - switch(message.what) { - case ASSOCIATING: - case ASSOCIATED: - case FOUR_WAY_HANDSHAKE: - case GROUP_HANDSHAKE: - case COMPLETED: - break; - case CMD_RSSI_POLL: - if (message.arg1 == mRssiPollToken) { - // Get Info and continue polling - requestPolledInfo(); - sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), - POLL_RSSI_INTERVAL_MSECS); - } else { - // Polling has completed - } - break; - case CMD_ENABLE_RSSI_POLL: - mRssiPollToken++; - if (mEnableRssiPolling) { - // first poll - requestPolledInfo(); - sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), - POLL_RSSI_INTERVAL_MSECS); - } - break; - default: - return handleTransition(message); - } - return HANDLED; - } - } - - class DormantState extends HierarchicalState { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - Message message = getCurrentMessage(); - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - - resetLoopDetection(); - mPasswordKeyMayBeIncorrect = false; - - sendSupplicantStateChangedBroadcast(stateChangeResult, false); - - /* TODO: reconnect is now being handled at DHCP failure handling - * If we run into issues with staying in Dormant state, might - * need a reconnect here - */ - } - @Override - public boolean processMessage(Message message) { - return handleTransition(message); - } - } - } } |