diff options
545 files changed, 7645 insertions, 5725 deletions
@@ -235596,7 +235596,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -236083,7 +236083,7 @@ synchronized="true" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -236149,7 +236149,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -236270,7 +236270,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -236639,7 +236639,7 @@ synchronized="true" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="l" type="android.webkit.WebSettings.LayoutAlgorithm"> @@ -236717,7 +236717,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="enabled" type="boolean"> @@ -236912,7 +236912,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="view" type="boolean"> @@ -237040,7 +237040,7 @@ abstract="false" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <method name="valueOf" @@ -237726,7 +237726,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -237748,7 +237748,7 @@ synchronized="false" static="true" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -237772,7 +237772,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -237783,7 +237783,7 @@ synchronized="false" static="true" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -238320,7 +238320,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="b" type="android.os.Bundle"> @@ -238376,7 +238376,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="b" type="android.os.Bundle"> @@ -238531,7 +238531,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="listener" type="android.webkit.WebView.PictureListener"> @@ -238803,7 +238803,7 @@ abstract="true" static="true" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <method name="onNewPicture" @@ -238813,7 +238813,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="view" type="android.webkit.WebView"> diff --git a/api/current.xml b/api/current.xml index b482602..fb4cdde 100644 --- a/api/current.xml +++ b/api/current.xml @@ -28850,7 +28850,7 @@ deprecated="not deprecated" visibility="public" > -<method name="completedDownload" +<method name="addCompletedDownload" return="long" abstract="false" native="false" @@ -94415,6 +94415,17 @@ visibility="public" > </method> +<method name="getDescription" + return="java.lang.String" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getManufacturer" return="java.lang.String" abstract="false" @@ -94437,7 +94448,7 @@ visibility="public" > </method> -<method name="getType" +<method name="getUri" return="java.lang.String" abstract="false" native="false" @@ -94869,13 +94880,13 @@ extends="java.lang.Object" abstract="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > <implements name="android.os.Parcelable"> </implements> -<method name="bulkTransfer" +<method name="describeContents" return="int" abstract="false" native="false" @@ -94885,17 +94896,9 @@ deprecated="not deprecated" visibility="public" > -<parameter name="endpoint" type="android.hardware.usb.UsbEndpoint"> -</parameter> -<parameter name="buffer" type="byte[]"> -</parameter> -<parameter name="length" type="int"> -</parameter> -<parameter name="timeout" type="int"> -</parameter> </method> -<method name="claimInterface" - return="boolean" +<method name="getDeviceClass" + return="int" abstract="false" native="false" synchronized="false" @@ -94904,13 +94907,9 @@ deprecated="not deprecated" visibility="public" > -<parameter name="intf" type="android.hardware.usb.UsbInterface"> -</parameter> -<parameter name="force" type="boolean"> -</parameter> </method> -<method name="close" - return="void" +<method name="getDeviceId" + return="int" abstract="false" native="false" synchronized="false" @@ -94920,33 +94919,21 @@ visibility="public" > </method> -<method name="controlTransfer" +<method name="getDeviceId" return="int" abstract="false" native="false" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="requestType" type="int"> -</parameter> -<parameter name="request" type="int"> -</parameter> -<parameter name="value" type="int"> -</parameter> -<parameter name="index" type="int"> -</parameter> -<parameter name="buffer" type="byte[]"> -</parameter> -<parameter name="length" type="int"> -</parameter> -<parameter name="timeout" type="int"> +<parameter name="name" type="java.lang.String"> </parameter> </method> -<method name="describeContents" - return="int" +<method name="getDeviceName" + return="java.lang.String" abstract="false" native="false" synchronized="false" @@ -94956,18 +94943,20 @@ visibility="public" > </method> -<method name="getDeviceClass" - return="int" +<method name="getDeviceName" + return="java.lang.String" abstract="false" native="false" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" > +<parameter name="id" type="int"> +</parameter> </method> -<method name="getDeviceId" +<method name="getDeviceProtocol" return="int" abstract="false" native="false" @@ -94978,21 +94967,19 @@ visibility="public" > </method> -<method name="getDeviceId" +<method name="getDeviceSubclass" return="int" abstract="false" native="false" synchronized="false" - static="true" + static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="name" type="java.lang.String"> -</parameter> </method> -<method name="getDeviceName" - return="java.lang.String" +<method name="getInterface" + return="android.hardware.usb.UsbInterface" abstract="false" native="false" synchronized="false" @@ -95001,21 +94988,21 @@ deprecated="not deprecated" visibility="public" > +<parameter name="index" type="int"> +</parameter> </method> -<method name="getDeviceName" - return="java.lang.String" +<method name="getInterfaceCount" + return="int" abstract="false" native="false" synchronized="false" - static="true" + static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="id" type="int"> -</parameter> </method> -<method name="getDeviceProtocol" +<method name="getProductId" return="int" abstract="false" native="false" @@ -95026,7 +95013,7 @@ visibility="public" > </method> -<method name="getDeviceSubclass" +<method name="getVendorId" return="int" abstract="false" native="false" @@ -95037,8 +95024,8 @@ visibility="public" > </method> -<method name="getFileDescriptor" - return="int" +<method name="writeToParcel" + return="void" abstract="false" native="false" synchronized="false" @@ -95047,21 +95034,31 @@ deprecated="not deprecated" visibility="public" > +<parameter name="parcel" type="android.os.Parcel"> +</parameter> +<parameter name="flags" type="int"> +</parameter> </method> -<method name="getInterface" - return="android.hardware.usb.UsbInterface" +<field name="CREATOR" + type="android.os.Parcelable.Creator" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> +<class name="UsbDeviceConnection" + extends="java.lang.Object" abstract="false" - native="false" - synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="index" type="int"> -</parameter> -</method> -<method name="getInterfaceCount" +<method name="bulkTransfer" return="int" abstract="false" native="false" @@ -95071,9 +95068,17 @@ deprecated="not deprecated" visibility="public" > +<parameter name="endpoint" type="android.hardware.usb.UsbEndpoint"> +</parameter> +<parameter name="buffer" type="byte[]"> +</parameter> +<parameter name="length" type="int"> +</parameter> +<parameter name="timeout" type="int"> +</parameter> </method> -<method name="getProductId" - return="int" +<method name="claimInterface" + return="boolean" abstract="false" native="false" synchronized="false" @@ -95082,9 +95087,13 @@ deprecated="not deprecated" visibility="public" > +<parameter name="intf" type="android.hardware.usb.UsbInterface"> +</parameter> +<parameter name="force" type="boolean"> +</parameter> </method> -<method name="getSerial" - return="java.lang.String" +<method name="close" + return="void" abstract="false" native="false" synchronized="false" @@ -95094,7 +95103,7 @@ visibility="public" > </method> -<method name="getVendorId" +<method name="controlTransfer" return="int" abstract="false" native="false" @@ -95104,9 +95113,23 @@ deprecated="not deprecated" visibility="public" > +<parameter name="requestType" type="int"> +</parameter> +<parameter name="request" type="int"> +</parameter> +<parameter name="value" type="int"> +</parameter> +<parameter name="index" type="int"> +</parameter> +<parameter name="buffer" type="byte[]"> +</parameter> +<parameter name="length" type="int"> +</parameter> +<parameter name="timeout" type="int"> +</parameter> </method> -<method name="releaseInterface" - return="boolean" +<method name="getFileDescriptor" + return="int" abstract="false" native="false" synchronized="false" @@ -95115,11 +95138,9 @@ deprecated="not deprecated" visibility="public" > -<parameter name="intf" type="android.hardware.usb.UsbInterface"> -</parameter> </method> -<method name="requestWait" - return="android.hardware.usb.UsbRequest" +<method name="getSerial" + return="java.lang.String" abstract="false" native="false" synchronized="false" @@ -95129,8 +95150,8 @@ visibility="public" > </method> -<method name="writeToParcel" - return="void" +<method name="releaseInterface" + return="boolean" abstract="false" native="false" synchronized="false" @@ -95139,27 +95160,26 @@ deprecated="not deprecated" visibility="public" > -<parameter name="parcel" type="android.os.Parcel"> -</parameter> -<parameter name="flags" type="int"> +<parameter name="intf" type="android.hardware.usb.UsbInterface"> </parameter> </method> -<field name="CREATOR" - type="android.os.Parcelable.Creator" - transient="false" - volatile="false" - static="true" - final="true" +<method name="requestWait" + return="android.hardware.usb.UsbRequest" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" deprecated="not deprecated" visibility="public" > -</field> +</method> </class> <class name="UsbEndpoint" extends="java.lang.Object" abstract="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -95198,17 +95218,6 @@ visibility="public" > </method> -<method name="getDevice" - return="android.hardware.usb.UsbDevice" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> <method name="getDirection" return="int" abstract="false" @@ -95231,17 +95240,6 @@ visibility="public" > </method> -<method name="getInterface" - return="android.hardware.usb.UsbInterface" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> <method name="getInterval" return="int" abstract="false" @@ -95322,17 +95320,6 @@ visibility="public" > </method> -<method name="getDevice" - return="android.hardware.usb.UsbDevice" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> <method name="getEndpoint" return="android.hardware.usb.UsbEndpoint" abstract="false" @@ -95457,30 +95444,30 @@ visibility="public" > </method> -<method name="isFunctionEnabled" +<method name="hasPermission" return="boolean" abstract="false" native="false" synchronized="false" - static="true" + static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="function" type="java.lang.String"> +<parameter name="device" type="android.hardware.usb.UsbDevice"> </parameter> </method> -<method name="isFunctionSupported" +<method name="hasPermission" return="boolean" abstract="false" native="false" synchronized="false" - static="true" + static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="function" type="java.lang.String"> +<parameter name="accessory" type="android.hardware.usb.UsbAccessory"> </parameter> </method> <method name="openAccessory" @@ -95497,7 +95484,20 @@ </parameter> </method> <method name="openDevice" - return="boolean" + return="android.hardware.usb.UsbDeviceConnection" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="device" type="android.hardware.usb.UsbDevice"> +</parameter> +</method> +<method name="requestPermission" + return="void" abstract="false" native="false" synchronized="false" @@ -95508,6 +95508,23 @@ > <parameter name="device" type="android.hardware.usb.UsbDevice"> </parameter> +<parameter name="pi" type="android.app.PendingIntent"> +</parameter> +</method> +<method name="requestPermission" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="accessory" type="android.hardware.usb.UsbAccessory"> +</parameter> +<parameter name="pi" type="android.app.PendingIntent"> +</parameter> </method> <field name="ACTION_USB_ACCESSORY_ATTACHED" type="java.lang.String" @@ -95553,17 +95570,6 @@ visibility="public" > </field> -<field name="ACTION_USB_STATE" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.hardware.usb.action.USB_STATE"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="EXTRA_ACCESSORY" type="java.lang.String" transient="false" @@ -95586,99 +95592,11 @@ visibility="public" > </field> -<field name="USB_CONFIGURATION" - type="java.lang.String" - transient="false" - volatile="false" - value=""configuration"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_CONNECTED" - type="java.lang.String" - transient="false" - volatile="false" - value=""connected"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_FUNCTION_ACCESSORY" - type="java.lang.String" - transient="false" - volatile="false" - value=""accessory"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_FUNCTION_ADB" +<field name="EXTRA_PERMISSION_GRANTED" type="java.lang.String" transient="false" volatile="false" - value=""adb"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_FUNCTION_DISABLED" - type="java.lang.String" - transient="false" - volatile="false" - value=""disabled"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_FUNCTION_ENABLED" - type="java.lang.String" - transient="false" - volatile="false" - value=""enabled"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_FUNCTION_MASS_STORAGE" - type="java.lang.String" - transient="false" - volatile="false" - value=""mass_storage"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_FUNCTION_MTP" - type="java.lang.String" - transient="false" - volatile="false" - value=""mtp"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="USB_FUNCTION_RNDIS" - type="java.lang.String" - transient="false" - volatile="false" - value=""rndis"" + value=""permission"" static="true" final="true" deprecated="not deprecated" @@ -95756,6 +95674,8 @@ deprecated="not deprecated" visibility="public" > +<parameter name="connection" type="android.hardware.usb.UsbDeviceConnection"> +</parameter> <parameter name="endpoint" type="android.hardware.usb.UsbEndpoint"> </parameter> </method> @@ -112529,255 +112449,6 @@ </package> <package name="android.mtp" > -<class name="MtpClient" - extends="java.lang.Object" - abstract="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<constructor name="MtpClient" - type="android.mtp.MtpClient" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -</constructor> -<method name="addListener" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="listener" type="android.mtp.MtpClient.Listener"> -</parameter> -</method> -<method name="close" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="deleteObject" - return="boolean" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -<parameter name="objectHandle" type="int"> -</parameter> -</method> -<method name="getDevice" - return="android.mtp.MtpDevice" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -</method> -<method name="getDevice" - return="android.mtp.MtpDevice" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="id" type="int"> -</parameter> -</method> -<method name="getDeviceList" - return="java.util.List<android.mtp.MtpDevice>" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="getObject" - return="byte[]" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -<parameter name="objectHandle" type="int"> -</parameter> -<parameter name="objectSize" type="int"> -</parameter> -</method> -<method name="getObjectInfo" - return="android.mtp.MtpObjectInfo" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -<parameter name="objectHandle" type="int"> -</parameter> -</method> -<method name="getObjectList" - return="java.util.List<android.mtp.MtpObjectInfo>" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -<parameter name="storageId" type="int"> -</parameter> -<parameter name="objectHandle" type="int"> -</parameter> -</method> -<method name="getStorageList" - return="java.util.List<android.mtp.MtpStorageInfo>" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -</method> -<method name="getThumbnail" - return="byte[]" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -<parameter name="objectHandle" type="int"> -</parameter> -</method> -<method name="importFile" - return="boolean" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="deviceName" type="java.lang.String"> -</parameter> -<parameter name="objectHandle" type="int"> -</parameter> -<parameter name="destPath" type="java.lang.String"> -</parameter> -</method> -<method name="isCamera" - return="boolean" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="device" type="android.hardware.usb.UsbDevice"> -</parameter> -</method> -<method name="removeListener" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="listener" type="android.mtp.MtpClient.Listener"> -</parameter> -</method> -</class> -<interface name="MtpClient.Listener" - abstract="true" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<method name="deviceAdded" - return="void" - abstract="true" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="device" type="android.mtp.MtpDevice"> -</parameter> -</method> -<method name="deviceRemoved" - return="void" - abstract="true" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="device" type="android.mtp.MtpDevice"> -</parameter> -</method> -</interface> <class name="MtpConstants" extends="java.lang.Object" abstract="false" @@ -113687,7 +113358,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="manager" type="android.hardware.usb.UsbManager"> +<parameter name="connection" type="android.hardware.usb.UsbDeviceConnection"> </parameter> </method> </class> @@ -118085,6 +117756,497 @@ </field> </class> </package> +<package name="android.net.rtp" +> +<class name="AudioCodec" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="getCodec" + return="android.net.rtp.AudioCodec" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="type" type="int"> +</parameter> +<parameter name="rtpmap" type="java.lang.String"> +</parameter> +<parameter name="fmtp" type="java.lang.String"> +</parameter> +</method> +<method name="getCodecs" + return="android.net.rtp.AudioCodec[]" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<field name="AMR" + type="android.net.rtp.AudioCodec" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="GSM" + type="android.net.rtp.AudioCodec" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="GSM_EFR" + type="android.net.rtp.AudioCodec" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="PCMA" + type="android.net.rtp.AudioCodec" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="PCMU" + type="android.net.rtp.AudioCodec" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="fmtp" + type="java.lang.String" + transient="false" + volatile="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="rtpmap" + type="java.lang.String" + transient="false" + volatile="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="type" + type="int" + transient="false" + volatile="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> +<class name="AudioGroup" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="AudioGroup" + type="android.net.rtp.AudioGroup" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</constructor> +<method name="clear" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getMode" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getStreams" + return="android.net.rtp.AudioStream[]" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="sendDtmf" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="event" type="int"> +</parameter> +</method> +<method name="setMode" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="mode" type="int"> +</parameter> +</method> +<field name="MODE_ECHO_SUPPRESSION" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MODE_MUTED" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MODE_NORMAL" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MODE_ON_HOLD" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> +<class name="AudioStream" + extends="android.net.rtp.RtpStream" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="AudioStream" + type="android.net.rtp.AudioStream" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="address" type="java.net.InetAddress"> +</parameter> +<exception name="SocketException" type="java.net.SocketException"> +</exception> +</constructor> +<method name="getCodec" + return="android.net.rtp.AudioCodec" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getDtmfType" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getGroup" + return="android.net.rtp.AudioGroup" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="isBusy" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="join" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="group" type="android.net.rtp.AudioGroup"> +</parameter> +</method> +<method name="setCodec" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="codec" type="android.net.rtp.AudioCodec"> +</parameter> +</method> +<method name="setDtmfType" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="type" type="int"> +</parameter> +</method> +</class> +<class name="RtpStream" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="associate" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="address" type="java.net.InetAddress"> +</parameter> +<parameter name="port" type="int"> +</parameter> +</method> +<method name="getLocalAddress" + return="java.net.InetAddress" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getLocalPort" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getMode" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getRemoteAddress" + return="java.net.InetAddress" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getRemotePort" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="isBusy" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="release" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="setMode" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="mode" type="int"> +</parameter> +</method> +<field name="MODE_NORMAL" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MODE_RECEIVE_ONLY" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MODE_SEND_ONLY" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> +</package> <package name="android.net.sip" > <class name="SipAudioCall" @@ -194914,7 +195076,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="contextStart" type="int"> @@ -206685,21 +206847,6 @@ visibility="public" > </method> -<method name="entryEvicted" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="deprecated" - visibility="protected" -> -<parameter name="key" type="K"> -</parameter> -<parameter name="value" type="V"> -</parameter> -</method> <method name="entryRemoved" return="void" abstract="false" @@ -210832,8 +210979,8 @@ visibility="public" > </method> -<method name="getMotionAxes" - return="int[]" +<method name="getMotionRange" + return="android.view.InputDevice.MotionRange" abstract="false" native="false" synchronized="false" @@ -210842,6 +210989,8 @@ deprecated="not deprecated" visibility="public" > +<parameter name="axis" type="int"> +</parameter> </method> <method name="getMotionRange" return="android.view.InputDevice.MotionRange" @@ -210855,6 +211004,19 @@ > <parameter name="axis" type="int"> </parameter> +<parameter name="source" type="int"> +</parameter> +</method> +<method name="getMotionRanges" + return="java.util.List<android.view.InputDevice.MotionRange>" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> </method> <method name="getName" return="java.lang.String" @@ -211220,6 +211382,17 @@ deprecated="not deprecated" visibility="public" > +<method name="getAxis" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getFlat" return="float" abstract="false" @@ -211275,6 +211448,17 @@ visibility="public" > </method> +<method name="getSource" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> </class> <class name="InputEvent" extends="java.lang.Object" @@ -218115,6 +218299,28 @@ visibility="public" > </field> +<field name="AXIS_BRAKE" + type="int" + transient="false" + volatile="false" + value="23" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_GAS" + type="int" + transient="false" + volatile="false" + value="22" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="AXIS_GENERIC_1" type="int" transient="false" @@ -218368,6 +218574,17 @@ visibility="public" > </field> +<field name="AXIS_RUDDER" + type="int" + transient="false" + volatile="false" + value="20" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="AXIS_RX" type="int" transient="false" @@ -218412,6 +218629,17 @@ visibility="public" > </field> +<field name="AXIS_THROTTLE" + type="int" + transient="false" + volatile="false" + value="19" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="AXIS_TOOL_MAJOR" type="int" transient="false" @@ -218467,6 +218695,17 @@ visibility="public" > </field> +<field name="AXIS_WHEEL" + type="int" + transient="false" + volatile="false" + value="21" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="AXIS_X" type="int" transient="false" @@ -240923,7 +241162,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -241410,7 +241649,7 @@ synchronized="true" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -241476,7 +241715,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -241597,7 +241836,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -241966,7 +242205,7 @@ synchronized="true" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="l" type="android.webkit.WebSettings.LayoutAlgorithm"> @@ -242044,7 +242283,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="enabled" type="boolean"> @@ -242239,7 +242478,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="view" type="boolean"> @@ -242367,7 +242606,7 @@ abstract="false" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <method name="valueOf" @@ -243053,7 +243292,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -243075,7 +243314,7 @@ synchronized="false" static="true" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -243099,7 +243338,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -243110,7 +243349,7 @@ synchronized="false" static="true" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </method> @@ -243647,7 +243886,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="b" type="android.os.Bundle"> @@ -243703,7 +243942,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="b" type="android.os.Bundle"> @@ -243858,7 +244097,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="listener" type="android.webkit.WebView.PictureListener"> @@ -244130,7 +244369,7 @@ abstract="true" static="true" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <method name="onNewPicture" @@ -244140,7 +244379,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="view" type="android.webkit.WebView"> @@ -244325,6 +244564,25 @@ <parameter name="realm" type="java.lang.String"> </parameter> </method> +<method name="onReceivedLoginRequest" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="view" type="android.webkit.WebView"> +</parameter> +<parameter name="realm" type="java.lang.String"> +</parameter> +<parameter name="account" type="java.lang.String"> +</parameter> +<parameter name="args" type="java.lang.String"> +</parameter> +</method> <method name="onReceivedSslError" return="void" abstract="false" @@ -266773,7 +267031,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="arg0" type="T"> +<parameter name="t" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 930c6b0..b6581e9 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -74,7 +74,7 @@ public class ActivityManager { static public int staticGetMemoryClass() { // Really brain dead right now -- just take this from the configured // vm heap size, and assume it is in megabytes and thus ends with "m". - String vmHeapSize = SystemProperties.get("dalvik.vm.growthlimit", ""); + String vmHeapSize = SystemProperties.get("dalvik.vm.heapgrowthlimit", ""); if (vmHeapSize != null && !"".equals(vmHeapSize)) { return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1)); } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 539e946..cc1f81c 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -401,10 +401,10 @@ class ContextImpl extends Context { return new UiModeManager(); }}); - registerService(USB_SERVICE, new StaticServiceFetcher() { - public Object createStaticService() { + registerService(USB_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(USB_SERVICE); - return new UsbManager(IUsbManager.Stub.asInterface(b)); + return new UsbManager(ctx, IUsbManager.Stub.asInterface(b)); }}); registerService(VIBRATOR_SERVICE, new ServiceFetcher() { diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index d04fa57..b88e5cf 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -376,8 +376,8 @@ public class DownloadManager { /** * This download shows in the notifications after completion ONLY. * It is usuable only with - * {@link DownloadManager#completedDownload(String, String, boolean, String, - * String, long, boolean)}. + * {@link DownloadManager#addCompletedDownload(String, String, + * boolean, String, String, long, boolean)}. */ public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; @@ -1111,7 +1111,7 @@ public class DownloadManager { * @return an ID for the download entry added to the downloads app, unique across the system * This ID is used to make future calls related to this download. */ - public long completedDownload(String title, String description, + public long addCompletedDownload(String title, String description, boolean isMediaScannerScannable, String mimeType, String path, long length, boolean showNotification) { // make sure the input args are non-null/non-zero diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 440cb54..efe2633 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1150,8 +1150,12 @@ public class DevicePolicyManager { * fail (most commonly returning {@link #ENCRYPTION_STATUS_ACTIVE}). * * <p>This policy controls encryption of the secure (application data) storage area. Data - * written to other areas (e.g. the directory returned by - * {@link android.os.Environment#getExternalStorageDirectory()} may or may not be encrypted. + * written to other storage areas may or may not be encrypted, and this policy does not require + * or control the encryption of any other storage areas. + * There is one exception: If {@link android.os.Environment#isExternalStorageEmulated()} is + * {@code true}, then the directory returned by + * {@link android.os.Environment#getExternalStorageDirectory()} must be written to disk + * within the encrypted storage area. * * <p>Important Note: On some devices, it is possible to encrypt storage without requiring * the user to create a device PIN or Password. In this case, the storage is encrypted, but diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java index 6539711..55368d6 100644 --- a/core/java/android/app/backup/WallpaperBackupHelper.java +++ b/core/java/android/app/backup/WallpaperBackupHelper.java @@ -110,11 +110,16 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu if (DEBUG) Slog.d(TAG, "Restoring wallpaper image w=" + options.outWidth + " h=" + options.outHeight); - // how much does the image differ from our preference? + // How much does the image differ from our preference? The threshold + // here is set to accept any image larger than our target, because + // scaling down is acceptable; but to reject images that are deemed + // "too small" to scale up attractively. The value 1.33 is just barely + // too low to pass Nexus 1 or Droid wallpapers for use on a Xoom, but + // will pass anything relatively larger. double widthRatio = mDesiredMinWidth / options.outWidth; double heightRatio = mDesiredMinHeight / options.outHeight; - if (widthRatio > 0.8 && widthRatio < 1.25 - && heightRatio > 0.8 && heightRatio < 1.25) { + if (widthRatio > 0 && widthRatio < 1.33 + && heightRatio > 0 && heightRatio < 1.33) { // sufficiently close to our resolution; go ahead and use it if (DEBUG) Slog.d(TAG, "wallpaper dimension match; using"); f.renameTo(new File(WALLPAPER_IMAGE)); diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index dd4096b..2111cce 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -2051,8 +2051,8 @@ public class SensorManager if (rv.length == 4) { Q[0] = rv[3]; } else { - //In this case, the w component of the quaternion is known to be a positive number - Q[0] = (float)Math.sqrt(1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]); + Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]; + Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0; } Q[1] = rv[0]; Q[2] = rv[1]; diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index be65bdb..495fa21 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -16,6 +16,7 @@ package android.hardware.usb; +import android.app.PendingIntent; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; import android.os.Bundle; @@ -50,6 +51,25 @@ interface IUsbManager */ void setAccessoryPackage(in UsbAccessory accessory, String packageName); + /* Returns true if the caller has permission to access the device. */ + boolean hasDevicePermission(in UsbDevice device); + + /* Returns true if the caller has permission to access the accessory. */ + boolean hasAccessoryPermission(in UsbAccessory accessory); + + /* Requests permission for the given package to access the device. + * Will display a system dialog to query the user if permission + * had not already been given. + */ + void requestDevicePermission(in UsbDevice device, String packageName, in PendingIntent pi); + + /* Requests permission for the given package to access the accessory. + * Will display a system dialog to query the user if permission + * had not already been given. Result is returned via pi. + */ + void requestAccessoryPermission(in UsbAccessory accessory, String packageName, + in PendingIntent pi); + /* Grants permission for the given UID to access the device */ void grantDevicePermission(in UsbDevice device, int uid); @@ -57,8 +77,8 @@ interface IUsbManager void grantAccessoryPermission(in UsbAccessory accessory, int uid); /* Returns true if the USB manager has default preferences or permissions for the package */ - boolean hasDefaults(String packageName, int uid); + boolean hasDefaults(String packageName); /* Clears default preferences and permissions for the package */ - oneway void clearDefaults(String packageName, int uid); + oneway void clearDefaults(String packageName); } diff --git a/core/java/android/hardware/usb/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java index 6cd9178..cc174d4 100644 --- a/core/java/android/hardware/usb/UsbAccessory.java +++ b/core/java/android/hardware/usb/UsbAccessory.java @@ -30,18 +30,21 @@ public class UsbAccessory implements Parcelable { private final String mManufacturer; private final String mModel; - private final String mType; + private final String mDescription; private final String mVersion; + private final String mUri; /** * UsbAccessory should only be instantiated by UsbService implementation * @hide */ - public UsbAccessory(String manufacturer, String model, String type, String version) { + public UsbAccessory(String manufacturer, String model, String description, + String version, String uri) { mManufacturer = manufacturer; mModel = model; - mType = type; + mDescription = description; mVersion = version; + mUri = uri; } /** @@ -51,8 +54,9 @@ public class UsbAccessory implements Parcelable { public UsbAccessory(String[] strings) { mManufacturer = strings[0]; mModel = strings[1]; - mType = strings[2]; + mDescription = strings[2]; mVersion = strings[3]; + mUri = strings[4]; } /** @@ -74,12 +78,12 @@ public class UsbAccessory implements Parcelable { } /** - * Returns the type of the accessory. + * Returns a user visible description of the accessory. * - * @return the accessory type + * @return the accessory description */ - public String getType() { - return mType; + public String getDescription() { + return mDescription; } /** @@ -91,6 +95,17 @@ public class UsbAccessory implements Parcelable { return mVersion; } + /** + * Returns the URI for the accessory. + * This is an optional URI that might show information about the accessory + * or provide the option to download an application for the accessory + * + * @return the accessory URI + */ + public String getUri() { + return mUri; + } + private static boolean compare(String s1, String s2) { if (s1 == null) return (s2 == null); return s1.equals(s2); @@ -102,18 +117,29 @@ public class UsbAccessory implements Parcelable { UsbAccessory accessory = (UsbAccessory)obj; return (compare(mManufacturer, accessory.getManufacturer()) && compare(mModel, accessory.getModel()) && - compare(mType, accessory.getType()) && - compare(mVersion, accessory.getVersion())); + compare(mDescription, accessory.getDescription()) && + compare(mVersion, accessory.getVersion()) && + compare(mUri, accessory.getUri())); } return false; } @Override + public int hashCode() { + return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^ + (mModel == null ? 0 : mModel.hashCode()) ^ + (mDescription == null ? 0 : mDescription.hashCode()) ^ + (mVersion == null ? 0 : mVersion.hashCode()) ^ + (mUri == null ? 0 : mUri.hashCode())); + } + + @Override public String toString() { return "UsbAccessory[mManufacturer=" + mManufacturer + ", mModel=" + mModel + - ", mType=" + mType + - ", mVersion=" + mVersion + "]"; + ", mDescription=" + mDescription + + ", mVersion=" + mVersion + + ", mUri=" + mUri + "]"; } public static final Parcelable.Creator<UsbAccessory> CREATOR = @@ -121,9 +147,10 @@ public class UsbAccessory implements Parcelable { public UsbAccessory createFromParcel(Parcel in) { String manufacturer = in.readString(); String model = in.readString(); - String type = in.readString(); + String description = in.readString(); String version = in.readString(); - return new UsbAccessory(manufacturer, model, type, version); + String uri = in.readString(); + return new UsbAccessory(manufacturer, model, description, version, uri); } public UsbAccessory[] newArray(int size) { @@ -138,7 +165,8 @@ public class UsbAccessory implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(mManufacturer); parcel.writeString(mModel); - parcel.writeString(mType); + parcel.writeString(mDescription); parcel.writeString(mVersion); + parcel.writeString(mUri); } } diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java index 37bd82b..9e536a7 100644 --- a/core/java/android/hardware/usb/UsbDevice.java +++ b/core/java/android/hardware/usb/UsbDevice.java @@ -19,33 +19,24 @@ package android.hardware.usb; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.os.ParcelFileDescriptor; import android.util.Log; import java.io.FileDescriptor; - /** * A class representing a USB device. */ -public final class UsbDevice implements Parcelable { +public class UsbDevice implements Parcelable { private static final String TAG = "UsbDevice"; - private String mName; - private int mVendorId; - private int mProductId; - private int mClass; - private int mSubclass; - private int mProtocol; - private Parcelable[] mInterfaces; - - // used by the JNI code - private int mNativeContext; - - private UsbDevice() { - } - + private final String mName; + private final int mVendorId; + private final int mProductId; + private final int mClass; + private final int mSubclass; + private final int mProtocol; + private final Parcelable[] mInterfaces; /** * UsbDevice should only be instantiated by UsbService implementation @@ -150,114 +141,6 @@ public final class UsbDevice implements Parcelable { return (UsbInterface)mInterfaces[index]; } - /* package */ boolean open(ParcelFileDescriptor pfd) { - return native_open(mName, pfd.getFileDescriptor()); - } - - /** - * Releases all system resources related to the device. - */ - public void close() { - native_close(); - } - - /** - * Returns an integer file descriptor for the device, or - * -1 if the device is not opened. - * This is intended for passing to native code to access the device - */ - public int getFileDescriptor() { - return native_get_fd(); - } - - /** - * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}. - * This must be done before sending or receiving data on any - * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface - * @param intf the interface to claim - * @param force true to disconnect kernel driver if necessary - * @return true if the interface was successfully claimed - */ - public boolean claimInterface(UsbInterface intf, boolean force) { - return native_claim_interface(intf.getId(), force); - } - - /** - * Releases exclusive access to a {@link android.hardware.usb.UsbInterface}. - * - * @return true if the interface was successfully released - */ - public boolean releaseInterface(UsbInterface intf) { - return native_release_interface(intf.getId()); - } - - /** - * Performs a control transaction on endpoint zero for this device. - * The direction of the transfer is determined by the request type. - * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is - * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write, - * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer - * is a read. - * - * @param requestType request type for this transaction - * @param request request ID for this transaction - * @param value value field for this transaction - * @param index index field for this transaction - * @param buffer buffer for data portion of transaction, - * or null if no data needs to be sent or received - * @param length the length of the data to send or receive - * @param timeout in milliseconds - * @return length of data transferred (or zero) for success, - * or negative value for failure - */ - public int controlTransfer(int requestType, int request, int value, - int index, byte[] buffer, int length, int timeout) { - return native_control_request(requestType, request, value, index, buffer, length, timeout); - } - - /** - * Performs a bulk transaction on the given endpoint. - * The direction of the transfer is determined by the direction of the endpoint - * - * @param endpoint the endpoint for this transaction - * @param buffer buffer for data to send or receive, - * @param length the length of the data to send or receive - * @param timeout in milliseconds - * @return length of data transferred (or zero) for success, - * or negative value for failure - */ - public int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) { - return native_bulk_request(endpoint.getAddress(), buffer, length, timeout); - } - - /** - * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation - * Note that this may return requests queued on multiple - * {@link android.hardware.usb.UsbEndpoint}s. - * When multiple endpoints are in use, {@link android.hardware.usb.UsbRequest#getEndpoint} and - * {@link android.hardware.usb.UsbRequest#getClientData} can be useful in determining - * how to process the result of this function. - * - * @return a completed USB request, or null if an error occurred - */ - public UsbRequest requestWait() { - UsbRequest request = native_request_wait(); - if (request != null) { - request.dequeue(); - } - return request; - } - - /** - * Returns the serial number for the device. - * This will return null if the device has not been opened. - * - * @return the device serial number - */ - public String getSerial() { - return native_get_serial(); - } - @Override public boolean equals(Object o) { if (o instanceof UsbDevice) { @@ -270,6 +153,11 @@ public final class UsbDevice implements Parcelable { } @Override + public int hashCode() { + return mName.hashCode(); + } + + @Override public String toString() { return "UsbDevice[mName=" + mName + ",mVendorId=" + mVendorId + ",mProductId=" + mProductId + ",mClass=" + mClass + @@ -287,11 +175,7 @@ public final class UsbDevice implements Parcelable { int subClass = in.readInt(); int protocol = in.readInt(); Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader()); - UsbDevice result = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, interfaces); - for (int i = 0; i < interfaces.length; i++) { - ((UsbInterface)interfaces[i]).setDevice(result); - } - return result; + return new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, interfaces); } public UsbDevice[] newArray(int size) { @@ -321,17 +205,6 @@ public final class UsbDevice implements Parcelable { return native_get_device_name(id); } - private native boolean native_open(String deviceName, FileDescriptor pfd); - private native void native_close(); - private native int native_get_fd(); - private native boolean native_claim_interface(int interfaceID, boolean force); - private native boolean native_release_interface(int interfaceID); - private native int native_control_request(int requestType, int request, int value, - int index, byte[] buffer, int length, int timeout); - private native int native_bulk_request(int endpoint, byte[] buffer, int length, int timeout); - private native UsbRequest native_request_wait(); - private native String native_get_serial(); - private static native int native_get_device_id(String name); private static native String native_get_device_name(int id); } diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java new file mode 100644 index 0000000..876287c --- /dev/null +++ b/core/java/android/hardware/usb/UsbDeviceConnection.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb; + +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.FileDescriptor; + + +/** + * A class representing a USB device. + */ +public class UsbDeviceConnection { + + private static final String TAG = "UsbDeviceConnection"; + + private final UsbDevice mDevice; + + // used by the JNI code + private int mNativeContext; + + /** + * UsbDevice should only be instantiated by UsbService implementation + * @hide + */ + public UsbDeviceConnection(UsbDevice device) { + mDevice = device; + } + + /* package */ boolean open(String name, ParcelFileDescriptor pfd) { + return native_open(name, pfd.getFileDescriptor()); + } + + /** + * Releases all system resources related to the device. + */ + public void close() { + native_close(); + } + + /** + * Returns an integer file descriptor for the device, or + * -1 if the device is not opened. + * This is intended for passing to native code to access the device + */ + public int getFileDescriptor() { + return native_get_fd(); + } + + /** + * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}. + * This must be done before sending or receiving data on any + * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface + * @param intf the interface to claim + * @param force true to disconnect kernel driver if necessary + * @return true if the interface was successfully claimed + */ + public boolean claimInterface(UsbInterface intf, boolean force) { + return native_claim_interface(intf.getId(), force); + } + + /** + * Releases exclusive access to a {@link android.hardware.usb.UsbInterface}. + * + * @return true if the interface was successfully released + */ + public boolean releaseInterface(UsbInterface intf) { + return native_release_interface(intf.getId()); + } + + /** + * Performs a control transaction on endpoint zero for this device. + * The direction of the transfer is determined by the request type. + * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is + * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write, + * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer + * is a read. + * + * @param requestType request type for this transaction + * @param request request ID for this transaction + * @param value value field for this transaction + * @param index index field for this transaction + * @param buffer buffer for data portion of transaction, + * or null if no data needs to be sent or received + * @param length the length of the data to send or receive + * @param timeout in milliseconds + * @return length of data transferred (or zero) for success, + * or negative value for failure + */ + public int controlTransfer(int requestType, int request, int value, + int index, byte[] buffer, int length, int timeout) { + return native_control_request(requestType, request, value, index, buffer, length, timeout); + } + + /** + * Performs a bulk transaction on the given endpoint. + * The direction of the transfer is determined by the direction of the endpoint + * + * @param endpoint the endpoint for this transaction + * @param buffer buffer for data to send or receive, + * @param length the length of the data to send or receive + * @param timeout in milliseconds + * @return length of data transferred (or zero) for success, + * or negative value for failure + */ + public int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) { + return native_bulk_request(endpoint.getAddress(), buffer, length, timeout); + } + + /** + * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation + * Note that this may return requests queued on multiple + * {@link android.hardware.usb.UsbEndpoint}s. + * When multiple endpoints are in use, {@link android.hardware.usb.UsbRequest#getEndpoint} and + * {@link android.hardware.usb.UsbRequest#getClientData} can be useful in determining + * how to process the result of this function. + * + * @return a completed USB request, or null if an error occurred + */ + public UsbRequest requestWait() { + UsbRequest request = native_request_wait(); + if (request != null) { + request.dequeue(); + } + return request; + } + + /** + * Returns the serial number for the device. + * This will return null if the device has not been opened. + * + * @return the device serial number + */ + public String getSerial() { + return native_get_serial(); + } + + private native boolean native_open(String deviceName, FileDescriptor pfd); + private native void native_close(); + private native int native_get_fd(); + private native boolean native_claim_interface(int interfaceID, boolean force); + private native boolean native_release_interface(int interfaceID); + private native int native_control_request(int requestType, int request, int value, + int index, byte[] buffer, int length, int timeout); + private native int native_bulk_request(int endpoint, byte[] buffer, int length, int timeout); + private native UsbRequest native_request_wait(); + private native String native_get_serial(); +} diff --git a/core/java/android/hardware/usb/UsbEndpoint.java b/core/java/android/hardware/usb/UsbEndpoint.java index a48d88f..bc2c2c1 100644 --- a/core/java/android/hardware/usb/UsbEndpoint.java +++ b/core/java/android/hardware/usb/UsbEndpoint.java @@ -23,16 +23,12 @@ import android.os.Parcelable; /** * A class representing an endpoint on a {@link android.hardware.usb.UsbInterface}. */ -public final class UsbEndpoint implements Parcelable { +public class UsbEndpoint implements Parcelable { - private int mAddress; - private int mAttributes; - private int mMaxPacketSize; - private int mInterval; - private UsbInterface mInterface; - - private UsbEndpoint() { - } + private final int mAddress; + private final int mAttributes; + private final int mMaxPacketSize; + private final int mInterval; /** * UsbEndpoint should only be instantiated by UsbService implementation @@ -119,29 +115,6 @@ public final class UsbEndpoint implements Parcelable { return mInterval; } - /** - * Returns the {@link android.hardware.usb.UsbInterface} this endpoint belongs to. - * - * @return the endpoint's interface - */ - public UsbInterface getInterface() { - return mInterface; - } - - /** - * Returns the {@link android.hardware.usb.UsbDevice} this endpoint belongs to. - * - * @return the endpoint's device - */ - public UsbDevice getDevice() { - return mInterface.getDevice(); - } - - // only used for parcelling - /* package */ void setInterface(UsbInterface intf) { - mInterface = intf; - } - @Override public String toString() { return "UsbEndpoint[mAddress=" + mAddress + ",mAttributes=" + mAttributes + diff --git a/core/java/android/hardware/usb/UsbInterface.java b/core/java/android/hardware/usb/UsbInterface.java index b3b0e81..2b4c7c0 100644 --- a/core/java/android/hardware/usb/UsbInterface.java +++ b/core/java/android/hardware/usb/UsbInterface.java @@ -25,15 +25,11 @@ import android.os.Parcelable; */ public class UsbInterface implements Parcelable { - private int mId; - private int mClass; - private int mSubclass; - private int mProtocol; - private UsbDevice mDevice; - private Parcelable[] mEndpoints; - - private UsbInterface() { - } + private final int mId; + private final int mClass; + private final int mSubclass; + private final int mProtocol; + private final Parcelable[] mEndpoints; /** * UsbInterface should only be instantiated by UsbService implementation @@ -104,20 +100,6 @@ public class UsbInterface implements Parcelable { return (UsbEndpoint)mEndpoints[index]; } - /** - * Returns the {@link android.hardware.usb.UsbDevice} this interface belongs to. - * - * @return the interface's device - */ - public UsbDevice getDevice() { - return mDevice; - } - - // only used for parcelling - /* package */ void setDevice(UsbDevice device) { - mDevice = device; - } - @Override public String toString() { return "UsbInterface[mId=" + mId + ",mClass=" + mClass + @@ -133,11 +115,7 @@ public class UsbInterface implements Parcelable { int subClass = in.readInt(); int protocol = in.readInt(); Parcelable[] endpoints = in.readParcelableArray(UsbEndpoint.class.getClassLoader()); - UsbInterface result = new UsbInterface(id, Class, subClass, protocol, endpoints); - for (int i = 0; i < endpoints.length; i++) { - ((UsbEndpoint)endpoints[i]).setInterface(result); - } - return result; + return new UsbInterface(id, Class, subClass, protocol, endpoints); } public UsbInterface[] newArray(int size) { diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 6683179..0e2cad8 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -17,6 +17,8 @@ package android.hardware.usb; +import android.app.PendingIntent; +import android.content.Context; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -53,6 +55,8 @@ public class UsbManager { * {@link #USB_FUNCTION_MASS_STORAGE}, {@link #USB_FUNCTION_ADB}, {@link #USB_FUNCTION_RNDIS}, * {@link #USB_FUNCTION_MTP} and {@link #USB_FUNCTION_ACCESSORY}. * </ul> + * + * {@hide} */ public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; @@ -98,7 +102,7 @@ public class UsbManager { * * This intent is sent when a USB accessory is detached. * <ul> - * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.usb.UsbAccessory} + * <li> {@link #EXTRA_ACCESSORY} containing the {@link UsbAccessory} * for the attached accessory that was detached * </ul> */ @@ -108,42 +112,56 @@ public class UsbManager { /** * Boolean extra indicating whether USB is connected or disconnected. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. + * + * {@hide} */ public static final String USB_CONNECTED = "connected"; /** * Integer extra containing currently set USB configuration. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. + * + * {@hide} */ public static final String USB_CONFIGURATION = "configuration"; /** * Name of the USB mass storage USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast + * + * {@hide} */ public static final String USB_FUNCTION_MASS_STORAGE = "mass_storage"; /** * Name of the adb USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast + * + * {@hide} */ public static final String USB_FUNCTION_ADB = "adb"; /** * Name of the RNDIS ethernet USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast + * + * {@hide} */ public static final String USB_FUNCTION_RNDIS = "rndis"; /** * Name of the MTP USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast + * + * {@hide} */ public static final String USB_FUNCTION_MTP = "mtp"; /** * Name of the Accessory USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast + * + * {@hide} */ public static final String USB_FUNCTION_ACCESSORY = "accessory"; @@ -151,6 +169,8 @@ public class UsbManager { * Value indicating that a USB function is enabled. * Used in {@link #USB_CONFIGURATION} extras bundle for the * {@link #ACTION_USB_STATE} broadcast + * + * {@hide} */ public static final String USB_FUNCTION_ENABLED = "enabled"; @@ -158,6 +178,8 @@ public class UsbManager { * Value indicating that a USB function is disabled. * Used in {@link #USB_CONFIGURATION} extras bundle for the * {@link #ACTION_USB_STATE} broadcast + * + * {@hide} */ public static final String USB_FUNCTION_DISABLED = "disabled"; @@ -176,12 +198,22 @@ public class UsbManager { */ public static final String EXTRA_ACCESSORY = "accessory"; - private IUsbManager mService; + /** + * Name of extra added to the {@link android.app.PendingIntent} + * passed into {@link #requestPermission(UsbDevice, PendingIntent)} + * or {@link #requestPermission(UsbAccessory, PendingIntent)} + * containing a boolean value indicating whether the user granted permission or not. + */ + public static final String EXTRA_PERMISSION_GRANTED = "permission"; + + private final Context mContext; + private final IUsbManager mService; /** * {@hide} */ - public UsbManager(IUsbManager service) { + public UsbManager(Context context, IUsbManager service) { + mContext = context; mService = service; } @@ -215,19 +247,22 @@ public class UsbManager { * @param device the device to open * @return true if we successfully opened the device */ - public boolean openDevice(UsbDevice device) { + public UsbDeviceConnection openDevice(UsbDevice device) { try { - ParcelFileDescriptor pfd = mService.openDevice(device.getDeviceName()); - if (pfd == null) { - return false; + String deviceName = device.getDeviceName(); + ParcelFileDescriptor pfd = mService.openDevice(deviceName); + if (pfd != null) { + UsbDeviceConnection connection = new UsbDeviceConnection(device); + boolean result = connection.open(deviceName, pfd); + pfd.close(); + if (result) { + return connection; + } } - boolean result = device.open(pfd); - pfd.close(); - return result; } catch (Exception e) { Log.e(TAG, "exception in UsbManager.openDevice", e); - return false; } + return null; } /** @@ -245,7 +280,7 @@ public class UsbManager { return new UsbAccessory[] { accessory }; } } catch (RemoteException e) { - Log.e(TAG, "RemoteException in getAccessoryList" , e); + Log.e(TAG, "RemoteException in getAccessoryList", e); return null; } } @@ -260,11 +295,99 @@ public class UsbManager { try { return mService.openAccessory(accessory); } catch (RemoteException e) { - Log.e(TAG, "RemoteException in openAccessory" , e); + Log.e(TAG, "RemoteException in openAccessory", e); return null; } } + /** + * Returns true if the caller has permission to access the device. + * Permission might have been granted temporarily via + * {@link #requestPermission(UsbDevice, PendingIntent)} or + * by the user choosing the caller as the default application for the device. + * + * @param device to check permissions for + * @return true if caller has permission + */ + public boolean hasPermission(UsbDevice device) { + try { + return mService.hasDevicePermission(device); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in hasPermission", e); + return false; + } + } + + /** + * Returns true if the caller has permission to access the accessory. + * Permission might have been granted temporarily via + * {@link #requestPermission(UsbAccessory, PendingIntent)} or + * by the user choosing the caller as the default application for the accessory. + * + * @param accessory to check permissions for + * @return true if caller has permission + */ + public boolean hasPermission(UsbAccessory accessory) { + try { + return mService.hasAccessoryPermission(accessory); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in hasPermission", e); + return false; + } + } + + /** + * Requests temporary permission for the given package to access the device. + * This may result in a system dialog being displayed to the user + * if permission had not already been granted. + * Success or failure is returned via the {@link android.app.PendingIntent} pi. + * If successful, this grants the caller permission to access the device only + * until the device is disconnected. + * + * The following extras will be added to pi: + * <ul> + * <li> {@link #EXTRA_DEVICE} containing the device passed into this call + * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether + * permission was granted by the user + * </ul> + * + * @param device to request permissions for + * @param pi PendingIntent for returning result + */ + public void requestPermission(UsbDevice device, PendingIntent pi) { + try { + mService.requestDevicePermission(device, mContext.getPackageName(), pi); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in requestPermission", e); + } + } + + /** + * Requests temporary permission for the given package to access the accessory. + * This may result in a system dialog being displayed to the user + * if permission had not already been granted. + * Success or failure is returned via the {@link android.app.PendingIntent} pi. + * If successful, this grants the caller permission to access the device only + * until the device is disconnected. + * + * The following extras will be added to pi: + * <ul> + * <li> {@link #EXTRA_ACCESSORY} containing the accessory passed into this call + * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether + * permission was granted by the user + * </ul> + * + * @param accessory to request permissions for + * @param pi PendingIntent for returning result + */ + public void requestPermission(UsbAccessory accessory, PendingIntent pi) { + try { + mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in requestPermission", e); + } + } + private static File getFunctionEnableFile(String function) { return new File("/sys/class/usb_composite/" + function + "/enable"); } @@ -275,6 +398,8 @@ public class UsbManager { * * @param function name of the USB function * @return true if the USB function is supported. + * + * {@hide} */ public static boolean isFunctionSupported(String function) { return getFunctionEnableFile(function).exists(); @@ -285,6 +410,8 @@ public class UsbManager { * * @param function name of the USB function * @return true if the USB function is enabled. + * + * {@hide} */ public static boolean isFunctionEnabled(String function) { try { @@ -300,7 +427,7 @@ public class UsbManager { /** * Enables or disables a USB function. * - * @hide + * {@hide} */ public static boolean setFunctionEnabled(String function, boolean enable) { try { diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java index 80085c1..5fe6c8c 100644 --- a/core/java/android/hardware/usb/UsbRequest.java +++ b/core/java/android/hardware/usb/UsbRequest.java @@ -23,9 +23,9 @@ import java.nio.ByteBuffer; /** * A class representing USB request packet. * This can be used for both reading and writing data to or from a - * {@link android.hardware.usb.UsbDevice}. + * {@link android.hardware.usb.UsbDeviceConnection}. * UsbRequests are sent asynchronously via {@link #queue} and the results - * are read by {@link android.hardware.usb.UsbDevice#requestWait}. + * are read by {@link android.hardware.usb.UsbDeviceConnection#requestWait}. */ public class UsbRequest { @@ -53,10 +53,9 @@ public class UsbRequest { * @param endpoint the endpoint to be used for this request. * @return true if the request was successfully opened. */ - public boolean initialize(UsbEndpoint endpoint) { + public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) { mEndpoint = endpoint; - return native_init(endpoint.getDevice(), - endpoint.getAddress(), endpoint.getAttributes(), + return native_init(connection, endpoint.getAddress(), endpoint.getAttributes(), endpoint.getMaxPacketSize(), endpoint.getInterval()); } @@ -94,7 +93,7 @@ public class UsbRequest { * This can be used in conjunction with {@link #setClientData} * to associate another object with this request, which can be useful for * maintaining state between calls to {@link #queue} and - * {@link android.hardware.usb.UsbDevice#requestWait} + * {@link android.hardware.usb.UsbDeviceConnection#requestWait} * * @return the client data for the request */ @@ -107,7 +106,7 @@ public class UsbRequest { * This can be used in conjunction with {@link #getClientData} * to associate another object with this request, which can be useful for * maintaining state between calls to {@link #queue} and - * {@link android.hardware.usb.UsbDevice#requestWait} + * {@link android.hardware.usb.UsbDeviceConnection#requestWait} * * @param data the client data for the request */ @@ -121,7 +120,7 @@ public class UsbRequest { * For IN endpoints, the endpoint will attempt to read the given number of bytes * into the specified buffer. * If the queueing operation is successful, we return true and the result will be - * returned via {@link android.hardware.usb.UsbDevice#requestWait} + * returned via {@link android.hardware.usb.UsbDeviceConnection#requestWait} * * @param buffer the buffer containing the bytes to write, or location to store * the results of a read @@ -166,8 +165,8 @@ public class UsbRequest { return native_cancel(); } - private native boolean native_init(UsbDevice device, int ep_address, int ep_attributes, - int ep_max_packet_size, int ep_interval); + private native boolean native_init(UsbDeviceConnection connection, int ep_address, + int ep_attributes, int ep_max_packet_size, int ep_interval); private native void native_close(); private native boolean native_queue_array(byte[] buffer, int length, boolean out); private native void native_dequeue_array(byte[] buffer, int length, boolean out); diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index ec5030c..e308c2c 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -423,9 +423,16 @@ public class Environment { /** * Returns whether the device has an external storage device which is - * emulated. If true, the device does not have real external storage - * and certain system services such as the package manager use this + * emulated. If true, the device does not have real external storage, and the directory + * returned by {@link #getExternalStorageDirectory()} will be allocated using a portion of + * the internal storage system. + * + * <p>Certain system services, such as the package manager, use this * to determine where to install an application. + * + * <p>Emulated external storage may also be encrypted - see + * {@link android.app.admin.DevicePolicyManager#setStorageEncryption( + * android.content.ComponentName, boolean)} for additional details. */ public static boolean isExternalStorageEmulated() { if (mIsExternalStorageEmulated == null) { diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 6d7b7ce..186af70 100755 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -414,8 +414,10 @@ public class TextToSpeech { /** * {@hide} + * Total number of cached speech parameters. + * This number should be equal to (max param position/2) + 1. */ - protected static final int NB_CACHED_PARAMS = 20; + protected static final int NB_CACHED_PARAMS = 10; } /** diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index 53fa7c2..ea5cdfe 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -1192,7 +1192,9 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable, * CURSOR_AT_OR_BEFORE, or CURSOR_AT * @param p the Paint object that is requesting this information * @return the offset of the next position, or -1 + * @deprecated This is an internal method, refrain from using it in your code */ + @Deprecated public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset, int cursorOpt, Paint p) { diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java index a1501e6..834dac3 100644 --- a/core/java/android/util/LruCache.java +++ b/core/java/android/util/LruCache.java @@ -139,8 +139,7 @@ public class LruCache<K, V> { * Caches {@code value} for {@code key}. The value is moved to the head of * the queue. * - * @return the previous value mapped by {@code key}. Although that entry is - * no longer cached, it has not been passed to {@link #entryEvicted}. + * @return the previous value mapped by {@code key}. */ public final V put(K key, V value) { if (key == null || value == null) { @@ -195,15 +194,14 @@ public class LruCache<K, V> { evictionCount++; } - entryEvicted(key, value); + entryRemoved(true, key, value, null); } } /** * Removes the entry for {@code key} if it exists. * - * @return the previous value mapped by {@code key}. Although that entry is - * no longer cached, it has not been passed to {@link #entryEvicted}. + * @return the previous value mapped by {@code key}. */ public final V remove(K key) { if (key == null) { @@ -226,16 +224,6 @@ public class LruCache<K, V> { } /** - * Calls {@link #entryRemoved}. - * - * @deprecated replaced by entryRemoved - */ - @Deprecated - protected void entryEvicted(K key, V value) { - entryRemoved(true, key, value, null); - } - - /** * Called for entries that have been evicted or removed. This method is * invoked when a value is evicted to make space, removed by a call to * {@link #remove}, or replaced by a call to {@link #put}. The default @@ -291,7 +279,7 @@ public class LruCache<K, V> { } /** - * Clear the cache, calling {@link #entryEvicted} on each removed entry. + * Clear the cache, calling {@link #entryRemoved} on each removed entry. */ public final void evictAll() { trimToSize(-1); // -1 will evict 0-sized elements diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 9a6a274..fa5479b 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -245,11 +245,12 @@ class GLES20Canvas extends HardwareCanvas { private static native void nDestroyDisplayList(int displayList); @Override - public boolean drawDisplayList(DisplayList displayList) { - return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList); + public boolean drawDisplayList(DisplayList displayList, Rect dirty) { + return nDrawDisplayList(mRenderer, + ((GLES20DisplayList) displayList).mNativeDisplayList, dirty); } - private static native boolean nDrawDisplayList(int renderer, int displayList); + private static native boolean nDrawDisplayList(int renderer, int displayList, Rect dirty); /////////////////////////////////////////////////////////////////////////// // Hardware layer diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index 262eb81..aeff31f 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -40,13 +40,6 @@ class GLES20DisplayList extends DisplayList { hostView = new WeakReference<View>(view); } - public void invalidateView() { - View v = hostView.get(); - if (v != null) { - v.invalidate(); - } - } - @Override HardwareCanvas start() { if (mStarted) { diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index e6fecc8..cb1003a 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -53,8 +53,13 @@ public abstract class HardwareCanvas extends Canvas { * Draws the specified display list onto this canvas. * * @param displayList The display list to replay. + * @param dirty The dirty region to redraw in the next pass, matters only + * if this method returns true, can be null. + * + * @return True if the content of the display list requires another + * drawing pass (invalidate()), false otherwise */ - abstract boolean drawDisplayList(DisplayList displayList); + abstract boolean drawDisplayList(DisplayList displayList, Rect dirty); /** * Draws the specified layer onto this canvas. diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index b53aa21..0cf7ae6 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -269,7 +269,7 @@ public abstract class HardwareRenderer { static EGLDisplay sEglDisplay; static EGLConfig sEglConfig; - private static Thread sEglThread; + private static Thread sEglThread; EGLSurface mEglSurface; @@ -284,6 +284,8 @@ public abstract class HardwareRenderer { final boolean mTranslucent; private boolean mDestroyed; + + private final Rect mRedrawClip = new Rect(); GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; @@ -606,8 +608,13 @@ public abstract class HardwareRenderer { DisplayList displayList = view.getDisplayList(); if (displayList != null) { - if (canvas.drawDisplayList(displayList)) { - view.invalidate(); + if (canvas.drawDisplayList(displayList, mRedrawClip)) { + if (mRedrawClip.isEmpty() || view.getParent() == null) { + view.invalidate(); + } else { + view.getParent().invalidateChild(view, mRedrawClip); + } + mRedrawClip.setEmpty(); } } else { // Shouldn't reach here @@ -646,8 +653,8 @@ public abstract class HardwareRenderer { private int checkCurrent() { // TODO: Don't check the current context when we have one per UI thread // TODO: Use a threadlocal flag to know whether the surface has changed - if (sEgl.eglGetCurrentContext() != sEglContext || - sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) { + if (!sEglContext.equals(sEgl.eglGetCurrentContext()) || + !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) { fallback(true); Log.e(LOG_TAG, "eglMakeCurrent failed " + diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index def1161..98d4eb9 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -20,7 +20,9 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; -import android.util.SparseArray; + +import java.util.ArrayList; +import java.util.List; /** * Describes the capabilities of a particular input device. @@ -43,8 +45,7 @@ public final class InputDevice implements Parcelable { private int mSources; private int mKeyboardType; - private final SparseArray<MotionRange> mMotionRanges = new SparseArray<MotionRange>(); - private int[] mMotionAxes; + private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>(); /** * A mask for input source classes. @@ -354,6 +355,11 @@ public final class InputDevice implements Parcelable { /** * Gets information about the range of values for a particular {@link MotionEvent} axis. + * If the device supports multiple sources, the same axis may have different meanings + * for each source. Returns information about the first axis found for any source. + * To obtain information about the axis for a specific source, use + * {@link #getMotionRange(int, int)}. + * * @param axis The axis constant. * @return The range of values, or null if the requested axis is not * supported by the device. @@ -363,30 +369,55 @@ public final class InputDevice implements Parcelable { * @see #getSupportedAxes() */ public MotionRange getMotionRange(int axis) { - return mMotionRanges.get(axis); + final int numRanges = mMotionRanges.size(); + for (int i = 0; i < numRanges; i++) { + final MotionRange range = mMotionRanges.get(i); + if (range.mAxis == axis) { + return range; + } + } + return null; } /** - * Gets the axis ids of all motion axes supported by this device. - * @return The axis ids of all motion axes supported by this device. + * Gets information about the range of values for a particular {@link MotionEvent} axis + * used by a particular source on the device. + * If the device supports multiple sources, the same axis may have different meanings + * for each source. + * + * @param axis The axis constant. + * @param source The source for which to return information. + * @return The range of values, or null if the requested axis is not + * supported by the device. * - * @see #getMotionRange(int) - */ - public int[] getMotionAxes() { - synchronized (this) { - if (mMotionAxes == null) { - final int count = mMotionRanges.size(); - mMotionAxes = new int[count]; - for (int i = 0; i < count; i++) { - mMotionAxes[i] = mMotionRanges.keyAt(i); - } + * @see MotionEvent#AXIS_X + * @see MotionEvent#AXIS_Y + * @see #getSupportedAxes() + */ + public MotionRange getMotionRange(int axis, int source) { + final int numRanges = mMotionRanges.size(); + for (int i = 0; i < numRanges; i++) { + final MotionRange range = mMotionRanges.get(i); + if (range.mAxis == axis && range.mSource == source) { + return range; } - return mMotionAxes; } + return null; } - private void addMotionRange(int axis, float min, float max, float flat, float fuzz) { - mMotionRanges.append(axis, new MotionRange(min, max, flat, fuzz)); + /** + * Gets the ranges for all axes supported by the device. + * @return The motion ranges for the device. + * + * @see #getMotionRange(int, int) + */ + public List<MotionRange> getMotionRanges() { + return mMotionRanges; + } + + private void addMotionRange(int axis, int source, + float min, float max, float flat, float fuzz) { + mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz)); } /** @@ -395,12 +426,16 @@ public final class InputDevice implements Parcelable { * @see InputDevice#getMotionRange(int) */ public static final class MotionRange { + private int mAxis; + private int mSource; private float mMin; private float mMax; private float mFlat; private float mFuzz; - private MotionRange(float min, float max, float flat, float fuzz) { + private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) { + mAxis = axis; + mSource = source; mMin = min; mMax = max; mFlat = flat; @@ -408,6 +443,22 @@ public final class InputDevice implements Parcelable { } /** + * Gets the axis id. + * @return The axis id. + */ + public int getAxis() { + return mAxis; + } + + /** + * Gets the source for which the axis is defined. + * @return The source. + */ + public int getSource() { + return mSource; + } + + /** * Gets the inclusive minimum value for the axis. * @return The inclusive minimum value. */ @@ -480,7 +531,8 @@ public final class InputDevice implements Parcelable { if (axis < 0) { break; } - addMotionRange(axis, in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); + addMotionRange(axis, in.readInt(), + in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); } } @@ -491,11 +543,11 @@ public final class InputDevice implements Parcelable { out.writeInt(mSources); out.writeInt(mKeyboardType); - final int numAxes = mMotionRanges.size(); - for (int i = 0; i < numAxes; i++) { - int axis = mMotionRanges.keyAt(i); - MotionRange range = mMotionRanges.valueAt(i); - out.writeInt(axis); + final int numRanges = mMotionRanges.size(); + for (int i = 0; i < numRanges; i++) { + MotionRange range = mMotionRanges.get(i); + out.writeInt(range.mAxis); + out.writeInt(range.mSource); out.writeFloat(range.mMin); out.writeFloat(range.mMax); out.writeFloat(range.mFlat); @@ -528,7 +580,7 @@ public final class InputDevice implements Parcelable { } description.append("\n"); - description.append(" Sources: ").append(Integer.toHexString(mSources)).append(" ("); + description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen"); @@ -541,10 +593,10 @@ public final class InputDevice implements Parcelable { final int numAxes = mMotionRanges.size(); for (int i = 0; i < numAxes; i++) { - int axis = mMotionRanges.keyAt(i); - MotionRange range = mMotionRanges.valueAt(i); - description.append(" ").append(MotionEvent.axisToString(axis)); - description.append(": min=").append(range.mMin); + MotionRange range = mMotionRanges.get(i); + description.append(" ").append(MotionEvent.axisToString(range.mAxis)); + description.append(": source=0x").append(Integer.toHexString(range.mSource)); + description.append(" min=").append(range.mMin); description.append(" max=").append(range.mMax); description.append(" flat=").append(range.mFlat); description.append(" fuzz=").append(range.mFuzz); diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 076f712..a17db5d 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -675,6 +675,87 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_RTRIGGER = 18; /** + * Constant used to identify the Throttle axis of a motion event. + * <p> + * <ul> + * <li>For a joystick, reports the absolute position of the throttle control. + * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed). + * </ul> + * </p> + * + * @see #getAxisValue(int, int) + * @see #getHistoricalAxisValue(int, int, int) + * @see MotionEvent.PointerCoords#getAxisValue(int) + * @see InputDevice#getMotionRange + */ + public static final int AXIS_THROTTLE = 19; + + /** + * Constant used to identify the Rudder axis of a motion event. + * <p> + * <ul> + * <li>For a joystick, reports the absolute position of the rudder control. + * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right). + * </ul> + * </p> + * + * @see #getAxisValue(int, int) + * @see #getHistoricalAxisValue(int, int, int) + * @see MotionEvent.PointerCoords#getAxisValue(int) + * @see InputDevice#getMotionRange + */ + public static final int AXIS_RUDDER = 20; + + /** + * Constant used to identify the Wheel axis of a motion event. + * <p> + * <ul> + * <li>For a joystick, reports the absolute position of the steering wheel control. + * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right). + * </ul> + * </p> + * + * @see #getAxisValue(int, int) + * @see #getHistoricalAxisValue(int, int, int) + * @see MotionEvent.PointerCoords#getAxisValue(int) + * @see InputDevice#getMotionRange + */ + public static final int AXIS_WHEEL = 21; + + /** + * Constant used to identify the Gas axis of a motion event. + * <p> + * <ul> + * <li>For a joystick, reports the absolute position of the gas (accelerator) control. + * The value is normalized to a range from 0.0 (no acceleration) + * to 1.0 (maximum acceleration). + * </ul> + * </p> + * + * @see #getAxisValue(int, int) + * @see #getHistoricalAxisValue(int, int, int) + * @see MotionEvent.PointerCoords#getAxisValue(int) + * @see InputDevice#getMotionRange + */ + public static final int AXIS_GAS = 22; + + /** + * Constant used to identify the Brake axis of a motion event. + * <p> + * <ul> + * <li>For a joystick, reports the absolute position of the brake control. + * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking). + * </ul> + * </p> + * + * @see #getAxisValue(int, int) + * @see #getHistoricalAxisValue(int, int, int) + * @see MotionEvent.PointerCoords#getAxisValue(int) + * @see InputDevice#getMotionRange + */ + public static final int AXIS_BRAKE = 23; + + /** * Constant used to identify the Generic 1 axis of a motion event. * The interpretation of a generic axis is device-specific. * @@ -877,6 +958,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { names.append(AXIS_HAT_Y, "AXIS_HAT_Y"); names.append(AXIS_LTRIGGER, "AXIS_LTRIGGER"); names.append(AXIS_RTRIGGER, "AXIS_RTRIGGER"); + names.append(AXIS_THROTTLE, "AXIS_THROTTLE"); + names.append(AXIS_RUDDER, "AXIS_RUDDER"); + names.append(AXIS_WHEEL, "AXIS_WHEEL"); + names.append(AXIS_GAS, "AXIS_GAS"); + names.append(AXIS_BRAKE, "AXIS_BRAKE"); names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1"); names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2"); names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3"); @@ -2071,6 +2157,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { * MotionEvent. For touch events, clients can use this to determine if the * user's finger was touching the edge of the display. * + * This property is only set for {@link #ACTION_DOWN} events. + * * @see #EDGE_LEFT * @see #EDGE_TOP * @see #EDGE_RIGHT diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index 0124151..5521e92 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -19,6 +19,7 @@ package android.view; import android.content.Context; import android.util.DisplayMetrics; import android.util.FloatMath; +import android.util.Log; /** * Detects transformation gestures involving more than one pointer ("multitouch") @@ -36,6 +37,8 @@ import android.util.FloatMath; * </ul> */ public class ScaleGestureDetector { + private static final String TAG = "ScaleGestureDetector"; + /** * The listener for receiving notifications when gestures occur. * If you want to listen for all the different gestures then implement @@ -170,6 +173,10 @@ public class ScaleGestureDetector { final int action = event.getActionMasked(); boolean handled = true; + if (action == MotionEvent.ACTION_DOWN) { + reset(); // Start fresh + } + if (!mGestureInProgress) { switch (action) { case MotionEvent.ACTION_DOWN: { @@ -197,6 +204,11 @@ public class ScaleGestureDetector { int index1 = event.getActionIndex(); int index0 = event.findPointerIndex(mActiveId0); mActiveId1 = event.getPointerId(index1); + if (index0 < 0 || index0 == index1) { + // Probably someone sending us a broken event stream. + index0 = findNewActiveIndex(event, index0 == index1 ? -1 : mActiveId1, index0); + mActiveId0 = event.getPointerId(index0); + } mActive0MostRecent = false; setContext(event); @@ -315,6 +327,7 @@ public class ScaleGestureDetector { final int index = event.findPointerIndex(actionId == mActiveId0 ? mActiveId1 : mActiveId0); mActiveId0 = event.getPointerId(index); + mActive0MostRecent = true; mActiveId1 = -1; mFocusX = event.getX(index); @@ -338,6 +351,18 @@ public class ScaleGestureDetector { mActiveId1 = event.getPointerId(event.getActionIndex()); mActive0MostRecent = false; + int index0 = event.findPointerIndex(mActiveId0); + if (index0 < 0 || mActiveId0 == mActiveId1) { + // Probably someone sending us a broken event stream. + Log.e(TAG, "Got " + MotionEvent.actionToString(action) + + " with bad state while a gesture was in progress. " + + "Did you forget to pass an event to " + + "ScaleGestureDetector#onTouchEvent?"); + index0 = findNewActiveIndex(event, + mActiveId0 == mActiveId1 ? -1 : mActiveId1, index0); + mActiveId0 = event.getPointerId(index0); + } + setContext(event); mGestureInProgress = mListener.onScaleBegin(this); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 3153ac5..f9692da 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2585,7 +2585,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } else { child.mPrivateFlags &= ~DIRTY_MASK; - ((HardwareCanvas) canvas).drawDisplayList(displayList); + ((HardwareCanvas) canvas).drawDisplayList(displayList, null); } } } else if (cache != null) { @@ -3680,7 +3680,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // flag coming from the child that initiated the invalidate if (view != null) { if ((view.mViewFlags & FADING_EDGE_MASK) != 0 && - view.getSolidColor() == 0 && !view.isOpaque()) { + view.getSolidColor() == 0) { opaqueFlag = DIRTY; } if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) { @@ -4275,11 +4275,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * does not exist within the group */ public View getChildAt(int index) { - try { - return mChildren[index]; - } catch (IndexOutOfBoundsException ex) { + if (index < 0 || index >= mChildrenCount) { return null; } + return mChildren[index]; } /** diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 5468230..a53c6d0 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -498,15 +498,21 @@ public final class ViewRoot extends Handler implements ViewParent, mAttachInfo.mHardwareAccelerationRequested = false; // Try to enable hardware acceleration if requested - if (attrs != null && - (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) { + final boolean hardwareAccelerated = + (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; + + if (attrs != null && hardwareAccelerated) { // Only enable hardware acceleration if we are not in the system process // The window manager creates ViewRoots to display animated preview windows // of launching apps and we don't want those to be hardware accelerated - if (!HardwareRenderer.sRendererDisabled) { + + final boolean systemHwAccelerated = + (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED_SYSTEM) != 0; + + if (!HardwareRenderer.sRendererDisabled || systemHwAccelerated) { // Don't enable hardware acceleration when we're not on the main thread - if (Looper.getMainLooper() != Looper.myLooper()) { - Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware " + if (!systemHwAccelerated && Looper.getMainLooper() != Looper.myLooper()) { + Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware " + "acceleration outside of the main thread, aborting"); return; } @@ -1606,13 +1612,9 @@ public final class ViewRoot extends Handler implements ViewParent, return; } catch (IllegalArgumentException e) { Log.e(TAG, "IllegalArgumentException locking surface", e); - try { - if (!sWindowSession.outOfMemory(mWindow)) { - Slog.w(TAG, "No processes killed for memory; killing self"); - Process.killProcess(Process.myPid()); - } - } catch (RemoteException ex) { - } + // Don't assume this is due to out of memory, it could be + // something else, and if it is something else then we could + // kill stuff (or ourself) for no reason. mLayoutRequested = true; // ask wm for a new surface next time. return; } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index ca932e9..8a18aaf 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -665,6 +665,17 @@ public interface WindowManager extends ViewManager { * XML attribute is set to true on an activity or on the application.</p> */ public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000; + + /** + * Like {@link #FLAG_HARDWARE_ACCELERATED} except for trusted system windows + * that need hardware acceleration (e.g. LockScreen), where hardware acceleration + * is generally disabled. This flag must be specified in addition to + * {@link #FLAG_HARDWARE_ACCELERATED} to enable hardware acceleration for system + * windows. + * + * @hide + */ + public static final int FLAG_HARDWARE_ACCELERATED_SYSTEM = 0x02000000; // ----- HIDDEN FLAGS. // These start at the high bit and go down. diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index ab4bfe1..c7a7374 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -1237,11 +1237,17 @@ class BrowserFrame extends Handler { } } - /*package*/ SearchBox getSearchBox() { return mSearchBox; } + /** + * Called by JNI when processing the X-Auto-Login header. + */ + private void autoLogin(String realm, String account, String args) { + mCallbackProxy.onReceivedLoginRequest(realm, account, args); + } + //========================================================================== // native functions //========================================================================== diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index c66d701..23fd12d 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -117,6 +117,7 @@ class CallbackProxy extends Handler { private static final int AUTH_CREDENTIALS = 137; private static final int SET_INSTALLABLE_WEBAPP = 138; private static final int NOTIFY_SEARCHBOX_LISTENERS = 139; + private static final int AUTO_LOGIN = 140; // Message triggered by the client to resume execution private static final int NOTIFY = 200; @@ -770,7 +771,7 @@ class CallbackProxy extends Handler { (WebHistoryItem) msg.obj, msg.arg1); } break; - case AUTH_CREDENTIALS: + case AUTH_CREDENTIALS: { String host = msg.getData().getString("host"); String realm = msg.getData().getString("realm"); username = msg.getData().getString("username"); @@ -778,6 +779,7 @@ class CallbackProxy extends Handler { mWebView.setHttpAuthUsernamePassword( host, realm, username, password); break; + } case SET_INSTALLABLE_WEBAPP: if (mWebChromeClient != null) { mWebChromeClient.setInstallableWebApp(); @@ -789,6 +791,17 @@ class CallbackProxy extends Handler { @SuppressWarnings("unchecked") List<String> suggestions = (List<String>) msg.obj; searchBox.handleSuggestions(msg.getData().getString("query"), suggestions); + break; + case AUTO_LOGIN: { + if (mWebViewClient != null) { + String realm = msg.getData().getString("realm"); + String account = msg.getData().getString("account"); + String args = msg.getData().getString("args"); + mWebViewClient.onReceivedLoginRequest(mWebView, realm, + account, args); + } + break; + } } } @@ -1051,6 +1064,20 @@ class CallbackProxy extends Handler { sendMessage(msg); } + void onReceivedLoginRequest(String realm, String account, String args) { + // Do an unsynchronized quick check to avoid posting if no callback has + // been set. + if (mWebViewClient == null) { + return; + } + Message msg = obtainMessage(AUTO_LOGIN); + Bundle bundle = msg.getData(); + bundle.putString("realm", realm); + bundle.putString("account", account); + bundle.putString("args", args); + sendMessage(msg); + } + //-------------------------------------------------------------------------- // DownloadListener functions. //-------------------------------------------------------------------------- diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java index 2dac7e9..3cb5e24 100644 --- a/core/java/android/webkit/DebugFlags.java +++ b/core/java/android/webkit/DebugFlags.java @@ -31,7 +31,7 @@ class DebugFlags { public static final boolean CACHE_MANAGER = false; public static final boolean CALLBACK_PROXY = false; public static final boolean COOKIE_MANAGER = false; - public static final boolean COOKIE_SYNC_MANAGER = true; + public static final boolean COOKIE_SYNC_MANAGER = false; public static final boolean FRAME_LOADER = false; public static final boolean J_WEB_CORE_JAVA_BRIDGE = false;// HIGHLY VERBOSE public static final boolean LOAD_LISTENER = false; @@ -41,7 +41,7 @@ class DebugFlags { public static final boolean URL_UTIL = false; public static final boolean WEB_BACK_FORWARD_LIST = false; public static final boolean WEB_SETTINGS = false; - public static final boolean WEB_SYNC_MANAGER = true; + public static final boolean WEB_SYNC_MANAGER = false; public static final boolean WEB_TEXT_VIEW = false; public static final boolean WEB_VIEW = false; public static final boolean WEB_VIEW_CORE = false; diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java new file mode 100644 index 0000000..2312160 --- /dev/null +++ b/core/java/android/webkit/HTML5VideoView.java @@ -0,0 +1,211 @@ + +package android.webkit; + +import android.graphics.SurfaceTexture; +import android.media.MediaPlayer; +import android.util.Log; +import android.webkit.HTML5VideoViewProxy; +import android.widget.MediaController; +import android.opengl.GLES20; +import java.io.IOException; +import java.util.Map; + +/** + * @hide This is only used by the browser + */ +public class HTML5VideoView implements MediaPlayer.OnPreparedListener{ + // Due to the fact that SurfaceTexture consume a lot of memory, we make it + // as static. m_textureNames is the texture bound with this SurfaceTexture. + private static SurfaceTexture mSurfaceTexture = null; + private static int[] mTextureNames; + + // Only when the video is prepared, we render using SurfaceTexture. + // This in fact is used to avoid showing the obsolete content when + // switching videos. + private static boolean mReadyToUseSurfTex = false; + + // For handling the seekTo before prepared, we need to know whether or not + // the video is prepared. Therefore, we differentiate the state between + // prepared and not prepared. + // When the video is not prepared, we will have to save the seekTo time, + // and use it when prepared to play. + private static final int STATE_NOTPREPARED = 0; + private static final int STATE_PREPARED = 1; + + // We only need state for handling seekTo + private int mCurrentState; + + // Basically for calling back the OnPrepared in the proxy + private HTML5VideoViewProxy mProxy; + + // Save the seek time when not prepared. This can happen when switching + // video besides initial load. + private int mSaveSeekTime; + + // This is used to find the VideoLayer on the native side. + private int mVideoLayerId; + + // Every video will have one MediaPlayer. Given the fact we only have one + // SurfaceTexture, there is only one MediaPlayer in action. Every time we + // switch videos, a new instance of MediaPlayer will be created in reset(). + private MediaPlayer mPlayer; + + private static HTML5VideoView mInstance = new HTML5VideoView(); + + // Video control FUNCTIONS: + public void start() { + if (mCurrentState == STATE_PREPARED) { + mPlayer.start(); + mReadyToUseSurfTex = true; + } + } + + public void pause() { + mPlayer.pause(); + } + + public int getDuration() { + return mPlayer.getDuration(); + } + + public int getCurrentPosition() { + return mPlayer.getCurrentPosition(); + } + + public void seekTo(int pos) { + if (mCurrentState == STATE_PREPARED) + mPlayer.seekTo(pos); + else + mSaveSeekTime = pos; + } + + public boolean isPlaying() { + return mPlayer.isPlaying(); + } + + public void release() { + mPlayer.release(); + } + + public void stopPlayback() { + mPlayer.stop(); + } + + private void reset(int videoLayerId) { + mPlayer = new MediaPlayer(); + mCurrentState = STATE_NOTPREPARED; + mProxy = null; + mVideoLayerId = videoLayerId; + mReadyToUseSurfTex = false; + } + + public static HTML5VideoView getInstance(int videoLayerId) { + // Every time we switch between the videos, a new MediaPlayer will be + // created. Make sure we call the m_player.release() when it is done. + mInstance.reset(videoLayerId); + return mInstance; + } + + private HTML5VideoView() { + // This is a singleton across WebViews (i.e. Tabs). + // HTML5VideoViewProxy will reset the internal state every time a new + // video start. + } + + public void setMediaController(MediaController m) { + this.setMediaController(m); + } + + public void setVideoURI(String uri, Map<String, String> headers) { + // When switching players, surface texture will be reused. + mPlayer.setTexture(getSurfaceTextureInstance()); + + // When there is exception, we could just bail out silently. + // No Video will be played though. Write the stack for debug + try { + mPlayer.setDataSource(uri, headers); + mPlayer.prepareAsync(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // TODO [FULL SCREEN SUPPORT] + + // Listeners setup FUNCTIONS: + public void setOnCompletionListener(HTML5VideoViewProxy proxy) { + mPlayer.setOnCompletionListener(proxy); + } + + public void setOnErrorListener(HTML5VideoViewProxy proxy) { + mPlayer.setOnErrorListener(proxy); + } + + public void setOnPreparedListener(HTML5VideoViewProxy proxy) { + mProxy = proxy; + mPlayer.setOnPreparedListener(this); + } + + // Inline Video specific FUNCTIONS: + + public SurfaceTexture getSurfaceTexture() { + return mSurfaceTexture; + } + + public void deleteSurfaceTexture() { + mSurfaceTexture = null; + return; + } + + // SurfaceTexture is a singleton here , too + private SurfaceTexture getSurfaceTextureInstance() { + // Create the surface texture. + if (mSurfaceTexture == null) + { + mTextureNames = new int[1]; + GLES20.glGenTextures(1, mTextureNames, 0); + mSurfaceTexture = new SurfaceTexture(mTextureNames[0]); + } + return mSurfaceTexture; + } + + public int getTextureName() { + return mTextureNames[0]; + } + + public int getVideoLayerId() { + return mVideoLayerId; + } + + public boolean getReadyToUseSurfTex() { + return mReadyToUseSurfTex; + } + + public void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) { + mSurfaceTexture.setOnFrameAvailableListener(l); + } + + @Override + public void onPrepared(MediaPlayer mp) { + mCurrentState = STATE_PREPARED; + seekTo(mSaveSeekTime); + if (mProxy != null) + mProxy.onPrepared(mp); + } + + // Pause the play and update the play/pause button + public void pauseAndDispatch(HTML5VideoViewProxy proxy) { + if (isPlaying()) { + pause(); + if (proxy != null) { + proxy.dispatchOnPaused(); + } + } + mReadyToUseSurfTex = false; + } + +} diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java index 85763da..b614d8f 100644 --- a/core/java/android/webkit/HTML5VideoViewProxy.java +++ b/core/java/android/webkit/HTML5VideoViewProxy.java @@ -19,6 +19,7 @@ package android.webkit; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.SurfaceTexture; import android.media.MediaPlayer; import android.media.MediaPlayer.OnPreparedListener; import android.media.MediaPlayer.OnCompletionListener; @@ -59,7 +60,8 @@ import java.util.TimerTask; class HTML5VideoViewProxy extends Handler implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, - MediaPlayer.OnErrorListener { + MediaPlayer.OnErrorListener, + SurfaceTexture.OnFrameAvailableListener { // Logging tag. private static final String LOGTAG = "HTML5VideoViewProxy"; @@ -101,7 +103,7 @@ class HTML5VideoViewProxy extends Handler private static HTML5VideoViewProxy mCurrentProxy; // The VideoView instance. This is a singleton for now, at least until // http://b/issue?id=1973663 is fixed. - private static VideoView mVideoView; + private static HTML5VideoView mHTML5VideoView; // The progress view. private static View mProgressView; // The container for the progress view and video view @@ -122,131 +124,149 @@ class HTML5VideoViewProxy extends Handler } // The spec says the timer should fire every 250 ms or less. private static final int TIMEUPDATE_PERIOD = 250; // ms - static boolean isVideoSelfEnded = false; - - private static final WebChromeClient.CustomViewCallback mCallback = - new WebChromeClient.CustomViewCallback() { - public void onCustomViewHidden() { - // At this point the videoview is pretty much destroyed. - // It listens to SurfaceHolder.Callback.SurfaceDestroyed event - // which happens when the video view is detached from its parent - // view. This happens in the WebChromeClient before this method - // is invoked. - mTimer.cancel(); - mTimer = null; - if (mVideoView.isPlaying()) { - mVideoView.stopPlayback(); + private static boolean isVideoSelfEnded = false; + // By using the baseLayer and the current video Layer ID, we can + // identify the exact layer on the UI thread to use the SurfaceTexture. + private static int mBaseLayer = 0; + + // TODO: [FULL SCREEN SUPPORT] + + // Every time webView setBaseLayer, this will be called. + // When we found the Video layer, then we set the Surface Texture to it. + // Otherwise, we may want to delete the Surface Texture to save memory. + public static void setBaseLayer(int layer) { + if (mHTML5VideoView != null) { + mBaseLayer = layer; + SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(); + int textureName = mHTML5VideoView.getTextureName(); + + int currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); + if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) { + boolean readyToUseSurfTex = + mHTML5VideoView.getReadyToUseSurfTex(); + boolean foundInTree = nativeSendSurfaceTexture(surfTexture, + layer, currentVideoLayerId, textureName, + readyToUseSurfTex); + if (readyToUseSurfTex && !foundInTree) { + mHTML5VideoView.pauseAndDispatch(mCurrentProxy); + mHTML5VideoView.deleteSurfaceTexture(); } - if (isVideoSelfEnded) - mCurrentProxy.dispatchOnEnded(); - else - mCurrentProxy.dispatchOnPaused(); - - // Re enable plugin views. - mCurrentProxy.getWebView().getViewManager().showAll(); - - isVideoSelfEnded = false; - mCurrentProxy = null; - mLayout.removeView(mVideoView); - mVideoView = null; - if (mProgressView != null) { - mLayout.removeView(mProgressView); - mProgressView = null; - } - mLayout = null; } - }; + } + } + + // When a WebView is paused, we also want to pause the video in it. + public static void pauseAndDispatch() { + if (mHTML5VideoView != null) { + mHTML5VideoView.pauseAndDispatch(mCurrentProxy); + // When switching out, clean the video content on the old page + // by telling the layer not readyToUseSurfTex. + setBaseLayer(mBaseLayer); + } + } + // This is on the UI thread. + // When native tell Java to play, we need to check whether or not it is + // still the same video by using videoLayerId and treat it differently. public static void play(String url, int time, HTML5VideoViewProxy proxy, - WebChromeClient client) { - if (mCurrentProxy == proxy) { - if (!mVideoView.isPlaying()) { - mVideoView.start(); + WebChromeClient client, int videoLayerId) { + int currentVideoLayerId = -1; + if (mHTML5VideoView != null) + currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); + + if (currentVideoLayerId != videoLayerId + || mHTML5VideoView.getSurfaceTexture() == null) { + // Here, we handle the case when switching to a new video, + // either inside a WebView or across WebViews + // For switching videos within a WebView or across the WebView, + // we need to pause the old one and re-create a new media player + // inside the HTML5VideoView. + if (mHTML5VideoView != null) { + mHTML5VideoView.pauseAndDispatch(mCurrentProxy); + // release the media player to avoid finalize error + mHTML5VideoView.release(); } - return; - } + // HTML5VideoView is singleton, however, the internal state will + // be reset since we are switching from one video to another. + // Then we need to set up all the source/listener etc... + mHTML5VideoView = HTML5VideoView.getInstance(videoLayerId); - if (mCurrentProxy != null) { - // Some other video is already playing. Notify the caller that its playback ended. - proxy.dispatchOnEnded(); - return; - } + mCurrentProxy = proxy; - mCurrentProxy = proxy; - // Create a FrameLayout that will contain the VideoView and the - // progress view (if any). - mLayout = new FrameLayout(proxy.getContext()); - FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT, - Gravity.CENTER); - mVideoView = new VideoView(proxy.getContext()); - mVideoView.setWillNotDraw(false); - mVideoView.setMediaController(new MediaController(proxy.getContext())); - - boolean isPrivate = mCurrentProxy.getWebView().isPrivateBrowsingEnabled(); - String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate); - Map<String, String> headers = new HashMap<String, String>(); - if (cookieValue != null) { - headers.put(COOKIE, cookieValue); - } - if (isPrivate) { - headers.put(HIDE_URL_LOGS, "true"); - } + // TODO: [FULL SCREEN SUPPORT] + + boolean isPrivate = mCurrentProxy.getWebView().isPrivateBrowsingEnabled(); + String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate); + Map<String, String> headers = new HashMap<String, String>(); + if (cookieValue != null) { + headers.put(COOKIE, cookieValue); + } + if (isPrivate) { + headers.put(HIDE_URL_LOGS, "true"); + } + + mHTML5VideoView.setVideoURI(url, headers); + mHTML5VideoView.setOnCompletionListener(proxy); + mHTML5VideoView.setOnPreparedListener(proxy); + mHTML5VideoView.setOnErrorListener(proxy); + mHTML5VideoView.setFrameAvailableListener(proxy); - mVideoView.setVideoURI(Uri.parse(url), headers); - mVideoView.setOnCompletionListener(proxy); - mVideoView.setOnPreparedListener(proxy); - mVideoView.setOnErrorListener(proxy); - mVideoView.seekTo(time); - mLayout.addView(mVideoView, layoutParams); - mProgressView = client.getVideoLoadingProgressView(); - if (mProgressView != null) { - mLayout.addView(mProgressView, layoutParams); - mProgressView.setVisibility(View.VISIBLE); + mHTML5VideoView.seekTo(time); + + mTimer = new Timer(); + + } else if (mCurrentProxy == proxy) { + // Here, we handle the case when we keep playing with one video + if (!mHTML5VideoView.isPlaying()) { + mHTML5VideoView.seekTo(time); + mHTML5VideoView.start(); + } + } else if (mCurrentProxy != null) { + // Some other video is already playing. Notify the caller that its playback ended. + proxy.dispatchOnEnded(); } - mLayout.setVisibility(View.VISIBLE); - mTimer = new Timer(); - mVideoView.start(); - client.onShowCustomView(mLayout, mCallback); - // Plugins like Flash will draw over the video so hide - // them while we're playing. - mCurrentProxy.getWebView().getViewManager().hideAll(); } public static boolean isPlaying(HTML5VideoViewProxy proxy) { - return (mCurrentProxy == proxy && mVideoView != null && mVideoView.isPlaying()); + return (mCurrentProxy == proxy && mHTML5VideoView != null + && mHTML5VideoView.isPlaying()); } public static int getCurrentPosition() { int currentPosMs = 0; - if (mVideoView != null) { - currentPosMs = mVideoView.getCurrentPosition(); + if (mHTML5VideoView != null) { + currentPosMs = mHTML5VideoView.getCurrentPosition(); } return currentPosMs; } public static void seek(int time, HTML5VideoViewProxy proxy) { - if (mCurrentProxy == proxy && time >= 0 && mVideoView != null) { - mVideoView.seekTo(time); + if (mCurrentProxy == proxy && time >= 0 && mHTML5VideoView != null) { + mHTML5VideoView.seekTo(time); } } public static void pause(HTML5VideoViewProxy proxy) { - if (mCurrentProxy == proxy && mVideoView != null) { - mVideoView.pause(); + if (mCurrentProxy == proxy && mHTML5VideoView != null) { + mHTML5VideoView.pause(); mTimer.purge(); } } public static void onPrepared() { - if (mProgressView == null || mLayout == null) { - return; - } + mHTML5VideoView.start(); mTimer.schedule(new TimeupdateTask(mCurrentProxy), TIMEUPDATE_PERIOD, TIMEUPDATE_PERIOD); - mProgressView.setVisibility(View.GONE); - mLayout.removeView(mProgressView); - mProgressView = null; + // TODO: [FULL SCREEN SUPPORT] + } + + public static void end() { + if (mCurrentProxy != null) { + if (isVideoSelfEnded) + mCurrentProxy.dispatchOnEnded(); + else + mCurrentProxy.dispatchOnPaused(); + } + isVideoSelfEnded = false; } } @@ -292,6 +312,14 @@ class HTML5VideoViewProxy extends Handler sendMessage(obtainMessage(TIMEUPDATE)); } + // When there is a frame ready from surface texture, we should tell WebView + // to refresh. + @Override + public void onFrameAvailable(SurfaceTexture surfaceTexture) { + // TODO: This should support partial invalidation too. + mWebView.invalidate(); + } + // Handler for the messages from WebCore or Timer thread to the UI thread. @Override public void handleMessage(Message msg) { @@ -300,8 +328,9 @@ class HTML5VideoViewProxy extends Handler case PLAY: { String url = (String) msg.obj; WebChromeClient client = mWebView.getWebChromeClient(); + int videoLayerID = msg.arg1; if (client != null) { - VideoPlayer.play(url, mSeekPosition, this, client); + VideoPlayer.play(url, mSeekPosition, this, client, videoLayerID); } break; } @@ -318,6 +347,10 @@ class HTML5VideoViewProxy extends Handler case ENDED: if (msg.arg1 == 1) VideoPlayer.isVideoSelfEnded = true; + VideoPlayer.end(); + break; + // TODO: [FULL SCREEN SUPPORT] + // For full screen case, end may need hide the view. case ERROR: { WebChromeClient client = mWebView.getWebChromeClient(); if (client != null) { @@ -500,6 +533,10 @@ class HTML5VideoViewProxy extends Handler super(Looper.getMainLooper()); // Save the WebView object. mWebView = webView; + // Pass Proxy into webview, such that every time we have a setBaseLayer + // call, we tell this Proxy to call the native to update the layer tree + // for the Video Layer's surface texture info + mWebView.setHTML5VideoViewProxy(this); // Save the native ptr mNativePointer = nativePtr; // create the message handler for this thread @@ -565,7 +602,7 @@ class HTML5VideoViewProxy extends Handler * Play a video stream. * @param url is the URL of the video stream. */ - public void play(String url, int position) { + public void play(String url, int position, int videoLayerID) { if (url == null) { return; } @@ -573,8 +610,8 @@ class HTML5VideoViewProxy extends Handler if (position > 0) { seek(position); } - Message message = obtainMessage(PLAY); + message.arg1 = videoLayerID; message.obj = url; sendMessage(message); } @@ -628,6 +665,14 @@ class HTML5VideoViewProxy extends Handler mPosterDownloader.start(); } + // These two function are called from UI thread only by WebView. + public void setBaseLayer(int layer) { + VideoPlayer.setBaseLayer(layer); + } + + public void pauseAndDispatch() { + VideoPlayer.pauseAndDispatch(); + } /** * The factory for HTML5VideoViewProxy instances. * @param webViewCore is the WebViewCore that is requesting the proxy. @@ -647,4 +692,7 @@ class HTML5VideoViewProxy extends Handler private native void nativeOnPaused(int nativePointer); private native void nativeOnPosterFetched(Bitmap poster, int nativePointer); private native void nativeOnTimeupdate(int position, int nativePointer); + private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture, + int baseLayer, int videoLayerId, int textureName, + boolean updateTexture); } diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java index 7c0e478..ccf3d6b 100644 --- a/core/java/android/webkit/WebHistoryItem.java +++ b/core/java/android/webkit/WebHistoryItem.java @@ -90,7 +90,9 @@ public class WebHistoryItem implements Cloneable { * another item, the identifiers will be the same even if they are not the * same object. * @return The id for this item. + * @deprecated This method is now obsolete. */ + @Deprecated public int getId() { return mId; } diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 71d6080..2b507fd 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -43,8 +43,10 @@ public class WebSettings { * SINGLE_COLUMN moves all content into one column that is the width of the * view. * NARROW_COLUMNS makes all columns no wider than the screen if possible. + * @deprecated This enum is now obsolete. */ // XXX: These must match LayoutAlgorithm in Settings.h in WebCore. + @Deprecated public enum LayoutAlgorithm { NORMAL, SINGLE_COLUMN, @@ -510,14 +512,18 @@ public class WebSettings { /** * Enables dumping the pages navigation cache to a text file. + * @deprecated This method is now obsolete. */ + @Deprecated public void setNavDump(boolean enabled) { mNavDump = enabled; } /** * Returns true if dumping the navigation cache is enabled. + * @deprecated This method is now obsolete. */ + @Deprecated public boolean getNavDump() { return mNavDump; } @@ -655,7 +661,9 @@ public class WebSettings { * Set whether the WebView uses its background for over scroll background. * If true, it will use the WebView's background. If false, it will use an * internal pattern. Default is true. + * @deprecated This method is now obsolete. */ + @Deprecated public void setUseWebViewBackgroundForOverscrollBackground(boolean view) { mUseWebViewBackgroundForOverscroll = view; } @@ -663,7 +671,9 @@ public class WebSettings { /** * Returns true if this WebView uses WebView's background instead of * internal pattern for over scroll background. + * @deprecated This method is now obsolete. */ + @Deprecated public boolean getUseWebViewBackgroundForOverscrollBackground() { return mUseWebViewBackgroundForOverscroll; } @@ -866,7 +876,9 @@ public class WebSettings { * WebView. * @param l A LayoutAlgorithm enum specifying the algorithm to use. * @see WebSettings.LayoutAlgorithm + * @deprecated This method is now obsolete. */ + @Deprecated public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) { // XXX: This will only be affective if libwebcore was built with // ANDROID_LAYOUT defined. @@ -881,7 +893,9 @@ public class WebSettings { * @return LayoutAlgorithm enum value describing the layout algorithm * being used. * @see WebSettings.LayoutAlgorithm + * @deprecated This method is now obsolete. */ + @Deprecated public synchronized LayoutAlgorithm getLayoutAlgorithm() { return mLayoutAlgorithm; } diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 28b0951..0f24edc 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -26,14 +26,15 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.ResultReceiver; 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; @@ -136,6 +137,23 @@ import junit.framework.Assert; // Used to determine whether onFocusChanged was called as a result of // calling remove(). private boolean mInsideRemove; + private class MyResultReceiver extends ResultReceiver { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + if (resultCode == InputMethodManager.RESULT_SHOWN + && mWebView != null) { + mWebView.revealSelection(); + } + } + + /** + * @param handler + */ + public MyResultReceiver(Handler handler) { + super(handler); + } + } + private MyResultReceiver mReceiver; // Types used with setType. Keep in sync with CachedInput.h private static final int NORMAL_TEXT_FIELD = 0; @@ -184,7 +202,7 @@ import junit.framework.Assert; } } }; - + mReceiver = new MyResultReceiver(mHandler); } public void setAutoFillable(int queryId) { @@ -362,6 +380,8 @@ import junit.framework.Assert; } } + /* package */ ResultReceiver getResultReceiver() { return mReceiver; } + /** * Determine whether this WebTextView currently represents the node * represented by ptr. diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 642cd02..8ef745b 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -43,6 +43,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; +import android.graphics.SurfaceTexture; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.net.Proxy; @@ -351,7 +352,8 @@ public class WebView extends AbsoluteLayout private ZoomManager mZoomManager; - private Rect mGLRectViewport = new Rect(); + private final Rect mGLRectViewport = new Rect(); + private final Rect mViewRectViewport = new Rect(); private boolean mGLViewportEmpty = false; /** @@ -496,15 +498,6 @@ public class WebView extends AbsoluteLayout // default is not set, the UI will continue handle them. private boolean mDeferTouchProcess; - // Currently, multi-touch events are sent to WebKit first then back to - // WebView while single-touch events are handled in WebView first. - // So there is a chance that a single-touch move event is handled in WebView - // before multi-touch events are finished. - // if mIsHandlingMultiTouch is true, which means multi-touch event handling - // is not finished, then any single-touch move event will be skipped. - // FIXME: send single-touch events to WebKit first then back to WebView. - private boolean mIsHandlingMultiTouch = false; - // to avoid interfering with the current touch events, track them // separately. Currently no snapping or fling in the deferred process mode private int mDeferTouchMode = TOUCH_DONE_MODE; @@ -616,6 +609,10 @@ public class WebView extends AbsoluteLayout private int mTouchHighlightX; private int mTouchHighlightY; + // Basically this proxy is used to tell the Video to update layer tree at + // SetBaseLayer time and to pause when WebView paused. + private HTML5VideoViewProxy mHTML5VideoViewProxy; + /* * Private message ids */ @@ -674,6 +671,7 @@ public class WebView extends AbsoluteLayout static final int SELECT_AT = 135; static final int SCREEN_ON = 136; + static final int ENTER_FULLSCREEN_VIDEO = 137; private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID; private static final int LAST_PACKAGE_MSG_ID = SET_TOUCH_HIGHLIGHT_RECTS; @@ -728,7 +726,8 @@ public class WebView extends AbsoluteLayout "SET_AUTOFILLABLE", // = 133; "AUTOFILL_COMPLETE", // = 134; "SELECT_AT", // = 135; - "SCREEN_ON" // = 136; + "SCREEN_ON", // = 136; + "ENTER_FULLSCREEN_VIDEO" // = 137; }; // If the site doesn't use the viewport meta tag to specify the viewport, @@ -847,17 +846,24 @@ public class WebView extends AbsoluteLayout private Rect mScrollingLayerBounds = new Rect(); private boolean mSentAutoScrollMessage = false; + // used for serializing asynchronously handled touch events. + private final TouchEventQueue mTouchEventQueue = new TouchEventQueue(); + // Used to notify listeners of a new picture. private PictureListener mPictureListener; /** * Interface to listen for new pictures as they change. + * @deprecated This interface is now obsolete. */ + @Deprecated public interface PictureListener { /** * Notify the listener that the picture has changed. * @param view The WebView that owns the picture. * @param picture The new picture. + * @deprecated This method is now obsolete. */ + @Deprecated public void onNewPicture(WebView view, Picture picture); } @@ -1128,10 +1134,13 @@ public class WebView extends AbsoluteLayout protected Set<String> doInBackground(Void... unused) { Set<String> installedPackages = new HashSet<String>(); PackageManager pm = mContext.getPackageManager(); - List<PackageInfo> packages = pm.getInstalledPackages(0); - for (PackageInfo p : packages) { - if (sGoogleApps.contains(p.packageName)) { - installedPackages.add(p.packageName); + for (String name : sGoogleApps) { + try { + PackageInfo pInfo = pm.getPackageInfo(name, + PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES); + installedPackages.add(name); + } catch(PackageManager.NameNotFoundException e) { + // package not found } } return installedPackages; @@ -1182,6 +1191,7 @@ public class WebView extends AbsoluteLayout // Initially use a size of two, since the user is likely to only hold // down two keys at a time (shift + another key) mKeysPressed = new Vector<Integer>(2); + mHTML5VideoViewProxy = null ; } /** @@ -1500,7 +1510,9 @@ public class WebView extends AbsoluteLayout /** * Enables platform notifications of data state and proxy changes. + * @deprecated Obsolete - platform notifications are always enabled. */ + @Deprecated public static void enablePlatformNotifications() { Network.enablePlatformNotifications(); } @@ -1508,7 +1520,9 @@ public class WebView extends AbsoluteLayout /** * If platform notifications are enabled, this should be called * from the Activity's onPause() or onStop(). + * @deprecated Obsolete - platform notifications are always enabled. */ + @Deprecated public static void disablePlatformNotifications() { Network.disablePlatformNotifications(); } @@ -1611,7 +1625,9 @@ public class WebView extends AbsoluteLayout * @param dest The file to store the serialized picture data. Will be * overwritten with this WebView's picture data. * @return True if the picture was successfully saved. + * @deprecated This method is now obsolete. */ + @Deprecated public boolean savePicture(Bundle b, final File dest) { if (dest == null || b == null) { return false; @@ -1672,7 +1688,9 @@ public class WebView extends AbsoluteLayout * @param b A Bundle containing the saved display data. * @param src The file where the picture data was stored. * @return True if the picture was successfully restored. + * @deprecated This method is now obsolete. */ + @Deprecated public boolean restorePicture(Bundle b, File src) { if (src == null || b == null) { return false; @@ -2890,6 +2908,11 @@ public class WebView extends AbsoluteLayout if (!mIsPaused) { mIsPaused = true; mWebViewCore.sendMessage(EventHub.ON_PAUSE); + // We want to pause the current playing video when switching out + // from the current WebView/tab. + if (mHTML5VideoViewProxy != null) { + mHTML5VideoViewProxy.pauseAndDispatch(); + } } } @@ -3001,7 +3024,8 @@ public class WebView extends AbsoluteLayout } /** - * Start an ActionMode for finding text in this WebView. + * Start an ActionMode for finding text in this WebView. Only works if this + * WebView is attached to the view system. * @param text If non-null, will be the initial text to search for. * Otherwise, the last String searched for in this WebView will * be used to start. @@ -3011,7 +3035,7 @@ public class WebView extends AbsoluteLayout */ public boolean showFindDialog(String text, boolean showIme) { FindActionModeCallback callback = new FindActionModeCallback(mContext); - if (startActionMode(callback) == null) { + if (getParent() == null || startActionMode(callback) == null) { // Could not start the action mode, so end Find on page return false; } @@ -3609,7 +3633,9 @@ public class WebView extends AbsoluteLayout * Set the Picture listener. This is an interface used to receive * notifications of a new Picture. * @param listener An implementation of WebView.PictureListener. + * @deprecated This method is now obsolete. */ + @Deprecated public void setPictureListener(PictureListener listener) { mPictureListener = listener; } @@ -4017,14 +4043,12 @@ public class WebView extends AbsoluteLayout } } - void setBaseLayer(int layer, Rect invalRect, boolean showVisualIndciator) { + void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator) { if (mNativeClass == 0) return; - if (invalRect == null) { - Rect rect = new Rect(0, 0, mContentWidth, mContentHeight); - nativeSetBaseLayer(layer, rect, showVisualIndciator); - } else { - nativeSetBaseLayer(layer, invalRect, showVisualIndciator); + nativeSetBaseLayer(layer, invalRegion, showVisualIndicator); + if (mHTML5VideoViewProxy != null) { + mHTML5VideoViewProxy.setBaseLayer(layer); } } @@ -4098,7 +4122,7 @@ public class WebView extends AbsoluteLayout } if (animateZoom) { mZoomManager.animateZoom(canvas); - } else { + } else if (!canvas.isHardwareAccelerated()) { canvas.scale(mZoomManager.getScale(), mZoomManager.getScale()); } @@ -4135,7 +4159,7 @@ public class WebView extends AbsoluteLayout if (canvas.isHardwareAccelerated()) { int functor = nativeGetDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport, - getScale(), extras); + mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras); ((HardwareCanvas) canvas).callDrawGLFunction(functor); } else { DrawFilter df = null; @@ -4265,7 +4289,7 @@ public class WebView extends AbsoluteLayout if (isTextView) { rebuildWebTextView(); if (inEditingMode()) { - imm.showSoftInput(mWebTextView, 0); + imm.showSoftInput(mWebTextView, 0, mWebTextView.getResultReceiver()); if (zoom) { didUpdateWebTextViewDimensions(INTERSECTS_SCREEN); } @@ -4965,7 +4989,9 @@ public class WebView extends AbsoluteLayout /** * Use this method to put the WebView into text selection mode. * Do not rely on this functionality; it will be deprecated in the future. + * @deprecated This method is now obsolete. */ + @Deprecated public void emulateShiftHeld() { setUpSelect(false, 0, 0); } @@ -5065,6 +5091,8 @@ public class WebView extends AbsoluteLayout } addAccessibilityApisToJavaScript(); + + mTouchEventQueue.reset(); } @Override @@ -5237,6 +5265,7 @@ public class WebView extends AbsoluteLayout // Then need to invert the Y axis, just for GL View rootView = getRootView(); int rootViewHeight = rootView.getHeight(); + mViewRectViewport.set(mGLRectViewport); int savedWebViewBottom = mGLRectViewport.bottom; mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeight(); mGLRectViewport.top = rootViewHeight - savedWebViewBottom; @@ -5244,7 +5273,8 @@ public class WebView extends AbsoluteLayout } else { mGLViewportEmpty = true; } - nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport); + nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport, + mGLViewportEmpty ? null : mViewRectViewport); } /** @@ -5416,34 +5446,17 @@ public class WebView extends AbsoluteLayout + " numPointers=" + ev.getPointerCount()); } - int action = ev.getActionMasked(); - if (ev.getPointerCount() > 1) { // Multi-touch - mIsHandlingMultiTouch = true; - - // If WebKit already showed no interests in this sequence of events, - // WebView handles them directly. - if (mPreventDefault == PREVENT_DEFAULT_NO) { - handleMultiTouchInWebView(ev); - } else { - passMultiTouchToWebKit(ev); - } - return true; + // If WebKit wasn't interested in this multitouch gesture, enqueue + // the event for handling directly rather than making the round trip + // to WebKit and back. + if (ev.getPointerCount() > 1 && mPreventDefault != PREVENT_DEFAULT_NO) { + passMultiTouchToWebKit(ev, mTouchEventQueue.nextTouchSequence()); } else { - final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector(); - if (detector != null) { - // ScaleGestureDetector needs a consistent event stream to operate properly. - // It won't take any action with fewer than two pointers, but it needs to - // update internal bookkeeping state. - detector.onTouchEvent(ev); - } + mTouchEventQueue.enqueueTouchEvent(ev); } - // Skip ACTION_MOVE for single touch if it's still handling multi-touch. - if (mIsHandlingMultiTouch && action == MotionEvent.ACTION_MOVE) { - return false; - } - - return handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY())); + // Since all events are handled asynchronously, we always want the gesture stream. + return true; } /* @@ -5471,7 +5484,6 @@ public class WebView extends AbsoluteLayout case MotionEvent.ACTION_DOWN: { mPreventDefault = PREVENT_DEFAULT_NO; mConfirmMove = false; - mIsHandlingMultiTouch = false; mInitialHitTestResult = null; if (!mScroller.isFinished()) { // stop the current scroll animation, but if this is @@ -5563,6 +5575,7 @@ public class WebView extends AbsoluteLayout ted.mReprocess = mDeferTouchProcess; ted.mNativeLayer = nativeScrollableLayer( contentX, contentY, ted.mNativeLayerRect, null); + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); if (mDeferTouchProcess) { // still needs to set them for compute deltaX/Y @@ -5609,6 +5622,7 @@ public class WebView extends AbsoluteLayout ted.mReprocess = mDeferTouchProcess; ted.mNativeLayer = mScrollingLayer; ted.mNativeLayerRect.set(mScrollingLayerRect); + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mLastSentTouchTime = eventTime; if (mDeferTouchProcess) { @@ -5790,6 +5804,7 @@ public class WebView extends AbsoluteLayout ted.mReprocess = mDeferTouchProcess; ted.mNativeLayer = mScrollingLayer; ted.mNativeLayerRect.set(mScrollingLayerRect); + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } mLastTouchUpTime = eventTime; @@ -5812,6 +5827,7 @@ public class WebView extends AbsoluteLayout ted.mNativeLayer = nativeScrollableLayer( contentX, contentY, ted.mNativeLayerRect, null); + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES){ mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); @@ -5936,7 +5952,7 @@ public class WebView extends AbsoluteLayout return true; } - private void passMultiTouchToWebKit(MotionEvent ev) { + private void passMultiTouchToWebKit(MotionEvent ev, long sequence) { TouchEventData ted = new TouchEventData(); ted.mAction = ev.getActionMasked(); final int count = ev.getPointerCount(); @@ -5951,13 +5967,13 @@ public class WebView extends AbsoluteLayout ted.mMetaState = ev.getMetaState(); ted.mReprocess = true; ted.mMotionEvent = MotionEvent.obtain(ev); + ted.mSequence = sequence; mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); cancelLongPress(); mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); - mPreventDefault = PREVENT_DEFAULT_IGNORE; } - private void handleMultiTouchInWebView(MotionEvent ev) { + void handleMultiTouchInWebView(MotionEvent ev) { if (DebugFlags.WEB_VIEW) { Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime() + " mTouchMode=" + mTouchMode @@ -5975,24 +5991,26 @@ public class WebView extends AbsoluteLayout float x = ev.getX(); float y = ev.getY(); - detector.onTouchEvent(ev); + if (mPreventDefault != PREVENT_DEFAULT_YES) { + detector.onTouchEvent(ev); - if (detector.isInProgress()) { - if (DebugFlags.WEB_VIEW) { - Log.v(LOGTAG, "detector is in progress"); - } - mLastTouchTime = ev.getEventTime(); - x = detector.getFocusX(); - y = detector.getFocusY(); - - cancelLongPress(); - mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); - if (!mZoomManager.supportsPanDuringZoom()) { - return; - } - mTouchMode = TOUCH_DRAG_MODE; - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); + if (detector.isInProgress()) { + if (DebugFlags.WEB_VIEW) { + Log.v(LOGTAG, "detector is in progress"); + } + mLastTouchTime = ev.getEventTime(); + x = detector.getFocusX(); + y = detector.getFocusY(); + + cancelLongPress(); + mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); + if (!mZoomManager.supportsPanDuringZoom()) { + return; + } + mTouchMode = TOUCH_DRAG_MODE; + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } } } @@ -6000,11 +6018,10 @@ public class WebView extends AbsoluteLayout if (action == MotionEvent.ACTION_POINTER_DOWN) { cancelTouch(); action = MotionEvent.ACTION_DOWN; - } else if (action == MotionEvent.ACTION_POINTER_UP) { + } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() == 2) { // set mLastTouchX/Y to the remaining point mLastTouchX = Math.round(x); mLastTouchY = Math.round(y); - mIsHandlingMultiTouch = false; } else if (action == MotionEvent.ACTION_MOVE) { // negative x or y indicate it is on the edge, skip it. if (x < 0 || y < 0) { @@ -6019,6 +6036,7 @@ public class WebView extends AbsoluteLayout if (shouldForwardTouchEvent()) { if (removeEvents) { mWebViewCore.removeMessages(EventHub.TOUCH_EVENT); + mTouchEventQueue.ignoreCurrentlyMissingEvents(); } TouchEventData ted = new TouchEventData(); ted.mIds = new int[1]; @@ -6028,6 +6046,7 @@ public class WebView extends AbsoluteLayout ted.mAction = MotionEvent.ACTION_CANCEL; ted.mNativeLayer = nativeScrollableLayer( x, y, ted.mNativeLayerRect, null); + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mPreventDefault = PREVENT_DEFAULT_IGNORE; } @@ -7105,6 +7124,351 @@ public class WebView extends AbsoluteLayout return mWebViewCore; } + /** + * Used only by TouchEventQueue to store pending touch events. + */ + private static class QueuedTouch { + long mSequence; + MotionEvent mEvent; // Optional + TouchEventData mTed; // Optional + + QueuedTouch mNext; + + public QueuedTouch set(TouchEventData ted) { + mSequence = ted.mSequence; + mTed = ted; + mEvent = null; + mNext = null; + return this; + } + + public QueuedTouch set(MotionEvent ev, long sequence) { + mEvent = MotionEvent.obtain(ev); + mSequence = sequence; + mTed = null; + mNext = null; + return this; + } + + public QueuedTouch add(QueuedTouch other) { + if (other.mSequence < mSequence) { + other.mNext = this; + return other; + } + + QueuedTouch insertAt = this; + while (insertAt.mNext != null && insertAt.mNext.mSequence < other.mSequence) { + insertAt = insertAt.mNext; + } + other.mNext = insertAt.mNext; + insertAt.mNext = other; + return this; + } + } + + /** + * WebView handles touch events asynchronously since some events must be passed to WebKit + * for potentially slower processing. TouchEventQueue serializes touch events regardless + * of which path they take to ensure that no events are ever processed out of order + * by WebView. + */ + private class TouchEventQueue { + private long mNextTouchSequence = Long.MIN_VALUE + 1; + private long mLastHandledTouchSequence = Long.MIN_VALUE; + private long mIgnoreUntilSequence = Long.MIN_VALUE; + private QueuedTouch mTouchEventQueue; + private QueuedTouch mQueuedTouchRecycleBin; + private int mQueuedTouchRecycleCount; + private static final int MAX_RECYCLED_QUEUED_TOUCH = 15; + + // milliseconds until we abandon hope of getting all of a previous gesture + private static final int QUEUED_GESTURE_TIMEOUT = 2000; + + private QueuedTouch obtainQueuedTouch() { + if (mQueuedTouchRecycleBin != null) { + QueuedTouch result = mQueuedTouchRecycleBin; + mQueuedTouchRecycleBin = result.mNext; + mQueuedTouchRecycleCount--; + return result; + } + return new QueuedTouch(); + } + + /** + * Allow events with any currently missing sequence numbers to be skipped in processing. + */ + public void ignoreCurrentlyMissingEvents() { + mIgnoreUntilSequence = mNextTouchSequence; + } + + private void recycleQueuedTouch(QueuedTouch qd) { + if (mQueuedTouchRecycleCount < MAX_RECYCLED_QUEUED_TOUCH) { + qd.mNext = mQueuedTouchRecycleBin; + mQueuedTouchRecycleBin = qd; + mQueuedTouchRecycleCount++; + } + } + + /** + * Reset the touch event queue. This will dump any pending events + * and reset the sequence numbering. + */ + public void reset() { + mNextTouchSequence = Long.MIN_VALUE + 1; + mLastHandledTouchSequence = Long.MIN_VALUE; + mIgnoreUntilSequence = Long.MIN_VALUE; + while (mTouchEventQueue != null) { + QueuedTouch recycleMe = mTouchEventQueue; + mTouchEventQueue = mTouchEventQueue.mNext; + recycleQueuedTouch(recycleMe); + } + } + + /** + * Return the next valid sequence number for tagging incoming touch events. + * @return The next touch event sequence number + */ + public long nextTouchSequence() { + return mNextTouchSequence++; + } + + /** + * Enqueue a touch event in the form of TouchEventData. + * The sequence number will be read from the mSequence field of the argument. + * + * If the touch event's sequence number is the next in line to be processed, it will + * be handled before this method returns. Any subsequent events that have already + * been queued will also be processed in their proper order. + * + * @param ted Touch data to be processed in order. + */ + public void enqueueTouchEvent(TouchEventData ted) { + if (ted.mSequence < mLastHandledTouchSequence) { + // Stale event and we already moved on; drop it. (Should not be common.) + Log.w(LOGTAG, "Stale touch event " + MotionEvent.actionToString(ted.mAction) + + " received from webcore; ignoring"); + return; + } + + dropStaleGestures(ted.mMotionEvent, ted.mSequence); + + if (mLastHandledTouchSequence + 1 == ted.mSequence) { + handleQueuedTouchEventData(ted); + + mLastHandledTouchSequence++; + + // Do we have any more? Run them if so. + QueuedTouch qd = mTouchEventQueue; + while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { + handleQueuedTouch(qd); + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + mLastHandledTouchSequence++; + } + mTouchEventQueue = qd; + } else { + QueuedTouch qd = obtainQueuedTouch().set(ted); + mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd); + } + } + + /** + * Enqueue a touch event in the form of a MotionEvent from the framework. + * + * If the touch event's sequence number is the next in line to be processed, it will + * be handled before this method returns. Any subsequent events that have already + * been queued will also be processed in their proper order. + * + * @param ev MotionEvent to be processed in order + */ + public void enqueueTouchEvent(MotionEvent ev) { + final long sequence = nextTouchSequence(); + + dropStaleGestures(ev, sequence); + + if (mLastHandledTouchSequence + 1 == sequence) { + handleQueuedMotionEvent(ev); + + mLastHandledTouchSequence++; + + // Do we have any more? Run them if so. + QueuedTouch qd = mTouchEventQueue; + while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { + handleQueuedTouch(qd); + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + mLastHandledTouchSequence++; + } + mTouchEventQueue = qd; + } else { + QueuedTouch qd = obtainQueuedTouch().set(ev, sequence); + mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd); + } + } + + private void dropStaleGestures(MotionEvent ev, long sequence) { + if (mTouchEventQueue == null) return; + + MotionEvent nextQueueEvent = mTouchEventQueue.mTed != null ? + mTouchEventQueue.mTed.mMotionEvent : mTouchEventQueue.mEvent; + + if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && nextQueueEvent != null) { + long eventTime = ev.getEventTime(); + long nextQueueTime = nextQueueEvent.getEventTime(); + if (eventTime > nextQueueTime + QUEUED_GESTURE_TIMEOUT) { + Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " + + "Ignoring previous queued events."); + QueuedTouch qd = mTouchEventQueue; + while (qd != null && qd.mSequence < sequence) { + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + } + mTouchEventQueue = qd; + mLastHandledTouchSequence = sequence - 1; + } + } + + if (mIgnoreUntilSequence > mLastHandledTouchSequence) { + QueuedTouch qd = mTouchEventQueue; + while (qd != null && qd.mSequence < mIgnoreUntilSequence && + qd.mSequence < sequence) { + mLastHandledTouchSequence = qd.mSequence; + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + } + mTouchEventQueue = qd; + } + } + + private void handleQueuedTouch(QueuedTouch qt) { + if (qt.mTed != null) { + handleQueuedTouchEventData(qt.mTed); + } else { + handleQueuedMotionEvent(qt.mEvent); + qt.mEvent.recycle(); + } + } + + private void handleQueuedMotionEvent(MotionEvent ev) { + int action = ev.getActionMasked(); + if (ev.getPointerCount() > 1) { // Multi-touch + handleMultiTouchInWebView(ev); + } else { + final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector(); + if (detector != null && mPreventDefault != PREVENT_DEFAULT_YES) { + // ScaleGestureDetector needs a consistent event stream to operate properly. + // It won't take any action with fewer than two pointers, but it needs to + // update internal bookkeeping state. + detector.onTouchEvent(ev); + } + + handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY())); + } + } + + private void handleQueuedTouchEventData(TouchEventData ted) { + if (!ted.mReprocess) { + if (ted.mAction == MotionEvent.ACTION_DOWN + && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) { + // if prevent default is called from WebCore, UI + // will not handle the rest of the touch events any + // more. + mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES + : PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN; + } else if (ted.mAction == MotionEvent.ACTION_MOVE + && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) { + // the return for the first ACTION_MOVE will decide + // whether UI will handle touch or not. Currently no + // support for alternating prevent default + mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES + : PREVENT_DEFAULT_NO; + } + if (mPreventDefault == PREVENT_DEFAULT_YES) { + mTouchHighlightRegion.setEmpty(); + } + } else { + if (ted.mPoints.length > 1) { // multi-touch + if (!ted.mNativeResult && mPreventDefault != PREVENT_DEFAULT_YES) { + mPreventDefault = PREVENT_DEFAULT_NO; + handleMultiTouchInWebView(ted.mMotionEvent); + } else { + mPreventDefault = PREVENT_DEFAULT_YES; + } + return; + } + + // prevent default is not called in WebCore, so the + // message needs to be reprocessed in UI + if (!ted.mNativeResult) { + // Following is for single touch. + switch (ted.mAction) { + case MotionEvent.ACTION_DOWN: + mLastDeferTouchX = contentToViewX(ted.mPoints[0].x) + - mScrollX; + mLastDeferTouchY = contentToViewY(ted.mPoints[0].y) + - mScrollY; + mDeferTouchMode = TOUCH_INIT_MODE; + break; + case MotionEvent.ACTION_MOVE: { + // no snapping in defer process + int x = contentToViewX(ted.mPoints[0].x) - mScrollX; + int y = contentToViewY(ted.mPoints[0].y) - mScrollY; + if (mDeferTouchMode != TOUCH_DRAG_MODE) { + mDeferTouchMode = TOUCH_DRAG_MODE; + mLastDeferTouchX = x; + mLastDeferTouchY = y; + startScrollingLayer(x, y); + startDrag(); + } + int deltaX = pinLocX((int) (mScrollX + + mLastDeferTouchX - x)) + - mScrollX; + int deltaY = pinLocY((int) (mScrollY + + mLastDeferTouchY - y)) + - mScrollY; + doDrag(deltaX, deltaY); + if (deltaX != 0) mLastDeferTouchX = x; + if (deltaY != 0) mLastDeferTouchY = y; + break; + } + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mDeferTouchMode == TOUCH_DRAG_MODE) { + // no fling in defer process + mScroller.springBack(mScrollX, mScrollY, 0, + computeMaxScrollX(), 0, + computeMaxScrollY()); + invalidate(); + WebViewCore.resumePriority(); + WebViewCore.resumeUpdatePicture(mWebViewCore); + } + mDeferTouchMode = TOUCH_DONE_MODE; + break; + case WebViewCore.ACTION_DOUBLETAP: + // doDoubleTap() needs mLastTouchX/Y as anchor + mLastTouchX = contentToViewX(ted.mPoints[0].x) - mScrollX; + mLastTouchY = contentToViewY(ted.mPoints[0].y) - mScrollY; + mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); + mDeferTouchMode = TOUCH_DONE_MODE; + break; + case WebViewCore.ACTION_LONGPRESS: + HitTestResult hitTest = getHitTestResult(); + if (hitTest != null && hitTest.mType + != HitTestResult.UNKNOWN_TYPE) { + performLongClick(); + } + mDeferTouchMode = TOUCH_DONE_MODE; + break; + } + } + } + } + } + //------------------------------------------------------------------------- // Methods can be called from a separate thread, like WebViewCore // If it needs to call the View system, it has to send message. @@ -7220,6 +7584,7 @@ public class WebView extends AbsoluteLayout ted.mNativeLayer = nativeScrollableLayer( ted.mPoints[0].x, ted.mPoints[0].y, ted.mNativeLayerRect, null); + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES) { mTouchMode = TOUCH_DONE_MODE; @@ -7265,7 +7630,7 @@ public class WebView extends AbsoluteLayout case NEW_PICTURE_MSG_ID: { // called for new content final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj; - setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds(), + setBaseLayer(draw.mBaseLayer, draw.mInvalRegion, getSettings().getShowVisualIndicator()); final Point viewSize = draw.mViewSize; WebViewCore.ViewState viewState = draw.mViewState; @@ -7434,106 +7799,13 @@ public class WebView extends AbsoluteLayout if (inFullScreenMode()) { break; } - if (msg.obj == null) { - if (msg.arg1 == MotionEvent.ACTION_DOWN - && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) { - // if prevent default is called from WebCore, UI - // will not handle the rest of the touch events any - // more. - mPreventDefault = msg.arg2 == 1 ? PREVENT_DEFAULT_YES - : PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN; - } else if (msg.arg1 == MotionEvent.ACTION_MOVE - && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) { - // the return for the first ACTION_MOVE will decide - // whether UI will handle touch or not. Currently no - // support for alternating prevent default - mPreventDefault = msg.arg2 == 1 ? PREVENT_DEFAULT_YES - : PREVENT_DEFAULT_NO; - } - if (mPreventDefault == PREVENT_DEFAULT_YES) { - mTouchHighlightRegion.setEmpty(); - } - } else { - TouchEventData ted = (TouchEventData) msg.obj; + TouchEventData ted = (TouchEventData) msg.obj; - if (ted.mPoints.length > 1) { // multi-touch - if (ted.mAction == MotionEvent.ACTION_POINTER_UP) { - mIsHandlingMultiTouch = false; - } - if (msg.arg2 == 0) { - mPreventDefault = PREVENT_DEFAULT_NO; - handleMultiTouchInWebView(ted.mMotionEvent); - } else { - mPreventDefault = PREVENT_DEFAULT_YES; - } - break; - } + // WebCore is responding to us; remove pending timeout. + // It will be re-posted when needed. + removeMessages(PREVENT_DEFAULT_TIMEOUT); - // prevent default is not called in WebCore, so the - // message needs to be reprocessed in UI - if (msg.arg2 == 0) { - // Following is for single touch. - switch (ted.mAction) { - case MotionEvent.ACTION_DOWN: - mLastDeferTouchX = contentToViewX(ted.mPoints[0].x) - - mScrollX; - mLastDeferTouchY = contentToViewY(ted.mPoints[0].y) - - mScrollY; - mDeferTouchMode = TOUCH_INIT_MODE; - break; - case MotionEvent.ACTION_MOVE: { - // no snapping in defer process - int x = contentToViewX(ted.mPoints[0].x) - mScrollX; - int y = contentToViewY(ted.mPoints[0].y) - mScrollY; - if (mDeferTouchMode != TOUCH_DRAG_MODE) { - mDeferTouchMode = TOUCH_DRAG_MODE; - mLastDeferTouchX = x; - mLastDeferTouchY = y; - startScrollingLayer(x, y); - startDrag(); - } - int deltaX = pinLocX((int) (mScrollX - + mLastDeferTouchX - x)) - - mScrollX; - int deltaY = pinLocY((int) (mScrollY - + mLastDeferTouchY - y)) - - mScrollY; - doDrag(deltaX, deltaY); - if (deltaX != 0) mLastDeferTouchX = x; - if (deltaY != 0) mLastDeferTouchY = y; - break; - } - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (mDeferTouchMode == TOUCH_DRAG_MODE) { - // no fling in defer process - mScroller.springBack(mScrollX, mScrollY, 0, - computeMaxScrollX(), 0, - computeMaxScrollY()); - invalidate(); - WebViewCore.resumePriority(); - WebViewCore.resumeUpdatePicture(mWebViewCore); - } - mDeferTouchMode = TOUCH_DONE_MODE; - break; - case WebViewCore.ACTION_DOUBLETAP: - // doDoubleTap() needs mLastTouchX/Y as anchor - mLastTouchX = contentToViewX(ted.mPoints[0].x) - mScrollX; - mLastTouchY = contentToViewY(ted.mPoints[0].y) - mScrollY; - mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); - mDeferTouchMode = TOUCH_DONE_MODE; - break; - case WebViewCore.ACTION_LONGPRESS: - HitTestResult hitTest = getHitTestResult(); - if (hitTest != null && hitTest.mType - != HitTestResult.UNKNOWN_TYPE) { - performLongClick(); - } - mDeferTouchMode = TOUCH_DONE_MODE; - break; - } - } - } + mTouchEventQueue.enqueueTouchEvent(ted); break; case REQUEST_KEYBOARD: @@ -7575,6 +7847,11 @@ public class WebView extends AbsoluteLayout setKeepScreenOn(msg.arg1 == 1); break; + case ENTER_FULLSCREEN_VIDEO: + int layerId = msg.arg1; + Log.v(LOGTAG, "Display the video layer " + layerId + " fullscreen"); + break; + case SHOW_FULLSCREEN: { View view = (View) msg.obj; int npp = msg.arg1; @@ -8236,6 +8513,10 @@ public class WebView extends AbsoluteLayout mWebViewCore.sendMessage(EventHub.SET_BACKGROUND_COLOR, color); } + /** + * @deprecated This method is now obsolete. + */ + @Deprecated public void debugDump() { nativeDebugDump(); mWebViewCore.sendMessage(EventHub.DUMP_NAVTREE); @@ -8253,6 +8534,15 @@ public class WebView extends AbsoluteLayout } /** + * Enable the communication b/t the webView and VideoViewProxy + * + * @hide only used by the Browser + */ + public void setHTML5VideoViewProxy(HTML5VideoViewProxy proxy) { + mHTML5VideoViewProxy = proxy; + } + + /** * Enable expanded tiles bound for smoother scrolling. * * @hide only used by the Browser @@ -8321,8 +8611,9 @@ public class WebView extends AbsoluteLayout boolean splitIfNeeded); private native void nativeDumpDisplayTree(String urlOrNull); private native boolean nativeEvaluateLayersAnimations(); - private native int nativeGetDrawGLFunction(Rect rect, float scale, int extras); - private native void nativeUpdateDrawGLFunction(Rect rect); + private native int nativeGetDrawGLFunction(Rect rect, Rect viewRect, + float scale, int extras); + private native void nativeUpdateDrawGLFunction(Rect rect, Rect viewRect); private native boolean nativeDrawGL(Rect rect, float scale, int extras); private native void nativeExtendSelection(int x, int y); private native int nativeFindAll(String findLower, String findUpper, @@ -8398,7 +8689,7 @@ public class WebView extends AbsoluteLayout private native void nativeSetFindIsEmpty(); private native void nativeSetFindIsUp(boolean isUp); private native void nativeSetHeightCanMeasure(boolean measure); - private native void nativeSetBaseLayer(int layer, Rect invalRect, + private native void nativeSetBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator); private native void nativeShowCursorTimed(); private native void nativeReplaceBaseContent(int content); diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index db605de..65026a5 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -256,4 +256,18 @@ public class WebViewClient { */ public void onScaleChanged(WebView view, float oldScale, float newScale) { } + + /** + * Notify the host application that a request to automatically log in the + * user has been processed. + * @param view The WebView requesting the login. + * @param realm The account realm used to look up accounts. + * @param account An optional account. If not null, the account should be + * checked against accounts on the device. If it is a valid + * account, it should be used to log in the user. + * @param args Authenticator specific arguments used to log in the user. + */ + public void onReceivedLoginRequest(WebView view, String realm, + String account, String args) { + } } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index c18c9e4..979eb2b 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -480,6 +480,15 @@ final class WebViewCore { mCallbackProxy.setInstallableWebApp(); } + /** + * Notify the webview that we want to display the video layer fullscreen. + */ + protected void enterFullscreenForVideoLayer(int layerId) { + if (mWebView == null) return; + Message.obtain(mWebView.mPrivateHandler, + WebView.ENTER_FULLSCREEN_VIDEO, layerId, 0).sendToTarget(); + } + //------------------------------------------------------------------------- // JNI methods //------------------------------------------------------------------------- @@ -825,6 +834,8 @@ final class WebViewCore { MotionEvent mMotionEvent; int mNativeLayer; Rect mNativeLayerRect = new Rect(); + long mSequence; + boolean mNativeResult; } static class GeolocationPermissionsData { @@ -1332,13 +1343,14 @@ final class WebViewCore { nativeScrollLayer(ted.mNativeLayer, ted.mNativeLayerRect); } + ted.mNativeResult = nativeHandleTouchEvent(ted.mAction, ted.mIds, + xArray, yArray, count, ted.mMetaState); Message.obtain( mWebView.mPrivateHandler, WebView.PREVENT_TOUCH_ID, ted.mAction, - nativeHandleTouchEvent(ted.mAction, ted.mIds, - xArray, yArray, count, ted.mMetaState) ? 1 : 0, - ted.mReprocess ? ted : null).sendToTarget(); + ted.mNativeResult ? 1 : 0, + ted).sendToTarget(); break; } diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index f27ced8..1d77388 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -23,6 +23,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; import android.os.SystemClock; +import android.util.FloatMath; import android.util.Log; import android.view.ScaleGestureDetector; import android.view.View; @@ -112,6 +113,22 @@ class ZoomManager { private float mZoomCenterY; /* + * Similar to mZoomCenterX(Y), these track the focus point of the scale + * gesture. The difference is these get updated every time when onScale is + * invoked no matter if a zooming really happens. + */ + private float mFocusX; + private float mFocusY; + + /* + * mFocusMovementQueue keeps track of the previous focus point movement + * has been through. Comparing to the difference of the gesture's previous + * span and current span, it determines if the gesture is for panning or + * zooming or both. + */ + private FocusMovementQueue mFocusMovementQueue; + + /* * These values represent the point around which the screen should be * centered after zooming. In other words it is used to determine the center * point of the visible document after the page has finished zooming. This @@ -196,6 +213,8 @@ class ZoomManager { * viewport size is. */ setZoomOverviewWidth(WebView.DEFAULT_VIEWPORT_WIDTH); + + mFocusMovementQueue = new FocusMovementQueue(); } /** @@ -336,6 +355,10 @@ class ZoomManager { return scale; } + public final boolean isScaleOverLimits(float scale) { + return scale <= mMinZoomScale || scale >= mMaxZoomScale; + } + public final boolean isZoomScaleFixed() { return mMinZoomScale >= mMaxZoomScale; } @@ -507,7 +530,7 @@ class ZoomManager { mTextWrapScale = scale; } - if (exceedsMinScaleIncrement(scale, mActualScale) || force) { + if (scale != mActualScale || force) { float oldScale = mActualScale; float oldInvScale = mInvActualScale; @@ -714,21 +737,81 @@ class ZoomManager { return mScaleDetector; } - private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener { + private class FocusMovementQueue { + private static final int QUEUE_CAPACITY = 5; + private float[] mQueue; + private float mSum; + private int mSize; + private int mIndex; + + FocusMovementQueue() { + mQueue = new float[QUEUE_CAPACITY]; + mSize = 0; + mSum = 0; + mIndex = 0; + } + + private void clear() { + mSize = 0; + mSum = 0; + mIndex = 0; + for (int i = 0; i < QUEUE_CAPACITY; ++i) { + mQueue[i] = 0; + } + } + private void add(float focusDelta) { + mSum += focusDelta; + if (mSize < QUEUE_CAPACITY) { // fill up the queue. + mSize++; + } else { // circulate the queue. + mSum -= mQueue[mIndex]; + } + mQueue[mIndex] = focusDelta; + mIndex = (mIndex + 1) % QUEUE_CAPACITY; + } + + private float getSum() { + return mSum; + } + } + + private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener { public boolean onScaleBegin(ScaleGestureDetector detector) { mInitialZoomOverview = false; dismissZoomPicker(); + mFocusMovementQueue.clear(); mWebView.mViewManager.startZoom(); mWebView.onPinchToZoomAnimationStart(); return true; } - public boolean onScale(ScaleGestureDetector detector) { + // If the user moves the fingers but keeps the same distance between them, + // we should do panning only. + public boolean isPanningOnly(ScaleGestureDetector detector) { + float prevFocusX = mFocusX; + float prevFocusY = mFocusY; + mFocusX = detector.getFocusX(); + mFocusY = detector.getFocusY(); + float focusDelta = (prevFocusX == 0 && prevFocusY == 0) ? 0 : + FloatMath.sqrt((mFocusX - prevFocusX) * (mFocusX - prevFocusX) + + (mFocusY - prevFocusY) * (mFocusY - prevFocusY)); + mFocusMovementQueue.add(focusDelta); + float deltaSpan = Math.abs(detector.getCurrentSpan() - detector.getPreviousSpan()); + return mFocusMovementQueue.getSum() > deltaSpan; + } + + public boolean handleScale(ScaleGestureDetector detector) { + float scale = detector.getScaleFactor() * mActualScale; + + // if scale is limited by any reason, don't zoom but do ask + // the detector to update the event. + boolean isScaleLimited = + isScaleOverLimits(scale) || scale < getZoomOverviewScale(); + // Prevent scaling beyond overview scale. - float scale = Math.max( - computeScaleWithLimits(detector.getScaleFactor() * mActualScale), - getZoomOverviewScale()); + scale = Math.max(computeScaleWithLimits(scale), getZoomOverviewScale()); + if (mPinchToZoomAnimating || willScaleTriggerZoom(scale)) { mPinchToZoomAnimating = true; // limit the scale change per step @@ -740,13 +823,21 @@ class ZoomManager { scale = computeScaleWithLimits(scale); // if the scale change is too small, regard it as jitter and skip it. if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_WITHOUT_JITTER) { - return false; + return isScaleLimited; } setZoomCenter(detector.getFocusX(), detector.getFocusY()); setZoomScale(scale, false); mWebView.invalidate(); return true; } + return isScaleLimited; + } + + public boolean onScale(ScaleGestureDetector detector) { + if (isPanningOnly(detector) || handleScale(detector)) { + mFocusMovementQueue.clear(); + return true; + } return false; } @@ -960,14 +1051,15 @@ class ZoomManager { final Point viewSize = drawData.mViewSize; updateZoomRange(viewState, viewSize.x, drawData.mMinPrefWidth); setupZoomOverviewWidth(drawData, mWebView.getViewWidth()); + final float overviewScale = getZoomOverviewScale(); if (!mMinZoomScaleFixed) { - mMinZoomScale = getZoomOverviewScale(); + mMinZoomScale = (mInitialScale > 0) ? + Math.min(mInitialScale, overviewScale) : overviewScale; mMaxZoomScale = Math.max(mMaxZoomScale, mMinZoomScale); } if (!mWebView.drawHistory()) { float scale; - final float overviewScale = getZoomOverviewScale(); WebSettings settings = mWebView.getSettings(); if (mInitialScale > 0) { diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index 200c870..fb57ce0 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -564,6 +564,9 @@ class FastScroller { } } else { int index = (int) (position * count); + // Don't overflow + if (index > count - 1) index = count - 1; + if (mList instanceof ExpandableListView) { ExpandableListView expList = (ExpandableListView) mList; expList.setSelectionFromTop(expList.getFlatListPosition( diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index d92588c..17b3bda 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -477,8 +477,7 @@ public class HorizontalScrollView extends FrameLayout { break; case MotionEvent.ACTION_POINTER_DOWN: { final int index = ev.getActionIndex(); - final float x = ev.getX(index); - mLastMotionX = x; + mLastMotionX = ev.getX(index); mActivePointerId = ev.getPointerId(index); break; } @@ -1446,6 +1445,7 @@ public class HorizontalScrollView extends FrameLayout { super.setOverScrollMode(mode); } + @SuppressWarnings({"SuspiciousNameCombination"}) @Override public void draw(Canvas canvas) { super.draw(canvas); diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 2802144..af954c9 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -3015,8 +3015,23 @@ public class ListView extends AbsListView { @Override public boolean isOpaque() { - return (mCachingActive && mIsCacheColorOpaque && mDividerIsOpaque && + boolean retValue = (mCachingActive && mIsCacheColorOpaque && mDividerIsOpaque && hasOpaqueScrollbars()) || super.isOpaque(); + if (retValue) { + // only return true if the list items cover the entire area of the view + final int listTop = mListPadding != null ? mListPadding.top : mPaddingTop; + View first = getChildAt(0); + if (first == null || first.getTop() > listTop) { + return false; + } + final int listBottom = getHeight() - + (mListPadding != null ? mListPadding.bottom : mPaddingBottom); + View last = getChildAt(getChildCount() - 1); + if (last == null || last.getBottom() < listBottom) { + return false; + } + } + return retValue; } @Override diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 9002b1d..72b70bc 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -1039,7 +1039,7 @@ public class PopupWindow { * * @return true if the popup is translated upwards to fit on screen */ - boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, + private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff, int yoff) { anchor.getLocationInWindow(mDrawingLocation); diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index 2d2165b..1c0a2bb 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -889,7 +889,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback boolean isConnected = mServiceConnection.isConnected(); boolean hasNewItems = false; - if (!isConnected) { + if (!isInCache && !isConnected) { // Requesting bind service will trigger a super.notifyDataSetChanged(), which will // in turn trigger another request to getView() requestBindService(); diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index 2d164fd..6088654 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -83,6 +83,7 @@ public class SearchView extends LinearLayout { private CursorAdapter mSuggestionsAdapter; private View mSearchButton; private View mSubmitButton; + private View mSearchPlate; private View mSubmitArea; private ImageView mCloseButton; private View mSearchEditFrame; @@ -190,6 +191,7 @@ public class SearchView extends LinearLayout { mQueryTextView.setSearchView(this); mSearchEditFrame = findViewById(R.id.search_edit_frame); + mSearchPlate = findViewById(R.id.search_plate); mSubmitArea = findViewById(R.id.submit_area); mSubmitButton = findViewById(R.id.search_go_btn); mCloseButton = (ImageView) findViewById(R.id.search_close_btn); @@ -258,6 +260,7 @@ public class SearchView extends LinearLayout { mSearchable = searchable; if (mSearchable != null) { updateSearchAutoComplete(); + updateQueryHint(); } // Cache the voice search capability mVoiceButtonEnabled = hasVoiceSearch(); @@ -575,19 +578,19 @@ public class SearchView extends LinearLayout { } private void updateSubmitButton(boolean hasText) { - mSubmitButton.setVisibility( - isSubmitAreaEnabled() ? (hasText ? VISIBLE : INVISIBLE) : GONE); + int visibility = GONE; + if (isSubmitAreaEnabled() && hasFocus() && (hasText || !mVoiceButtonEnabled)) { + visibility = VISIBLE; + } + mSubmitButton.setVisibility(visibility); } private void updateSubmitArea() { int visibility = GONE; - if (isSubmitAreaEnabled()) { - if (mSubmitButton.getVisibility() == VISIBLE - || mVoiceButton.getVisibility() == VISIBLE) { - visibility = VISIBLE; - } else { - visibility = INVISIBLE; - } + if (isSubmitAreaEnabled() + && (mSubmitButton.getVisibility() == VISIBLE + || mVoiceButton.getVisibility() == VISIBLE)) { + visibility = VISIBLE; } mSubmitArea.setVisibility(visibility); } @@ -601,6 +604,11 @@ public class SearchView extends LinearLayout { mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET); } + private void updateFocusedState(boolean focused) { + mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + } + private void setImeVisibility(boolean visible) { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); @@ -851,16 +859,11 @@ public class SearchView extends LinearLayout { * Update the visibility of the voice button. There are actually two voice search modes, * either of which will activate the button. * @param empty whether the search query text field is empty. If it is, then the other - * criteria apply to make the voice button visible. Otherwise the voice button will not - * be visible - i.e., if the user has typed a query, remove the voice button. + * criteria apply to make the voice button visible. */ private void updateVoiceButton(boolean empty) { - // If the voice button is to be visible, show it - // Else, make it gone if the submit button is enabled, otherwise invisible to - // avoid losing the real-estate - int visibility = mSubmitButtonEnabled ? GONE : INVISIBLE; - - if (mVoiceButtonEnabled && !isIconified() && empty) { + int visibility = GONE; + if (mVoiceButtonEnabled && !isIconified() && (empty || !mSubmitButtonEnabled)) { visibility = VISIBLE; mSubmitButton.setVisibility(GONE); } @@ -958,7 +961,8 @@ public class SearchView extends LinearLayout { } void onTextFocusChanged() { - updateCloseButton(); + updateViewsVisibility(isIconified()); + updateFocusedState(mQueryTextView.hasFocus()); } private boolean onItemClicked(int position, int actionKey, String actionMsg) { diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index bab469b..21c61bd 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -531,6 +531,8 @@ public class StackView extends AdapterViewAnimator { @Override protected void dispatchDraw(Canvas canvas) { + boolean expandClipRegion = false; + canvas.getClipBounds(stackInvalidateRect); final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -540,12 +542,22 @@ public class StackView extends AdapterViewAnimator { child.getAlpha() == 0f || child.getVisibility() != VISIBLE) { lp.resetInvalidateRect(); } - stackInvalidateRect.union(lp.getInvalidateRect()); + Rect childInvalidateRect = lp.getInvalidateRect(); + if (!childInvalidateRect.isEmpty()) { + expandClipRegion = true; + stackInvalidateRect.union(childInvalidateRect); + } + } + + // We only expand the clip bounds if necessary. + if (expandClipRegion) { + canvas.save(Canvas.CLIP_SAVE_FLAG); + canvas.clipRect(stackInvalidateRect, Region.Op.UNION); + super.dispatchDraw(canvas); + canvas.restore(); + } else { + super.dispatchDraw(canvas); } - canvas.save(Canvas.CLIP_SAVE_FLAG); - canvas.clipRect(stackInvalidateRect, Region.Op.UNION); - super.dispatchDraw(canvas); - canvas.restore(); } private void onLayout() { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 09c1ac5..13b9285f 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4498,8 +4498,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ canvas.restore(); - - updateCursorControllerPositions(); } private void updateCursorsPositions() { @@ -4557,15 +4555,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ protected void updateCursorControllerPositions() { - // No need to create the controllers if they were not already - if (mInsertionPointCursorController != null && - mInsertionPointCursorController.isShowing()) { - mInsertionPointCursorController.updatePosition(); - } - if (mSelectionModifierCursorController != null && - mSelectionModifierCursorController.isShowing()) { - mSelectionModifierCursorController.updatePosition(); - } + // TODO remove } @Override @@ -7356,14 +7346,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (isTextEditable() || mTextIsSelectable) { - if (mScrollX != oldScrollX || mScrollY != oldScrollY) { + if (mScrollX != oldScrollX || mScrollY != oldScrollY) { // TODO remove // Hide insertion anchor while scrolling. Leave selection. - hideInsertionPointCursorController(); - // No need to create the controller, since there is nothing to update. - if (mSelectionModifierCursorController != null && - mSelectionModifierCursorController.isShowing()) { - mSelectionModifierCursorController.updatePosition(); - } + hideInsertionPointCursorController(); // TODO any motion should hide it } if (touchIsFinished) { @@ -7373,7 +7358,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener handled |= imm != null && imm.showSoftInput(this, 0); } - boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect(); if (!selectAllGotFocus && hasSelection()) { startSelectionActionMode(); @@ -8653,26 +8637,31 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - private class HandleView extends View implements ViewTreeObserver.OnScrollChangedListener { + private class HandleView extends View implements ViewTreeObserver.OnPreDrawListener { private Drawable mDrawable; - private final ScrollingPopupWindow mContainer; - private int mPositionX; - private int mPositionY; + private final PopupWindow mContainer; + // Position with respect to the parent TextView + private int mPositionX, mPositionY; private final CursorController mController; private boolean mIsDragging; - private float mTouchToWindowOffsetX; - private float mTouchToWindowOffsetY; + // Offset from touch position to mPosition + private float mTouchToWindowOffsetX, mTouchToWindowOffsetY; private float mHotspotX; // Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up private float mTouchOffsetY; // Where the touch position should be on the handle to ensure a maximum cursor visibility private float mIdealVerticalOffset; - private int mLastParentX; - private int mLastParentY; + // Parent's (TextView) position in window + private int mLastParentX, mLastParentY; private float mDownPositionX, mDownPositionY; + // PopupWindow container absolute position with respect to the enclosing window private int mContainerPositionX, mContainerPositionY; - private long mTouchTimer; + // Visible or not (scrolled off screen), whether or not this handle should be visible + private boolean mIsActive = false; + // The insertion handle can have an associated PastePopupMenu private boolean mIsInsertionHandle = false; + // Used to detect taps on the insertion handle, which will affect the PastePopupMenu + private long mTouchTimer; private PastePopupMenu mPastePopupWindow; // Touch-up filter: number of previous positions remembered @@ -8684,12 +8673,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mPreviousOffsetIndex = 0; private int mNumberPreviousOffsets = 0; - public void startTouchUpFilter(int offset) { + private void startTouchUpFilter(int offset) { mNumberPreviousOffsets = 0; addPositionToTouchUpFilter(offset); } - public void addPositionToTouchUpFilter(int offset) { + private void addPositionToTouchUpFilter(int offset) { if (mNumberPreviousOffsets > 0 && mPreviousOffsets[mPreviousOffsetIndex] == offset) { // Make sure only actual changes of position are recorded. @@ -8702,7 +8691,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mNumberPreviousOffsets++; } - public void filterOnTouchUp() { + private void filterOnTouchUp() { final long now = SystemClock.uptimeMillis(); int i = 0; int index = mPreviousOffsetIndex; @@ -8725,16 +8714,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public HandleView(CursorController controller, int pos) { super(TextView.this.mContext); mController = controller; - mContainer = new ScrollingPopupWindow(TextView.this.mContext, null, + mContainer = new PopupWindow(TextView.this.mContext, null, com.android.internal.R.attr.textSelectHandleWindowStyle); mContainer.setSplitTouchEnabled(true); mContainer.setClippingEnabled(false); mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); + mContainer.setContentView(this); - setOrientation(pos); + setPosition(pos); } - public void setOrientation(int pos) { + private void setPosition(int pos) { int handleWidth; switch (pos) { case LEFT: { @@ -8774,38 +8764,48 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } final int handleHeight = mDrawable.getIntrinsicHeight(); - mTouchOffsetY = -0.3f * handleHeight; mIdealVerticalOffset = 0.7f * handleHeight; + invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(mDrawable.getIntrinsicWidth(), - mDrawable.getIntrinsicHeight()); + setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); } public void show() { - if (!isPositionVisible()) { - hide(); - return; - } - mContainer.setContentView(this); - mContainerPositionX = mPositionX; - mContainerPositionY = mPositionY - TextView.this.getHeight(); - mContainer.showAsDropDown(TextView.this, mContainerPositionX, mContainerPositionY); + updateContainerPosition(); + if (isShowing()) { + mContainer.update(mContainerPositionX, mContainerPositionY, + mRight - mLeft, mBottom - mTop); - // Hide paste view when handle is moved on screen. - hidePastePopupWindow(); + hidePastePopupWindow(); + } else { + mContainer.showAtLocation(TextView.this, 0, + mContainerPositionX, mContainerPositionY); + + mIsActive = true; + + ViewTreeObserver vto = TextView.this.getViewTreeObserver(); + vto.addOnPreDrawListener(this); + } } - public void hide() { + private void dismiss() { mIsDragging = false; mContainer.dismiss(); hidePastePopupWindow(); + } + + public void hide() { + dismiss(); + + mIsActive = false; + ViewTreeObserver vto = TextView.this.getViewTreeObserver(); - vto.removeOnScrollChangedListener(this); + vto.removeOnPreDrawListener(this); } public boolean isShowing() { @@ -8856,44 +8856,59 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private void moveTo(int x, int y) { mPositionX = x - TextView.this.mScrollX; mPositionY = y - TextView.this.mScrollY; - if (isPositionVisible()) { - int[] coords = null; - if (mContainer.isShowing()) { - final int containerPositionX = mPositionX; - final int containerPositionY = mPositionY - TextView.this.getHeight(); - - if (containerPositionX != mContainerPositionX || - containerPositionY != mContainerPositionY) { - mContainerPositionX = containerPositionX; - mContainerPositionY = containerPositionY; - - mContainer.update(TextView.this, mContainerPositionX, mContainerPositionY, - mRight - mLeft, mBottom - mTop); - - // Hide paste popup window as soon as a scroll occurs. - hidePastePopupWindow(); - } - } else { - show(); + + if (mIsDragging) { + TextView.this.getLocationInWindow(mTempCoords); + if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) { + mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX; + mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY; + mLastParentX = mTempCoords[0]; + mLastParentY = mTempCoords[1]; } + // Hide paste popup window as soon as the handle is dragged. + hidePastePopupWindow(); + } + } - if (mIsDragging) { - if (coords == null) { - coords = mTempCoords; - TextView.this.getLocationInWindow(coords); + /** + * Updates the global container's position. + * @return whether or not the position has actually changed + */ + private boolean updateContainerPosition() { + // TODO Prevent this using different HandleView subclasses + mController.updateOffset(this, mController.getCurrentOffset(this)); + TextView.this.getLocationInWindow(mTempCoords); + final int containerPositionX = mTempCoords[0] + mPositionX; + final int containerPositionY = mTempCoords[1] + mPositionY; + + if (containerPositionX != mContainerPositionX || + containerPositionY != mContainerPositionY) { + mContainerPositionX = containerPositionX; + mContainerPositionY = containerPositionY; + return true; + } + return false; + } + + public boolean onPreDraw() { + if (updateContainerPosition()) { + if (isPositionVisible()) { + mContainer.update(mContainerPositionX, mContainerPositionY, + mRight - mLeft, mBottom - mTop); + + if (mIsActive && !isShowing()) { + show(); } - if (coords[0] != mLastParentX || coords[1] != mLastParentY) { - mTouchToWindowOffsetX += coords[0] - mLastParentX; - mTouchToWindowOffsetY += coords[1] - mLastParentY; - mLastParentX = coords[0]; - mLastParentY = coords[1]; + } else { + if (isShowing()) { + dismiss(); } - // Hide paste popup window as soon as the handle is dragged. - hidePastePopupWindow(); } - } else { - hide(); + + // Hide paste popup as soon as the view is scrolled or moved + hidePastePopupWindow(); } + return true; } @Override @@ -8979,7 +8994,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mIsDragging; } - void positionAtCursor(final int offset) { + void positionAtCursor(int offset) { addPositionToTouchUpFilter(offset); final int width = mDrawable.getIntrinsicWidth(); final int height = mDrawable.getIntrinsicHeight(); @@ -9013,50 +9028,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mPastePopupWindow.hide(); } } - - /** - * A popup window, attached to a view, and that listens to scroll events in its anchors' - * view hierarchy, so that it is automatically moved on such events. - */ - private class ScrollingPopupWindow extends PopupWindow { - - private int[] mDrawingLocations = new int[2]; - - public ScrollingPopupWindow(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, - int xoff, int yoff) { - anchor.getLocationInWindow(mDrawingLocations); - p.x = mDrawingLocations[0] + xoff; - p.y = mDrawingLocations[1] + anchor.getHeight() + yoff; - - // Hide paste popup as soon as the view is scrolled. - hidePastePopupWindow(); - - if (!isPositionVisible()) { - dismiss(); - onHandleBecomeInvisible(); - } - - return false; - } - } - - public void onScrollChanged() { - if (isPositionVisible()) { - show(); - ViewTreeObserver vto = TextView.this.getViewTreeObserver(); - vto.removeOnScrollChangedListener(this); - } - } - - public void onHandleBecomeInvisible() { - ViewTreeObserver vto = TextView.this.getViewTreeObserver(); - vto.addOnScrollChangedListener(this); - } } private class InsertionPointCursorController implements CursorController { @@ -9074,7 +9045,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } public void show(int delayBeforePaste) { - updatePosition(); + getHandle().show(); hideDelayed(); removePastePopupCallback(); final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime; @@ -9213,7 +9184,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEndHandle == null) mEndHandle = new HandleView(this, HandleView.RIGHT); mIsShowing = true; - updatePosition(); mStartHandle.show(); mEndHandle.show(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 1cca21d..d86504d 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1581,7 +1581,7 @@ public final class BatteryStatsImpl extends BatteryStats { // Update discharge amounts. if (mOnBatteryInternal) { - updateDischargeScreenLevels(false, true); + updateDischargeScreenLevelsLocked(false, true); } } } @@ -1602,7 +1602,7 @@ public final class BatteryStatsImpl extends BatteryStats { // Update discharge amounts. if (mOnBatteryInternal) { - updateDischargeScreenLevels(true, false); + updateDischargeScreenLevelsLocked(true, false); } } } @@ -4030,7 +4030,7 @@ public final class BatteryStatsImpl extends BatteryStats { clearHistoryLocked(); } - void updateDischargeScreenLevels(boolean oldScreenOn, boolean newScreenOn) { + void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) { if (oldScreenOn) { int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel; if (diff > 0) { @@ -4055,69 +4055,73 @@ public final class BatteryStatsImpl extends BatteryStats { void setOnBattery(boolean onBattery, int oldStatus, int level) { synchronized(this) { - boolean doWrite = false; - Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE); - m.arg1 = onBattery ? 1 : 0; - mHandler.sendMessage(m); - mOnBattery = mOnBatteryInternal = onBattery; - - long uptime = SystemClock.uptimeMillis() * 1000; - long mSecRealtime = SystemClock.elapsedRealtime(); - long realtime = mSecRealtime * 1000; - if (onBattery) { - // We will reset our status if we are unplugging after the - // battery was last full, or the level is at 100, or - // we have gone through a significant charge (from a very low - // level to a now very high level). - if (oldStatus == BatteryManager.BATTERY_STATUS_FULL - || level >= 90 - || (mDischargeCurrentLevel < 20 && level >= 80)) { - doWrite = true; - resetAllStatsLocked(); - mDischargeStartLevel = level; - } - updateKernelWakelocksLocked(); - mHistoryCur.batteryLevel = (byte)level; - mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; - if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: " - + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(mSecRealtime); - mTrackBatteryUptimeStart = uptime; - mTrackBatteryRealtimeStart = realtime; - mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); - mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); - mDischargeCurrentLevel = mDischargeUnplugLevel = level; - if (mScreenOn) { - mDischargeScreenOnUnplugLevel = level; - mDischargeScreenOffUnplugLevel = 0; - } else { - mDischargeScreenOnUnplugLevel = 0; - mDischargeScreenOffUnplugLevel = level; - } - mDischargeAmountScreenOn = 0; - mDischargeAmountScreenOff = 0; - doUnplugLocked(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); + setOnBatteryLocked(onBattery, oldStatus, level); + } + } + + void setOnBatteryLocked(boolean onBattery, int oldStatus, int level) { + boolean doWrite = false; + Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE); + m.arg1 = onBattery ? 1 : 0; + mHandler.sendMessage(m); + mOnBattery = mOnBatteryInternal = onBattery; + + long uptime = SystemClock.uptimeMillis() * 1000; + long mSecRealtime = SystemClock.elapsedRealtime(); + long realtime = mSecRealtime * 1000; + if (onBattery) { + // We will reset our status if we are unplugging after the + // battery was last full, or the level is at 100, or + // we have gone through a significant charge (from a very low + // level to a now very high level). + if (oldStatus == BatteryManager.BATTERY_STATUS_FULL + || level >= 90 + || (mDischargeCurrentLevel < 20 && level >= 80)) { + doWrite = true; + resetAllStatsLocked(); + mDischargeStartLevel = level; + } + updateKernelWakelocksLocked(); + mHistoryCur.batteryLevel = (byte)level; + mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(mSecRealtime); + mTrackBatteryUptimeStart = uptime; + mTrackBatteryRealtimeStart = realtime; + mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); + mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); + mDischargeCurrentLevel = mDischargeUnplugLevel = level; + if (mScreenOn) { + mDischargeScreenOnUnplugLevel = level; + mDischargeScreenOffUnplugLevel = 0; } else { - updateKernelWakelocksLocked(); - mHistoryCur.batteryLevel = (byte)level; - mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; - if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: " - + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(mSecRealtime); - mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; - mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; - mDischargeCurrentLevel = level; - if (level < mDischargeUnplugLevel) { - mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1; - mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level; - } - updateDischargeScreenLevels(mScreenOn, mScreenOn); - doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); + mDischargeScreenOnUnplugLevel = 0; + mDischargeScreenOffUnplugLevel = level; } - if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) { - if (mFile != null) { - writeAsyncLocked(); - } + mDischargeAmountScreenOn = 0; + mDischargeAmountScreenOff = 0; + doUnplugLocked(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); + } else { + updateKernelWakelocksLocked(); + mHistoryCur.batteryLevel = (byte)level; + mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(mSecRealtime); + mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; + mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; + mDischargeCurrentLevel = level; + if (level < mDischargeUnplugLevel) { + mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1; + mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level; + } + updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn); + doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); + } + if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) { + if (mFile != null) { + writeAsyncLocked(); } } } @@ -4127,72 +4131,74 @@ public final class BatteryStatsImpl extends BatteryStats { public void setBatteryState(int status, int health, int plugType, int level, int temp, int volt) { - boolean onBattery = plugType == BATTERY_PLUGGED_NONE; - int oldStatus = mHistoryCur.batteryStatus; - if (!mHaveBatteryLevel) { - mHaveBatteryLevel = true; - // We start out assuming that the device is plugged in (not - // on battery). If our first report is now that we are indeed - // plugged in, then twiddle our state to correctly reflect that - // since we won't be going through the full setOnBattery(). - if (onBattery == mOnBattery) { - if (onBattery) { - mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; - } else { - mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; + synchronized(this) { + boolean onBattery = plugType == BATTERY_PLUGGED_NONE; + int oldStatus = mHistoryCur.batteryStatus; + if (!mHaveBatteryLevel) { + mHaveBatteryLevel = true; + // We start out assuming that the device is plugged in (not + // on battery). If our first report is now that we are indeed + // plugged in, then twiddle our state to correctly reflect that + // since we won't be going through the full setOnBattery(). + if (onBattery == mOnBattery) { + if (onBattery) { + mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; + } else { + mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; + } } + oldStatus = status; } - oldStatus = status; - } - if (onBattery) { - mDischargeCurrentLevel = level; - mRecordingHistory = true; - } - if (onBattery != mOnBattery) { - mHistoryCur.batteryLevel = (byte)level; - mHistoryCur.batteryStatus = (byte)status; - mHistoryCur.batteryHealth = (byte)health; - mHistoryCur.batteryPlugType = (byte)plugType; - mHistoryCur.batteryTemperature = (char)temp; - mHistoryCur.batteryVoltage = (char)volt; - setOnBattery(onBattery, oldStatus, level); - } else { - boolean changed = false; - if (mHistoryCur.batteryLevel != level) { - mHistoryCur.batteryLevel = (byte)level; - changed = true; + if (onBattery) { + mDischargeCurrentLevel = level; + mRecordingHistory = true; } - if (mHistoryCur.batteryStatus != status) { + if (onBattery != mOnBattery) { + mHistoryCur.batteryLevel = (byte)level; mHistoryCur.batteryStatus = (byte)status; - changed = true; - } - if (mHistoryCur.batteryHealth != health) { mHistoryCur.batteryHealth = (byte)health; - changed = true; - } - if (mHistoryCur.batteryPlugType != plugType) { mHistoryCur.batteryPlugType = (byte)plugType; - changed = true; - } - if (temp >= (mHistoryCur.batteryTemperature+10) - || temp <= (mHistoryCur.batteryTemperature-10)) { mHistoryCur.batteryTemperature = (char)temp; - changed = true; - } - if (volt > (mHistoryCur.batteryVoltage+20) - || volt < (mHistoryCur.batteryVoltage-20)) { mHistoryCur.batteryVoltage = (char)volt; - changed = true; + setOnBatteryLocked(onBattery, oldStatus, level); + } else { + boolean changed = false; + if (mHistoryCur.batteryLevel != level) { + mHistoryCur.batteryLevel = (byte)level; + changed = true; + } + if (mHistoryCur.batteryStatus != status) { + mHistoryCur.batteryStatus = (byte)status; + changed = true; + } + if (mHistoryCur.batteryHealth != health) { + mHistoryCur.batteryHealth = (byte)health; + changed = true; + } + if (mHistoryCur.batteryPlugType != plugType) { + mHistoryCur.batteryPlugType = (byte)plugType; + changed = true; + } + if (temp >= (mHistoryCur.batteryTemperature+10) + || temp <= (mHistoryCur.batteryTemperature-10)) { + mHistoryCur.batteryTemperature = (char)temp; + changed = true; + } + if (volt > (mHistoryCur.batteryVoltage+20) + || volt < (mHistoryCur.batteryVoltage-20)) { + mHistoryCur.batteryVoltage = (char)volt; + changed = true; + } + if (changed) { + addHistoryRecordLocked(SystemClock.elapsedRealtime()); + } } - if (changed) { - addHistoryRecordLocked(SystemClock.elapsedRealtime()); + if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) { + // We don't record history while we are plugged in and fully charged. + // The next time we are unplugged, history will be cleared. + mRecordingHistory = false; } } - if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) { - // We don't record history while we are plugged in and fully charged. - // The next time we are unplugged, history will be cleared. - mRecordingHistory = false; - } } public void updateKernelWakelocksLocked() { diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index e3a66c5..586ba87 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -43,6 +43,7 @@ import android.view.ViewGroup; import android.view.ViewParent; import android.view.Window; import android.widget.AdapterView; +import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; @@ -385,7 +386,7 @@ public class ActionBarView extends ViewGroup { if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) { mHomeAsUpView.setVisibility((options & ActionBar.DISPLAY_HOME_AS_UP) != 0 - ? VISIBLE : INVISIBLE); + ? VISIBLE : GONE); } if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) { @@ -957,4 +958,60 @@ public class ActionBarView extends ViewGroup { } } } + + private static class HomeView extends FrameLayout { + private View mUpView; + private View mIconView; + + public HomeView(Context context) { + this(context, null); + } + + public HomeView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + mUpView = findViewById(com.android.internal.R.id.up); + mIconView = (ImageView) findViewById(com.android.internal.R.id.home); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0); + final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); + int width = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin; + int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin; + measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0); + final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); + width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin; + height = Math.max(height, + iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin); + setMeasuredDimension(width, height); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int vCenter = (b - t) / 2; + int width = r - l; + if (mUpView.getVisibility() != GONE) { + final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); + final int upHeight = mUpView.getMeasuredHeight(); + final int upWidth = mUpView.getMeasuredWidth(); + final int upTop = t + vCenter - upHeight / 2; + mUpView.layout(l, upTop, l + upWidth, upTop + upHeight); + final int upOffset = upLp.leftMargin + upWidth + upLp.rightMargin; + width -= upOffset; + l += upOffset; + } + final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); + final int iconHeight = mIconView.getMeasuredHeight(); + final int iconWidth = mIconView.getMeasuredWidth(); + final int hCenter = (r - l) / 2; + final int iconLeft = l + iconLp.leftMargin + hCenter - iconWidth / 2; + final int iconTop = t + iconLp.topMargin + vCenter - iconHeight / 2; + mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight); + } + } } diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java index 5ac903d..076a1cb 100644 --- a/core/java/com/android/internal/widget/PointerLocationView.java +++ b/core/java/com/android/internal/widget/PointerLocationView.java @@ -23,6 +23,7 @@ import android.graphics.RectF; import android.graphics.Paint.FontMetricsInt; import android.util.Log; import android.view.InputDevice; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -97,7 +98,8 @@ public class PointerLocationView extends View { public PointerLocationView(Context c) { super(c); - setFocusable(true); + setFocusableInTouchMode(true); + mVC = ViewConfiguration.get(c); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); @@ -505,22 +507,69 @@ public class PointerLocationView extends View { @Override public boolean onTouchEvent(MotionEvent event) { addPointerEvent(event); + + if (event.getAction() == MotionEvent.ACTION_DOWN && !isFocused()) { + requestFocus(); + } return true; } @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { + final int source = event.getSource(); + if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { addPointerEvent(event); + } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { + Log.i(TAG, "Joystick: " + event); + } else if ((source & InputDevice.SOURCE_CLASS_POSITION) != 0) { + Log.i(TAG, "Position: " + event); + } else { + Log.i(TAG, "Generic: " + event); + } + return true; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (shouldLogKey(keyCode)) { + final int repeatCount = event.getRepeatCount(); + if (repeatCount == 0) { + Log.i(TAG, "Key Down: " + event); + } else { + Log.i(TAG, "Key Repeat #" + repeatCount + ": " + event); + } return true; } - return super.onGenericMotionEvent(event); + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (shouldLogKey(keyCode)) { + Log.i(TAG, "Key Up: " + event); + return true; + } + return super.onKeyUp(keyCode, event); + } + + private static boolean shouldLogKey(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + case KeyEvent.KEYCODE_DPAD_CENTER: + return true; + default: + return KeyEvent.isGamepadButton(keyCode) + || KeyEvent.isModifierKey(keyCode); + } } @Override public boolean onTrackballEvent(MotionEvent event) { Log.i(TAG, "Trackball: " + event); - return super.onTrackballEvent(event); + return true; } // HACK diff --git a/core/java/com/android/internal/widget/WaveView.java b/core/java/com/android/internal/widget/WaveView.java index d6f2e1a..288865f 100644 --- a/core/java/com/android/internal/widget/WaveView.java +++ b/core/java/com/android/internal/widget/WaveView.java @@ -40,7 +40,7 @@ import com.android.internal.R; public class WaveView extends View implements ValueAnimator.AnimatorUpdateListener { private static final String TAG = "WaveView"; private static final boolean DBG = false; - private static final int WAVE_COUNT = 5; // default wave count + private static final int WAVE_COUNT = 20; // default wave count private static final long VIBRATE_SHORT = 20; // msec private static final long VIBRATE_LONG = 20; // msec diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 2ed938a..1c4dc29 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -124,6 +124,7 @@ LOCAL_SRC_FILES:= \ android_hardware_Camera.cpp \ android_hardware_SensorManager.cpp \ android_hardware_UsbDevice.cpp \ + android_hardware_UsbDeviceConnection.cpp \ android_hardware_UsbRequest.cpp \ android_debug_JNITest.cpp \ android_util_FileObserver.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 878af3d..0e071a4 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -78,6 +78,7 @@ extern int register_android_opengl_jni_GLES20(JNIEnv* env); extern int register_android_hardware_Camera(JNIEnv *env); extern int register_android_hardware_SensorManager(JNIEnv *env); extern int register_android_hardware_UsbDevice(JNIEnv *env); +extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env); extern int register_android_hardware_UsbRequest(JNIEnv *env); extern int register_android_media_AudioRecord(JNIEnv *env); @@ -1274,6 +1275,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_hardware_Camera), REG_JNI(register_android_hardware_SensorManager), REG_JNI(register_android_hardware_UsbDevice), + REG_JNI(register_android_hardware_UsbDeviceConnection), REG_JNI(register_android_hardware_UsbRequest), REG_JNI(register_android_media_AudioRecord), REG_JNI(register_android_media_AudioSystem), diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index f89967b..ee3e209 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -91,7 +91,7 @@ static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) { return nullObjectReturn("decoder->buildTileIndex returned false"); } - SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, width, height); + SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, stream, width, height); return GraphicsJNI::createBitmapRegionDecoder(env, bm); } diff --git a/core/jni/android_hardware_UsbDevice.cpp b/core/jni/android_hardware_UsbDevice.cpp index b01820c..c2950ea 100644 --- a/core/jni/android_hardware_UsbDevice.cpp +++ b/core/jni/android_hardware_UsbDevice.cpp @@ -24,190 +24,8 @@ #include <usbhost/usbhost.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - using namespace android; -static jfieldID field_context; - -struct usb_device* get_device_from_object(JNIEnv* env, jobject javaDevice) -{ - return (struct usb_device*)env->GetIntField(javaDevice, field_context); -} - -// in android_hardware_UsbEndpoint.cpp -extern struct usb_endpoint* get_endpoint_from_object(JNIEnv* env, jobject javaEndpoint); - -static jboolean -android_hardware_UsbDevice_open(JNIEnv *env, jobject thiz, jstring deviceName, - jobject fileDescriptor) -{ - int fd = getParcelFileDescriptorFD(env, fileDescriptor); - // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy - fd = dup(fd); - if (fd < 0) - return false; - - const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL); - struct usb_device* device = usb_device_new(deviceNameStr, fd); - if (device) { - env->SetIntField(thiz, field_context, (int)device); - } else { - LOGE("usb_device_open failed for %s", deviceNameStr); - close(fd); - } - - env->ReleaseStringUTFChars(deviceName, deviceNameStr); - return (device != NULL); -} - -static void -android_hardware_UsbDevice_close(JNIEnv *env, jobject thiz) -{ - LOGD("close\n"); - struct usb_device* device = get_device_from_object(env, thiz); - if (device) { - usb_device_close(device); - env->SetIntField(thiz, field_context, 0); - } -} - -static jint -android_hardware_UsbDevice_get_fd(JNIEnv *env, jobject thiz) -{ - struct usb_device* device = get_device_from_object(env, thiz); - if (!device) { - LOGE("device is closed in native_get_fd"); - return -1; - } - return usb_device_get_fd(device); -} - -static jboolean -android_hardware_UsbDevice_claim_interface(JNIEnv *env, jobject thiz, int interfaceID, jboolean force) -{ - struct usb_device* device = get_device_from_object(env, thiz); - if (!device) { - LOGE("device is closed in native_claim_interface"); - return -1; - } - - int ret = usb_device_claim_interface(device, interfaceID); - if (ret && force && errno == EBUSY) { - // disconnect kernel driver and try again - usb_device_connect_kernel_driver(device, interfaceID, false); - ret = usb_device_claim_interface(device, interfaceID); - } - return ret == 0; -} - -static jint -android_hardware_UsbDevice_release_interface(JNIEnv *env, jobject thiz, int interfaceID) -{ - struct usb_device* device = get_device_from_object(env, thiz); - if (!device) { - LOGE("device is closed in native_release_interface"); - return -1; - } - int ret = usb_device_release_interface(device, interfaceID); - if (ret == 0) { - // allow kernel to reconnect its driver - usb_device_connect_kernel_driver(device, interfaceID, true); - } - return ret; -} - -static jint -android_hardware_UsbDevice_control_request(JNIEnv *env, jobject thiz, - jint requestType, jint request, jint value, jint index, - jbyteArray buffer, jint length, jint timeout) -{ - struct usb_device* device = get_device_from_object(env, thiz); - if (!device) { - LOGE("device is closed in native_control_request"); - return -1; - } - - jbyte* bufferBytes = NULL; - if (buffer) { - if (env->GetArrayLength(buffer) < length) { - env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL); - return -1; - } - bufferBytes = env->GetByteArrayElements(buffer, 0); - } - - jint result = usb_device_control_transfer(device, requestType, request, - value, index, bufferBytes, length, timeout); - - if (bufferBytes) - env->ReleaseByteArrayElements(buffer, bufferBytes, 0); - - return result; -} - -static jint -android_hardware_UsbDevice_bulk_request(JNIEnv *env, jobject thiz, - jint endpoint, jbyteArray buffer, jint length, jint timeout) -{ - struct usb_device* device = get_device_from_object(env, thiz); - if (!device) { - LOGE("device is closed in native_control_request"); - return -1; - } - - jbyte* bufferBytes = NULL; - if (buffer) { - if (env->GetArrayLength(buffer) < length) { - env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL); - return -1; - } - bufferBytes = env->GetByteArrayElements(buffer, 0); - } - - jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout); - - if (bufferBytes) - env->ReleaseByteArrayElements(buffer, bufferBytes, 0); - - return result; -} - -static jobject -android_hardware_UsbDevice_request_wait(JNIEnv *env, jobject thiz) -{ - struct usb_device* device = get_device_from_object(env, thiz); - if (!device) { - LOGE("device is closed in native_request_wait"); - return NULL; - } - - struct usb_request* request = usb_request_wait(device); - if (request) - return (jobject)request->client_data; - else - return NULL; -} - -static jstring -android_hardware_UsbDevice_get_serial(JNIEnv *env, jobject thiz) -{ - struct usb_device* device = get_device_from_object(env, thiz); - if (!device) { - LOGE("device is closed in native_request_wait"); - return NULL; - } - char* serial = usb_device_get_serial(device); - if (!serial) - return NULL; - jstring result = env->NewStringUTF(serial); - free(serial); - return result; -} - static jint android_hardware_UsbDevice_get_device_id(JNIEnv *env, jobject clazz, jstring name) { @@ -227,21 +45,6 @@ android_hardware_UsbDevice_get_device_name(JNIEnv *env, jobject clazz, jint id) } static JNINativeMethod method_table[] = { - {"native_open", "(Ljava/lang/String;Ljava/io/FileDescriptor;)Z", - (void *)android_hardware_UsbDevice_open}, - {"native_close", "()V", (void *)android_hardware_UsbDevice_close}, - {"native_get_fd", "()I", (void *)android_hardware_UsbDevice_get_fd}, - {"native_claim_interface", "(IZ)Z",(void *)android_hardware_UsbDevice_claim_interface}, - {"native_release_interface","(I)Z", (void *)android_hardware_UsbDevice_release_interface}, - {"native_control_request", "(IIII[BII)I", - (void *)android_hardware_UsbDevice_control_request}, - {"native_bulk_request", "(I[BII)I", - (void *)android_hardware_UsbDevice_bulk_request}, - {"native_request_wait", "()Landroid/hardware/usb/UsbRequest;", - (void *)android_hardware_UsbDevice_request_wait}, - { "native_get_serial", "()Ljava/lang/String;", - (void*)android_hardware_UsbDevice_get_serial }, - // static methods { "native_get_device_id", "(Ljava/lang/String;)I", (void*)android_hardware_UsbDevice_get_device_id }, @@ -256,11 +59,6 @@ int register_android_hardware_UsbDevice(JNIEnv *env) LOGE("Can't find android/hardware/usb/UsbDevice"); return -1; } - field_context = env->GetFieldID(clazz, "mNativeContext", "I"); - if (field_context == NULL) { - LOGE("Can't find UsbDevice.mNativeContext"); - return -1; - } return AndroidRuntime::registerNativeMethods(env, "android/hardware/usb/UsbDevice", method_table, NELEM(method_table)); diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp new file mode 100644 index 0000000..ec36a38 --- /dev/null +++ b/core/jni/android_hardware_UsbDeviceConnection.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "UsbDeviceConnectionJNI" + +#include "utils/Log.h" + +#include "jni.h" +#include "JNIHelp.h" +#include "android_runtime/AndroidRuntime.h" + +#include <usbhost/usbhost.h> + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +using namespace android; + +static jfieldID field_context; + +struct usb_device* get_device_from_object(JNIEnv* env, jobject connection) +{ + return (struct usb_device*)env->GetIntField(connection, field_context); +} + +static jboolean +android_hardware_UsbDeviceConnection_open(JNIEnv *env, jobject thiz, jstring deviceName, + jobject fileDescriptor) +{ + int fd = getParcelFileDescriptorFD(env, fileDescriptor); + // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy + fd = dup(fd); + if (fd < 0) + return false; + + const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL); + struct usb_device* device = usb_device_new(deviceNameStr, fd); + if (device) { + env->SetIntField(thiz, field_context, (int)device); + } else { + LOGE("usb_device_open failed for %s", deviceNameStr); + close(fd); + } + + env->ReleaseStringUTFChars(deviceName, deviceNameStr); + return (device != NULL); +} + +static void +android_hardware_UsbDeviceConnection_close(JNIEnv *env, jobject thiz) +{ + LOGD("close\n"); + struct usb_device* device = get_device_from_object(env, thiz); + if (device) { + usb_device_close(device); + env->SetIntField(thiz, field_context, 0); + } +} + +static jint +android_hardware_UsbDeviceConnection_get_fd(JNIEnv *env, jobject thiz) +{ + struct usb_device* device = get_device_from_object(env, thiz); + if (!device) { + LOGE("device is closed in native_get_fd"); + return -1; + } + return usb_device_get_fd(device); +} + +static jboolean +android_hardware_UsbDeviceConnection_claim_interface(JNIEnv *env, jobject thiz, + int interfaceID, jboolean force) +{ + struct usb_device* device = get_device_from_object(env, thiz); + if (!device) { + LOGE("device is closed in native_claim_interface"); + return -1; + } + + int ret = usb_device_claim_interface(device, interfaceID); + if (ret && force && errno == EBUSY) { + // disconnect kernel driver and try again + usb_device_connect_kernel_driver(device, interfaceID, false); + ret = usb_device_claim_interface(device, interfaceID); + } + return ret == 0; +} + +static jint +android_hardware_UsbDeviceConnection_release_interface(JNIEnv *env, jobject thiz, int interfaceID) +{ + struct usb_device* device = get_device_from_object(env, thiz); + if (!device) { + LOGE("device is closed in native_release_interface"); + return -1; + } + int ret = usb_device_release_interface(device, interfaceID); + if (ret == 0) { + // allow kernel to reconnect its driver + usb_device_connect_kernel_driver(device, interfaceID, true); + } + return ret; +} + +static jint +android_hardware_UsbDeviceConnection_control_request(JNIEnv *env, jobject thiz, + jint requestType, jint request, jint value, jint index, + jbyteArray buffer, jint length, jint timeout) +{ + struct usb_device* device = get_device_from_object(env, thiz); + if (!device) { + LOGE("device is closed in native_control_request"); + return -1; + } + + jbyte* bufferBytes = NULL; + if (buffer) { + if (env->GetArrayLength(buffer) < length) { + env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL); + return -1; + } + bufferBytes = env->GetByteArrayElements(buffer, 0); + } + + jint result = usb_device_control_transfer(device, requestType, request, + value, index, bufferBytes, length, timeout); + + if (bufferBytes) + env->ReleaseByteArrayElements(buffer, bufferBytes, 0); + + return result; +} + +static jint +android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz, + jint endpoint, jbyteArray buffer, jint length, jint timeout) +{ + struct usb_device* device = get_device_from_object(env, thiz); + if (!device) { + LOGE("device is closed in native_control_request"); + return -1; + } + + jbyte* bufferBytes = NULL; + if (buffer) { + if (env->GetArrayLength(buffer) < length) { + env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL); + return -1; + } + bufferBytes = env->GetByteArrayElements(buffer, 0); + } + + jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout); + + if (bufferBytes) + env->ReleaseByteArrayElements(buffer, bufferBytes, 0); + + return result; +} + +static jobject +android_hardware_UsbDeviceConnection_request_wait(JNIEnv *env, jobject thiz) +{ + struct usb_device* device = get_device_from_object(env, thiz); + if (!device) { + LOGE("device is closed in native_request_wait"); + return NULL; + } + + struct usb_request* request = usb_request_wait(device); + if (request) + return (jobject)request->client_data; + else + return NULL; +} + +static jstring +android_hardware_UsbDeviceConnection_get_serial(JNIEnv *env, jobject thiz) +{ + struct usb_device* device = get_device_from_object(env, thiz); + if (!device) { + LOGE("device is closed in native_request_wait"); + return NULL; + } + char* serial = usb_device_get_serial(device); + if (!serial) + return NULL; + jstring result = env->NewStringUTF(serial); + free(serial); + return result; +} + +static JNINativeMethod method_table[] = { + {"native_open", "(Ljava/lang/String;Ljava/io/FileDescriptor;)Z", + (void *)android_hardware_UsbDeviceConnection_open}, + {"native_close", "()V", (void *)android_hardware_UsbDeviceConnection_close}, + {"native_get_fd", "()I", (void *)android_hardware_UsbDeviceConnection_get_fd}, + {"native_claim_interface", "(IZ)Z",(void *)android_hardware_UsbDeviceConnection_claim_interface}, + {"native_release_interface","(I)Z", (void *)android_hardware_UsbDeviceConnection_release_interface}, + {"native_control_request", "(IIII[BII)I", + (void *)android_hardware_UsbDeviceConnection_control_request}, + {"native_bulk_request", "(I[BII)I", + (void *)android_hardware_UsbDeviceConnection_bulk_request}, + {"native_request_wait", "()Landroid/hardware/usb/UsbRequest;", + (void *)android_hardware_UsbDeviceConnection_request_wait}, + { "native_get_serial", "()Ljava/lang/String;", + (void*)android_hardware_UsbDeviceConnection_get_serial }, +}; + +int register_android_hardware_UsbDeviceConnection(JNIEnv *env) +{ + jclass clazz = env->FindClass("android/hardware/usb/UsbDeviceConnection"); + if (clazz == NULL) { + LOGE("Can't find android/hardware/usb/UsbDeviceConnection"); + return -1; + } + field_context = env->GetFieldID(clazz, "mNativeContext", "I"); + if (field_context == NULL) { + LOGE("Can't find UsbDeviceConnection.mNativeContext"); + return -1; + } + + return AndroidRuntime::registerNativeMethods(env, "android/hardware/usb/UsbDeviceConnection", + method_table, NELEM(method_table)); +} + diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp index b497adb..6bd67d1 100644 --- a/core/jni/android_hardware_UsbRequest.cpp +++ b/core/jni/android_hardware_UsbRequest.cpp @@ -35,8 +35,8 @@ struct usb_request* get_request_from_object(JNIEnv* env, jobject java_request) return (struct usb_request*)env->GetIntField(java_request, field_context); } -// in android_hardware_UsbDevice.cpp -extern struct usb_device* get_device_from_object(JNIEnv* env, jobject java_device); +// in android_hardware_UsbDeviceConnection.cpp +extern struct usb_device* get_device_from_object(JNIEnv* env, jobject connection); static jboolean android_hardware_UsbRequest_init(JNIEnv *env, jobject thiz, jobject java_device, @@ -107,7 +107,7 @@ android_hardware_UsbRequest_queue_array(JNIEnv *env, jobject thiz, } return false; } else { - // save a reference to ourselves so UsbDevice.waitRequest() can find us + // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us request->client_data = (void *)env->NewGlobalRef(thiz); return true; } @@ -155,7 +155,7 @@ android_hardware_UsbRequest_queue_direct(JNIEnv *env, jobject thiz, request->buffer = NULL; return false; } else { - // save a reference to ourselves so UsbDevice.waitRequest() can find us + // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us // we also need this to make sure our native buffer is not deallocated // while IO is active request->client_data = (void *)env->NewGlobalRef(thiz); @@ -187,7 +187,7 @@ android_hardware_UsbRequest_cancel(JNIEnv *env, jobject thiz) } static JNINativeMethod method_table[] = { - {"native_init", "(Landroid/hardware/usb/UsbDevice;IIII)Z", + {"native_init", "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z", (void *)android_hardware_UsbRequest_init}, {"native_close", "()V", (void *)android_hardware_UsbRequest_close}, {"native_queue_array", "([BIZ)Z", (void *)android_hardware_UsbRequest_queue_array}, diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index f78f83c..b6619ab 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -315,7 +315,11 @@ static jint android_media_AudioRecord_readInByteArray(JNIEnv *env, jobject thiz } // get the pointer to where we'll record the audio - recordBuff = (jbyte *)env->GetPrimitiveArrayCritical(javaAudioData, NULL); + // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such + // a way that it becomes much more efficient. When doing so, we will have to prevent the + // AudioSystem callback to be called while in critical section (in case of media server + // process crash for instance) + recordBuff = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL); if (recordBuff == NULL) { LOGE("Error retrieving destination for recorded audio data, can't record"); @@ -327,7 +331,7 @@ static jint android_media_AudioRecord_readInByteArray(JNIEnv *env, jobject thiz ssize_t readSize = lpRecorder->read(recordBuff + offsetInBytes, sizeInBytes > (jint)recorderBuffSize ? (jint)recorderBuffSize : sizeInBytes ); - env->ReleasePrimitiveArrayCritical(javaAudioData, recordBuff, 0); + env->ReleaseByteArrayElements(javaAudioData, recordBuff, 0); return (jint) readSize; } diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 8409adc..44d2a52 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -530,8 +530,12 @@ static jint android_media_AudioTrack_native_write(JNIEnv *env, jobject thiz, } // get the pointer for the audio data from the java array + // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such + // a way that it becomes much more efficient. When doing so, we will have to prevent the + // AudioSystem callback to be called while in critical section (in case of media server + // process crash for instance) if (javaAudioData) { - cAudioData = (jbyte *)env->GetPrimitiveArrayCritical(javaAudioData, NULL); + cAudioData = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL); if (cAudioData == NULL) { LOGE("Error retrieving source of audio data to play, can't play"); return 0; // out of memory or no data to load @@ -543,7 +547,7 @@ static jint android_media_AudioTrack_native_write(JNIEnv *env, jobject thiz, jint written = writeToTrack(lpTrack, javaAudioFormat, cAudioData, offsetInBytes, sizeInBytes); - env->ReleasePrimitiveArrayCritical(javaAudioData, cAudioData, 0); + env->ReleaseByteArrayElements(javaAudioData, cAudioData, 0); //LOGV("write wrote %d (tried %d) bytes in the native AudioTrack with offset %d", // (int)written, (int)(sizeInBytes), (int)offsetInBytes); diff --git a/core/jni/android_os_Power.cpp b/core/jni/android_os_Power.cpp index a46c2dd..5cfb9b1 100644 --- a/core/jni/android_os_Power.cpp +++ b/core/jni/android_os_Power.cpp @@ -20,7 +20,7 @@ #include "android_runtime/AndroidRuntime.h" #include <utils/misc.h> #include <hardware_legacy/power.h> -#include <sys/reboot.h> +#include <cutils/android_reboot.h> namespace android { @@ -77,25 +77,26 @@ setScreenState(JNIEnv *env, jobject clazz, jboolean on) static void android_os_Power_shutdown(JNIEnv *env, jobject clazz) { - sync(); #ifdef HAVE_ANDROID_OS - reboot(RB_POWER_OFF); + android_reboot(ANDROID_RB_POWEROFF, 0, 0); +#else + sync(); #endif } static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason) { - sync(); #ifdef HAVE_ANDROID_OS if (reason == NULL) { - reboot(RB_AUTOBOOT); + android_reboot(ANDROID_RB_RESTART, 0, 0); } else { const char *chars = env->GetStringUTFChars(reason, NULL); - __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, - LINUX_REBOOT_CMD_RESTART2, (char*) chars); + android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); env->ReleaseStringUTFChars(reason, chars); // In case it fails. } jniThrowIOException(env, errno); +#else + sync(); #endif } diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 5deed1e..9e00a7d 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -44,6 +44,13 @@ //#undef LOGV //#define LOGV(...) fprintf(stderr, __VA_ARGS__) +#define DEBUG_DEATH 0 +#if DEBUG_DEATH +#define LOGDEATH LOGD +#else +#define LOGDEATH LOGV +#endif + using namespace android; // ---------------------------------------------------------------------------- @@ -363,6 +370,7 @@ class DeathRecipientList : public RefBase { Mutex mLock; public: + DeathRecipientList(); ~DeathRecipientList(); void add(const sp<JavaDeathRecipient>& recipient); @@ -380,6 +388,7 @@ public: { // These objects manage their own lifetimes so are responsible for final bookkeeping. // The list holds a strong reference to this object. + LOGDEATH("Adding JDR %p to DRL %p", this, list.get()); list->add(this); android_atomic_inc(&gNumDeathRefs); @@ -390,7 +399,7 @@ public: { JNIEnv* env = javavm_to_jnienv(mVM); - LOGV("Receiving binderDied() on JavaDeathRecipient %p\n", this); + LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this); env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mSendDeathNotice, mObject); @@ -399,15 +408,16 @@ public: report_exception(env, excep, "*** Uncaught exception returned from death notification!"); } - - clearReference(); } void clearReference() { sp<DeathRecipientList> list = mList.promote(); if (list != NULL) { + LOGDEATH("Removing JDR %p from DRL %p", this, list.get()); list->remove(this); + } else { + LOGDEATH("clearReference() on JDR %p but DRL wp purged", this); } } @@ -433,7 +443,12 @@ private: // ---------------------------------------------------------------------------- +DeathRecipientList::DeathRecipientList() { + LOGDEATH("New DRL @ %p", this); +} + DeathRecipientList::~DeathRecipientList() { + LOGDEATH("Destroy DRL @ %p", this); AutoMutex _l(mLock); // Should never happen -- the JavaDeathRecipient objects that have added themselves @@ -447,6 +462,7 @@ DeathRecipientList::~DeathRecipientList() { void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) { AutoMutex _l(mLock); + LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get()); mList.push_back(recipient); } @@ -456,6 +472,7 @@ void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) { List< sp<JavaDeathRecipient> >::iterator iter; for (iter = mList.begin(); iter != mList.end(); iter++) { if (*iter == recipient) { + LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get()); mList.erase(iter); return; } @@ -518,7 +535,7 @@ jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); if (object != NULL) { - LOGV("objectForBinder %p: created new proxy %p !\n", val.get(), object); + LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object); // The proxy holds a reference to the native object. env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get()); val->incStrong(object); @@ -1030,7 +1047,7 @@ static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, assert(false); } - LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient); + LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient); if (!target->localBinder()) { DeathRecipientList* list = (DeathRecipientList*) @@ -1062,7 +1079,7 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, return JNI_FALSE; } - LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); + LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); if (!target->localBinder()) { status_t err = NAME_NOT_FOUND; @@ -1071,6 +1088,7 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, DeathRecipientList* list = (DeathRecipientList*) env->GetIntField(obj, gBinderProxyOffsets.mOrgue); sp<JavaDeathRecipient> origJDR = list->find(recipient); + LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get()); if (origJDR != NULL) { wp<IBinder::DeathRecipient> dr; err = target->unlinkToDeath(origJDR, NULL, flags, &dr); @@ -1101,7 +1119,7 @@ static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) DeathRecipientList* drl = (DeathRecipientList*) env->GetIntField(obj, gBinderProxyOffsets.mOrgue); - LOGV("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl); + LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl); env->SetIntField(obj, gBinderProxyOffsets.mObject, 0); env->SetIntField(obj, gBinderProxyOffsets.mOrgue, 0); drl->decStrong((void*)javaObjectForIBinder); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 7a609a5..a78f660 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -35,7 +35,6 @@ #include <DisplayListRenderer.h> #include <LayerRenderer.h> -#include <OpenGLDebugRenderer.h> #include <OpenGLRenderer.h> #include <SkiaShader.h> #include <SkiaColorFilter.h> @@ -60,7 +59,6 @@ using namespace uirenderer; // Debug #define DEBUG_RENDERER 0 -#define PROFILE_RENDERER 0 // Debug #if DEBUG_RENDERER @@ -99,11 +97,7 @@ static jboolean android_view_GLES20Canvas_preserveBackBuffer(JNIEnv* env, jobjec static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) { RENDERER_LOGD("Create OpenGLRenderer"); -#if PROFILE_RENDERER - return new OpenGLDebugRenderer; -#else return new OpenGLRenderer; -#endif } static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz, @@ -139,7 +133,8 @@ static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz, static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, Functor *functor) { - return renderer->callDrawGLFunction(functor); + android::uirenderer::Rect dirty; + return renderer->callDrawGLFunction(functor, dirty); } // ---------------------------------------------------------------------------- @@ -503,8 +498,14 @@ static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env, } static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env, - jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) { - return renderer->drawDisplayList(displayList); + jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, jobject dirty) { + android::uirenderer::Rect bounds; + bool redraw = renderer->drawDisplayList(displayList, bounds); + if (redraw && dirty != NULL) { + env->CallVoidMethod(dirty, gRectClassInfo.set, + int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom)); + } + return redraw; } // ---------------------------------------------------------------------------- @@ -663,7 +664,8 @@ static JNINativeMethod gMethods[] = { { "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList }, { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList }, { "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer }, - { "nDrawDisplayList", "(II)Z", (void*) android_view_GLES20Canvas_drawDisplayList }, + { "nDrawDisplayList", "(IILandroid/graphics/Rect;)Z", + (void*) android_view_GLES20Canvas_drawDisplayList }, { "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt }, { "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume }, diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp index e7ea8c8..3d24bee 100644 --- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp @@ -400,7 +400,7 @@ static jint jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) { } static jint jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) { - if (!(readdraw == EGL_READ) || (readdraw == EGL_DRAW)) { + if ((readdraw != EGL_READ) && (readdraw != EGL_DRAW)) { doThrow(_env, "java/lang/IllegalArgumentException"); return 0; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 0ad174f..c684e7e 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1379,12 +1379,6 @@ android:excludeFromRecents="true"> </activity> - <activity android:name="com.android.server.usb.UsbResolverActivity" - android:theme="@style/Theme.Holo.Dialog.Alert" - android:finishOnCloseSystemDialogs="true" - android:excludeFromRecents="true"> - </activity> - <service android:name="com.android.server.LoadAverageService" android:exported="true" /> diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png Binary files differnew file mode 100644 index 0000000..6840962 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png Binary files differnew file mode 100644 index 0000000..b3196c3 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png Binary files differnew file mode 100644 index 0000000..c44ae7a --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png Binary files differnew file mode 100644 index 0000000..e240a2d --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png Binary files differindex 52fccf8..7855cda 100644 --- a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png Binary files differindex 0354599..c062773 100644 --- a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png diff --git a/core/res/res/drawable-hdpi/stat_notify_call_mute.png b/core/res/res/drawable-hdpi/stat_notify_call_mute.png Binary files differindex 048f56e..9887faa 100755 --- a/core/res/res/drawable-hdpi/stat_notify_call_mute.png +++ b/core/res/res/drawable-hdpi/stat_notify_call_mute.png diff --git a/core/res/res/drawable-hdpi/stat_notify_car_mode.png b/core/res/res/drawable-hdpi/stat_notify_car_mode.png Binary files differindex 76dd2ae..94f288c 100644 --- a/core/res/res/drawable-hdpi/stat_notify_car_mode.png +++ b/core/res/res/drawable-hdpi/stat_notify_car_mode.png diff --git a/core/res/res/drawable-hdpi/stat_notify_chat.png b/core/res/res/drawable-hdpi/stat_notify_chat.png Binary files differindex d7c1545..bddea50 100644 --- a/core/res/res/drawable-hdpi/stat_notify_chat.png +++ b/core/res/res/drawable-hdpi/stat_notify_chat.png diff --git a/core/res/res/drawable-hdpi/stat_notify_disk_full.png b/core/res/res/drawable-hdpi/stat_notify_disk_full.png Binary files differindex 9956fad..b44ce58 100755 --- a/core/res/res/drawable-hdpi/stat_notify_disk_full.png +++ b/core/res/res/drawable-hdpi/stat_notify_disk_full.png diff --git a/core/res/res/drawable-hdpi/stat_notify_email_generic.png b/core/res/res/drawable-hdpi/stat_notify_email_generic.png Binary files differindex 4ea619c..8d60237 100644 --- a/core/res/res/drawable-hdpi/stat_notify_email_generic.png +++ b/core/res/res/drawable-hdpi/stat_notify_email_generic.png diff --git a/core/res/res/drawable-hdpi/stat_notify_error.png b/core/res/res/drawable-hdpi/stat_notify_error.png Binary files differindex 598094f..6942871 100755 --- a/core/res/res/drawable-hdpi/stat_notify_error.png +++ b/core/res/res/drawable-hdpi/stat_notify_error.png diff --git a/core/res/res/drawable-hdpi/stat_notify_gmail.png b/core/res/res/drawable-hdpi/stat_notify_gmail.png Binary files differindex 7028ea7..bf8582a 100644 --- a/core/res/res/drawable-hdpi/stat_notify_gmail.png +++ b/core/res/res/drawable-hdpi/stat_notify_gmail.png diff --git a/core/res/res/drawable-hdpi/stat_notify_missed_call.png b/core/res/res/drawable-hdpi/stat_notify_missed_call.png Binary files differindex b0f7a6e..6df57ff3 100644 --- a/core/res/res/drawable-hdpi/stat_notify_missed_call.png +++ b/core/res/res/drawable-hdpi/stat_notify_missed_call.png diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard.png b/core/res/res/drawable-hdpi/stat_notify_sdcard.png Binary files differindex a916488..0857774 100755 --- a/core/res/res/drawable-hdpi/stat_notify_sdcard.png +++ b/core/res/res/drawable-hdpi/stat_notify_sdcard.png diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png Binary files differindex e267700..3880496 100755 --- a/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png +++ b/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png Binary files differindex 233e438..ac984ef 100755 --- a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png +++ b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png diff --git a/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png Binary files differindex 42101077..b7ba4ba 100755 --- a/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png +++ b/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png diff --git a/core/res/res/drawable-hdpi/stat_notify_sync.png b/core/res/res/drawable-hdpi/stat_notify_sync.png Binary files differindex 2076c55..76319b0 100755 --- a/core/res/res/drawable-hdpi/stat_notify_sync.png +++ b/core/res/res/drawable-hdpi/stat_notify_sync.png diff --git a/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png Binary files differindex 2076c55..863c3d7 100755 --- a/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png +++ b/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png diff --git a/core/res/res/drawable-hdpi/stat_notify_sync_error.png b/core/res/res/drawable-hdpi/stat_notify_sync_error.png Binary files differindex bade508..0083c3f 100755 --- a/core/res/res/drawable-hdpi/stat_notify_sync_error.png +++ b/core/res/res/drawable-hdpi/stat_notify_sync_error.png diff --git a/core/res/res/drawable-hdpi/stat_notify_voicemail.png b/core/res/res/drawable-hdpi/stat_notify_voicemail.png Binary files differindex 43fe530..499325b 100755 --- a/core/res/res/drawable-hdpi/stat_notify_voicemail.png +++ b/core/res/res/drawable-hdpi/stat_notify_voicemail.png diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png Binary files differindex 5c42e53..8d80709 100644 --- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-hdpi/stat_sys_adb.png b/core/res/res/drawable-hdpi/stat_sys_adb.png Binary files differindex af713e8..877e731 100755 --- a/core/res/res/drawable-hdpi/stat_sys_adb.png +++ b/core/res/res/drawable-hdpi/stat_sys_adb.png diff --git a/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png Binary files differindex 42a774e..526fbfa 100644 --- a/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png +++ b/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png diff --git a/core/res/res/drawable-hdpi/stat_sys_data_usb.png b/core/res/res/drawable-hdpi/stat_sys_data_usb.png Binary files differindex 6987b09..606ef80 100755 --- a/core/res/res/drawable-hdpi/stat_sys_data_usb.png +++ b/core/res/res/drawable-hdpi/stat_sys_data_usb.png diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim0.png b/core/res/res/drawable-hdpi/stat_sys_download_anim0.png Binary files differindex 943e620..0510128 100644 --- a/core/res/res/drawable-hdpi/stat_sys_download_anim0.png +++ b/core/res/res/drawable-hdpi/stat_sys_download_anim0.png diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png Binary files differindex 28edae1..631622b 100644 --- a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png +++ b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim2.png b/core/res/res/drawable-hdpi/stat_sys_download_anim2.png Binary files differindex 556a46f..e300245 100644 --- a/core/res/res/drawable-hdpi/stat_sys_download_anim2.png +++ b/core/res/res/drawable-hdpi/stat_sys_download_anim2.png diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim3.png b/core/res/res/drawable-hdpi/stat_sys_download_anim3.png Binary files differindex 422d72b..fd220e3 100644 --- a/core/res/res/drawable-hdpi/stat_sys_download_anim3.png +++ b/core/res/res/drawable-hdpi/stat_sys_download_anim3.png diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim4.png b/core/res/res/drawable-hdpi/stat_sys_download_anim4.png Binary files differindex 24a0db5..a1ea9e3 100644 --- a/core/res/res/drawable-hdpi/stat_sys_download_anim4.png +++ b/core/res/res/drawable-hdpi/stat_sys_download_anim4.png diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim5.png b/core/res/res/drawable-hdpi/stat_sys_download_anim5.png Binary files differindex 97e5a6b..7804a29 100644 --- a/core/res/res/drawable-hdpi/stat_sys_download_anim5.png +++ b/core/res/res/drawable-hdpi/stat_sys_download_anim5.png diff --git a/core/res/res/drawable-hdpi/stat_sys_gps_on.png b/core/res/res/drawable-hdpi/stat_sys_gps_on.png Binary files differindex 0d6f622..542ebb0 100644 --- a/core/res/res/drawable-hdpi/stat_sys_gps_on.png +++ b/core/res/res/drawable-hdpi/stat_sys_gps_on.png diff --git a/core/res/res/drawable-hdpi/stat_sys_secure.png b/core/res/res/drawable-hdpi/stat_sys_secure.png Binary files differindex 8d24990..c4a17de 100755 --- a/core/res/res/drawable-hdpi/stat_sys_secure.png +++ b/core/res/res/drawable-hdpi/stat_sys_secure.png diff --git a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png Binary files differindex 82c06a9..a9a2b2e 100755 --- a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png +++ b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png diff --git a/core/res/res/drawable-hdpi/stat_sys_throttled.png b/core/res/res/drawable-hdpi/stat_sys_throttled.png Binary files differindex bd8323a..99ae4ac 100755 --- a/core/res/res/drawable-hdpi/stat_sys_throttled.png +++ b/core/res/res/drawable-hdpi/stat_sys_throttled.png diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png Binary files differindex 45f3c7b..48ba735 100644 --- a/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png +++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png Binary files differindex f4d5a72..cbb06a5 100644 --- a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png +++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png Binary files differindex b7448c8..e4edda9 100644 --- a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png +++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png Binary files differindex dfbd726..c2a9b03 100644 --- a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png +++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png Binary files differindex c4513bf..23f2f9d 100644 --- a/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png +++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png Binary files differindex cc21de2..3fd8b7f 100644 --- a/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png +++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png diff --git a/core/res/res/drawable-hdpi/stat_sys_warning.png b/core/res/res/drawable-hdpi/stat_sys_warning.png Binary files differindex 2783d89..0d1a33c 100755 --- a/core/res/res/drawable-hdpi/stat_sys_warning.png +++ b/core/res/res/drawable-hdpi/stat_sys_warning.png diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png Binary files differindex b9435b6..ae77fa0 100644 --- a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png Binary files differindex 477d820..c6bdfcc 100644 --- a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png +++ b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png Binary files differindex 5b62564..62e3274 100644 --- a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png Binary files differindex 881edeb..b7512fa 100644 --- a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png +++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..bfc6f83 --- /dev/null +++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png Binary files differnew file mode 100644 index 0000000..708ba90 --- /dev/null +++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..0da1e9c --- /dev/null +++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png Binary files differnew file mode 100644 index 0000000..2e93557 --- /dev/null +++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png Binary files differindex cb3f35b..7aeaad6 100644 --- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png Binary files differindex 742b137..cf46f32 100644 --- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png +++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png Binary files differnew file mode 100644 index 0000000..9a24b9c --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png Binary files differnew file mode 100644 index 0000000..93d9741 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png Binary files differnew file mode 100644 index 0000000..f462d98 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png Binary files differnew file mode 100644 index 0000000..30373a6 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png Binary files differindex 959b4e4..ae3e6bf 100644 --- a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png Binary files differindex 41333b8..c61e3fa 100644 --- a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png diff --git a/core/res/res/drawable-mdpi/stat_notify_call_mute.png b/core/res/res/drawable-mdpi/stat_notify_call_mute.png Binary files differindex be26065..845ec86 100644 --- a/core/res/res/drawable-mdpi/stat_notify_call_mute.png +++ b/core/res/res/drawable-mdpi/stat_notify_call_mute.png diff --git a/core/res/res/drawable-mdpi/stat_notify_car_mode.png b/core/res/res/drawable-mdpi/stat_notify_car_mode.png Binary files differindex 60d9202..dfd2e0a 100644 --- a/core/res/res/drawable-mdpi/stat_notify_car_mode.png +++ b/core/res/res/drawable-mdpi/stat_notify_car_mode.png diff --git a/core/res/res/drawable-mdpi/stat_notify_chat.png b/core/res/res/drawable-mdpi/stat_notify_chat.png Binary files differindex 36ac850..e4464c2 100644 --- a/core/res/res/drawable-mdpi/stat_notify_chat.png +++ b/core/res/res/drawable-mdpi/stat_notify_chat.png diff --git a/core/res/res/drawable-mdpi/stat_notify_disk_full.png b/core/res/res/drawable-mdpi/stat_notify_disk_full.png Binary files differindex 4e198ef..69b513c 100755 --- a/core/res/res/drawable-mdpi/stat_notify_disk_full.png +++ b/core/res/res/drawable-mdpi/stat_notify_disk_full.png diff --git a/core/res/res/drawable-mdpi/stat_notify_email_generic.png b/core/res/res/drawable-mdpi/stat_notify_email_generic.png Binary files differindex a01485e..42d518d 100644 --- a/core/res/res/drawable-mdpi/stat_notify_email_generic.png +++ b/core/res/res/drawable-mdpi/stat_notify_email_generic.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 69c02d7..ddf0a2f 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_gmail.png b/core/res/res/drawable-mdpi/stat_notify_gmail.png Binary files differindex 55bae33..516e865 100644 --- a/core/res/res/drawable-mdpi/stat_notify_gmail.png +++ b/core/res/res/drawable-mdpi/stat_notify_gmail.png diff --git a/core/res/res/drawable-mdpi/stat_notify_missed_call.png b/core/res/res/drawable-mdpi/stat_notify_missed_call.png Binary files differindex 58030fd..d2e3631 100644 --- a/core/res/res/drawable-mdpi/stat_notify_missed_call.png +++ b/core/res/res/drawable-mdpi/stat_notify_missed_call.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 0071bf4..8f64201 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 c04d70d..fc051fa 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 2880934..b936f45 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_sim_toolkit.png b/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png Binary files differindex ee7b10c..87327b4 100755 --- a/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png +++ b/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png diff --git a/core/res/res/drawable-mdpi/stat_notify_sync.png b/core/res/res/drawable-mdpi/stat_notify_sync.png Binary files differindex ef9d4eb..4876b8e 100644 --- a/core/res/res/drawable-mdpi/stat_notify_sync.png +++ b/core/res/res/drawable-mdpi/stat_notify_sync.png diff --git a/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png Binary files differindex ef9d4eb..8372756 100644 --- a/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png +++ b/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png diff --git a/core/res/res/drawable-mdpi/stat_notify_sync_error.png b/core/res/res/drawable-mdpi/stat_notify_sync_error.png Binary files differindex f55bf58..2725549 100644 --- a/core/res/res/drawable-mdpi/stat_notify_sync_error.png +++ b/core/res/res/drawable-mdpi/stat_notify_sync_error.png diff --git a/core/res/res/drawable-mdpi/stat_notify_voicemail.png b/core/res/res/drawable-mdpi/stat_notify_voicemail.png Binary files differindex b72a07a..67a0f91 100644 --- a/core/res/res/drawable-mdpi/stat_notify_voicemail.png +++ b/core/res/res/drawable-mdpi/stat_notify_voicemail.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 90dd76e..de63297 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 2c4d2b5..e259ca5 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_data_bluetooth.png b/core/res/res/drawable-mdpi/stat_sys_data_bluetooth.png Binary files differindex f7f554e..46f6901 100644 --- a/core/res/res/drawable-mdpi/stat_sys_data_bluetooth.png +++ b/core/res/res/drawable-mdpi/stat_sys_data_bluetooth.png diff --git a/core/res/res/drawable-mdpi/stat_sys_data_usb.png b/core/res/res/drawable-mdpi/stat_sys_data_usb.png Binary files differindex 6cdfab7..44860bf 100644 --- a/core/res/res/drawable-mdpi/stat_sys_data_usb.png +++ b/core/res/res/drawable-mdpi/stat_sys_data_usb.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 c6f2f4e..9c77ecb 100644 --- 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 429ebd7..4bf5e6c 100644 --- 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 b3de461..2211810 100644 --- 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 195498e..7db3096 100644 --- 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 8fc3e86..894dd63 100644 --- 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 c6f2f4e..889c01e 100644 --- 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_gps_on.png b/core/res/res/drawable-mdpi/stat_sys_gps_on.png Binary files differindex ab59f7c..e0b9d6e 100644 --- a/core/res/res/drawable-mdpi/stat_sys_gps_on.png +++ b/core/res/res/drawable-mdpi/stat_sys_gps_on.png diff --git a/core/res/res/drawable-mdpi/stat_sys_secure.png b/core/res/res/drawable-mdpi/stat_sys_secure.png Binary files differindex db73d06..7167c3a 100644 --- a/core/res/res/drawable-mdpi/stat_sys_secure.png +++ b/core/res/res/drawable-mdpi/stat_sys_secure.png diff --git a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png Binary files differindex 0673060..25fef56 100644 --- a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png +++ b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png diff --git a/core/res/res/drawable-mdpi/stat_sys_throttled.png b/core/res/res/drawable-mdpi/stat_sys_throttled.png Binary files differindex 28a293b..2cbe7f4 100644 --- a/core/res/res/drawable-mdpi/stat_sys_throttled.png +++ b/core/res/res/drawable-mdpi/stat_sys_throttled.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 f804e5e..6a05585 100644 --- 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 0cbb85c..af492c8 100644 --- 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 cfa74f3..4ba150c8 100644 --- 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 de5c314..cbcf280 100644 --- 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 8847949..cb8628c 100644 --- 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 f804e5e..e7a5376 100644 --- 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/stat_sys_warning.png b/core/res/res/drawable-mdpi/stat_sys_warning.png Binary files differindex 494c96a..2a764fa 100644 --- a/core/res/res/drawable-mdpi/stat_sys_warning.png +++ b/core/res/res/drawable-mdpi/stat_sys_warning.png diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png Binary files differindex b9435b6..ae77fa0 100644 --- a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png Binary files differindex 477d820..c6bdfcc 100644 --- a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png +++ b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png Binary files differindex 3549948..b7413b3 100644 --- a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png Binary files differindex 6db03cb..82e7a03 100644 --- a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..4b0ea21 --- /dev/null +++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png Binary files differnew file mode 100644 index 0000000..e87591c --- /dev/null +++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..14f69b1 --- /dev/null +++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png Binary files differnew file mode 100644 index 0000000..85329ca --- /dev/null +++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png Binary files differindex 670439a..7e130d9 100644 --- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png Binary files differindex 90e26e2..050d1c0 100644 --- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png diff --git a/core/res/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png b/core/res/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png Binary files differindex f8063d1..a526fcf 100644 --- a/core/res/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png +++ b/core/res/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png diff --git a/core/res/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png b/core/res/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png Binary files differindex 577f7cc..3640f55 100644 --- a/core/res/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png +++ b/core/res/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png diff --git a/core/res/res/drawable/textfield_searchview_holo_dark.xml b/core/res/res/drawable/textfield_searchview_holo_dark.xml new file mode 100644 index 0000000..1396f83 --- /dev/null +++ b/core/res/res/drawable/textfield_searchview_holo_dark.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_focused="true" + android:drawable="@drawable/textfield_search_selected_holo_dark" /> + <item android:drawable="@drawable/textfield_search_default_holo_dark" /> +</selector> + diff --git a/core/res/res/drawable/textfield_searchview_holo_light.xml b/core/res/res/drawable/textfield_searchview_holo_light.xml new file mode 100644 index 0000000..5198f9c --- /dev/null +++ b/core/res/res/drawable/textfield_searchview_holo_light.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_focused="true" + android:drawable="@drawable/textfield_search_selected_holo_light" /> + <item android:drawable="@drawable/textfield_search_default_holo_light" /> +</selector> + diff --git a/core/res/res/drawable/textfield_searchview_right_holo_dark.xml b/core/res/res/drawable/textfield_searchview_right_holo_dark.xml new file mode 100644 index 0000000..b4f1ca1 --- /dev/null +++ b/core/res/res/drawable/textfield_searchview_right_holo_dark.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_focused="true" + android:drawable="@drawable/textfield_search_right_selected_holo_dark" /> + <item android:drawable="@drawable/textfield_search_right_default_holo_dark" /> +</selector> + diff --git a/core/res/res/drawable/textfield_searchview_right_holo_light.xml b/core/res/res/drawable/textfield_searchview_right_holo_light.xml new file mode 100644 index 0000000..e521bf6 --- /dev/null +++ b/core/res/res/drawable/textfield_searchview_right_holo_light.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_focused="true" + android:drawable="@drawable/textfield_search_right_selected_holo_light" /> + <item android:drawable="@drawable/textfield_search_right_default_holo_light" /> +</selector> + diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml index e8b5637..c82f91d 100644 --- a/core/res/res/layout/action_bar_home.xml +++ b/core/res/res/layout/action_bar_home.xml @@ -14,16 +14,18 @@ limitations under the License. --> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:background="?android:attr/selectableItemBackground"> +<view xmlns:android="http://schemas.android.com/apk/res/android" + class="com.android.internal.widget.ActionBarView$HomeView" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:background="?android:attr/selectableItemBackground" > <ImageView android:id="@android:id/up" android:src="?android:attr/homeAsUpIndicator" - android:layout_gravity="top|left" - android:visibility="invisible" + android:layout_gravity="center_vertical|left" + android:visibility="gone" android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:layout_marginRight="-12dip" /> <ImageView android:id="@android:id/home" android:layout_width="wrap_content" android:layout_height="match_parent" @@ -31,4 +33,4 @@ android:paddingRight="16dip" android:layout_gravity="center" android:scaleType="center" /> -</FrameLayout> +</view> diff --git a/core/res/res/layout/media_controller.xml b/core/res/res/layout/media_controller.xml index f4a701e..582101a 100644 --- a/core/res/res/layout/media_controller.xml +++ b/core/res/res/layout/media_controller.xml @@ -59,7 +59,7 @@ style="?android:attr/progressBarStyleHorizontal" android:layout_width="0dip" android:layout_weight="1" - android:layout_height="30dip" + android:layout_height="32dip" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" /> diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml index c41c2de..c52b73f 100644 --- a/core/res/res/layout/search_view.xml +++ b/core/res/res/layout/search_view.xml @@ -54,6 +54,10 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" + android:layout_marginLeft="4dip" + android:layout_marginRight="4dip" + android:layout_marginTop="4dip" + android:layout_marginBottom="4dip" android:orientation="horizontal"> <!-- Inner layout contains the app icon, button(s) and EditText --> @@ -64,7 +68,7 @@ android:layout_weight="1" android:layout_gravity="center_vertical" android:orientation="horizontal" - android:background="?android:attr/editTextBackground"> + android:background="?android:attr/searchViewTextField"> <ImageView android:id="@+id/search_app_icon" @@ -91,7 +95,7 @@ android:inputType="text|textAutoComplete" android:imeOptions="actionSearch" android:dropDownHeight="wrap_content" - android:dropDownAnchor="@id/search_plate" + android:dropDownAnchor="@id/search_edit_frame" android:dropDownVerticalOffset="0dip" android:dropDownHorizontalOffset="0dip" /> @@ -110,38 +114,39 @@ </LinearLayout> - </LinearLayout> - - <LinearLayout - android:id="@+id/submit_area" - android:orientation="horizontal" - android:layout_width="wrap_content" - android:layout_height="match_parent"> - - <ImageView - android:id="@+id/search_go_btn" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:paddingLeft="16dip" - android:paddingRight="16dip" - android:background="?android:attr/selectableItemBackground" - android:src="?android:attr/searchViewGoIcon" - android:visibility="gone" - android:focusable="true" - /> - - <ImageView - android:id="@+id/search_voice_btn" + <LinearLayout + android:id="@+id/submit_area" + android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:paddingLeft="16dip" - android:paddingRight="16dip" - android:src="?android:attr/searchViewVoiceIcon" - android:background="?android:attr/selectableItemBackground" - android:visibility="gone" - android:focusable="true" - /> + android:background="?android:attr/searchViewTextFieldRight"> + + <ImageView + android:id="@+id/search_go_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:background="?android:attr/selectableItemBackground" + android:src="?android:attr/searchViewGoIcon" + android:visibility="gone" + android:focusable="true" + /> + + <ImageView + android:id="@+id/search_voice_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:src="?android:attr/searchViewVoiceIcon" + android:background="?android:attr/selectableItemBackground" + android:visibility="gone" + android:focusable="true" + /> + </LinearLayout> </LinearLayout> + </LinearLayout> diff --git a/core/res/res/raw-xlarge/incognito_mode_start_page.html b/core/res/res/raw-xlarge/incognito_mode_start_page.html new file mode 100644 index 0000000..492658d --- /dev/null +++ b/core/res/res/raw-xlarge/incognito_mode_start_page.html @@ -0,0 +1,24 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/> + <title>New incognito tab</title> + </head> + <body> + <p><strong>You've gone incognito</strong>. Pages you view in this tab + won't appear in your browser history or search history, and they won't + leave other traces, like cookies, on your device after you close the + incognito tab. Any files you download or bookmarks you create will be + preserved, however.</p> + + <p><strong>Going incognito doesn't affect the behavior of other people, + servers, or software. Be wary of:</strong></p> + + <ul> + <li>Websites that collect or share information about you</li> + <li>Internet service providers or employers that track the pages you visit</li> + <li>Malicious software that tracks your keystrokes in exchange for free smileys</li> + <li>Surveillance by secret agents</li> + <li>People standing behind you</li> + </ul> + </body> +</html> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index e778340..e9261d9 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"محو بيانات الهاتف بدون تحذير، وذلك عبر إجراء إعادة الضبط بحسب بيانات المصنع"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تعيين الخادم الوكيل العمومي للجهاز"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"تعيين الخادم الوكيل العمومي للجهاز لكي يتم استخدامه أثناء تمكين السياسة. يعين مشرف الجهاز الأول فقط الخادم الوكيل العمومي الفعال."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"تعيين انتهاء صلاحية كلمة المرور"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"التحكم في الوقت المستغرق قبل الحاجة إلى تغيير كلمة مرور شاشة التوقف"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"ضبط انتهاء كلمة مرور تأمين شاشة"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"التحكم في عدد مرات تغيير كلمة مرور تأمين الشاشة"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تعيين تشفير التخزين"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"طلب تشفير بيانات التطبيق المخزنة"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 0e95bfb..d15baa9 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Изтриване на данните в телефона без предупреждение чрез възстановяване на фабричните настройки"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Задаване на глобален прокси сървър за устройството"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Задаване на глобалния прокси сървър, който да се използва, когато правилото е активирано. Само първият администратор на устройството задава действителния глобален прокси сървър."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Задаване на срок на валидност на паролата"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролирайте след колко време трябва да се променя паролата за заключване на екрана"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Изтичане на паролата"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролирайте колко често трябва да се променя паролата за заключен екран"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Шифроване за хранилището"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Изисква съхраняваните данни за приложенията да бъдат шифровани"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index daf0e37..263f1c4 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Esborra les dades del telèfon sense advertiment mitjançant un restabliment de les dades de fàbrica"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Defineix el servidor intermediari global del dispositiu"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Defineix el servidor intermediari global del dispositiu que cal utilitzar mentre la política estigui activada. Només el primer administrador del dispositiu pot definir el servidor intermediari global efectiu."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Defineix la caducitat de la contrasenya"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controla quant de temps abans de la pantalla de bloqueig cal canviar la contrasenya"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Defineix la caducitat de la contrasenya de bloqueig de pantalla"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controla la freqüència amb què cal canviar la contrasenya de bloqueig de pantalla"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptació d’emmagatzematge"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requereix que les dades de l\'aplicació emmagatzemades estiguin encriptades"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 58c7678..b93989f 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Bez upozornění smazat všechna data telefonu obnovením továrních dat"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastavit globální proxy server zařízení"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Vyberte globální proxy server, který se bude používat, když jsou zásady aktivní. Aktuální globální proxy server nastavuje pouze první správce zařízení."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavit konec platnosti hesla"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ovládání doby, po jejímž uplynutí je nutné změnit heslo pro odemknutí obrazovky"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavit vypršení hesla zámku"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Určuje, jak často je třeba měnit heslo pro uzamčení obrazovky"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavit šifrování úložiště"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Požadovat šifrování ukládaných dat"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 8dfc384..25246f6 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Slet telefonens data uden varsel ved at gendanne fabriksindstillinger"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Angiv enhedens globale proxy"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Angiv enhedens globale proxy, der skal bruges, mens politikken er aktiveret. Kun den første enhedsadministrator angiver den effektive globale proxy."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Angiv udløb for adgangskode"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontroller, hvor lang tid der skal gå, før adgangskoden til skærmlåsen skal ændres."</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Angiv udløb for skærmlåskoden"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Administrer, hvor tit skærmlåsens adgangskode skal skiftes"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angiv kryptering af lager"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kræv, at gemte programdata krypteres"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 881bf13..08f29ba 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Telefon ohne Warnung löschen"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Den globalen Proxy des Geräts festlegen"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Den bei aktivierter Richtlinie zu verwendenden globalen Proxy des Geräts festlegen. Nur der erste Geräteadministrator kann den gültigen globalen Proxy festlegen."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Ablauf des Passworts festlegen"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Zeitraum bis zur Änderung des Passworts für die Bildschirmsperre festlegen"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Ablauf von Sperr-Passwort festlegen"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Legen Sie fest, wie häufig das Passwort zum Sperren des Bildschirms geändert werden muss."</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Speicherverschlüsselung"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Anforderung, dass gespeicherte Anwendungsdaten verschlüsselt werden"</string> <string-array name="phoneTypes"> @@ -811,7 +811,7 @@ <string name="dialog_alert_title" msgid="2049658708609043103">"Achtung"</string> <string name="loading" msgid="1760724998928255250">"Wird geladen..."</string> <string name="capital_on" msgid="1544682755514494298">"EIN"</string> - <string name="capital_off" msgid="6815870386972805832">"Aus"</string> + <string name="capital_off" msgid="6815870386972805832">"AUS"</string> <string name="whichApplication" msgid="4533185947064773386">"Aktion durchführen mit"</string> <string name="alwaysUse" msgid="4583018368000610438">"Standardmäßig für diese Aktion verwenden"</string> <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Standardeinstellung zurücksetzen unter \"Einstellungen > Anwendungen > Anwendungen verwalten\""</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index ccd1c4c..8b9a8df 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Διαγραφή των δεδομένων του τηλεφώνου χωρίς προειδοποίηση με επαναφορά των εργοστασιακών δεδομένων"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ρύθμιση του γενικού διακομιστή μεσολάβησης της συσκευής"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ορίστε τη χρήση του γενικού διακομιστή μεσολάβησης της συσκευής όταν είναι ενεργοποιημένη η πολιτική. Μόνο ο διαχειριστής της πρώτης συσκευής ορίζει τον ισχύοντα γενικό διακομιστή μεσολάβησης."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Ορισμός λήξης κωδικού πρόσβασης"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ελέγξτε πόσος χρόνος απομένει προτού πρέπει να αλλάξετε τον κωδικό πρόσβασης κλειδώματος της οθόνης"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Ορισμός λήξης κωδ. κλειδ. οθ."</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Επιλέξτε πόσο συχνά θα πρέπει να αλλάζει ο κωδικός πρόσβασης κλειδώματος οθόνης"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ορισμός κρυπτογρ. αποθ. χώρου"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Να απαιτείται η κρυπτογράφηση των αποθηκευμένων δεδομένων εφαρμογής"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 90c52fc..0a511eb 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Erase the phone\'s data without warning by performing a factory data reset"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Set the device global proxy"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Set the device\'s global proxy to be used while policy is enabled. Only the first device admin sets the effective global proxy."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Set password expiry"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Control how long before lock-screen password needs to be changed"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Set lock-screen password expiry"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Control how frequently the lock-screen password must be changed"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Set storage encryption"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Require that stored application data be encrypted"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 68a225a..688565b 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -211,7 +211,7 @@ <string name="permlab_enableCarMode" msgid="5684504058192921098">"habilitar el modo de auto"</string> <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Permite que una aplicación habilite el modo auto."</string> <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"eliminar los procesos de fondo"</string> - <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Permite que una aplicación elimine los procesos de fondo de otras aplicaciones, aun si la memoria no es baja."</string> + <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Permite que una aplicación elimine los procesos de fondo de otras aplicaciones, aun si la no queda poco espacio en la memoria."</string> <string name="permlab_forceStopPackages" msgid="1447830113260156236">"forzar la detención de otras aplicaciones"</string> <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Permite que una aplicación provoque la detención de otras aplicaciones."</string> <string name="permlab_forceBack" msgid="1804196839880393631">"provocar que la aplicación se acerque"</string> @@ -257,7 +257,7 @@ <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite al propietario vincularse a la interfaz de nivel superior de un fondo de pantalla. Se debe evitar utilizarlo en aplicaciones normales."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string> <string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Permite al propietario vincularse a la interfaz de nivel superior del servicio de widget. Se debe evitar utilizarlo en aplicaciones normales."</string> - <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivo"</string> + <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivos"</string> <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permite que el propietario envíe sus intentos a un administrador de dispositivos. No se necesita para las aplicaciones normales."</string> <string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar la orientación de la pantalla"</string> <string name="permdesc_setOrientation" msgid="6335814461615851863">"Admite una aplicación que cambia la rotación de la pantalla en cualquier momento. Se debe evitar utilizarlo en aplicaciones normales."</string> @@ -277,12 +277,12 @@ <string name="permdesc_installPackages" msgid="526669220850066132">"Admite una aplicación que instala paquetes de Android nuevos o actualizados. Las aplicaciones maliciosas pueden utilizarlo para agregar aplicaciones nuevas con permisos arbitrariamente potentes."</string> <string name="permlab_clearAppCache" msgid="4747698311163766540">"eliminar todos los datos de memoria caché de la aplicación"</string> <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite que una aplicación libere espacio de almacenamiento en el tablet eliminando archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string> - <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Admite una aplicación que libera espacio de almacenamiento en el teléfono al eliminar archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string> + <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Permite que una aplicación libere espacio de almacenamiento en el teléfono borrando archivos del directorio de memoria caché de la aplicación. En general el acceso está muy restringido al proceso del sistema."</string> <string name="permlab_movePackage" msgid="728454979946503926">"Mover recursos de la aplicación"</string> <string name="permdesc_movePackage" msgid="6323049291923925277">"Permite a una aplicación mover recursos de aplicación de medios internos a externos y viceversa."</string> <string name="permlab_readLogs" msgid="6615778543198967614">"lee los datos confidenciales del registro"</string> <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permite que una aplicación lea diversos archivos de registro del sistema. Esto le permite descubrir información general acerca de lo que haces con el tablet, y puede potencialmente incluir información personal o privada."</string> - <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Admite una aplicación que lee diversos archivos de registro del sistema. Esto te permite descubrir información general acerca de lo que haces con el teléfono, y puede potencialmente incluir información personal o privada."</string> + <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Permite que una aplicación lea los diversos archivos de registro del sistema. Esto le permite descubrir información general acerca de lo que haces con el teléfono, y puede potencialmente incluir información personal o privada."</string> <string name="permlab_diagnostic" msgid="8076743953908000342">"leer y escribir a recursos dentro del grupo de diagnóstico"</string> <string name="permdesc_diagnostic" msgid="3121238373951637049">"Admite una aplicación que lee y escribe a cualquier recurso dentro del grupo de diagnóstico; por ejemplo, archivos con /dev. Esto puede afectar potencialmente la estabilidad y la seguridad del sistema. Debe utilizarlo SÓLO el fabricante o el operador en los diagnósticos específicos del hardware."</string> <string name="permlab_changeComponentState" msgid="79425198834329406">"activar o desactivar componentes de la aplicación"</string> @@ -296,15 +296,15 @@ <string name="permdesc_writeSecureSettings" msgid="5497873143539034724">"Permite a una aplicación modificar los datos de la configuración segura de los sistemas. Las aplicaciones normales no deben utilizarlo."</string> <string name="permlab_writeGservices" msgid="2149426664226152185">"modificar el mapa de servicios de Google"</string> <string name="permdesc_writeGservices" msgid="6602362746516676175">"Admite una aplicación que modifica el mapa de servicios de Google. Las aplicaciones normales no deben utilizarlo."</string> - <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"iniciar automáticamente durante la inicialización"</string> + <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"ejecutar automáticamente al iniciar"</string> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Permite que una aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que el tablet demore más en inicializar y que la aplicación retarde el funcionamiento total del tablet al estar en ejecución constante."</string> - <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Admite una aplicación que se inicia cuando el sistema haya finalizado la inicialización. Esto puede ocasionar que se demore más tiempo en inicializar el teléfono y que la aplicación retarde el funcionamiento total del teléfono al estar en ejecución constante."</string> + <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Permite que una aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que el teléfono tarde más en inicializarse y que la aplicación demore el funcionamiento total del teléfono al estar en ejecución constante."</string> <string name="permlab_broadcastSticky" msgid="7919126372606881614">"enviar emisiones pegajosas"</string> <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permite que una aplicación envíe emisiones adhesivas, que permanecen luego de que finaliza la emisión. Las aplicaciones maliciosas pueden hacer que la tableta funcione más lento y esté inestable haciendo que utilicen demasiada memoria."</string> <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Admite una aplicación que envía emisiones pegajosas, las cuales permanecen luego de que finaliza la emisión. Las aplicaciones maliciosas pueden hacer lento e inestable al teléfono, ya que ocasiona que utilice demasiada memoria."</string> <string name="permlab_readContacts" msgid="6219652189510218240">"leer datos de contacto"</string> <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permite que una aplicación lea todos los datos de de contacto (direcciones) almacenados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para enviar tus datos a otras personas."</string> - <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Admite una aplicación que lee todos los datos de (direcciones) de contactos almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string> + <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Permite que una aplicación lea todos los datos (direcciones) de contactos almacenados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para enviar tus datos a otras personas."</string> <string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string> <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de (dirección) guardados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string> <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Admite una aplicación que modifica los datos de (dirección de) contacto guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string> @@ -340,9 +340,9 @@ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permite que la aplicación desactive todo el tablet de manera permanente. Esto es muy peligroso."</string> <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Admite que la aplicación desactive todo el teléfono de manera permanente. Esto es muy peligroso."</string> <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forzar reinicio del tablet"</string> - <string name="permlab_reboot" product="default" msgid="2898560872462638242">"provocar el reinicio del teléfono"</string> + <string name="permlab_reboot" product="default" msgid="2898560872462638242">"forzar reinicio del teléfono"</string> <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permite que la aplicación provoque el reinicio del tablet."</string> - <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Admite que la aplicación provoque que el teléfono se reinicie."</string> + <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Permite que la aplicación fuerce el reinicio del tablet."</string> <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"montar y desmontar filesystems"</string> <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Admite que la aplicación monte y desmonte filesystems para obtener almacenamiento extraíble."</string> <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"espacio de almacenamiento externo del formato"</string> @@ -374,7 +374,7 @@ <string name="permlab_callPrivileged" msgid="4198349211108497879">"llamar directamente a cualquier número de teléfono"</string> <string name="permdesc_callPrivileged" msgid="244405067160028452">"Admite que la aplicación llame a cualquier número de teléfono, incluidos los números de emergencia, sin tu intervención. Las aplicaciones maliciosas pueden realizar llamadas innecesarias e ilegales a los servicios de emergencia."</string> <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar directamente la configuración CDMA del tablet"</string> - <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"comienza directamente la configuración CDMA del teléfono"</string> + <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente la configuración CDMA del teléfono"</string> <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Admite la aplicación para comenzar con el aprovisionamiento CDMA. Las aplicaciones maliciosas pueden comenzar con el aprovisionamiento CDMA sin necesidad."</string> <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar las notificaciones de actualización de ubicación"</string> <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Permite activar y desactivar las notificaciones de actualización de ubicación de la radio. Las aplicaciones normales no deben utilizarlo."</string> @@ -429,7 +429,7 @@ <string name="permlab_changeNetworkState" msgid="958884291454327309">"cambiar la conectividad de la red"</string> <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Permite que una aplicación cambie el estado de la conectividad de red."</string> <string name="permlab_changeTetherState" msgid="2702121155761140799">"Cambiar la conectividad de anclaje a red"</string> - <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Permite que una aplicación cambie el estado de la conectividad de red del anclaje."</string> + <string name="permdesc_changeTetherState" msgid="8905815579146349568">"ermite que una aplicación cambie el estado de la conectividad de anclaje a red."</string> <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"cambiar la configuración del uso de datos del fondo"</string> <string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Admite una aplicación que cambia la configuración del uso de datos del fondo."</string> <string name="permlab_accessWifiState" msgid="8100926650211034400">"ver el estado de Wi-Fi"</string> @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Borrar los datos del teléfono sin advertencias al restablecer la configuración original"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Configura el proxy global de dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Configuración del proxy global de dispositivo que se utilizará mientras se habilita la política. Sólo la primera administración de dispositivo configura el proxy global efectivo."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Establecer la caducidad de la contraseña"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Verifica cuánto tiempo antes debes cambiar la contraseña de la pantalla de bloqueo"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Establecer la caducidad del bloqueo de pantalla"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar cuán a menudo se debe cambiar la contraseña de bloqueo de pantalla"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Establecer la encriptación del almacenamiento"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requiere que los datos almacenados de la aplicación estén encriptados"</string> <string-array name="phoneTypes"> @@ -835,7 +835,7 @@ <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> se inició originalmente."</string> <string name="smv_application" msgid="295583804361236288">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha violado su política StrictMode autoimpuesta."</string> <string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha violado su política StrictMode autoimpuesta."</string> - <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> Correr"</string> + <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string> <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Selecciona cambiar la aplicación"</string> <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"¿Deseas cambiar aplicaciones?"</string> <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Ya se está ejecutando una aplicación que debe detenerse antes de iniciar una nueva."</string> @@ -923,17 +923,17 @@ <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Almacenamiento USB dañado. Es posible que debas reformatearlo."</string> <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Tarjeta SD dañada. Es posible que debas reformatearla."</string> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Almacenamiento USB extraído inesperadamente"</string> - <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Tarjeta SD extraída de forma imprevista"</string> + <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Almacenamiento USB extraído de forma imprevista"</string> <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desmontar el almacenamiento USB antes de extraerlo para evitar la pérdida de datos."</string> <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Es seguro extraer el almacenamiento USB"</string> - <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Tarjeta SD fácil de extraer"</string> + <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Es seguro extraer la tarjeta SD"</string> <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Puedes extraer de forma segura el almacenamiento USB."</string> - <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes eliminar la tarjeta SD sin riesgos."</string> + <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes extraer de forma segura la tarjeta SD."</string> <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Almacenamiento USB extraído"</string> <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Tarjeta SD extraída"</string> <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Almacenamiento USB eliminado. Insertar nuevos medios."</string> - <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Tarjeta SD eliminada. Inserta una nueva."</string> + <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Tarjeta SD extraída. Insertar una nueva."</string> <string name="activity_list_empty" msgid="4168820609403385789">"No se encontraron actividades coincidentes"</string> <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar la estadística de uso de los componentes"</string> <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Permite la modificación de estadísticas recopiladas sobre el uso de componentes. Las aplicaciones normales no deben utilizarlo."</string> @@ -966,8 +966,8 @@ <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string> <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocolo de túnel punto a punto"</string> <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de nivel 2"</string> - <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Clave previamente compartida según L2TP/IPSec VPN"</string> - <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certificado según L2TP/IPSec VPN"</string> + <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basada en clave compartida previamente"</string> + <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basada en certificado"</string> <string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No se seleccionó un archivo."</string> <string name="reset" msgid="2448168080964209908">"Restablecer"</string> @@ -995,7 +995,7 @@ <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Borrando almacenamiento USB..."</string> <string name="progress_erasing" product="default" msgid="2115214724367534095">"Borrando tarjeta SD..."</string> <string name="format_error" product="nosdcard" msgid="4320339096529911637">"No pudo borrar el almacenamiento USB."</string> - <string name="format_error" product="default" msgid="1343380371925238343">"No pudo borrar la tarjeta SD."</string> + <string name="format_error" product="default" msgid="1343380371925238343">"No se pudo borrar la tarjeta SD."</string> <string name="media_bad_removal" msgid="7960864061016603281">"Se ha extraído la tarjeta SD antes de ser desmontada."</string> <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Se está verificando el almacenamiento USB en este momento."</string> <string name="media_checking" product="default" msgid="7334762503904827481">"Se está verificando la tarjeta SD en este momento."</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 82b774b..9ab0169 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Borrado de los datos del teléfono sin avisar restableciendo datos de fábrica"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir el servidor proxy global"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Define el servidor proxy global que se debe utilizar mientras la política esté habilitada. Solo el primer administrador de dispositivos define el servidor proxy global efectivo."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Definir caducidad de contraseña"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Permite controlar cuándo se debe cambiar la contraseña de bloqueo de la pantalla."</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Definir caducidad bloqueo pantalla"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar la frecuencia con la que se debe cambiar el bloqueo de pantalla"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptación de almacenamiento"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exige que se encripten los datos de la aplicación almacenados."</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index d8451e0..655f250 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"پاک کردن داده های گوشی بدون هشدار با انجام یک عملکرد بازنشانی داده های کارخانه"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تنظیم پروکسی جهانی دستگاه"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"پروکسی جهانی دستگاه مورد نظر را جهت استفاده هنگام فعال بودن خط مشی تنظیم کنید. فقط اولین سرپرست دستگاه پروکسی جهانی مفید را تنظیم می کند."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"کنترل مدت زمانی که رمز ورود صفحه قفل قبل از تغییر یافتن لازم دارد"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود قفل صفحه"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"کنترل تعداد دفعات تغییر رمز ورود قفل صفحه"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"نیاز به رمزگذاری داده های برنامه کاربردی ذخیره شده دارد"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index eab76b3..28312a1 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Tyhjennä puhelimen tiedot varoituksetta palauttamalla tehdasasetukset."</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Aseta laitteen yleinen välityspalvelin"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Aseta laitteen yleinen välityspalvelin käyttöön, kun käytäntö on käytössä. Vain ensimmäinen laitteen järjestelmänhallitsija voi asettaa käytettävän yleisen välityspalvelimen."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Aseta salasanan voimassaoloaika"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Valitse, kuinka pian ruudunlukituksen poiston salasana tulee vaihtaa"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Aseta ruudunlukituksen salasanan voimassaoloaika"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Määritä, miten usein ruudunlukituksen salasana tulee vaihtaa"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Aseta tallennustilan salaus"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pakota tallennettujen sovellustietojen salaus"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index cba5a15..7a6c43a 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -160,7 +160,7 @@ <string name="permgroupdesc_messages" msgid="7045736972019211994">"Permet de lire et rédiger vos SMS, e-mails et autres messages."</string> <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vos informations personnelles"</string> <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accéder directement aux contacts et à l\'agenda enregistrés sur la tablette"</string> - <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accédez directement aux contacts et à l\'agenda enregistrés sur votre téléphone."</string> + <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accéder directement aux contacts et à l\'agenda enregistrés sur votre téléphone"</string> <string name="permgrouplab_location" msgid="635149742436692049">"Votre position"</string> <string name="permgroupdesc_location" msgid="2430258821648348660">"Suivre votre position géographique"</string> <string name="permgrouplab_network" msgid="5808983377727109831">"Communications réseau"</string> @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Effacer les données du téléphone sans avertissement, en restaurant la configuration usine"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Définir le proxy global du mobile"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Indiquer le proxy global à utiliser pour ce mobile lorsque les règles sont activées. Seul l\'administrateur principal du mobile peut définir le proxy global utilisé."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Définir la date d\'expiration du mot de passe"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Définir la fréquence de changement du mot de passe de verrouillage d\'écran"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Définir exp. mot passe verr."</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Contrôler la fréquence de modification du mot de passe de verrouillage de l\'écran"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Définir cryptage du stockage"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exiger que les données d\'application stockées soient cryptées"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index cd69188..860bec9 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Izbriši podatke telefona bez upozorenja vraćanjem u tvorničko stanje"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"postavi globalni proxy uređaja"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Postavi globalni proxy uređaja za upotrebu dok su pravila omogućena. Samo prvi administrator uređaja postavlja djelotvoran globalni proxy."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Postavi istek zaporke"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nadzirite za koliko vremena zaporka za zaključani zaslon treba biti promijenjena"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Post. istek zap. zaklj. zasl."</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nadzirite koliko se često mora mijenjati zaporka za zaključavanje zaslona"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Postavi enkripciju za pohranu"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Zahtijevaj da pohranjeni podaci aplikacije budu kriptirani"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index c2a976f..f962f35 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Figyelmeztetés nélkül törli a telefon összes adatát, visszaállítva a gyári adatokat"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Az eszköz globális proxyjának beállítása"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Az eszköz globális proxyja lesz használatban, amíg az irányelv engedélyezve van. Csak az eszköz első rendszergazdája állíthatja be a tényleges globális proxyt."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Jelszó lejáratának beállítása"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Azt vezérli, mennyi időnként kell módosítani a képernyőt zároló jelszót"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Képernyőjelszó érvényessége"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Adja meg, hogy milyen gyakran kell módosítani a képernyőzár jelszavát"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Tárhelytitkosítás beállítása"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Megköveteli a tárolt alkalmazásadatok titkosítását"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 19a5cc4..7b10651 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Hapus data ponsel tanpa peringatan, dengan menyetel ulang data pabrik"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Setel proxy global perangkat"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Setel proxy global perangkat yang akandigunakan ketika kebijakan diaktifkan. Hanya admin perangkat pertama yang menyetel procy global yang berlaku."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Setel waktu kedaluwarsa sandi"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrol berapa lama sebelum sandi penguncian layar perlu diubah"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Setel kedaluwarsa sandi pengunci layar"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrol seberapa sering sandi pengunci layar harus diganti"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setel enkripsi penyimpanan"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Mengharuskan data aplikasi yang disimpan untuk dienkripsi"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 83da3be..76b6d1d 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Cancella i dati del telefono senza preavviso eseguendo un ripristino dati di fabbrica"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Imposta il proxy globale del dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Imposta il proxy globale del dispositivo in modo da utilizzarlo mentre la norma è attiva. Il proxy globale effettivo è impostabile solo dal primo amministratore del dispositivo."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Imposta scadenza password"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabilisci la scadenza della password di blocco dello schermo"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Imposta scadenza password blocco schermo"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabilisci la frequenza di modifica della password di blocco dello schermo"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Imposta crittografia archivio"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Richiede la crittografia dei dati applicazione memorizzati"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 2ee3b7c..1b597c8 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"מחק את נתוני הטלפון ללא אזהרה, על ידי ביצוע איפוס נתוני יצרן"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"הגדר את שרת ה-proxy הגלובלי של ההתקן"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"הגדר את שרת proxy הגלובלי של ההתקן לשימוש כאשר המדיניות מופעלת. רק מנהל ההתקן הראשון מגדיר את שרת ה-proxy הגלובלי הפעיל."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"הגדר תפוגת תוקף של סיסמה"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"שלוט בפרק הזמן הדרוש לשינוי הסיסמה של נעילת המסך"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"הגדר תאריך תפוגה לסיסמה של נעילת המסך"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"שלוט בתדירות שבה הסיסמה של נעילת המסך חייבת להשתנות"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"הגדר הצפנת אחסון"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"דורש שנתוני היישום המאוחסנים יהיו מוצפנים"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 04ee3a5..7594744 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"警告せずにデータの初期化を実行して端末内のデータを消去します。"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"端末のグローバルプロキシを設定"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ポリシーが有効になっている場合は端末のグローバルプロキシが使用されるように設定します。有効なグローバルプロキシを設定できるのは最初のデバイス管理者だけです。"</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"パスワードの有効期限の設定"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"画面ロックパスワードの変更が必要になるまでの期間を指定します"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"解除パスワードの有効期限の設定"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"ロック解除パスワードの変更が必要になる頻度を指定します"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ストレージ暗号化の設定"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"保存したアプリケーションデータが暗号化されるようにする"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 71c1b90..a718344 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"공장 초기화를 수행하여 경고 없이 휴대전화 데이터를 지웁니다."</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"기기 전체 프록시 설정"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"정책이 사용 설정되어 있는 동안 사용될 기기 전체 프록시를 설정합니다. 첫 번째 기기 관리자가 설정한 전체 프록시만 유효합니다."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"비밀번호 만료 설정"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"화면 잠금 비밀번호를 변경해야 하는 기간 변경"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"화면 잠금 비밀번호 만료 설정"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"화면 잠금 비밀번호 변경 빈도 설정"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"저장소 암호화 설정"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"저장한 애플리케이션 데이터를 암호화해야 합니다."</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 32f2bf7..2580af9 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Be įspėjimo ištrinti telefono duomenis iš naujo nustatant gamyklinius duomenis"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nustatyti įrenginio bendrąjį tarpinį serverį"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Nustatyti įrenginio bendrąjį tarpinį serverį, kad būtų naudojamas, kol įgalinta politika. Tik pirmasis įrenginio administratorius nustato efektyvų bendrąjį tarpinį serverį."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Nustatyti slaptažodžio galiojimo pabaigą"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Valdyti, per kiek laiko iki ekrano užrakinimo turi būti pakeistas slaptažodis"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Nust. ekr. užr. slapt. gal. pab."</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Valdykite, kaip dažnai reikia keisti ekrano užrakto slaptažodį"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nustatyti atmintinės šifruotę"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Saugomos programos duomenys turi būti šifruoti"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 77fb533..b7adf2d 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Dzēš tālruņa datus bez brīdinājuma, veicot rūpnīcas datu atiestatīšanu"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Iestatīt ierīces globālo starpniekserveri"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Iestatiet izmantojamo ierīces globālo starpniekserveri, kad ir iespējota politika. Spēkā esošo globālo starpniekserveri iestata tikai pirmās ierīces administrators."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Paroles beigu termiņa iestatīšana"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolē ekrāna bloķēšanas paroles maiņas intervālu"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Ekr. bloķ. paroles term. iest."</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolē, cik bieži ir jāmaina ekrāna bloķēšanas parole."</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Skatīt atmiņas šifrējumu"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pieprasīt, lai saglabātie lietojumprogrammas dati tiktu šifrēti"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index e010d7a..d3463fd 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Tilbakestill telefonens data uten advarsel ved å utføre tilbakestilling til fabrikkstandard"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Angi enhetens globale mellomtjener"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Angir den globale mellomtjeneren på enheten som skal brukes når regelen er aktivert. Kun den opprinnelige administratoren av enheten kan angi den globale mellomtjeneren."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Angi utløpsdato for passordet"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Velg hvor lenge det skal gå før passordet til låseskjermen må byttes"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Angi utløpsdato for skjermlåspassordet"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Velg hvor lenge det skal gå før passordet til skjermlåsen må byttes"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angi lagringskryptering"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Krever at lagrede programdata krypteres"</string> <string-array name="phoneTypes"> @@ -924,7 +924,7 @@ <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Minnekortet er skadet. Du må kanskje formatere det."</string> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-lagring fjernet uventet"</string> <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Minnekortet ble tatt ut uventet"</string> - <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Koble fra USB-lagring før enheten tas ut av maskinen for å unngå tap av data."</string> + <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Koble fra USB-enheten før du tar den ut for å unngå tap av data."</string> <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Avmonter minnekortet før det tas ut, for å unngå datatap."</string> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-lagring kan trygt fjernes"</string> <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Trygt å ta ut minnekort"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index cc24b00..68ab40c 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"De gegevens van de telefoon zonder waarschuwing wissen door de fabrieksinstellingen te herstellen"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Algemene proxy voor het apparaat instellen"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Stel de algemene proxy voor het apparaat in die moet worden gebruikt terwijl het beleid is geactiveerd. Alleen de eerste apparaatbeheerder stelt de algemene proxy in."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Verval wachtwoord instellen"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Beheren hoe lang het duurt voordat het wachtwoord voor schermvergrendeling moet worden gewijzigd"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Verval wachtwoord instellen"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Beheren hoe vaak het wachtwoord voor schermvergrendeling moet worden gewijzigd"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Codering voor opslag instellen"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vereisen dat opgeslagen toepassingsgegevens kunnen worden gecodeerd"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 5ee4216..4c5f062 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Wymazywanie danych z telefonu bez ostrzeżenia, przez przywrócenie danych fabrycznych"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ustaw globalny serwer proxy urządzenia"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ustaw globalny serwer proxy urządzenia do wykorzystywania przy włączonych zasadach. Tylko pierwszy administrator urządzenia ustawia obowiązujący globalny serwer proxy."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Ustaw wygasanie hasła"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrola czasu, po którym należy zmienić hasło blokowania ekranu"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Ustaw wygasanie hasła blokady"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrola częstości zmian hasła ekranu blokady"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ustaw szyfrowanie pamięci"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Wymaga szyfrowania danych zapisanych aplikacji"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 855b966..014bf88 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Apagar os dados do telefone sem avisar, ao efectuar uma reposição de dados de fábrica"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir o proxy global do aparelho"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Definir o proxy global do aparelho a ser utilizado quando a política estiver activada. Só o primeiro administrador do aparelho define o proxy global efectivo."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Definir tempo de validade da palavra-passe"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controle com que antecedência é necessário alterar a palavra-passe de bloqueio do ecrã"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Def. valid. palavra-passe bloq. ecrã"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a palavra-passe deve ser alterada"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Def. encriptação armazenamento"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requerer encriptação dos dados da aplicação armazenados"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index ba3600e..07907fb 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Apaga os dados do telefone sem aviso, executando uma redefinição da configuração original"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir o proxy global do dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Configura o proxy global do dispositivo para ser usado enquanto a política estiver ativada. Somente o primeiro administrador do dispositivo pode configurar um verdadeiro proxy global."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Definir validade da senha"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controle quanto tempo uma senha de bloqueio de tela deve ficar ativa antes de ser alterada"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Definir val. da senha de bloqueio"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a senha da tela de bloqueio deve ser alterada"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Definir criptografia de armazenamento"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exigir que os dados do aplicativo armazenado sejam criptografados"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 4d29c25..59fc5c9 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Ştergeţi datele din telefon fără avertisment, efectuând resetarea configurării din fabrică"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Setaţi serverul proxy global pentru dispozitiv"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Setaţi serverul proxy global pentru dispozitiv care să fie utilizat cât timp politica este activă. Numai primul administrator al dispozitivului poate seta serverul proxy global activ."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Setaţi expirarea parolei"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlarea duratei până când parola de blocare a ecranului trebuie modificată"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Expirare parolă blocare ecran"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabiliţi frecvenţa de schimbare a parolei de blocare a ecranului"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setaţi criptarea stocării"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Necesită ca datele aplicaţiei stocate să fie criptate"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 541f414..c4e68a9 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Уничтожить все данные на телефоне без предупреждения путем сброса настроек"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Глобальный прокси-сервер"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Настройте глобальный прокси-сервер устройства, который будет использоваться при активной политике. Глобальный прокси-сервер должен настроить первый администратор устройства."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Задать время действия пароля"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Задать время действия пароля перед появлением экрана блокировки"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Задать срок действия пароля"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Укажите, как часто следует менять пароль блокировки экрана"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Настроить шифрование хранилища"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Требует шифровать данные приложений, находящиеся в хранилище."</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index a97876d..5d10d27 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Bez predchádzajúceho upozornenia zmazať všetky údaje tým, že sa obnovia továrenské nastavenia telefónu"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastaviť globálny server proxy zariadenia"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Vyberte globálny server proxy, ktorý sa bude používať po aktivácii pravidiel. Platný globálny server proxy nastavuje iba prvý správca zariadenia."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Nastaviť dátum vypršania platnosti hesla"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ovládanie doby, po uplynutí ktorej treba zmeniť heslo na odomknutie obrazovky"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Nastav. koniec platnosti hesla"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nastavte, ako často sa musí zmeniť heslo na uzamknutie obrazovky"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastaviť šifr. ukl. priestoru"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vyžaduje šifrovanie uložených údajov aplikácií"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 4e9a739..3d003fb 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Brisanje (s tovarniško ponastavitvijo) vseh podatkov v telefonu brez opozorila"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastavitev globalnega strežnika proxy za napravo"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Nastavite globalni strežnik proxy naprave, ki bo v uporabi, ko je pravilnik omogočen. Samo skrbnik prve naprave lahko nastavi veljaven globalni strežnik proxy."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavitev poteka gesla"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nastavite, koliko časa prej je treba spremeniti geslo za odklepanje zaslona"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavitev poteka gesla za zaklepanje zaslona"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Določite, kako pogosto je treba spremeniti geslo za zaklepanje zaslona"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavitev šifriranja shrambe"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Shranjeni podatki programa morajo biti šifrirani"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 7377cd9..a8d9e29 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Брисање података на телефону без упозорења враћањем фабричких података"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Подесите глобални прокси сервер уређаја"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Подесите глобални прокси сервер уређаја који ће се користити док су омогућене смернице. Само први администратор уређаја поставља ефективни глобални прокси сервер."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Подеси време истека лозинке"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролишите време када лозинка за закључавање екрана треба да се промени"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Подешавање истека лозинке екрана"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролишите колико често лозинка за закључавање екрана мора да се мења"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Подешавање шифровања складишта"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Захтева да сачувани подаци апликације буду шифровани"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 5c1c3d8..9b93047 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Ta bort data från telefonen utan förvarning genom att återställa standardinställningarna"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ange global proxyserver"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ange vilken global proxyserver som ska användas när policyn är aktiverad. Endast den första enhetsadministratören anger den faktiska globala proxyservern."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Ange lösenordets utgångsdatum"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Se hur långt det är kvar till du måste ändra lösenordet till låsningsskärmen"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Ange lösenordets utgångsdatum"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Styr hur ofta lösenordet till skärmlåset måste ändras"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ange krypterad lagring"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kräv att sparade applikationsdata krypteras."</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index cebae1c..62dfc29 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"ลบข้อมูลของโทรศัพท์โดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์ที่จะใช้ขณะเปิดการใช้งานนโยบาย เฉพาะผู้ดูแลอุปกรณ์คนแรกเท่านั้นที่ตั้งค่าพร็อกซีส่วนกลางที่มีผลบังคับ"</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"ตั้งค่าการหมดอายุของรหัสผ่าน"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"ควบคุมระยะเวลาก่อนที่จะต้องเปลี่ยนรหัสผ่านการล็อกหน้าจอ"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"ตั้งค่าวันหมดอายุของรหัสผ่านล็อกหน้าจอ"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"ควบคุมความถี่ในการเปลี่ยนรหัสผ่านล็อกหน้าจอ"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ตั้งค่าการเข้ารหัสที่เก็บข้อมูล"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"กำหนดว่าแอปพลิเคชันที่จัดเก็บต้องมีการเข้ารหัส"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index a9a90ee..08c3ff7 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Burahin ang data ng telepono nang walang babala, sa pamamagitan ng pagsasagawa ng pag-reset sa data ng factory"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Itakda ang pandaigdigang proxy ng device"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Itakda ang pandaigdigang proxy ng device na gagamitin habang pinagana ang patakaran. Tanging ang unang admin ng device ang magtatakda sa may bisang pandaigdigang proxy."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Itakda pag-expire ng password"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolin kung gaano katagal bago kailangang palitan ang password sa pag-lock ng screen"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Itakda expire password pag-lock scr"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolin kung gaano kadalas dapat na mapalitan ang password sa pag-lock ng screen"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Itakda pag-encrypt ng imbakan"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Hinging naka-encrypt ang nakaimbak na data ng application"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 066aae9..0b0ef01 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek telefondaki verileri uyarıda bulunmadan silin"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Cihaz genelinde geçerli proxy\'i ayarla"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Politika etkin olduğunda kullanılacak cihaz genelinde geçerli proxy\'yi ayarlayın. Etkin genel proxy\'yi yalnızca ilk cihaz yöneticisi ayarlar."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Şifre süre sonu tarihi ayarla"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ekran kilitleme şifresinin ne kadar süre sonra değiştirilmesi gerekeceğini denetleyin."</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Ekr kilt şifr süre sonu ayarla"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ekran kilitleme şifresinin hangi sıklıkla değiştirilmesi gerektiğini denetleyin"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Deplm şifrelemesini ayarla"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Depolanan uygulama verisinin şifrelenmiş olmasını gerektir"</string> <string-array name="phoneTypes"> @@ -828,7 +828,7 @@ <string name="anr_application_process" msgid="4185842666452210193">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması (<xliff:g id="PROCESS">%2$s</xliff:g> işleminde) yanıt vermiyor."</string> <string name="anr_process" msgid="1246866008169975783">"<xliff:g id="PROCESS">%1$s</xliff:g> işlemi yanıt vermiyor."</string> <string name="force_close" msgid="3653416315450806396">"Kapanmaya zorla"</string> - <string name="report" msgid="4060218260984795706">"Rapor"</string> + <string name="report" msgid="4060218260984795706">"Bildir"</string> <string name="wait" msgid="7147118217226317732">"Bekle"</string> <string name="launch_warning_title" msgid="8323761616052121936">"Uygulama yönlendirildi"</string> <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> şimdi çalışıyor."</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index bdfb444..eabbea1 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Видаляє дані телефону без попередження, відновлюючи заводські налаштування"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Установ. глоб. проксі пристрою"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Устан. використ. глоб. проксі, коли ввімкнено політику. Лише адміністратор першого пристрою встановлює активний глоб. проксі."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Установити термін дії пароля"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Регулює, за скільки часу перед блокуванням екрана треба змінювати пароль"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Установити термін дії пароля блокування екрана"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролювати частоту зміни пароля блокування екрана"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Установити шифрування носія"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Потрібно, щоб дані збереженої програми були зашифровані"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 8019069..812004b 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Xóa dữ liệu trên điện thoại mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Đặt proxy chung của điện thoại"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Đặt proxy chung của điện thoại được sử dụng trong khi chính sách được bật. Chỉ quản trị viên đầu tiên của điện thoại mới có thể đặt proxy chung hiệu quả."</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Đặt hết hạn mật khẩu"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kiểm soát thời lượng trước khi mật khẩu khóa màn hình cần được thay đổi"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"Đặt hết hạn mật khẩu khóa màn hình"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kiểm soát tần suất bắt buộc phải thay đổi mật khẩu khóa màn hình"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Đặt mã hóa dung lượng lưu trữ"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Yêu cầu dữ liệu ứng dụng được lưu trữ phải được mã hóa"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 072dcc1..3b70dd7 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"恢复出厂设置时,将擦除手机上的数据而不发送警告"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"设置设备全局代理"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"请设置在启用政策的情况下要使用的设备全局代理。只有第一设备管理员才可设置有效的全局代理。"</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"设置密码有效期"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制屏幕锁定密码的使用期限"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"设置锁定屏幕密码的有效期"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制锁定屏幕密码的更改频率"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"设置存储设备加密"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"需要对存储的应用程序数据进行加密"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index ec515bc..e72b28e 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -486,8 +486,8 @@ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"執行重設為原廠設定時,系統會直接清除手機資料而不提出警告"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"設定裝置全域 Proxy"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"設定政策啟用時所要使用的裝置全域 Proxy,只有第一個裝置管理員所設定的全域 Proxy 具有效力。"</string> - <!-- outdated translation 4740941403188940274 --> <string name="policylab_expirePassword" msgid="885279151847254056">"設定密碼到期日"</string> - <!-- outdated translation 6626724939177185949 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制螢幕鎖定密碼的使用期限"</string> + <string name="policylab_expirePassword" msgid="885279151847254056">"設定螢幕上鎖密碼到期日"</string> + <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制螢幕上鎖密碼的變更頻率"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"設定儲存裝置加密"</string> <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"必須為儲存的應用程式資料加密"</string> <string-array name="phoneTypes"> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index f363bd3..71a8b2a 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -729,6 +729,10 @@ <attr name="searchViewEditQuery" format="reference" /> <!-- SearchView query refinement icon background --> <attr name="searchViewEditQueryBackground" format="reference" /> + <!-- SearchView text field background for the left section --> + <attr name="searchViewTextField" format="reference" /> + <!-- SearchView text field background for the right section --> + <attr name="searchViewTextFieldRight" format="reference" /> <!-- Specifies a drawable to use for the 'home as up' indicator. --> <attr name="homeAsUpIndicator" format="reference" /> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 41ee55a..11c3916 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -982,7 +982,7 @@ <eat-comment /> <style name="MediaButton"> - <item name="android:background">@android:drawable/media_button_background</item> + <item name="android:background">@null</item> <item name="android:layout_width">71dip</item> <item name="android:layout_height">52dip</item> </style> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index b7cc7f9..5f4ea32 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -285,6 +285,8 @@ <!-- SearchView attributes --> <item name="searchDropdownBackground">@android:drawable/spinner_dropdown_background</item> + <item name="searchViewTextField">@drawable/textfield_searchview_holo_dark</item> + <item name="searchViewTextFieldRight">@drawable/textfield_searchview_right_holo_dark</item> <item name="searchViewCloseIcon">@android:drawable/ic_clear</item> <item name="searchViewSearchIcon">@android:drawable/ic_search</item> <item name="searchViewGoIcon">@android:drawable/ic_go</item> @@ -393,6 +395,8 @@ <!-- SearchView attributes --> <item name="searchDropdownBackground">@android:drawable/search_dropdown_light</item> + <item name="searchViewTextField">@drawable/textfield_searchview_holo_light</item> + <item name="searchViewTextFieldRight">@drawable/textfield_searchview_right_holo_light</item> <item name="searchViewCloseIcon">@android:drawable/ic_clear_holo_light</item> <item name="searchViewSearchIcon">@android:drawable/ic_search_api_holo_light</item> <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_holo_light</item> diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java index 5b76e39..d23dfd3 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java @@ -19,6 +19,7 @@ package com.android.connectivitymanagertest; import android.os.Bundle; import android.test.InstrumentationTestRunner; import android.test.InstrumentationTestSuite; + import com.android.connectivitymanagertest.stress.WifiApStress; import com.android.connectivitymanagertest.stress.WifiStressTest; @@ -44,8 +45,13 @@ public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunn @Override public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); - suite.addTestSuite(WifiApStress.class); - suite.addTestSuite(WifiStressTest.class); + if (!UtilHelper.isWifiOnly()) { + suite.addTestSuite(WifiApStress.class); + suite.addTestSuite(WifiStressTest.class); + } else { + // only the wifi stress tests + suite.addTestSuite(WifiStressTest.class); + } return suite; } @@ -57,11 +63,13 @@ public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunn @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - String valueStr = (String) icicle.get("softap_iterations"); - if (valueStr != null) { - int iteration = Integer.parseInt(valueStr); - if (iteration > 0) { - mSoftapIterations = iteration; + if (!UtilHelper.isWifiOnly()) { + String valueStr = (String) icicle.get("softap_iterations"); + if (valueStr != null) { + int iteration = Integer.parseInt(valueStr); + if (iteration > 0) { + mSoftapIterations = iteration; + } } } diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java index 3d4dc3d..20aae47 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java @@ -19,7 +19,7 @@ package com.android.connectivitymanagertest; import android.os.Bundle; import android.test.InstrumentationTestRunner; import android.test.InstrumentationTestSuite; -import android.util.Log; + import com.android.connectivitymanagertest.functional.ConnectivityManagerMobileTest; import com.android.connectivitymanagertest.functional.WifiConnectionTest; @@ -35,10 +35,24 @@ import junit.framework.TestSuite; */ public class ConnectivityManagerTestRunner extends InstrumentationTestRunner { + public String TEST_SSID = null; + @Override public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); - suite.addTestSuite(ConnectivityManagerMobileTest.class); + if (!UtilHelper.isWifiOnly()) { + suite.addTestSuite(ConnectivityManagerMobileTest.class); + } else { + // create a new test suite + suite.setName("ConnectivityManagerWifiOnlyFunctionalTests"); + String[] methodNames = {"testConnectToWifi", "testConnectToWifWithKnownAP", + "testDisconnectWifi", "testDataConnectionOverAMWithWifi", + "testDataConnectionWithWifiToAMToWifi", "testWifiStateChange"}; + Class<ConnectivityManagerMobileTest> testClass = ConnectivityManagerMobileTest.class; + for (String method: methodNames) { + suite.addTest(TestSuite.createTest(testClass, method)); + } + } suite.addTestSuite(WifiConnectionTest.class); return suite; } @@ -56,6 +70,4 @@ public class ConnectivityManagerTestRunner extends InstrumentationTestRunner { TEST_SSID = testSSID; } } - - public String TEST_SSID = null; } diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/UtilHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/UtilHelper.java new file mode 100644 index 0000000..1b966bf --- /dev/null +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/UtilHelper.java @@ -0,0 +1,27 @@ +/* + * 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.SystemProperties; + +public class UtilHelper { + public static boolean isWifiOnly() { + return "wifi-only".equals(SystemProperties.get("ro.carrier")); + } + + +} diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java index b87021a..d9b770a 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java @@ -17,6 +17,7 @@ package com.android.connectivitymanagertest.functional; import com.android.connectivitymanagertest.ConnectivityManagerTestActivity; +import com.android.connectivitymanagertest.UtilHelper; import android.content.Intent; import android.content.Context; @@ -48,7 +49,7 @@ public class ConnectivityManagerMobileTest private WakeLock wl; public ConnectivityManagerMobileTest() { - super(PKG_NAME, ConnectivityManagerTestActivity.class); + super(ConnectivityManagerTestActivity.class); } @Override @@ -68,13 +69,15 @@ public class ConnectivityManagerMobileTest Log.v(LOG_TAG, "airplane is not disabled, disable it."); cmActivity.setAirplaneMode(getInstrumentation().getContext(), false); } - if (!cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)) { - // Note: When the test fails in setUp(), tearDown is not called. In that case, - // the activity is destroyed which blocks the next test at "getActivity()". - // tearDown() is called here to avoid that situation. - tearDown(); - fail("Device is not connected to Mobile, setUp failed"); + if (!UtilHelper.isWifiOnly()) { + if (!cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED, + ConnectivityManagerTestActivity.LONG_TIMEOUT)) { + // Note: When the test fails in setUp(), tearDown is not called. In that case, + // the activity is destroyed which blocks the next test at "getActivity()". + // tearDown() is called here to avoid that situation. + tearDown(); + fail("Device is not connected to Mobile, setUp failed"); + } } } @@ -128,8 +131,8 @@ public class ConnectivityManagerMobileTest // As Wifi stays in DISCONNETED, Mobile statys in CONNECTED, // the connectivity manager will not broadcast any network connectivity event for Wifi NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, networkInfo.getState(), - NetworkState.DO_NOTHING, State.CONNECTED); + cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, + networkInfo.getState(), NetworkState.DO_NOTHING, State.CONNECTED); networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI); cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(), NetworkState.DO_NOTHING, State.DISCONNECTED); @@ -162,10 +165,13 @@ public class ConnectivityManagerMobileTest @LargeTest public void testConnectToWifi() { assertNotNull("SSID is null", TEST_ACCESS_POINT); - //Prepare for connectivity verification - NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, networkInfo.getState(), - NetworkState.TO_DISCONNECTION, State.DISCONNECTED); + NetworkInfo networkInfo; + if (!UtilHelper.isWifiOnly()) { + //Prepare for connectivity verification + networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, + networkInfo.getState(), NetworkState.TO_DISCONNECTION, State.DISCONNECTED); + } networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI); cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(), NetworkState.TO_CONNECTION, State.CONNECTED); @@ -179,8 +185,10 @@ public class ConnectivityManagerMobileTest Log.v(LOG_TAG, "wifi state is enabled"); assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); - assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); + if (!UtilHelper.isWifiOnly()) { + assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, + State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); + } // validate states if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) { @@ -189,11 +197,13 @@ public class ConnectivityManagerMobileTest cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI)); assertTrue(false); } - if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) { - Log.v(LOG_TAG, "Mobile state transition validation failed."); - Log.v(LOG_TAG, "reason: " + - cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE)); - assertTrue(false); + if (!UtilHelper.isWifiOnly()) { + if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) { + Log.v(LOG_TAG, "Mobile state transition validation failed."); + Log.v(LOG_TAG, "reason: " + + cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE)); + assertTrue(false); + } } } @@ -225,16 +235,21 @@ public class ConnectivityManagerMobileTest // Wait for the Wifi state to be DISABLED assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); - assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); - assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); + assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, + State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); + if (!UtilHelper.isWifiOnly()) { + assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, + State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); + } - //Prepare for connectivity state verification - NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, - networkInfo.getState(), NetworkState.DO_NOTHING, - State.DISCONNECTED); + NetworkInfo networkInfo; + if (!UtilHelper.isWifiOnly()) { + //Prepare for connectivity state verification + networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, + networkInfo.getState(), NetworkState.DO_NOTHING, + State.DISCONNECTED); + } networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI); cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(), NetworkState.TO_CONNECTION, State.CONNECTED); @@ -246,8 +261,10 @@ public class ConnectivityManagerMobileTest // Wait for Wifi to be connected and mobile to be disconnected assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); - assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); + if (!UtilHelper.isWifiOnly()) { + assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, + State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); + } // validate wifi states if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) { @@ -277,11 +294,14 @@ public class ConnectivityManagerMobileTest Log.v(LOG_TAG, "exception: " + e.toString()); } - NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, - networkInfo.getState(), - NetworkState.TO_CONNECTION, - State.CONNECTED); + NetworkInfo networkInfo; + if (!UtilHelper.isWifiOnly()) { + networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, + networkInfo.getState(), + NetworkState.TO_CONNECTION, + State.CONNECTED); + } networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI); cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(), NetworkState.TO_DISCONNECTION, State.DISCONNECTED); @@ -291,8 +311,10 @@ public class ConnectivityManagerMobileTest assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); - assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); + if (!UtilHelper.isWifiOnly()) { + assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, + State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); + } // validate states if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) { @@ -301,11 +323,13 @@ public class ConnectivityManagerMobileTest cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI)); assertTrue(false); } - if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) { - Log.v(LOG_TAG, "Mobile state transition validation failed."); - Log.v(LOG_TAG, "reason: " + - cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE)); - assertTrue(false); + if (!UtilHelper.isWifiOnly()) { + if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) { + Log.v(LOG_TAG, "Mobile state transition validation failed."); + Log.v(LOG_TAG, "reason: " + + cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE)); + assertTrue(false); + } } } @@ -377,14 +401,16 @@ public class ConnectivityManagerMobileTest // Eanble airplane mode cmActivity.setAirplaneMode(getInstrumentation().getContext(), true); - assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); - - NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, - networkInfo.getState(), - NetworkState.DO_NOTHING, - State.DISCONNECTED); + NetworkInfo networkInfo; + if (!UtilHelper.isWifiOnly()) { + assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, + State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); + networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, + networkInfo.getState(), + NetworkState.DO_NOTHING, + State.DISCONNECTED); + } networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI); cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(), NetworkState.TO_CONNECTION, State.CONNECTED); @@ -402,11 +428,13 @@ public class ConnectivityManagerMobileTest cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI)); assertTrue("State validation failed", false); } - if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) { - Log.v(LOG_TAG, "state validation for Mobile failed"); - Log.v(LOG_TAG, "reason: " + - cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE)); - assertTrue("state validation failed", false); + if (!UtilHelper.isWifiOnly()) { + if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) { + Log.v(LOG_TAG, "state validation for Mobile failed"); + Log.v(LOG_TAG, "reason: " + + cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE)); + assertTrue("state validation failed", false); + } } cmActivity.setAirplaneMode(getInstrumentation().getContext(), false); } @@ -452,8 +480,10 @@ public class ConnectivityManagerMobileTest assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); - assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); + if (!UtilHelper.isWifiOnly()) { + assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, + State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT)); + } // validate the state transition if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) { diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java index 2f2a283..7578e67 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java @@ -18,6 +18,7 @@ package com.android.connectivitymanagertest.stress; import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner; import com.android.connectivitymanagertest.ConnectivityManagerTestActivity; +import com.android.connectivitymanagertest.UtilHelper; import android.content.Context; import android.net.ConnectivityManager; @@ -264,18 +265,22 @@ public class WifiStressTest assertTrue("Wait for Wi-Fi to idle timeout", mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED, 6 * ConnectivityManagerTestActivity.SHORT_TIMEOUT)); - // use long timeout as the pppd startup may take several retries. - assertTrue("Wait for cellular connection timeout", - mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED, - ConnectivityManagerTestActivity.LONG_TIMEOUT)); + if (!UtilHelper.isWifiOnly()) { + // use long timeout as the pppd startup may take several retries. + assertTrue("Wait for cellular connection timeout", + mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED, + ConnectivityManagerTestActivity.LONG_TIMEOUT)); + } sleep(mWifiSleepTime + WIFI_IDLE_DELAY, "Interrupted while device is in sleep mode"); // Verify the wi-fi is still off and data connection is on assertEquals("Wi-Fi is reconnected", State.DISCONNECTED, mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState()); - assertEquals("Cellular connection is down", State.CONNECTED, - mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState()); - assertTrue("Mobile is connected, but no data connection.", mAct.pingTest(null)); + if (!UtilHelper.isWifiOnly()) { + assertEquals("Cellular connection is down", State.CONNECTED, + mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState()); + assertTrue("Mobile is connected, but no data connection.", mAct.pingTest(null)); + } // Turn screen on again mAct.turnScreenOn(); diff --git a/core/tests/coretests/src/android/util/LruCacheTest.java b/core/tests/coretests/src/android/util/LruCacheTest.java index 7e46e26..5a97158 100644 --- a/core/tests/coretests/src/android/util/LruCacheTest.java +++ b/core/tests/coretests/src/android/util/LruCacheTest.java @@ -183,20 +183,15 @@ public final class LruCacheTest extends TestCase { * Replacing the value for a key doesn't cause an eviction but it does bring * the replaced entry to the front of the queue. */ - public void testPutDoesNotCauseEviction() { - final List<String> evictionLog = new ArrayList<String>(); - List<String> expectedEvictionLog = new ArrayList<String>(); - LruCache<String, String> cache = new LruCache<String, String>(3) { - @Override protected void entryEvicted(String key, String value) { - evictionLog.add(key + "=" + value); - } - }; + public void testPutCauseEviction() { + List<String> log = new ArrayList<String>(); + LruCache<String, String> cache = newRemovalLogCache(log); cache.put("a", "A"); cache.put("b", "B"); cache.put("c", "C"); cache.put("b", "B2"); - assertEquals(expectedEvictionLog, evictionLog); + assertEquals(Arrays.asList("b=B>B2"), log); assertSnapshot(cache, "a", "A", "c", "C", "b", "B2"); } diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl index 6d925d6..68a158e 100644 --- a/data/keyboards/Generic.kl +++ b/data/keyboards/Generic.kl @@ -261,6 +261,23 @@ key 233 HEADSETHOOK # key 239 "KEY_KBDILLUMUP" # key 240 "KEY_UNKNOWN" +key 256 BUTTON_1 +key 257 BUTTON_2 +key 258 BUTTON_3 +key 259 BUTTON_4 +key 260 BUTTON_5 +key 261 BUTTON_6 +key 262 BUTTON_7 +key 263 BUTTON_8 +key 264 BUTTON_9 +key 265 BUTTON_10 +key 266 BUTTON_11 +key 267 BUTTON_12 +key 268 BUTTON_13 +key 269 BUTTON_14 +key 270 BUTTON_15 +key 271 BUTTON_16 + key 288 BUTTON_1 key 289 BUTTON_2 key 290 BUTTON_3 @@ -409,6 +426,10 @@ axis 0x02 Z axis 0x03 RX axis 0x04 RY axis 0x05 RZ +axis 0x06 THROTTLE +axis 0x07 RUDDER +axis 0x08 WHEEL +axis 0x09 GAS +axis 0x0a BRAKE axis 0x10 HAT_X axis 0x11 HAT_Y -
\ No newline at end of file diff --git a/data/keyboards/Vendor_045e_Product_028e.kl b/data/keyboards/Vendor_045e_Product_028e.kl new file mode 100644 index 0000000..99f046a --- /dev/null +++ b/data/keyboards/Vendor_045e_Product_028e.kl @@ -0,0 +1,46 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# XBox 360 USB Controller +# + +key 304 BUTTON_A +key 305 BUTTON_B +key 307 BUTTON_X +key 308 BUTTON_Y +key 310 BUTTON_L1 +key 311 BUTTON_R1 +key 314 BUTTON_SELECT +key 315 BUTTON_START +key 316 BUTTON_MODE +key 317 BUTTON_THUMBL +key 318 BUTTON_THUMBR + +# Left and right stick. +# The reported value for flat is 128 out of a range from -32767 to 32768, which is absurd. +# This confuses applications that rely on the flat value because the joystick actually +# settles in a flat range of +/- 4096 or so. +axis 0x00 X flat 4096 +axis 0x01 Y flat 4096 +axis 0x03 Z flat 4096 +axis 0x04 RZ flat 4096 + +# Triggers. +axis 0x02 LTRIGGER +axis 0x05 RTRIGGER + +# Hat. +axis 0x10 HAT_X +axis 0x11 HAT_Y diff --git a/data/keyboards/Vendor_046d_Product_c294.kl b/data/keyboards/Vendor_046d_Product_c294.kl new file mode 100644 index 0000000..5492f49 --- /dev/null +++ b/data/keyboards/Vendor_046d_Product_c294.kl @@ -0,0 +1,53 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Logitech G25 Racing Wheel (in Compatibility Mode) +# + +# 4 way buttons above hat +key 0x121 BUTTON_A +key 0x123 BUTTON_B +key 0x120 BUTTON_X +key 0x122 BUTTON_Y + +# Row of buttons under hat +key 0x12b BUTTON_1 +key 0x128 BUTTON_2 +key 0x129 BUTTON_3 +key 0x12a BUTTON_4 + +# Gear shift positions +# 0x12a top-left gear (aliased as BUTTON_4) +# 0x12b bottom-left gear (aliased as BUTTON_1) + +# Buttons on wheel +key 0x127 BUTTON_L1 +key 0x126 BUTTON_R1 + +# Toggles under wheel +key 0x125 BUTTON_L2 +key 0x124 BUTTON_R2 + +# Hat +axis 0x10 HAT_X +axis 0x11 HAT_Y + +# Steering Wheel +axis 0x00 WHEEL + +# Accelerator / Brake +# 00..7e : accelerator +# 80..ff : brake +axis 0x01 split 0x7f GAS BRAKE diff --git a/data/keyboards/Vendor_046d_Product_c299.kl b/data/keyboards/Vendor_046d_Product_c299.kl new file mode 100644 index 0000000..d42963d --- /dev/null +++ b/data/keyboards/Vendor_046d_Product_c299.kl @@ -0,0 +1,62 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Logitech G25 Racing Wheel (in Native Mode) +# + +# 4 way buttons above hat +key 0x121 BUTTON_A +key 0x123 BUTTON_B +key 0x120 BUTTON_X +key 0x122 BUTTON_Y + +# Row of buttons under hat +key 0x12b BUTTON_1 +key 0x128 BUTTON_2 +key 0x129 BUTTON_3 +key 0x12a BUTTON_4 + +# Gear shift positions +key 0x12c BUTTON_5 +key 0x12d BUTTON_6 +key 0x12e BUTTON_7 +key 0x12f BUTTON_8 +key 0x2d0 BUTTON_9 +key 0x2d1 BUTTON_10 +key 0x2d2 BUTTON_11 + +# Buttons on wheel +key 0x127 BUTTON_L1 +key 0x126 BUTTON_R1 + +# Toggles under wheel +key 0x125 BUTTON_L2 +key 0x124 BUTTON_R2 + +# Hat +axis 0x10 HAT_X +axis 0x11 HAT_Y + +# Steering Wheel +axis 0x00 WHEEL + +# Clutch +axis 0x01 invert GENERIC_1 + +# Accelerator +axis 0x02 invert GAS + +# Brake +axis 0x05 invert BRAKE diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk index 5b367b9..335298c 100644 --- a/data/keyboards/common.mk +++ b/data/keyboards/common.mk @@ -19,7 +19,10 @@ keylayouts := \ Generic.kl \ AVRCP.kl \ qwerty.kl \ + Vendor_045e_Product_028e.kl \ Vendor_046d_Product_c216.kl \ + Vendor_046d_Product_c294.kl \ + Vendor_046d_Product_c299.kl \ Vendor_046d_Product_c532.kl \ Vendor_054c_Product_0268.kl \ Vendor_05ac_Product_0239.kl \ diff --git a/docs/html/guide/appendix/faq/commontasks.jd b/docs/html/guide/appendix/faq/commontasks.jd index 4747379..b0c96b1 100644 --- a/docs/html/guide/appendix/faq/commontasks.jd +++ b/docs/html/guide/appendix/faq/commontasks.jd @@ -1,821 +1,8 @@ -page.title=Common Tasks and How to Do Them in Android -parent.title=FAQs, Tips, and How-to -parent.link=index.html @jd:body -<ul> - <li><a href="#neweclipseandroidproject">Creating an Android Application using - the Eclipse plugin</a></li> - <li><a href="#newandroidprojectnoeclipse">Creating an Android Application without - the Eclipse plugin</a></li> - <li><a href="#addexternallibrary">Adding an External Library (.jar) using Eclipse</a></li> - <li><a href="#implementcallbacks">Implementing Activity callbacks</a> (Android - calls your activity at various key moments in its life cycle. You must know - how to handle each of these to draw your screen, initialize class members, - and acquire data.)</li> - <li><a href="#opennewscreen">Opening a new screen</a></li> - <li><a href="#listening">Listening for button clicks </a></li> - <li><a href="#configurewindowproperties">Configuring general window properties </a></li> - <li><a href="#localhostalias">Referring to localhost from the emulated environment</a></li> - <li><a href="#appstate">Storing and retrieving state</a></li> - <li><a href="{@docRoot}guide/topics/data/data-storage.html#preferences">Storing and retrieving preferences</a></li> - <li><a href="#storingandretrieving">Storing and retrieving larger or more complex - persistent data</a> (files and data) </li> - <li><a href="#playback">Playing audio, video, still, or other media files</a></li> - <li><a href="#broadcastreceivers">Listening for and broadcasting global messages - and setting alarms</a></li> - <li><a href="#alerts">Displaying alerts </a></li> - <li><a href="#progressbar">Displaying a progress bar</a> </li> - <li><a href="#addmenuitems">Adding items to the screen menu</a> </li> - <li><a href="#webpage">Display a web page</a> </li> - <li><a href="#binding">Binding to data</a></li> - <li><a href="#handle">Getting a Handle to a Screen Element</a></li> - <li><a href="#captureimages">Capture images from the phone camera </a></li> - <li><a href="#threading">Handling expensive operations in the UI thread</a></li> - <li><a href="#selectingtext">Selecting, highlighting, or styling portions of - text</a></li> - <li><a href="#querymap">Utilizing attributes in a Map query</a></li> - <li><a href="#filelist">List of files for an Android application</a></li> - <li><a href="#logging">Print messages to a log file</a></li> -</ul> -<p>The ApiDemos sample application includes many, many examples of common -tasks and UI features. See the code inside -<code><sdk>samples/ApiDemos</code> and the other sample applications -under the <code>samples/</code> folder in the SDK.</p> - - -<h2 id="neweclipseandroidproject">Creating an Android Application using the Eclipse Plugin</h2> - -<p>Using the Android Eclipse plugin is the fastest and easiest way -to start creating a new Android application. The plugin automatically generates -the correct project structure for your application, and keeps the resources -compiled for you automatically.</p> - -<p>It is still a good idea to know what is going on though. Take a look at <a -href="{@docRoot}guide/topics/fundamentals.html">Application Fundamentals</a> -to understand the basics of how an Android application works.</p> - -<p>You should also take a look at the ApiDemos application and the other sample -applications included in the SDK, in the <code><sdk>/samples/</code> -folder in the SDK.</p> - -<p>Finally, a great way to started with Android development in Eclipse is to -follow both the <a href="{@docRoot}resources/tutorials/hello-world.html">Hello, -World</a> and <a -href="{@docRoot}resources/tutorials/notepad/index.html">Notepad</a> code -tutorials. In particular, the start of the Hello Android tutorial is an -excellent introduction to creating a new Android application in Eclipse.</p> - -<h2 id="newandroidprojectnoeclipse">Creating an Android Application without the Eclipse Plugin</h2> - -<p>This topic describes the manual steps in creating an Android application. -Before reading this, you should read <a -href="{@docRoot}guide/topics/fundamentals.html">Application Fundamentals</a> -to understand the basics of how an Android application works. You might also -want to look at the sample code included with the Android SDK, in the -<code><sdk>/samples/</code> directory. </p> - -<p>Here is a list of the basic steps in building an application.</p> -<ol> - <li><strong>Create your required resource files</strong> This includes - the AndroidManifest.xml global description file, string files that your application - needs, and layout files describing your user interface. A full list of optional - and required files and syntax details for each is given in <a href="#filelist">File - List for an Android Application</a>. </li> - <li><strong>Design your user interface</strong> See <a - href="{@docRoot}guide/topics/ui/index.html">User Interface</a> for - details on elements of the Android screen. </li> - <li><strong>Implement your Activity </strong>(this page)<strong> </strong> You - will create one class/file for each screen in your application. Screens will - inherit from an {@link android.app android.app} class, typically {@link android.app.Activity - android.app.Activity} for basic screens, {@link android.app.ListActivity - android.app.ListActivity} for list screens, or {@link android.app.Dialog - android.app.Dialog} for dialog boxes. You will implement the required callbacks - that let you draw your screen, query data, and commit changes, and also perform - any required tasks such as opening additional screens or reading data from - the device. Common tasks, such as opening a new screen or reading data from - the device, are described below. - The list of files you'll need for your application are described in <a href="#filelist">List - of Files for an Android Application</a>. </li> - <li><strong><a href="{@docRoot}guide/developing/other-ide.html#buildingwithant">Build and install your - package</a>.</strong> The Android SDK has some nice tools for generating - projects and debugging code. </li> -</ol> - -<h2 id="addexternallibrary">Adding an External Library (.jar) using Eclipse</h2> -<p> -You can use a third party JAR in your application by adding it to your Eclipse project as follows: -</p> -<ol> -<li> -In the <strong>Package Explorer</strong> panel, right-click on your project and select <strong>Properties</strong>. -<li> -Select <strong>Java Build Path</strong>, then the tab <strong>Libraries</strong>. -<li> -Press the <strong>Add External JARs...</strong> button and select the JAR file. -</ol> -<p> -Alternatively, if you want to include third party JARs with your package, create a new directory for them within your project and select <strong>Add Library...</strong> instead.</p> -<p> -It is not necessary to put external JARs in the assets folder. -</p> - -<a name="implementcallbacks" id="implementcallbacks"></a> -<h2>Implementing Activity Callbacks</h2> -<p>Android calls a number of callbacks to let you draw your screen, store data before - pausing, and refresh data after closing. You must implement at least some of - these methods. See the <a -href="{@docRoot}guide/topics/fundamentals/activites.html#Lifecycle">Activities</a> - document to learn when and in what order these methods - are called. Here are some of the standard types of screen classes that Android provides:</p> -<ul> - <li>{@link android.app.Activity android.app.Activity} - This is a standard screen, - with no specialization.</li> - <li>{@link android.app.ListActivity android.app.ListActivity} - This is a screen - that is used to display a list of something. It hosts a ListView object, - and exposes methods to let you identify the selected item, receive callbacks - when the selected item changes, and perform other list-related actions. </li> - <li>{@link android.app.Dialog android.app.Dialog} - This is a small, popup dialog-style - window that isn't intended to remain in the history stack. (It is not resizeable - or moveable by the user.)</li> -</ul> - -<a name="opennewscreen" id="opennewscreen"></a><h2>Opening a New Screen</h2> -<p>Your Activity will often need to open another Activity screen as it progresses. - This new screen can be part of the same application or part of another application, - the new screen can be floating or full screen, it can return a result, and you - can decide whether to close this screen and remove it from the history stack - when you are done with it, or to keep the screen open in history. These next - sections describe all these options. </p> -<h3>Floating or full?<a name="floatingorfull" id="floatingorfull"></a></h3> -<p>When you open a new screen you can decide whether to make it transparent or floating, - or full-screen. The choice of new screen affects the event sequence of events - in the old screen (if the new screen obscures the old screen, a different - series of events is called in the old screen). See the <a - href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">Activities</a> document for -details. </p> -<p>Transparent or floating windows are implemented in three - standard ways: </p> -<ul> - <li>Create an {@link android.app.Dialog app.Dialog} class </li> - <li>Create an {@link android.app.AlertDialog app.AlertDialog} class </li> - <li>Set the {@link android.R.style#Theme_Dialog} <em>theme</em> attribute to <code>@android:style/Theme.Dialog</code> - in your AndroidManifest.xml file. For example: - <pre><activity class="AddRssItem" android:label="Add an item" android:theme="@android:style/Theme.Dialog"/> -</pre></li> -</ul> -<p>Calling startActivity() or startActivityForResult() will open a new screen in whatever - way it defines itself (if it uses a floating theme it will be floating, - otherwise it will be full screen). </p> -<h3>Opening a Screen </h3> -<p>When you want to open a new screen, you can either explicitly specify the activity - class to open, or you can let the operating system decide which screen to open, - based upon the data and various parameters you pass in. A screen is opened by - calling {@link android.app.Activity#startActivity(android.content.Intent) startActivity} - and passing in an {@link android.content.Intent Intent} object, which specifies - the criteria for the handling screen. To specify a specific screen, call Intent.setClass - or setClassName with the exact activity class to open. Otherwise, set a variety - of values and data, and let Android decide which screen is appropriate to open. - Android will find one or zero Activities that match the specified requirements; - it will never open multiple activities for a single request. More information - on Intents and how Android resolves them to a specific class is given in the - {@link android.content.Intent Intent} topic. </p> -<a name="intentexamples" id="intentexamples"></a><h3>Some Intent examples </h3> -<p>The following snippet loads the com.android.samples.Animation1 class, and - passes it some arbitrary data.:</p> -<pre>Intent myIntent = new Intent(); -myIntent.setClassName("com.android.samples", "com.android.samples.Animation1"); -myIntent.putExtra("com.android.samples.SpecialValue", "Hello, Joe!"); // key/value pair, where key needs current package prefix. -startActivity(myIntent); </pre> -<p>The next snippet requests that a Web page be opened by specifying the VIEW action, - and a URI data string starting with "http://" schema:</p> -<pre>Intent myIntent = new Intent(Intent.VIEW_ACTION, Uri.parse("http://www.google.com"));</pre> -<p>Here is the intent filter from the AndroidManifest.xml file for com.android.browser:</p> -<pre><intent-filter> - <action android:name="android.intent.action.VIEW" /> - <category android:name="android.intent.category.DEFAULT" /> - <scheme android:name="http" /> - <scheme android:name="https" /> - <scheme android:name="file" /> -</intent-filter> </pre> -<p>Android defines a number of standard values, for instance the action constants - defined by {@link android.content.Intent}. You can define custom values, but - both the caller and handler must use them. See the <intent-filter> - tag description in <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml - File</a> for more information on the manifest syntax for the handling - application. </p> -<a name="returningaresult" id="returningaresult"></a><h3>Returning a Result from a Screen</h3> -<p>A window can return a result after it closes. This result will be passed back - into the calling Activity's {@link android.app.Activity#onActivityResult(int,int,android.content.Intent) - onActivityResult()} method, which can supply an Intent containing arbitrary data, along with - the request code passed to startActivityForResult(). Note that you must call the {@link - android.app.Activity#startActivityForResult(android.content.Intent,int) startActivityForResult()} - method that accepts a request code parameter to get this callback. The following - code demonstrates opening a new screen and retrieving a result. </p> -<pre>// Open the new screen. -public void onClick(View v){ - // Start the activity whose result we want to retrieve. The - // result will come back with request code GET_CODE. - Intent intent = new Intent(this, com.example.app.ChooseYourBoxer.class); - startActivityForResult(intent, CHOOSE_FIGHTER); -} - -// Listen for results. -protected void onActivityResult(int requestCode, int resultCode, Intent data){ - // See which child activity is calling us back. - switch (resultCode) { - case CHOOSE_FIGHTER: - // This is the standard resultCode that is sent back if the - // activity crashed or didn't doesn't supply an explicit result. - if (resultCode == RESULT_CANCELED){ - myMessageboxFunction("Fight cancelled"); - } - else { - myFightFunction(data); - } - default: - break; - } -} - -// Class SentResult -// Temporary screen to let the user choose something. - private OnClickListener mLincolnListener = new OnClickListener(){ - public void onClick(View v) { - Bundle stats = new Bundle(); - stats.putString("height","6\'4\""); - stats.putString("weight", "190 lbs"); - stats.putString("reach", "74\""); - setResult(RESULT_OK, "Lincoln", stats); - finish(); - } - }; - - private OnClickListener mWashingtonListener = new OnClickListener() { - public void onClick(View v){ - Bundle stats = new Bundle(); - stats.putString("height","6\'2\""); - stats.putString("weight", "190 lbs"); - stats.putString("reach", "73\""); - setResult(RESULT_OK, "Washington", Bundle); - finish(); - } - }; - </pre> -<h3>Lifetime of the new screen </h3> -<p>An activity can remove itself from the history stack by calling {@link android.app.Activity#finish() - Activity.finish()} on itself, or the activity that opened the screen can call - {@link android.app.Activity#finishActivity(int) Activity.finishActivity()} - on any screens that it opens to close them. </p> -<a name="listening" id="listening"></a><h2>Listening for Button Clicks</h2> -<p>Button click and other UI event capturing are covered in <a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a> on the UI Design page.</p> -<a name="configurewindowproperties" id="configurewindowproperties"></a><h2>Configuring General Window Properties</h2> -<p>You can set a number of general window properties, such as whether to display - a title, whether the window is floating, and whether it displays an icon, by - calling methods on the {@link android.view.Window Window} member - of the underlying View object for the window. Examples include calling {@link - android.app.Activity#getWindow() getWindow().requestFeature()} (or the convenience - method {@link android.app.Activity#requestWindowFeature(int) requestWindowFeature(<em>some_feature</em>)}) - to hide the title. Here is an example of hiding the title bar:</p> -<pre>//Hide the title bar -requestWindowFeature(Window.FEATURE_NO_TITLE); -</pre> -<p>A better way to achieve the same end is to specify a theme in your Android -Manifest file:</p> -<pre><application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar"> -</pre> -<p>This is preferable because it tells the system not to show a title bar while -your application is starting up. With the explicit method call, your application -will have a title bar visible to the user until <code>onCreate</code> runs.</p> -<p>(Note that this can be applied to either the <code><application></code> -tag or to individual <code><activity></code> tags.)</p> -<a name="localhostalias" id="localhostalias"></a><h2>Referring to localhost from the emulated environment</h2> -<p> -If you need to refer to your host computer's <em>localhost</em>, such as when you -want the emulator client to contact a server running on the same host, use the alias -<code>10.0.2.2</code> to refer to the host computer's loopback interface. -From the emulator's perspective, localhost (<code>127.0.0.1</code>) refers to its own -loopback interface. -</p> -<a name="appstate" id="appstate"></a><h2>Storing and Retrieving State</h2> -<p>If your application is dumped from memory because of space concerns, it will lose - all user interface state information such as checkbox state and text box values - as well as class member values. Android calls {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) - Activity.onSaveInstanceState} before it pauses the application. This method hands in a {@link - android.os.Bundle Bundle} that can be used to store name/value pairs that will - persist and be handed back to the application even if it is dropped from memory. - Android will pass this Bundle back to you when it calls {@link android.app.Activity#onCreate(android.os.Bundle) - onCreate()}. This Bundle only exists while the application is still in the history - stack (whether or not it has been removed from memory) and will be lost when - the application is finalized. See the topics for {@link android.app.Activity#onSaveInstanceState} and - {@link android.app.Activity#onCreate} for - examples of storing and retrieving state.</p> -<p>Read more about the lifecycle of an activity in <a -href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a> document.</p> -<h3>Storing and Retrieving Larger or More Complex Persistent Data<a name="storingandretrieving" id="storingandretrieving"></a></h3> -<p>Your application can store files or complex collection objects, and reserve them - for private use by itself or other activities in the application, or it can expose - its data to all other applications on the device. See <a href="{@docRoot}guide/topics/data/data-storage.html">Storing, - Retrieving, and Exposing Data</a> to learn how to store and retrieve private data, - how to store and retrieve common data from the device, and how to expose your - private data to other applications.</p> -<a name="playback" id="playback"></a><h2>Playing Media Files</h2> -<p>Please see the document <a href="{@docRoot}guide/topics/media/index.html">Audio and Video</a> for more details.</p> -<a name="broadcastreceivers" id="broadcastreceivers"></a><h2>Listening For and Broadcasting Global Messages, and Setting Alarms</h2> -<p>You can create a listening class that can be notified or even instantiated whenever - a specific type of system message is sent. -</p> -<p>The listening classes, called broadcast receivers, extend {@link android.content.BroadcastReceiver - BroadcastReceiver}. If you want Android to instantiate the object whenever an appropriate - intent notification is sent, define the receiver with a <code><receiver></code> element - in the AndroidManifest.xml file. If the caller is expected to instantiate the - object in preparation to receive a message, this is not required. The receiver - will get a call to their {@link android.content.BroadcastReceiver#onReceive(android.content.Context,android.content.Intent) - BroadcastReceiver.onReceive()} method. A receiver can define an <code><intent-filter></code> tag - that describes the types of messages it will receive. Just as Android's IntentResolver - will look for appropriate Activity matches for a startActivity() call, it will - look for any matching Receivers (but it will send the message to all matching - receivers, not to the "best" match). </p> -<p>To send a notification, the caller creates an {@link android.content.Intent Intent} - object and calls {@link android.app.Activity#sendBroadcast(android.content.Intent) - Context.sendBroadcast()} with that Intent. Multiple recipients can receive - the same message. You can broadcast an Intent message to an intent receiver in - any application, not only your own. If the receiving class is not registered - using <code><receiver></code> in its manifest, you can dynamically instantiate - and register a receiver by calling {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,android.content.IntentFilter) - Context.registerReceiver()}. </p> -<p>Receivers can include intent filters to specify what kinds of intents they are - listening for. Alternatively, if you expect a single known caller to contact - a single known receiver, the receiver does not specify an intent filter, and - the caller specifies the receiver's class name in the Intent by calling {@link - android.content.Intent#setClassName(java.lang.String, java.lang.String) Intent.setClassName()} - with the recipient's class name. The recipient receives a {@link android.content.Context - Context} object that refers to its own package, not to the package of the sender.</p> -<p><em><strong>Note:</strong></em> If a receiver or broadcaster - enforces permissions, your application might need to request permission - to send or receive messages from that object. You can request permission by using - the <uses-permission> tag in the manifest. </p> -<p>Here is a code snippet of a sender and receiver. This example does not demonstrate - registering receivers dynamically. For a full code example, see the AlarmService - class in the ApiDemos project.</p> -<h3>Sending the message</h3> -<pre>// We are sending this to a specific recipient, so we will -// only specify the recipient class name. -Intent intent = new Intent(this, AlarmReceiver.class); -intent.putExtra("message","Wake up."); -sendBroadcast(intent); -</pre> -<h3>Receiving the message</h3> -<p><strong>Receiver AndroidManifest.xml </strong>(because there is no intent filter - child, this class will only receive a broadcast when the receiver class is specified - by name, as is done in this example):</p> -<pre> -<receiver class=".AlarmReceiver" /></pre> -<p><strong>Receiver Java code: </strong></p> -<pre> -public class AlarmReceiver extends BroadcastReceiver{ - // Display an alert that we've received a message. - @Override - public void onReceive(Context context, Intent intent){ - // Send a text notification to the screen. - NotificationManager nm = (NotificationManager) - context.getSystemService(Context.NOTIFICATION_SERVICE); - nm.notifyWithText(R.id.alarm, - "Alarm!!!", - NotificationManager.LENGTH_SHORT, - null); - } -} </pre> -<h3>Other system messages</h3> -<p>You can listen for other system messages sent by Android as well, such as USB - connection/removal messages, SMS arrival messages, and timezone changes. See - {@link android.content.Intent} for a list of broadcast messages to listen for. - Messages are marked "Broadcast Action" in the documentation. </p> -<h3>Listening for phone events<a name="phoneevents" id="phoneevents"></a></h3> -<p>The {@link android.telephony android.telephony} package overview page describes how to - register to listen for phone events. </p> -<a name="alarms" id="alarms"></a><h3>Setting Alarms </h3> -<p>Android provides an {@link android.app.AlarmManager AlarmManager} service that - will let you specify an Intent to send at a designated time. This intent is typically - used to start an application at a preset time. (Note: If you want to send - a notification to a sleeping or running application, use {@link android.os.Handler - Handler} instead.)</p> -<a name="alerts" id="alerts"></a><h2>Displaying Alerts</h2> -<p>There are two major kinds of alerts that you may display to the user: -(1) Normal alerts are displayed in response to a user action, such as -trying to perform an action that is not allowed. (2) Out-of-band alerts, -called notifications, are -displayed as a result of something happening in the background, such as the -user receiving new e-mail.</p> - -<a name="dialogsandalerts" id="dialogsandalerts"></a><h3>Normal Alerts</h3> - -<p>Android provides a number of ways for you to show popup notifications to your - user as they interact with your application. </p> -<table width="100%" border="1"> - <tr> - <th scope="col">Class</th> - <th scope="col">Description</th> - </tr> - <tr> - <td>{@link android.app.Dialog app.Dialog}</td> - <td>A generic floating dialog box with a layout that you design. </td> - </tr> - <tr> - <td><p>{@link android.app.AlertDialog app.AlertDialog}</p></td> - <td>A popup alert dialog with two buttons (typically OK and Cancel) that - take callback handlers. See the section after this table for more details. </td> - </tr> - <tr> - <td>{@link android.app.ProgressDialog ProgressDialog} </td> - <td>A dialog box used to indicate progress of an operation with a known progress - value or an indeterminate length (setProgress(bool)). See <strong>Views</strong> > <strong>Progress Bar</strong> in - ApiDemos for examples. </td> - </tr> - <tr> - <td>Activity</td> - <td>By setting the theme of an activity to - {@link android.R.style#Theme_Dialog - android:theme="@android:style/Theme.Dialog"}, - your activity will take on - the appearance of a normal dialog, floating on top of whatever was - underneath it. You usually set the theme through the - {@link android.R.attr#theme android:theme} attribute in your AndroidManifest.xml. - The advantage of this - over Dialog and AlertDialog is that Application has a much better managed - life cycle than dialogs: if a dialog goes to the background and is killed, - you cannot recapture state, whereas Application exposes a {@link android.os.Bundle - Bundle} of saved values in <code>onCreate()</code> to help you maintain state.</td> - </tr> -</table> -<h3>AlertDialog</h3> -<p>This is a basic warning dialog box that lets you configure a message, button text, - and callback. You can create one by calling using the {@link - android.app.AlertDialog.Builder} class, as shown here. </p> -<pre>private Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - switch (msg.what) { - case ACCEPT_CALL: - answer(msg.obj); - break; - - case BOUNCE_TO_VOICEMAIL: - voicemail(msg.obj); - break; - - } - } -}; - - -private void IncomingMotherInLawCall(Connection c) { - String Text; - - // "Answer" callback. - Message acceptMsg = Message.obtain(); - acceptMsg.target = mHandler; - acceptMsg.what = ACCEPT_CALL; - acceptMsg.obj = c.getCall(); - - // "Cancel" callback. - final Message rejectMsg = Message.obtain(); - rejectMsg.target = mHandler; - rejectMsg.what = BOUNCE_TO_VOICEMAIL; - rejectMsg.obj = c.getCall(); - - new AlertDialog.Builder(this) - .setMessage("Phyllis is calling") - .setPositiveButton("Answer", acceptMsg) - .setOnCancelListener(new OnCancelListener() { - public void onCancel(DialogInterface dialog) { - rejectMsg.sendToTarget(); - }}); - .show(); -} </pre> - -<h3>Notifications</h3> - -<p>Out-of-band alerts should always be displayed using the -{@link android.app.NotificationManager}, which allows you to tell the user -about something they may be interested in without disrupting what they are -currently doing. A notification can be anything from a brief pop-up box -informing the user of the new information, through displaying a persistent -icon in the status bar, to vibrating, playing sounds, or flashing lights to -get the user's attention. In all cases, the user must explicitly shift their -focus to the notification before they can interact with it.</p> - -<p>The following code demonstrates using NotificationManager to display a basic text - popup when a new SMS message arrives in a listening service, and provides the - current message count. You can see several more examples in the ApiDemos application, - under app/ (named <em>notification</em>*.java).</p> -<pre>static void setNewMessageIndicator(Context context, int messageCount){ - // Get the static global NotificationManager object. - NotificationManager nm = NotificationManager.getDefault();</p> - - // If we're being called because a new message has been received, - // then display an icon and a count. Otherwise, delete the persistent - // message. - if (messageCount > 0) { - nm.notifyWithText(myApp.NOTIFICATION_GUID, // ID for this notification. - messageCount + " new message" + messageCount > 1 ? "s":"", // Text to display. - NotificationManager.LENGTH_SHORT); // Show it for a short time only. - } -}</pre> -<p>To display a notification in the status bar and have it launch an intent when - the user selects it (such as the new text message notification does), call {@link - android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}, - and pass in vibration patterns, status bar icons, or Intents to associate with - the notification. </p> -<a name="progressbar" id="progressbar"></a><h2>Displaying a Progress Bar</h2> -<p>An activity can display a progress bar to notify the user that something is happening. - To display a progress bar in a screen, call {@link android.app.Activity#requestWindowFeature(int) - Activity.requestWindowFeature(Window.FEATURE_PROGRESS)}. To set the value - of the progress bar, call {@link android.view.Window#setFeatureInt(int,int) - Activity.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, <em>level</em>)}. - Progress bar values are from 0 to 9,999, or set the value to 10,000 to make the - progress bar invisible. </p> -<p>You can also use the {@link android.app.ProgressDialog ProgressDialog} class, - which enables a dialog box with an embedded progress bar to send a "I'm working - on it" notification to the user. </p> -<a name="addmenuitems" id="addmenuitems"></a><h2>Adding Items to the Screen Menu</h2> -<p>See <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>.</p> - -<a name="webpage" id="webpage"></a><h2>Display a Web Page</h2> -<p>Use the {@link android.webkit.WebView webkit.WebView} object. </p> -<a name="binding" id="binding"></a><h2>Binding to Data</h2> -<p>You can bind a ListView to a set of underlying data by using a shim class called - {@link android.widget.ListAdapter ListAdapter} (or a subclass). ListAdapter subclasses - bind to a variety of data sources, and expose a common set of methods such as - getItem() and getView(), and uses them to pick View items to display in its list. - You can extend ListAdapter and override getView() to create your own custom list - items. There are essentially only two steps you need to perform to bind to data: </p> -<ol> - <li>Create a ListAdapter object and specify its data source</li> - <li>Give the ListAdapter to your ListView object.</li> -</ol> -<p>That's it!</p> -<p>Here's an example of binding a ListActivity screen to the results from a cursor - query. (Note that the setListAdapter() method shown is a convenience method that - gets the page's ListView object and calls setAdapter() on it.)</p> -<pre>// Run a query and get a Cursor pointing to the results. -Cursor c = People.query(this.getContentResolver(), null); -startManagingCursor(c); - -// Create the ListAdapter. A SimpleCursorAdapter lets you specify two interesting things: -// an XML template for your list item, and -// The column to map to a specific item, by ID, in your template. -ListAdapter adapter = new SimpleCursorAdapter(this, - android.R.layout.simple_list_item_1, // Use a template that displays a text view - c, // Give the cursor to the list adapter - new String[] {People.NAME} , // Map the NAME column in the people database to... - new String[] {"text1"}); // The "text1" view defined in the XML template -setListAdapter(adapter);</pre> -<p>See view/List4 in the ApiDemos project for an example of extending ListAdapter - for a new data type. </p> - -<a name="handle"></a> - -<h2>Getting a Handle to a Screen Element</h2> -<p>You can get a handle to a screen element by calling {@link -android.app.Activity#findViewById(int) Activity.findViewById}. You can then use -the handle to set or retrieve any values exposed by the object. </p> -<a name="captureimages" id="captureimages"></a><h2>Capture Images from the Phone Camera</h2> -<p>You can hook into the device's camera onto your own Canvas object by using the - {@link android.hardware.Camera Camera} class. See that class's documentation, - and the ApiDemos project's Camera Preview application (Graphics/Camera Preview) - for example code. </p> - - -<a name="threading" id="threading"></a><h2>Handling Expensive Operations in the UI Thread</h2> -<p>Avoid performing long-running operations (such as network I/O) directly in the UI thread — -the main thread of an application where the UI is run — or your application may be blocked -and become unresponsive. Here is a brief summary of the recommended approach for handling expensive operations:</p> -<ol> -<li>Create a Handler object in your UI thread</li> -<li>Spawn off worker threads to perform any required expensive operations</li> -<li>Post results from a worker thread back to the UI thread's handler either through a Runnable or a {@link android.os.Message}</li> -<li>Update the views on the UI thread as needed</li> -</ol> - -<p>The following outline illustrates a typical implementation:</p> - -<pre> -public class MyActivity extends Activity { - - [ . . . ] - // Need handler for callbacks to the UI thread - final Handler mHandler = new Handler(); - - // Create runnable for posting - final Runnable mUpdateResults = new Runnable() { - public void run() { - updateResultsInUi(); - } - }; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - [ . . . ] - } - - protected void startLongRunningOperation() { - - // Fire off a thread to do some work that we shouldn't do directly in the UI thread - Thread t = new Thread() { - public void run() { - mResults = doSomethingExpensive(); - mHandler.post(mUpdateResults); - } - }; - t.start(); - } - - private void updateResultsInUi() { - - // Back in the UI thread -- update our UI elements based on the data in mResults - [ . . . ] - } -} -</pre> - -<p>For further discussions on this topic, see -<a href="{@docRoot}guide/practices/design/responsiveness.html">Designing for Responsiveness</a> -and the {@link android.os.Handler} documentation.</p> - -<a name="selectingtext" id="selectingtext"></a><h2>Selecting, Highlighting, or Styling Portions of Text</h2> -<p>You can highlight or style the formatting of strings or substrings of text in - a TextView object. There are two ways to do this:</p> -<ul> - <li>If you use a <a href="{@docRoot}guide/topics/resources/available-resources.html#stringresources">string resource</a>, - you can add some simple styling, such as bold or italic using HTML notation. - The currently supported tags are: <code>B</code> (bold), - <code>I</code> (italic), <code>U</code> (underline), - <code>TT</code> (monospace), <code>BIG</code>, <code>SMALL</code>, - <code>SUP</code> (superscript), <code>SUB</code> (subscript), - and <code>STRIKE</code> (strikethrough). - So, for example, in res/values/strings.xml you could declare this:<br /> - <code><resource><br /> - <string id="@+id/styled_welcome_message">We - are <b><i>so</i></b> glad to see you.</string><br /> - </resources></code></li> - <li>To style text on the fly, or to add highlighting or more complex styling, - you must use the Spannable object as described next. </li> -</ul> -<p>To style text on the fly, you must make sure the TextView is using {@link android.text.Spannable} - storage for the text (this will always be true if the TextView is an EditText), - retrieve its text with {@link android.widget.TextView#getText}, and call {@link - android.text.Spannable#setSpan}, passing in a new style class from the {@link - android.text.style} package and the selection range. </p> -<p>The following code snippet demonstrates creating a string with a highlighted section, - italic section, and bold section, and adding it to an EditText object. </p> -<pre>// Get our EditText object. -EditText vw = (EditText)findViewById(R.id.text); - -// Set the EditText's text. -vw.setText("Italic, highlighted, bold."); - -// If this were just a TextView, we could do: -// vw.setText("Italic, highlighted, bold.", TextView.BufferType.SPANNABLE); -// to force it to use Spannable storage so styles can be attached. -// Or we could specify that in the XML. - -// Get the EditText's internal text storage -Spannable str = vw.getText(); - -// Create our span sections, and assign a format to each. -str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); -str.setSpan(new BackgroundColorSpan(0xFFFFFF00), 8, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); -str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 21, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); -</pre> - -<a name="querymap" id="querymap"></a><h2>Utilizing attributes in a Map query</h2> -<p> -When using a search intent to ask the Maps activity to search for something, the Maps activity responds to the following attributes in the optional context bundle: -</p> -<pre> - float "centerLatitude" default 0.0f - float "centerLongitude" default 0.0f - float "latitudeSpan" default 0.0f - float "longitudeSpan" default 0.0f - int "zoomLevel" default 10 -</pre> -<p> -This context information is used to center the search result in a particular area, and is equivalent to adjusting the Map activity to the described location and zoom level before issuing the query. -</p> -<p> -If the latitudeSpan, longitudeSpan, and zoomLevel attributes are not consistent, then it is undefined which one takes precedence. -</p> - -<a name="filelist" id="filelist"></a><h2>List of Files for an Android Application</h2> -<p>The following list describes the structure and files of an Android application. - Many of these files can be built for you (or stubbed out) by the android tool - shipped in the tools/ menu of the SDK. </p> -<table width="100%" border="0"> - <tr> - <td width="28%" valign="top">MyApp/<br /></td> - <td width="72%" valign="top"> </td> - </tr> - <tr> - <td valign="top"> AndroidManifest.xml</td> - <td valign="top">(<em>required</em>) Advertises the screens that this application provides, - where they can be launched (from the main program menu or elsewhere), - any content providers it implements and what kind of data they handle, - where the implementation classes are, and other application-wide - information. Syntax details for this file are described in <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>.</td> - </tr> - <tr> - <td valign="top"> src/<br /> - /<em>myPackagePath</em>/.../<em>MyClass</em>.java</td> - <td valign="top">(<em>required</em>) This folder holds all the source code files for your - application, inside the appropriate package subfolders. </td> - </tr> - <tr> - <td valign="top"> res/</td> - <td valign="top">(<em>required</em>) This folder holds all the <em>resources</em> for - your application. Resources are external data files or description files - that are compiled into your code at build time. Files in different folders - are compiled differently, so you must put the proper resource into the - proper folder. (See <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources</a> for details.)</td> - </tr> - <tr> - <td valign="top"> anim/<br /> - <em>animation1</em>.xml<br /> - <em>...</em></td> - <td valign="top">(<em>optional</em>) Holds any animation XML description files that the - application uses. The format of these files is described in <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources</a>. </td> - </tr> - <tr> - <td valign="top"> drawable/<br /> - <em>some_picture</em>.png<br /> - <em>some_stretchable</em>.9.png<br /> - <em>some_background</em>.xml<br /> - ...</td> - <td valign="top">(<em>optional</em>) Zero or more files that will be compiled to {@link - android.graphics.drawable android.graphics.drawable} resources. Files - can be image files (png, gif, or other) or XML files describing other - graphics such as bitmaps, stretchable bitmaps, or gradients. Supported - bitmap file formats are PNG (preferred), JPG, and GIF (discouraged), - as well as the custom 9-patch stretchable bitmap format. These formats - are described in <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources</a>. </td> - </tr> - <tr> - <td valign="top"> layout/<br /> - <em>screen_1_layout</em>.xml<br /> - ...<br /></td> - <td valign="top">(<em>optional</em>) Holds all the XML files describing screens or parts - of screens. Although you could create a screen in Java, defining them - in XML files is typically easier. A layout file is similar in concept - to an HTML file that describes the screen layout and components. See <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> for more information about designing screens, and <a href="{@docRoot}guide/topics/resources/available-resources.html#layoutresources">Available Resource Types</a> for the syntax of these files.</td> - </tr> - <tr> - <td valign="top"> values/<br /> - arrays<br /> - classes.xml<br /> - colors.xml<br /> - dimens.xml<br /> - strings.xml<br /> - styles.xml<br /> - values.xml<br /></td> - <td valign="top"><p>(<em>optional</em>) XML files describing additional resources - such as strings, colors, and styles. The naming, quantity, and number - of these files are not enforced--any XML file is compiled, but these - are the standard names given to these files. However, the syntax - of these files is prescribed by Android, and described in <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources</a>. </p> - </td> - </tr> - <tr> - <td valign="top"> xml/</td> - <td valign="top">(<em>optional</em>) XML files that can be read at run time on the device. </td> - </tr> - <tr> - <td valign="top"> raw/</td> - <td valign="top">(<em>optional</em>) Any files to be copied directly to the device. </td> - </tr> -</table> - - -<a name="logging" ></a> -<h2>Print Messages to a Log File</h2> - -<p>To write log messages from your application:</p> -<ol><li>Import <code>android.util.Log</code>.</li> - <li>Use <code>Log.v()</code>, <code>Log.d()</code>, <code>Log.i()</code>, - <code>Log.w()</code>, or <code>Log.e()</code> to log messages. - (See the {@link android.util.Log} class.)<br/> E.g., - <code>Log.e(this.toString(), "error: " + err.toString())</code></li> - <li>Launch <a href="{@docRoot}guide/developing/tools/ddms.html">DDMS</a> from a terminal - by executing <code>ddms</code> in your Android SDK <code>/tools</code> path.</li> - <li>Run your application in the Android emulator.</li> - <li>From the DDMS application, select the emulator - (e.g., "emulator-5554") and click <b>Device > Run logcat...</b> - to view all the log data.</li> -</ol> -<p class="note"><strong>Note:</strong> If you are running Eclipse and -encounter a warning about the VM debug port when opening DDMS, you can ignore it -if you're only interested in logs. However, if you want to further inspect and -control your processes from DDMS, then you should close Eclipse before launching DDMS so that -it may use the VM debugging port.</p> - +<script type="text/javascript"> + document.location=toRoot+"resources/faq/commontasks.html" +</script> +<p>You should have already been redirected by your browser. Please follow +<a href="{@docRoot}resources/faq/commontasks.html">this link</a>.</p>
\ No newline at end of file diff --git a/docs/html/guide/appendix/faq/framework.jd b/docs/html/guide/appendix/faq/framework.jd index 33b69ac..a79686e 100644 --- a/docs/html/guide/appendix/faq/framework.jd +++ b/docs/html/guide/appendix/faq/framework.jd @@ -1,197 +1,8 @@ -page.title=Android Application Framework FAQ -parent.title=FAQs, Tips, and How-to -parent.link=index.html @jd:body -<ul> - <li><a href="#1">Do all the Activities and Services of an - application run in a single process?</a></li> - <li><a href="#2">Do all Activities run in the main thread of - an application process?</a></li> - <li><a href="#3">How do I pass complicated data structures - from one Activity/Service to another?</a></li> - <li><a href="#4">How can I check if an Activity is already - running before starting it?</a></li> - <li><a href="#5">If an Activity starts a remote service, is - there any way for the Service to pass a message back to the Activity?</a></li> - <li><a href="#6">How to avoid getting the Application not - responding dialog?</a></li> - <li><a href="#7">How does an application know if a package is - added or removed?</a></li> -</ul> - - -<a name="1" id="1"></a> - -<h2>Do all the Activities and Services of an application run in a -single process?</h2> - -<p>All Activities and Services in an application run in a single process by -default. If needed, you can declare an <code>android:process</code> attribute -in your manifest file, to explicitly place a component (Activity/Service) in -another process.</p> - - - -<a name="2" id="2"></a> - -<h2>Do all Activities run in the main thread of an application -process?</h2> - -<p>By default, all of the application code in a single process runs -in the main UI thread. This is the same thread -that also handles UI events. The only exception is the code that handles -IPC calls coming in from other processes. The system maintains a -separate pool of transaction threads in each process to dispatch all -incoming IPC calls. The developer should create separate threads for any -long-running code, to avoid blocking the main UI thread.</p> - - - -<a name="3" id="3"></a> - -<h2>How do I pass data between Activities/Services within a single -application?</h2> - -<p>It depends on the type of data that you want to share:</p> - -<h3>Primitive Data Types</h3> - -<p>To share primitive data between Activities/Services in an -application, use Intent.putExtras(). For passing primitive data that -needs to persist use the -<a href="{@docRoot}guide/topics/data/data-storage.html#preferences"> -Preferences</a> storage mechanism.</p> - -<h3>Non-Persistent Objects</h3> - -<p>For sharing complex non-persistent user-defined objects for short -duration, the following approaches are recommended: -</p> - <h4>The android.app.Application class</h4> - <p>The android.app.Application is a base class for those who need to -maintain global application state. It can be accessed via -getApplication() from any Activity or Service. It has a couple of -life-cycle methods and will be instantiated by Android automatically if -your register it in AndroidManifest.xml.</p> - - <h4>A public static field/method</h4> - <p>An alternate way to make data accessible across Activities/Services is to use <em>public static</em> -fields and/or methods. You can access these static fields from any other -class in your application. To share an object, the activity which creates your object sets a -static field to point to this object and any other activity that wants to use -this object just accesses this static field.</p> - - <h4>A HashMap of WeakReferences to Objects</h4> - <p>You can also use a HashMap of WeakReferences to Objects with Long -keys. When an activity wants to pass an object to another activity, it -simply puts the object in the map and sends the key (which is a unique -Long based on a counter or time stamp) to the recipient activity via -intent extras. The recipient activity retrieves the object using this -key.</p> - - <h4>A Singleton class</h4> - <p>There are advantages to using a static Singleton, such as you can -refer to them without casting getApplication() to an -application-specific class, or going to the trouble of hanging an -interface on all your Application subclasses so that your various -modules can refer to that interface instead. </p> -<p>But, the life cycle of a static is not well under your control; so -to abide by the life-cycle model, the application class should initiate and -tear down these static objects in the onCreate() and onTerminate() methods -of the Application Class</p> -</p> - -<h3>Persistent Objects</h3> - -<p>Even while an application appears to continue running, the system -may choose to kill its process and restart it later. If you have data -that you need to persist from one activity invocation to the next, you -need to represent that data as state that gets saved by an activity when -it is informed that it might go away.</p> - -<p>For sharing complex persistent user-defined objects, the -following approaches are recommended: -<ul> - <li>Application Preferences</li> - <li>Files</li> - <li>contentProviders</li> - <li>SQLite DB</li> -</ul> -</p> - -<p>If the shared data needs to be retained across points where the application -process can be killed, then place that data in persistent storage like -Application Preferences, SQLite DB, Files or ContentProviders. Please refer to -the <a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a> -for further details on how to use these components.</p> - - - - -<a name="4" id="4"></a> - -<h2>How can I check if an Activity is already running before starting -it?</h2> - -<p>The general mechanism to start a new activity if its not running— -or to bring the activity stack to the front if is already running in the -background— is the to use the NEW_TASK_LAUNCH flag in the startActivity() -call.</p> - - - -<a name="5" id="5"></a> - -<h2>If an Activity starts a remote service, is there any way for the -Service to pass a message back to the Activity?</h2> - -<p>The remote service can define a callback interface and register it with the -clients to callback into the clients. The -{@link android.os.RemoteCallbackList RemoteCallbackList} class provides methods to -register and unregister clients with the service, and send and receive -messages.</p> - -<p>The sample code for remote service callbacks is given in <a -href="{@docRoot}guide/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">ApiDemos/RemoteService</a></p> - - - -<a name="6" id="6"></a> - -<h2>How to avoid getting the Application not responding dialog?</h2> - -<p>Please read the <a href="{@docRoot}guide/practices/design/responsiveness.html">Designing for Responsiveness</a> -document.</p> - - - - -<a name="7" id="7"></a> - -<h2>How does an application know if a package is added or removed? -</h2> - -<p>Whenever a package is added, an intent with PACKAGE_ADDED action -is broadcast by the system. Similarly when a package is removed, an -intent with PACKAGE_REMOVED action is broadcast. To receive these -intents, you should write something like this: -<pre> - <receiver android:name ="com.android.samples.app.PackageReceiver"> - <intent-filter> - <action android:name="android.intent.action.PACKAGE_ADDED"/> - <action android:name="android.intent.action.PACKAGE_REMOVED"/> - - <data android:scheme="package" /> - </intent-filter> - </receiver> - </pre> - <br> -Here PackageReceiver is a BroadcastReceiver class.Its onReceive() -method is invoked, every time an application package is installed or -removed. - -</p> - - +<script type="text/javascript"> + document.location=toRoot+"resources/faq/framework.html" +</script> +<p>You should have already been redirected by your browser. Please follow +<a href="{@docRoot}resources/faq/framework.html">this link</a>.</p>
\ No newline at end of file diff --git a/docs/html/guide/appendix/faq/index.jd b/docs/html/guide/appendix/faq/index.jd index 90415ae..4194663 100644 --- a/docs/html/guide/appendix/faq/index.jd +++ b/docs/html/guide/appendix/faq/index.jd @@ -1,15 +1,8 @@ -page.title=FAQs, Tips, and How-to @jd:body -<dl> - <dt><a href="commontasks.html">Common Development Tasks and How To Do Them</a></dt> - <dd>Quick and to the point — how-to's for a variety of development tasks you are likely to use.</dd> - <dt><a href="framework.html">Application Framework FAQ</a></dt> - <dd>Common questions about the Android Application Framework.</dd> - <dt><a href="troubleshooting.html">Troubleshooting Tips</a></dt> - <dd>Answers to help you troubleshoot common problems.</dd> - <dt><a href="licensingandoss.html">Open Source Licensing FAQ</a></dt> - <dd>Common topics around licensing and Android Open Source</dd> - <dt><a href="security.html">Android Security FAQ</a></dt> - <dd>Answers to common questions about Android security.</dd> -</dl> +<script type="text/javascript"> + document.location=toRoot+"resources/faq/index.html" +</script> + +<p>You should have already been redirected by your browser. Please follow +<a href="{@docRoot}resources/faq/index.html">this link</a>.</p>
\ No newline at end of file diff --git a/docs/html/guide/appendix/faq/licensingandoss.jd b/docs/html/guide/appendix/faq/licensingandoss.jd index c267fe8..0da97db 100644 --- a/docs/html/guide/appendix/faq/licensingandoss.jd +++ b/docs/html/guide/appendix/faq/licensingandoss.jd @@ -1,19 +1,8 @@ -page.title=Android Open Source Licensing FAQ -parent.title=FAQs, Tips, and How-to -parent.link=index.html @jd:body -<ul> - <li><a href="#mirror">Where can I find the open source components of Android?</a></li> - <li><a href="#timeline">When will we see more code released under open source licenses?</a></li> - <li><a href="#apache2">Why are you releasing the code under the Apache License instead of GPLv2?</a></li> -</ul> +<script type="text/javascript"> + document.location=toRoot+"resources/faq/licensingandoss.html" +</script> -<a name="mirror" id="mirror"></a><h2>Where can I find the open source components of Android?</h2> -<p>The source code for the full Android stack is available from the <a href="http://source.android.com">Android Open Source Project </a> site. - -<p>Other mirrored GPL and LGPL'd components are available at <a href="http://code.google.com/p/android/downloads/list"><code>http://code.google.com/p/android/downloads/list</code></a>.</p> -<p>Notices for other licenses can be found within the SDK.</p> - -<a name="apache2" id="apache2"></a><h2>Why are you releasing the code under the Apache License instead of GPLv2?</h2> -<p>One of the best explanations for the reasoning behind releasing code under Apache2 can be found in a <a href="http://arstechnica.com/news.ars/post/20071106-why-google-chose-the-apache-software-license-over-gplv2.html">ArsTechnica article</a> by Ryan Paul.</p> +<p>You should have already been redirected by your browser. Please follow +<a href="{@docRoot}resources/faq/licensingandoss.html">this link</a>.</p>
\ No newline at end of file diff --git a/docs/html/guide/appendix/faq/security.jd b/docs/html/guide/appendix/faq/security.jd index b0d832b..88bcd51 100644 --- a/docs/html/guide/appendix/faq/security.jd +++ b/docs/html/guide/appendix/faq/security.jd @@ -1,156 +1,8 @@ -page.title=Android Security FAQ -parent.title=FAQs, Tips, and How-to -parent.link=index.html @jd:body -<ul> - <li><a href="#secure">Is Android Secure?</a></li> - <li><a href="#issue">I think I found a security flaw. How do I report - it?</a></li> - <li><a href="#informed">How can I stay informed of Android security - announcements?</a></li> - <li><a href="#use">How do I securely use my Android phone?</a></li> - <li><a href="#malware">I think I found malicious software being distributed - for Android. How can I help?</a></li> - <li><a href="#fixes">How will Android-powered devices receive security fixes?</a> - </li> - <li><a href="#directfix">Can I get a fix directly from the Android Platform - Project?</a></li> -</ul> +<script type="text/javascript"> + document.location=toRoot+"resources/faq/security.html" +</script> - -<a name="secure" id="secure"></a><h2>Is Android secure?</h2> - -<p>The security and privacy of our users' data is of primary importance to the -Android Open Source Project. We are dedicated to building and maintaining one -of the most secure mobile platforms available while still fulfilling our goal -of opening the mobile device space to innovation and competition.</p> - -<p>The Android Platform provides a rich <a -href="http://code.google.com/android/devel/security.html">security model</a> -that allows developers to request the capabilities, or access, needed by their -application and to define new capabilities that other applications can request. -The Android user can choose to grant or deny an application's request for -certain capabilities on the handset.</p> - -<p>We have made great efforts to secure the Android platform, but it is -inevitable that security bugs will be found in any system of this complexity. -Therefore, the Android team works hard to find new bugs internally and responds -quickly and professionally to vulnerability reports from external researchers. -</p> - - -<a name="issue" id="issue"></a><h2>I think I found a security flaw. How do I -report it?</h2> - -<p>You can reach the Android security team at <a -href="mailto:security@android.com">security@android.com</a>. If you like, you -can protect your message using our <a -href="http://code.google.com/android/security_at_android_dot_com.txt">PGP -key</a>.</p> - -<p>We appreciate researchers practicing responsible disclosure by emailing us -with a detailed summary of the issue and keeping the issue confidential while -users are at risk. In return, we will make sure to keep the researcher informed -of our progress in issuing a fix and will properly credit the reporter(s) when -we announce the patch. We will always move swiftly to mitigate or fix an -externally-reported flaw and will publicly announce the fix once patches are -available to users.</p> - - -<a name="informed" id="informed"></a><h2>How can I stay informed of Android -security announcements?</h2> - -<p>An important part of sustainably securing a platform, such as, Android is -keeping the user and security community informed of bugs and fixes. We will -publicly announce security bugs when the fixes are available via postings to -the <a -href="http://groups.google.com/group/android-security-announce">android-security-announce</a> -group on Google Groups. You can subscribe to this group as you would a mailing -list and view the archives here.</p> - -<p>For more general discussion of Android platform security, or how to use -security features in your Android application, please subscribe to <a -href="http://groups.google.com/group/android-security-discuss">android-security-discuss</a>. -</p> - - -<a name="use" id="use"></a><h2>How do I securely use my Android phone?</h2> - -<p>As an open platform, Android allows users to load software from any -developer onto a device. As with a home PC, the user must be -aware of who is providing the software they are downloading and must decide -whether they want to grant the application the capabilities it requests. -This decision can be informed by the user's judgment of the software -developer's trustworthiness, and where the software came from.</p> - -<p>Despite the security protections in Android, it is important -for users to only download and install software from developers they trust. -More details on how Android users can make smart security decisions will be -released when consumer devices become available.</p> - - -<a name="malware" id="malware"></a><h2>I think I found malicious software being -distributed for Android. How can I help?</h2> - -<p>Like any other open platform, it will be possible for unethical developers -to create malicious software, known as <a -href="http://en.wikipedia.org/wiki/Malware">malware</a>, for Android. If you -think somebody is trying to spread malware, please let us know at <a -href="mailto:security@android.com">security@android.com</a>. Please include as -much detail about the application as possible, with the location it is -being distributed from and why you suspect it of being malicious software.</p> - -<p>The term <i>malicious software</i> is subjective, and we cannot make an -exhaustive definition. Some examples of what the Android Security Team believes -to be malicious software is any application that: -<ul> - <li>drains the device's battery very quickly;</li> - <li>shows the user unsolicited messages (especially messages urging the - user to buy something);</li> - <li>resists (or attempts to resist) the user's effort to uninstall it;</li> - <li>attempts to automatically spread itself to other devices;</li> - <li>hides its files and/or processes;</li> - <li>discloses the user's private information to a third party, without the - user's knowledge and consent;</li> - <li>destroys the user's data (or the device itself) without the user's - knowledge and consent;</li> - <li>impersonates the user (such as by sending email or buying things from a - web store) without the user's knowledge and consent; or</li> - <li>otherwise degrades the user's experience with the device.</li> -</ul> -</p> - - -<a name="fixes" id="fixes"></a><h2>How will Android-powered devices receive security -fixes?</h2> - -<p>The manufacturer of each device is responsible for distributing software -upgrades for it, including security fixes. Many devices will update themselves -automatically with software downloaded "over the air", while some devices -require the user to upgrade them manually.</p> - -<p>When Android-powered devices are publicly available, this FAQ will provide links how -Open Handset Alliance members release updates.</p> - -<a name="directfix" id="directfix"></a><h2>Can I get a fix directly from the -Android Platform Project?</h2> - -<p>Android is a mobile platform that will be released as open source and -available for free use by anybody. This means that there will be many -Android-based products available to consumers, and most of them will be created -without the knowledge or participation of the Android Open Source Project. Like -the maintainers of other open source projects, we cannot build and release -patches for the entire ecosystem of products using Android. Instead, we will -work diligently to find and fix flaws as quickly as possible and to distribute -those fixes to the manufacturers of the products.</p> - -<p>In addition, We will add security fixes to the open source distribution of -Android and publicly announce the changes on <a -href="http://groups.google.com/group/android-security-announce">android-security-announce</a>. -</p> - -<p>If you are making an Android-powered device and would like to know how you can -properly support your customers by keeping abreast of software updates, please -contact us at <a -href="mailto:info@openhandsetalliance.com">info@openhandsetalliance.com</a>.</p> +<p>You should have already been redirected by your browser. Please follow +<a href="{@docRoot}resources/faq/security.html">this link</a>.</p>
\ No newline at end of file diff --git a/docs/html/guide/appendix/faq/troubleshooting.jd b/docs/html/guide/appendix/faq/troubleshooting.jd index 86ab187..e3a9e4182 100755 --- a/docs/html/guide/appendix/faq/troubleshooting.jd +++ b/docs/html/guide/appendix/faq/troubleshooting.jd @@ -1,335 +1,8 @@ -page.title=Troubleshooting -parent.title=FAQs, Tips, and How-to -parent.link=index.html @jd:body +<script type="text/javascript"> + document.location=toRoot+"resources/faq/troubleshooting.html" +</script> -<p>Here are some tips and tricks for common Android errors. Don't forget to use the - ddms logcat capability to get a deeper view when errors occur. See <a href="{@docRoot}guide/developing/debug-tasks.html">Debugging</a> for more debugging tips. </p> -<ul> - <li><a href="#installeclipsecomponents">ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui".</a></li> - <li><a href="#nodevice">ADB reports "no device" when an emulator is running</a></li> - <li><a href="#noapp">My new application/activity isn't showing up in the device application - list </a></li> - <li><a href="#noupdate">I updated my app, but the updates don't seem to be showing up on - the device</a></li> - <li><a href="#layout_wilih">I'm getting a "Binary XML file line #2: You must supply a layout_wilih - attribute" error when I start an application</a></li> - <li><a href="#permission">My request to (<em>make a call, catch an incoming SMS, receive - a notification, send an intent to an Android application</em>) is being - ignored</a></li> - <li><a href="#build">Help! My project won't build in Eclipse</a></li> - <li><a href="#eclipse">Eclipse isn't talking to the emulator</a></li> - <li><a href="#majorminor">When I go to preferences in Eclipse and select "Android", I get the following error message: Unsupported major.minor version 49.0.</a></li> - <li><a href="#apidemosreinstall">I can't install ApiDemos apps in my IDE because of a signing error</a></li> - <li><a href="#gesturebuilderinstall">I can't install the GestureBuilder sample -app in the emulator</a></li> - <li><a href="#signingcalendar">I can't compile my app because the build tools generated an expired debug certificate</a></li> - <li><a href="#manifestfiles">Unable to view manifest files from within Eclipse</a></li> -</ul> - -<a name="installeclipsecomponents" id="installeclipsecomponents"></a><h2>ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui".</h2> -<p> -The "Android Editors" feature of the ADT Plugin requires specific Eclipse components, such as WST. If you -encounter this error message during ADT installation, you need to install the -required Eclipse components and then try the ADT installation again. Follow the steps below to install the required components for the -Android Editors feature, based on the version of Eclipse that you are using.</p> - -<table style="font-size:100%"> -<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr> -<tr> -<td width="50%"> -<ol> -<li>From the dialog where you select the <strong>Update sites to visit</strong>, select the checkboxes for both the -ADT site, and the Callisto/Europa/Ganymede Discovery Site (you may want to -check <strong>Automatically select mirrors</strong> at the bottom).</li> -<li>Click <strong>Finish</strong>.</li> -<li>In the <strong>Next</strong> dialog, select the Android Plugins.</li> -<li>Now, expand the tree item of the discovery site. It seems that if you -don't do it, it doesn't load the content of the discovery site.</li> -<li>On the right, click <strong>Select required</strong>. This will select all the components -that are required to install the Android plugin (wst, emf, etc...).</li> -<li>Click <strong>Next</strong>, accept the agreement, click <strong>Install All</strong>, and restart Eclipse.</li> -</ol> -</td> -<td> -<ol> - <li>Select <strong>Help</strong> > <strong>Software Updates...</strong></li> - <li>Select the <strong>Installed Software</strong> tab.</li> - <li>Click <strong>Update...</strong></li> - <li>If an update for ADT is available, select it and click <strong>Finish</strong>.</li> -</ol> -</td> -</tr> -</table> - - -</p> -<a name="nodevice"></a><h2>ADB reports "no device" when an emulator is running</h2> - <p>Try restarting adb by stopping it (<code>adb - kill-server</code>) then any other adb command to restart it.</p> - -<a name="noapp"></a><h2>My new application/activity isn't showing up in the - applications list </h2> -<ul> - <li>You often must restart your device or emulator before a new activity shows - up in the applications list. This is particularly true when it is a completely - new application with a new AndroidManifest.xml file.</li> - <li>If this is for a new activity in an existing AndroidManifest.xml file, did - you include an <code><activity></code> tag for your app (or a <code><service></code> tag - for a service, or a <code><receiver></code> tag for a receiver, etc.)? </li> - <li>Make sure that your AndroidManifest.xml file is valid. Errors in attribute - values, such as the <em>value </em> attribute in <code><action <em>value</em>="<em><something></em>"></code> - will often not be caught by compilers, but will prevent your application - from being displayed because the intent filter will not be matched. Extra - spaces or other characters can often sneak into these strings.</li> - <li>Did you send your .apk file to the device (<a href="{@docRoot}guide/developing/tools/adb.html#move">adb install</a>)?</li> - <li>Run logcat on your device (<code>adb logcat</code>) - and then install your .apk file. Check the logcat output to see whether the - application is being installed and recognized properly. Here's sample output - from a successful installation: -<pre>I/FileObserver( 414): *** onEvent wfd: 3 mask: 8 path: MyRSSReader.apk -D/PackageManager( 414): Scanning package: /data/app/MyRSSReader.apk -D/PackageManager( 414): Adding package com.example.codelab.rssexample -D/PackageManager( 414): Registered content provider: my_rss_item, className = com.example.codelab.rssexample.RssContentProvider, isSyncable = false -D/PackageManager( 414): Providers: com.example.codelab.rssexample.RssContentProvider -D/PackageManager( 414): Activities: com.example.codelab.rssexample.MyRssReader com.example.codelab.rssexample.MyRssReader2 </pre> - </li> - <li>If logcat shows that the package manager is having problems loading the manifest - file, force your manifest to be recompiled by adding a space in the file and - compiling it.</li> -</ul> -<a name="noupdate"></a><h2>I updated my app, but the updates don't seem to be showing up on the device</h2> - <p>Did you remember to send your .apk file to the device (<a href="{@docRoot}guide/developing/tools/adb.html#move">adb - install</a>)?</p> - -<a name="layout_wilih"></a><h2>I'm getting a "Binary XML file line #2: You must supply a layout_wilih - attribute" error - when I start an application (but I declare a layout_wilih attribute <em>right - there!!!</em>)</h2> -<ul> - <li>Make sure that the SDK you are building with is the same version as the Android - OS that you are running on. </li> - <li>Make sure that you're calling setContentView() early in your onCreate() method. - Calling other methods, such as setListAdapter() before calling setContentView() - can sometimes create odd errors when Android tries to access screen elements - that haven't been set before.</li> -</ul> -<a name="permission"></a><h2>My request to (<em>make a call, catch an incoming SMS, -receive a notification, send an intent to an Android application</em>) is being -ignored</h2> - <p>You might not have permission (or might not have requested permission) to - call this activity or receive this intent. Many standard Android activities, - such as making a call, have a permission assigned to it to prevent arbitrary - applications from sending or receiving requests. See <a - href="{@docRoot}guide/topics/security/security.html">Security and - Permissions</a> for more information on permissions, and - {@link android.Manifest.permission Manifest.permission} for a list of - standard permissions supported by the Android platform. -</p> -<a name="build"></a><h2>Help! My project won't build in Eclipse</h2> -<p>If your project doesn't build, you may notice symptoms such as new -resources added in the <code>res/</code> sub-folders not showing up in the R class, -the emulator not being started, not being able to run the application, or even seeming to run an old version of the application.</p> -<p>To troubleshoot these types of problems, first try:</p> -<ol> - <li>Switch to the DDMS view in Eclipse (if you don't already have it open): - <ol type="a"> - <li>From the menu select <code>Window > Open Perspective > Other</code></li> - <li>Select DDMS from the list and hit OK</li> - </ol> - </li> - <li>In the Devices panel (top right panel by default), click on the down triangle - to bring up the panel menu</li> - <li>Select <code>Reset ADB</code> from the menu, and then try running the - application again</li> -</ol> -<p>If the above still doesn't work, you can try these steps:</p> -<ol> - <li> - Check the console and problems tabs at the bottom of the Eclipse UI - </li> - <li> - If there are problems listed in either place, they should give you a clue - what is wrong - </li> - <li> - If you aren't sure if the problems are fresh or stale, clear the console - with a right click > Clear, then clean the project - </li> - <li> - To clean the project (a good idea with any kind of build error), select - Project > Clean from the eclipse main menu, then select the project you - are working on (or clean all) - </li> -</ol> -<a name="eclipse"></a><h2>Eclipse isn't talking to the emulator</h2> -<p>When communication doesn't seem to be happening between Eclipse and the emulator, symptoms can include: nothing happening when you press run, the emulator hanging waiting -for a debugger to connect, or errors that Eclipse reports about not being able -to find the emulator or shell. By far the most common symptom is that when you press run, the emulator starts (or -is already running), but the application doesn't start.</p> -<p> -You may find any of these steps will fix the problem and with practice you -probably can figure out which one you need to do for your particular issue, but -to start with, the safest option is to run through all of them in order:</p> -<ol> - <li> - Quit the emulator if it is running - </li> - <li> - Check that any emulator processes are killed (sometimes they can hang, use ps on unix or mac, or task manager in the process view on - windows). - </li> - <li> - Quit Eclipse - </li> - <li> - From the command line, type: -<pre>adb kill-server </pre> - </li> - <li> - Start Eclipse and try again - </li> -</ol> - -<a name="majorminor"></a><h2>When I go to preferences in Eclipse and select "Android", I get the following error message: Unsupported major.minor version 49.0.</h2> -<p>This error is displayed if you are using an older version of the JDK. Please make sure you are using JDK version 5 or 6.</p> - -<h2 id="apidemosreinstall">I can't install ApiDemos apps in my IDE because of a signing error</a></h2> - -<p>The Android system requires that all applications be signed, as described in - <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>. The ApiDemos -applications included with the SDK are preinstalled on the emulator and for that reason have been -compiled and signed with a private key.</p> - -If you want to modify or run one of the ApiDemos apps from Eclipse/ADT or other IDE, you can do so -so only after you uninstall the <em>preinstalled</em> version of the app from the emulator. If -you try to run an ApiDemos app from your IDE without removing the preinstalled version first, -you will get errors similar to these: </p> - -<pre>[2008-08-13 15:14:15 - ApiDemos] Re-installation failed due to different application signatures. -[2008-08-13 15:14:15 - ApiDemos] You must perform a full uninstall of the application. WARNING: ...This will remove the application data! -[2008-08-13 15:14:15 - ApiDemos] Please execute 'adb uninstall com.android.samples' in a shell.</pre> - -<p>The error occurs because, in this case, you are attempting to install another copy of ApiDemos -onto the emulator, a copy that is signed with a different certificate. (The Android IDE tools will -have signed the app with a debug certificate, where the existing version was already signed with -a private certificate.) The system does not allow this type of reinstallation. </p> - -<p>To resolve the issue, you need to fully uninstall the preinstalled and then reinstall it using -the adb tool. Here's how to do that:</p> - -<ol> - <li>In a terminal, change to the tools directory of the SDK.</li> - <li>If no emulator instance is running, start an emulator using using the command <code>emulator &</code>.</li> - <li>Uninstall the preinstalled app using the command <code>adb uninstall com.android.samples</code>.</li> - <li>Reinstall the app using the command <code>adb install <path to the ApiDemos.apk></code>. If you are - working in Eclipse/ADT, you can just compile and run the app in the normal way. </li> -</ol> - -<p>Note that if multiple emulator instances are running, you need to direct your uninstall/install -commands to the emulator instance that you are targeting. To do that you can add the -<code>-s <serialNumber></code> to the command, for example: </p> - -<pre>adb -s emulator-5556 install</pre> - -<p>For more information about adb, see the <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> -documentation.</p> - -<h2 id="gesturebuilderinstall">I can't install the GestureBuilder sample -app in the emulator</a></h2> - -<p>This is similar to the ApiDemos problem described above, except that -you cannot fix it by uninstalling GestureBuilder from the emulator. The -GestureBuilder app cannot be uninstalled because it is currently installed -within the system files themselves.</p> - -<p><strong>Symptoms</strong></p> - -<ul><li><p>You cannot run GestureBuilder in the emulator:</p> - -<pre>[2009-12-10 14:57:19 - GestureBuilderActivity]Re-installation failed due to different application signatures. -[2009-12-10 14:57:19 - GestureBuilderActivity]You must perform a full uninstall of the application. WARNING: This will remove the application data! -[2009-12-10 14:57:19 - GestureBuilderActivity]Please execute 'adb uninstall com.android.gesture.builder' in a shell.</pre> -</li> - -<li><p>Running <code>adb uninstall com.android.gesture.builder</code> fails:</p> -<pre>$ adb uninstall com.android.gesture.builder - Failure</pre> -</li></ul> - -<p>For now, the work-around is to change the sample's package name -so that the system can install it as a new app rather than as a -replacement for the existing GestureBuilder app. To change the -package name, open the manifest file and modify the package attribute -of the manifest element. Next, update imports and other references to -the package name, rebuild the app, and run it in an AVD.</p> - -<p>For example, here's how you could do this in Eclipse:</p> - -<ol> - <li>Right-click on the package name -(<code>src/com.android.gesture.builder</code>).</li> - <li>Select <strong>Refactor > Rename</strong> and change the name, for example to -<code>com.android.gestureNEW.builder</code>. </li> - <li>Open the manifest file. Inside the <code><manifest></code> -tag, change the package name to -<code>com.android.gestureNEW.builder</code>.</li> - <li>Open each of the two Activity files and do Ctrl-Shift-O to add -missing import packages, then save each file.</li> -<li>Run the GestureBuilder application on the emulator.</li> -</ol> - -<p>If you get an error message such as "Could not load /sdcard/gestures. -Make sure you have a mounted SD card," be sure that your target AVD has an -SD card. To create an AVD that has an SD card, use the -<a href="{@docRoot}guide/developing/tools/avd.html#options"><code>-c</code> -option</a> in the <code>android create avd</code> command.</p> - -<h2 id="signingcalendar">I can't compile my app because the build tools generated an expired debug certificate</h2> - -<p>If your development machine uses a locale that has a non-Gregorian calendar, you may encounter problems when first trying to compile and run your application. Specifically, you may find that the Android build tools won't compile your application because the debug key is expired. </p> - -<p>The problem occurs because the Keytool utility — included in the JDK and used by the Android build tools — fails to properly handle non-Gregorian locales and may create validity dates that are in the past. That is, it may generate a debug key that is already expired, which results in the compile error.</p> - -<p>If you encounter this problem, follow these steps to work around it: </p> - -<ol> -<li>First, delete the debug keystore/key already generated by the Android build tools. Specifically, delete the <code>debug.keystore</code> file. On Linux/Mac OSX, the file is stored in <code>~/.android</code>. On Windows XP, the file is stored in <code> -C:\Documents and Settings\<user>\.android</code>. On Windows Vista, the file is stored in <code> -C:\Users\<user>\.android</code></li> -<li>Next, you can either -<ul> -<li>Temporarily change your development machine's locale (date and time) to one that uses a Gregorian calendar, for example, United States. Once the locale is changed, use the Android build tools to compile and install your app. The build tools will regenerate a new keystore and debug key with valid dates. Once the new debug key is generated, you can reset your development machine to the original locale. </li> -<li>Alternatively, if you do not want to change your machine's locale settings, you can generate the keystore/key on any machine using the Gregorian calendar, then copy the <code>debug.keystore</code> file from that computer to the proper location on your development machine. </li> -</ul> -</li> -</ol> - -<p>This problem has been verified on Windows and may apply to other platforms. </p> - -<p>For general information about signing Android applications, see -<a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>. </p> - -<h2 id="manifestfiles">Unable to view manifest files from within -Eclipse</a></h2> - -<p>When you try to open an application's manifest file from within -Eclipse, you might get an error such as this one:</p> -<pre>An error has occurred. See error log for more details. -org.eclipse.wst.sse.ui.StructuredTextEditor.isBlockSelectionModeEnabled()Z</pre> - -<p>Try reverting to the 3.0 version of the Eclipse XML Editors and -Tools. If this does not work, remove the 3.1 version of the tool. To do -this in Eclipse 3.4:</p> - -<ol> - <li>Select <strong>Help > Software Updates...</strong></li> - <li>Select the <strong>Installed Software</strong> tab.</li> - <li>Select <strong>Eclipse XML Editors and Tools</strong>.</li> - <li>Click <strong>Uninstall</strong>.</li> - <li>Click <strong>Finish</strong>.</li> -</ol> - -<p>When you restart Eclipse, you should be able to view the manifest -files. </p> +<p>You should have already been redirected by your browser. Please follow +<a href="{@docRoot}resources/faq/troubleshooting.html">this link</a>.</p>
\ No newline at end of file diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd index abfae5d..3127e10 100644 --- a/docs/html/guide/developing/device.jd +++ b/docs/html/guide/developing/device.jd @@ -119,7 +119,7 @@ USB device support on Linux. The USB Vendor ID is the value given to the <table> <tr> - <th>Manufacturer</th><th>USB Vendor ID</th></tr> + <th>Company</th><th>USB Vendor ID</th></tr> <tr> <td>Acer</td> <td><code>0502</code></td></tr> @@ -133,6 +133,9 @@ USB device support on Linux. The USB Vendor ID is the value given to the <td>Garmin-Asus</td> <td><code>091E</code></td></tr> <tr> + <td>Google</td> + <td><code>18d1</code></td></tr> + <tr> <td>HTC</td> <td><code>0bb4</code></td></tr> <tr> diff --git a/docs/html/guide/developing/index.jd b/docs/html/guide/developing/index.jd index 3a64dbc..4257bf0 100644 --- a/docs/html/guide/developing/index.jd +++ b/docs/html/guide/developing/index.jd @@ -23,7 +23,7 @@ page.title=Introduction before continuing.</p> </li> - <li>Set up Android Virtual Devices or hardware devices</a>. + <li>Set up Android Virtual Devices or hardware devices. <p>You need to create Android Virtual Devices (AVD) or connect hardware devices on which you will install your applications.</p> @@ -66,8 +66,8 @@ information. run tests within an emulator or device.</p> </li> </ol> - - <h2 id="EssentialTools">Essential command line tools</h2> + +<h2 id="EssentialTools">Essential command line tools</h2> <p>When developing in IDEs or editors other than Eclipse, be familiar with all of the tools below, because you will have to run them from the command line.</p> @@ -112,6 +112,43 @@ information. Eclipse, such as the <code>adb</code> shell commands. You might also need to call Keytool and Jarsigner to sign your applications, but you can set up Eclipse to do this automatically as well.</p> - <p>For more information on the tools provided with the Android SDK, see the +<p>For more information on the tools provided with the Android SDK, see the <a href="{@docRoot}guide/developing/tools/index.html">Tools</a> section of the documentation.</p> + +<h2 id="ThirdParty">Third-Party Development Tools</h2> +<p> + The tools described in this section are not developed by the Android SDK team. The Android Dev Guide + does not provide documentation for these tools. Please refer to the linked documents in each + section for documentation. +</p> +<h3 id="IntelliJ">Developing in IntelliJ IDEA</h3> +<div style="float: right"> +<img alt="The IntelliJ graphical user interface" height="500px" src="{@docRoot}images/developing/intellijidea_android_ide.png"/> +</div> +<p> + IntelliJ IDEA is a powerful Java IDE from JetBrains that provides + full-cycle Android development support in both the free Community + Edition and the Ultimate edition. +</p> +<p> + The IDE ensures compatibility with the latest Android SDK and offers a + smart code editor with completion, quick navigation between code and + resources, a graphical debugger, unit testing support using Android + Testing Framework, and the ability to run applications in either the + emulator or a USB-connected device. +</p> +<p> + <strong>Links:</strong> +</p> +<ul> + <li> + <a href="http://www.jetbrains.com/idea">IntelliJ IDEA official website</a> +</li> + <li> + <a href="http://www.jetbrains.com/idea/features/google_android.html">Android support in IntelliJ IDEA</a> +</li> + <li> + <a href="http://wiki.jetbrains.net/intellij/Android">IntelliJ IDEA Android Tutorials</a> + </li> +</ul> diff --git a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd index 97c7c1f..c0795d7 100644 --- a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd +++ b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd @@ -128,7 +128,7 @@ device.startActivity(component=runComponent) device.press('KEYCODE_MENU','DOWN_AND_UP') # Takes a screenshot -result = device.takeSnapShot() +result = device.takeSnapshot() # Writes the screenshot to a file result.writeToFile('myproject/shot1.png','png') diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index b13600c..c258949 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -630,7 +630,7 @@ <span class="zh-TW" style="display:none">準備發佈</span> </a></li> <li><a href="<?cs var:toroot ?>guide/publishing/publishing.html"> - <span class="en">Publishing Your Applications</span> + <span class="en">Publishing on Android Market</span> </a></li> </ul> </li> diff --git a/docs/html/guide/publishing/app-signing.jd b/docs/html/guide/publishing/app-signing.jd index 93077a0..df240e2 100644 --- a/docs/html/guide/publishing/app-signing.jd +++ b/docs/html/guide/publishing/app-signing.jd @@ -260,8 +260,8 @@ looks like this:</p> <p>To fix this problem, simply delete the <code>debug.keystore</code> file. The default storage location for AVDs is in <code>~/.android/</code> on OS X and Linux, -in <code>C:\Documents and Settings\<user>\.android\</code> on Windows XP, and in -<code>C:\Users\<user>\.android\</code> on Windows Vista.</p> +in <code>C:\Documents and Settings\<user>\.android\</code> on Windows XP, and in +<code>C:\Users\<user>\.android\</code> on Windows Vista and Windows 7.</p> <p>The next time you build, the build tools will regenerate a new keystore and debug key.</p> diff --git a/docs/html/guide/publishing/publishing.jd b/docs/html/guide/publishing/publishing.jd index af1ea74..0cbba53 100644 --- a/docs/html/guide/publishing/publishing.jd +++ b/docs/html/guide/publishing/publishing.jd @@ -1,4 +1,4 @@ -page.title=Publishing Your Applications +page.title=Publishing on Android Market @jd:body <div id="qv-wrapper"> @@ -16,22 +16,22 @@ page.title=Publishing Your Applications <h2>In this document</h2> <ol> -<li><a href="#overview">Publishing on Android Market</a> - <ol> - <li><a href="#marketupgrade">Publishing Updates on Android Market</a></li> - <li><a href="#marketLicensing">Using Android Market Licensing Service</a></li> - <li><a href="#marketintent">Using Intents to Launch the Market Application</a></li> - </ol></li> -<!-- -<li><span style="color:ccc">Publishing on Other Hosted Services</a></li> -<li><span style="color:ccc">Publishing through a Web Server</a></li> ---> +<li><a href="#overview">About Android Market</a> +<li><a href="#marketupgrade">Publishing Updates on Android Market</a></li> +<li><a href="#marketLicensing">Using Android Market Licensing Service</a></li> +<li><a href="#marketintent">Linking to Your Apps on Android Market</a> + <ol> + <li><a href="#OpeningDetails">Opening an app's details page</a></li> + <li><a href="#PerformingSearch">Performing a search</a></li> + <li><a href="#UriSummary">Summary of URI formats</a></li> + </ol> +</li> </ol> <h2>See also</h2> <ol> -<li><a href="{@docRoot}guide/publishing/licensing.html">Licensing Your Applications</a></li> +<li><a href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a></li> <li><a href="{@docRoot}guide/publishing/preparing.html">Preparing to Publish</a></li> </ol> @@ -39,43 +39,45 @@ page.title=Publishing Your Applications <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;">Interested in publishing your app on Android Market?</p> - <a id="publish-link" href="http://market.android.com/publish">Go to Android Market »</a> + <h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2> + <p><a href="http://market.android.com/publish">Go to Android Market</a> to +create a developer account and upload your application. For more information about the +required assets, listing details, and options, see <a +href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading +applications</a>.</p> </div> </div> </div> </div> -<p>Publishing an application means testing it, packaging it appropriately, and making -it available to users of Android-powered mobile devices for download or sideload.</p> +<p>If you've followed the steps outlined in <a +href="{@docRoot}guide/publishing/preparing.html">Preparing to Publish</a>, the result of the process +is a compiled {@code .apk} file that is signed with your private release key. Your application is +now ready to be published publicly so users can install it.</p> -<p>If you've followed the steps outlined in -<a href="{@docRoot}guide/publishing/preparing.html">Preparing to -Publish Your Applications</a>, the result of the process is a compiled .apk that -is signed with your release private key. Inside the .apk, the application is -properly versioned and any MapView elements reference a Maps API Key that you -obtained by registering the MD5 fingerprint of the same certificate used to sign -the .apk. Your application is now ready for publishing. </p> +<p>You can publish your application and allow users to install it any way you choose, including +from your own web server. This document provides information about publishing your Android +application with Android Market.</p> -<p>The sections below provide information about publishing your Android -application to mobile device users.</p> -<h2 id="overview">Publishing on Android Market</h2> +<h2 id="overview">About Android Market</h2> -<p>Android Market is a hosted service that makes it easy for users to find and -download Android applications to their Android-powered devices, and makes it -easy for developers to publish their applications to Android users.</p> +<p>Android Market is a service that makes it easy for users to find and download Android +applications to their Android-powered devices, either from the Android Market application on their +device or from the Android Market web site (<a +href="http://market.android.com">market.android.com</a>). As a developer, you can use Android Market +to distribute your applications to users on all types of Android-powered devices, all around the +world.</p> <p>To publish your application on Android Market, you first need to register -with the service using your Google account and agree to the terms of service. +with the service using a Google account and agree to the terms of service. Once you are registered, you can upload your application to the service whenever -you want, as many times as you want, and then publish it when you are ready. -Once published, users can see your application, download it, and rate it using -the Market application installed on their Android-powered devices. </p> +you want, update it as many times as you want, and then publish it when you are ready. +Once published, users can see your application, download it, and rate it. </p> <p>To register as an Android Market developer and get started with publishing, -visit the Android Market: </p> +visit the Android Market publisher site: </p> <p style="margin-left:3em;"><a href="http://market.android.com/publish">http://market.android.com/publish</a> @@ -94,22 +96,24 @@ validity period ends after <span style="color:red">22 October 2033</span>. </li> <code>android:versionName</code> attribute in the <a href="{@docRoot}guide/topics/manifest/manifest-element.html"><code><manifest></code></a> -element of its manifest. The server uses the <code>android:versionCode</code> as +element of its manifest file. The server uses the <code>android:versionCode</code> as the basis for identifying the application internally and handling updates, and it displays the <code>android:versionName</code> to users as the application's version.</li> <li>Your application must define both an <code>android:icon</code> and an -<code>android:label</code> attribute in the <code><application></code> -element of its manifest.</li> +<code>android:label</code> attribute in the <a +href="{@docRoot}guide/topics/manifest/application-element.html"><code><application></code></a> +element of its manifest file.</li> </ol> </div> -<h3 id="marketupgrade">Publishing Updates on Android Market</h3> + +<h2 id="marketupgrade">Publishing Updates on Android Market</h2> <p>At any time after publishing an application on Android Market, you can upload and publish an update to the same application package. When you publish an update to an application, users who have already installed the -application will automatically receive a notification that an update is +application may receive a notification that an update is available for the application. They can then choose to update the application to the latest version.</p> @@ -117,190 +121,231 @@ to the latest version.</p> the <code>android:versionCode</code> and <code>android:versionName</code> attributes in the <a href="{@docRoot}guide/topics/manifest/manifest-element.html"><code><manifest></code></a> -element of the manifest file. Also, the package name must be the same and the -.apk must be signed with the same private key. If the package name and signing +element of the manifest file. Also, the package name must be the same as the existing version and +the {@code .apk} file must be signed with the same private key. If the package name and signing certificate do <em>not</em> match those of the existing version, Market will -consider it a new application and will not offer it to users as an update.</p> +consider it a new application, publish it as such, and will not offer it to existing users as an +update.</p> -<h3 id="marketLicensing">Using Android Market Licensing Service</h3> +<h2 id="marketLicensing">Using Android Market Licensing Service</h2> <p>Android Market offers a licensing service that lets you enforce licensing policies for paid applications that you publish through Android Market. With -Android Market Licensing, your applications can query Android Market at run time -to obtain their licensing status for the current user, then allow or disallow -further use as appropriate. Using the service, you can apply a flexible -licensing policy on an application-by-application basis — each +Android Market Licensing, your applications can query Android Market at runtime +to obtain the licensing status for the current user, then allow or disallow +further use of the application as appropriate. Using the service, you can apply a flexible +licensing policy on an application-by-application basis—each application can enforce its licensing status in the way most appropriate for it. </p> <p>Any application that you publish through Android Market can use the Android -Market Licensing Service. The service uses no dedicated framework APIs, you can -add licensing to any legacy application that uses a minimum API level of 3 or +Market Licensing Service. The service uses no dedicated framework APIs, so you can +add licensing to any application that uses a minimum API Level of 3 or higher.</p> <p>For complete information about Android Market Licensing Service and how to -use it in your application, see <a -href="{@docRoot}guide/publishing/licensing.html">Licensing Your -Applications</a>.</p> +use it in your application, read <a +href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a>.</p> -<h3 id="marketintent">Using Intents to Launch the Market Application on -a Device</h3> -<p>Android-powered devices include a preinstalled Market application that gives -users access to the Android Market site. From Market, users can -browse or search available applications, read ratings and reviews, and -download/install applications.</p> +<h2 id="marketintent">Linking to Your Apps on Android Market</h2> -<p>You can launch the Market application from another Android -application by sending an Intent to the system. You might want to do -this, for example, to help the user locate and download an update to an -installed application, or to let the user know about related -applications that are available for download. </p> +<p>To help users discover your published applications, you can use two special Android Market URIs +that direct users to your application's details page or perform a search for all of your published +applications in Android Market. You can use these URIs to do the following:</p> -<p>To launch Market, you send an ACTION_VIEW Intent, passing a Market-handled -URI string as the Intent data. In most cases, your application would call -startActivity() to send the ACTION_VIEW Intent with the Market-handled URI.</p> - -<p>The URI that you supply with the Intent lets the system route the intent -properly and also expresses the type of action that you want Market to perform -after launch. Currently, you can have Market take these actions:</p> +<ul> + <li>Create a button in your application or a link on a web page that opens one of your +application's details page in the Android Market application or web site.</li> + <li>Create a button in your application or a link on a web page that searches for all your +published applications in the Android Market application or web site.</li> +</ul> +<p>You can launch the Android Market application or web site in the following ways:</p> <ul> -<li>Initiate a search for applications on Android Market, based on the query -parameters that you provide, or </li> -<li>Load the Details page for a specific application on Android Market, based on -the application's package name.</li> + <li>Initiate an {@link android.content.Intent} from your application that launches the +Android Market application on the user's device. The intent must use the {@link +android.content.Intent#ACTION_VIEW} action, and include intent data with the appropriate +Android Market URI scheme.</li> + <li>Provide a hyperlink on a web page that opens the Android Market web site.</li> </ul> -<h4>Initiating a search</h4> +<p>In both cases, you need to create a URI that indicates either the application you'd like to view +in Android Market or the search you'd like to perform. The URI is quite similar whether you want +to open the application or open the web site. The only difference is the URI prefix.</p> + +<p>To open the Android Market application on the device, the prefix for the intent's data URI +is:</p> + +<p style="margin-left:2em"><code>market://</code></p> + +<p>To open the Android Market web site, the prefix for the link URI is:</p> + +<p style="margin-left:2em"><code>http://market.android.com/</code></p> + +<p>To complete each URI, you must append a string that specifies either the +application for which you want to view or the search to execute. The following sections +describe how to create a complete URI for each case.</p> + +<p class="note"><strong>Note:</strong> If you create a link to open the Android Market web site and +the user selects it from an Android-powered device, the Android Market application will also resolve +the link so the user can use the native application instead of the web site. Also, because the +Android Market application also reads the {@code http://} URIs, you can also use them in an intent, +but you should usually use the {@code market://} URIs for an intent, so that the native application +is opened by default. You should use {@code http://} URIs only when creating links from a web +page.</p> + + +<h3 id="OpeningDetails">Opening an app's details page</h3> + +<p>As described above, you can open the details page for a specific application either on the +Android Market application or the Android Market web site. The details page allows the user to see +the application description, screenshots, reviews and more, and choose to install it.</p> -<p>Your application can initiate a search on Android Market for applications -that match the query parameters that you provide. To do so, your application -sends an ACTION_VIEW Intent that includes a URI and query parameters in this +<p>The format for the URI that opens the details page is:</p> + +<p style="margin-left:2em"><code><URI_prefix><b>details?id=</b><package_name></code></p> + +<p>The <code><package_name></code> is a placeholder for the target application's fully +qualified package name, as declared in the <a +href="{@docRoot}guide/topics/manifest/manifest-element.html#package">{@code +package}</a> attribute of the <a href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code +<manifest>}</a> element in the application's manifest file.</p> + + +<h4>Opening details in the Android Market application</h4> + +<p>To open the details page in the Android Market application, create an intent with the +{@link android.content.Intent#ACTION_VIEW} action and include a data URI in this format:</p> + +<p style="margin-left:2em"><code>market://details?id=<package_name></code></p> + +<p>For example, here's how you can create an intent and open an application's details page in the +Android Market application:</p> + +<pre> +Intent intent = new Intent(Intent.ACTION_VIEW); +intent.setData(Uri.parse("market://details?id=com.android.example")); +startActivity(intent); +</pre> + + +<h4>Opening details on the Android Market web site</h4> + +<p>To open the details page on the Android Market web site, create a link with a URI in this format:</p> -<p style="margin-left:2em"><code>market://search?q=<paramtype>:<value></code></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;">Searches on Android Market</p> -<p>When you initiate a search, Android Market returns results from matches in -the public metadata supplied by developers in their Android Market profiles or -application publishing information, but not from the developer's private account -or from the certificate used to sign the application. </p> - </div> -</div> +<p style="margin-left:2em"> + <code>http://market.android.com/details?id=<package_name></code> +</p> + +<p>For example, here's a link that opens an application's details page on the Android Market web +site:</p> -<p>Using this URI format, you can search for applications by:</p> +<pre> +<a href="http://market.android.com/details?id=com.android.example">App Link</a> +</pre> + + + +<h3 id="PerformingSearch">Performing a search</h3> + +<p>To initiate a search in Android Market, the format for the URI is:</p> + +<p style="margin-left:2em"> + <code><URI_prefix><b>search?q=</b><query></code> +</p> + +<p>The <code><query></code> is a placeholder for the search query to execute in Android +Market. The query can be a raw text string or you can include a parameter that performs a search +based on the publisher name:</p> <ul> -<li>Package name</li> -<li>Developer name</li> -<li>String match across application name, developer name, and -description, or </li> -<li>Any combination of the above</li> + <li>To perform a raw text search, append the query string: + <p><code><URI_prefix><b>search?q=</b><search_query></code></p></li> + + <li>To search based on the publisher name, use the {@code pub:} parameter in the query, followed +by the publisher name: + <p><code><URI_prefix><b>search?q=pub:</b><publisher_name></code></p> + <p>You can use this type of search to show all of your published applications.</p></li> </ul> -<p>The table at the bottom of this page specifies the <code>paramtypes</code> -and <code>values</code> that correspond to each of these types of search. </p> -<p>When you send an intent to initiate a search for applications, Market sends -the search query to the server and displays the result. To the user, the -experience is something like this: </p> +<h4>Searching the Android Market application</h4> -<ol> -<li>The user presses a link or button in your application.</li> -<li>The Market application launches and takes control of the screen, displaying -a progress indicator labeled "Searching" until it receives the search -results.</li> -<li>Market receives the search results and displays them. Depending on the query -parameters, the search results may include a list of one or more applications. -</li> -<li>From the results page, the user can select an app to go to its Details page, -which offers information about the app and lets the user download/purchase the -app.</li> -</ol> +<p>To perform a search in the Android Market application, create an intent with the +{@link android.content.Intent#ACTION_VIEW} action and include a data URI in this format:</p> -<h4>Loading an application's Details page</h4> +<p style="margin-left:2em"><code>market://search?q=<query></code></p> -<p>In Android Market, every application has a Details page that provides an -overview of the application for users. For example, the page includes a short -description of the app and screen shots of it in use, if supplied by the -developer, as well as feedback from users and information about the developer. -The Details page also includes an "Install" button that lets the user trigger -the download/purchase of the application.</p> +<p>The query may include the {@code pub:} parameter described above.</p> -<p>If you want to refer the user to a specific appplication, your application -can take the user directly to the application's Details page. To do so, your -application sends an ACTION_VIEW Intent that includes a URI and query parameter -in this format:</p> +<p>For example, here's how you can initiate a search in the Android Market application, based on the +publisher name:</p> -<p style="margin-left:2em"><code>market://details?id=<packagename></code></p> +<pre> +Intent intent = new Intent(Intent.ACTION_VIEW); +intent.setData(Uri.parse("market://search?q=pub:Your Publisher Name")); +startActivity(intent); +</pre> -<p>In this case, the <code>packagename</code> parameter is target application's -fully qualified package name, as declared in the <code>package</code> attribute -of the <code>manifest</code> element in the application's manifest file. For example:</p> +<p>The search result shows all applications published by the publisher and which are compatible with +the current device.</p> -<p style="margin-left:2em"><code>market://details?id=com.example.android.jetboy</code></p> -<h4>Android Market URIs</h4> +<h4>Searching the Android Market web site</h4> -<p>The table below provides a list of URIs and actions currently -supported by the Market application.</p> +<p>To perform a search on the Android Market web site, create a link with a URI in this +format:</p> + +<p style="margin-left:2em"> + <code>http://market.android.com/search?q=<query></code> +</p> -<p>Note that these URIs work only when passed as Intent data — you -can't currently load the URIs in a web browser, either on a desktop machine or -on the device. </p> +<p>The query may include the {@code pub:} parameter described above.</p> + +<p>For example, here's a link that initiates a search on the Android Market web site, based on the +publisher name:</p> + +<pre> +<a href="http://market.android.com/search?q=pub:Your Publisher Name">Search Link</a> +</pre> + +<p>The search result shows all applications published by the publisher.</p> + + + +<h3 id="UriSummary">Summary of URI formats</h3> + +<p>The table below provides a summary of the URIs currently supported by the Android Market (both on +the web and in the Android application), as discussed in the previous sections.</p> <table> <tr> -<th width="25%">For this Result</th> -<th>Pass this URI with the ACTION_VIEW Intent</th> -<th width="36%">Comments</th> -</tr> -<tr> -<td>Display the Details screen for a specific application, as identified -by the app's fully qualified package name.</td> -<td><code>http://market.android.com/details?id=<packagename></code> -or<br> -<code>market://details?id=<packagename></code></td> -<td>Note that the package name that you specify is <em>not</em> specific to any -version of an application. Therefore, Market always displays the Details page for the -latest version of the application.</td> -</tr> -<tr> -<td>Search for an application by its fully qualified Java package name and -display the result.</td> -<td><code>http://market.android.com/search?q=pname:<package></code> or<br> -<code>market://search?q=pname:<package></code></td> -<td>Searches only the Java package name of applications. Returns only exact -matches.</td> +<th>For this result</th> +<th>Use this URI in a web page link</th> +<th>Or this URI in an {@link android.content.Intent#ACTION_VIEW} intent</th> </tr> <tr> -<td>Search for applications by developer name and display the results.</td> -<td><code>http://market.android.com/search?q=pub:<Developer Name></code> -or<br> <code>market://search?q=pub:<Developer Name></code></td> -<td>Searches only the "Developer Name" fields of Market public profiles. -Returns exact matches only. </td> +<td>Display the details screen for a specific application</td> +<td><code>http://market.android.com/details?id=<package_name></code> +<td><code>market://details?id=<package_name></code></td> </tr> <tr> -<td>Search for applications by substring and display the results.</td> -<td><code>http://market.android.com/search?q=<substring></code> or -<br><code>market://search?q=<substring></code></td> -<td>Searches all public fields (application title, developer name, and -application description) for all applications. Returns exact and partial -matches.</td> +<td>Search for applications using a general string query.</td> +<td><code>http://market.android.com/search?q=<query></code></td> +<td><code>market://search?q=<query></code></td> </tr> <tr> -<td>Search using multiple query parameters and display the results.</td> -<td>Example:<p><code>http://market.android.com/search?q=world pname:com.android.hello pub:Android</code></p></td> -<td>Returns a list of applications meeting all the supplied parameters. </td> +<td>Search for applications by publisher name</td> +<td><nobr><code>http://market.android.com/search?q=pub:<publisher_name></code></nobr></td> +<td><nobr><code>market://search?q=pub:<publisher_name></code></nobr></td> </tr> + </table> + diff --git a/docs/html/guide/topics/resources/menu-resource.jd b/docs/html/guide/topics/resources/menu-resource.jd index d09790b..5c1eed0 100644 --- a/docs/html/guide/topics/resources/menu-resource.jd +++ b/docs/html/guide/topics/resources/menu-resource.jd @@ -250,7 +250,7 @@ on the data that is currently displayed.</td></tr> android:icon="@drawable/group_item1_icon" /> <item android:id="@+id/group_item2" android:onClick="onGroupItemClick" - android:title="G@string/group_item2" + android:title="@string/group_item2" android:icon="@drawable/group_item2_icon" /> </group> <item android:id="@+id/submenu" diff --git a/docs/html/guide/topics/wireless/bluetooth.jd b/docs/html/guide/topics/wireless/bluetooth.jd index b3c7687..ae078b9 100644 --- a/docs/html/guide/topics/wireless/bluetooth.jd +++ b/docs/html/guide/topics/wireless/bluetooth.jd @@ -554,7 +554,7 @@ private class AcceptThread extends Thread { BluetoothServerSocket tmp = null; try { // MY_UUID is the app's UUID string, also used by the client code - tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); + tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { } mmServerSocket = tmp; } @@ -690,7 +690,7 @@ private class ConnectThread extends Thread { public void run() { // Cancel discovery because it will slow down the connection - mAdapter.cancelDiscovery(); + mBluetoothAdapter.cancelDiscovery(); try { // Connect the device through the socket. This will block diff --git a/docs/html/images/avd-manager.png b/docs/html/images/avd-manager.png Binary files differindex 69ce972..c33d8a8 100644 --- a/docs/html/images/avd-manager.png +++ b/docs/html/images/avd-manager.png diff --git a/docs/html/images/billing_package.png b/docs/html/images/billing_package.png Binary files differindex ec04c2d..951e117 100755..100644 --- a/docs/html/images/billing_package.png +++ b/docs/html/images/billing_package.png diff --git a/docs/html/images/developing/adt-props-isLib.png b/docs/html/images/developing/adt-props-isLib.png Binary files differindex 18bdb33..49c9111 100644 --- a/docs/html/images/developing/adt-props-isLib.png +++ b/docs/html/images/developing/adt-props-isLib.png diff --git a/docs/html/images/developing/adt-props-libRef.png b/docs/html/images/developing/adt-props-libRef.png Binary files differindex e61df51..73bccbd 100644 --- a/docs/html/images/developing/adt-props-libRef.png +++ b/docs/html/images/developing/adt-props-libRef.png diff --git a/docs/html/images/developing/intellijidea_android_ide.png b/docs/html/images/developing/intellijidea_android_ide.png Binary files differnew file mode 100644 index 0000000..b73a4e9 --- /dev/null +++ b/docs/html/images/developing/intellijidea_android_ide.png diff --git a/docs/html/images/licensing_add_library.png b/docs/html/images/licensing_add_library.png Binary files differindex 90b4435..3bbe6d5 100644 --- a/docs/html/images/licensing_add_library.png +++ b/docs/html/images/licensing_add_library.png diff --git a/docs/html/images/licensing_gapis_8.png b/docs/html/images/licensing_gapis_8.png Binary files differindex 43ad262..480d989 100644 --- a/docs/html/images/licensing_gapis_8.png +++ b/docs/html/images/licensing_gapis_8.png diff --git a/docs/html/images/licensing_package.png b/docs/html/images/licensing_package.png Binary files differindex 5da5632..eb2c5cf 100644 --- a/docs/html/images/licensing_package.png +++ b/docs/html/images/licensing_package.png diff --git a/docs/html/resources/faq/commontasks.jd b/docs/html/resources/faq/commontasks.jd index a5f5177..b211db0 100644 --- a/docs/html/resources/faq/commontasks.jd +++ b/docs/html/resources/faq/commontasks.jd @@ -223,7 +223,7 @@ public void onClick(View v){ // Listen for results. protected void onActivityResult(int requestCode, int resultCode, Intent data){ // See which child activity is calling us back. - switch (resultCode) { + switch (requestCode) { case CHOOSE_FIGHTER: // This is the standard resultCode that is sent back if the // activity crashed or didn't doesn't supply an explicit result. @@ -257,7 +257,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data){ stats.putString("height","6\'2\""); stats.putString("weight", "190 lbs"); stats.putString("reach", "73\""); - setResult(RESULT_OK, "Washington", Bundle); + setResult(RESULT_OK, "Washington", stats); finish(); } }; @@ -289,7 +289,12 @@ your application is starting up. With the explicit method call, your application will have a title bar visible to the user until <code>onCreate</code> runs.</p> <p>(Note that this can be applied to either the <code><application></code> tag or to individual <code><activity></code> tags.)</p> -<a name="localhostalias" id="localhostalias"></a><h2>Referring to localhost from the emulated environment</h2> +<p class="caution"><strong>Caution:</strong> This theme will also hide the Action Bar on Android +3.0 and higher. If you want to keep the Action Bar, but hide the title bar, see how you can <a +href="{@docRoot}guide/topics/ui/themes.html#SelectATheme">select a theme based on platform +version</a>.</p> +<a name="localhostalias" id="localhostalias"></a><h2>Referring to localhost from the emulated +environment</h2> <p> If you need to refer to your host computer's <em>localhost</em>, such as when you want the emulator client to contact a server running on the same host, use the alias diff --git a/docs/html/resources/tutorials/hello-world.jd b/docs/html/resources/tutorials/hello-world.jd index 020c738..b11770f 100644 --- a/docs/html/resources/tutorials/hello-world.jd +++ b/docs/html/resources/tutorials/hello-world.jd @@ -433,7 +433,7 @@ The entire file should now look like this: </pre> </li> -<li>Now open and modify your <code>HelloAndroid</code> class use the +<li>Now open and modify your <code>HelloAndroid</code> class and use the XML layout. Edit the file to look like this: <pre> package com.example.helloandroid; diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd index 3a7b39f..97717fe 100644 --- a/docs/html/sdk/eclipse-adt.jd +++ b/docs/html/sdk/eclipse-adt.jd @@ -594,13 +594,14 @@ href="#troubleshooting">Troubleshooting</a> section.</p> <p>ADT is a plugin for the Eclipse IDE. Before you can install or use ADT, you must have a compatible version of Eclipse installed on your development -computer. </p> +computer. Check the <a +href="requirements.html">System Requirements</a> document for +a list of Eclipse versions that are compatible with the Android SDK.</li></p> <ul> <li>If Eclipse is already installed on your computer, make sure that it is -a version that is compatible with ADT and the Android SDK. Check the <a -href="requirements.html">System Requirements</a> document for -a list of Eclipse versions that are compatible with the Android SDK.</li> +a version that is compatible with ADT and the Android SDK. + <li>If you need to install or update Eclipse, you can download it from this location: @@ -608,7 +609,7 @@ location: "http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a> </p> -<p>For Eclipse 3.5 or newer, the "Eclipse Classic" version is recommended. Otherwise, a Java or RCP +<p>The "Eclipse Classic" version is recommended. Otherwise, a Java or RCP version of Eclipse is recommended.</p></li> </ul> @@ -624,19 +625,15 @@ ADT installation as described in the steps below. </p> <h3 id="downloading">Downloading the ADT Plugin</h3> -<p>Use Update Manager feature of your Eclipse installation to install the latest +<p>Use the Update Manager feature of your Eclipse installation to install the latest revision of ADT on your development computer.<p> <p>Assuming that you have a compatible version of the Eclipse IDE installed, as described in <a href="#preparing">Preparing for Installation</a>, above, follow these steps to download the ADT plugin and install it in your Eclipse -environment. </p> +environment.</p> + -<table style="font-size:100%"> -<tr><th>Eclipse 3.5 (Galileo) and 3.6 (Helios)</th><th>Eclipse 3.4 (Ganymede)</th></tr> -<tr> -<td width="45%"> -<!-- 3.5+ steps --> <ol> <li>Start Eclipse, then select <strong>Help</strong> > <strong>Install New Software...</strong>.</li> @@ -655,35 +652,6 @@ the checkbox next to Developer Tools and click <strong>Next</strong>.</li> <li>When the installation completes, restart Eclipse. </li> </ol> -</td> -<td width="50%"> - -<!-- 3.4 steps --> -<ol> - <li>Start Eclipse, then select <strong>Help</strong> > <strong>Software Updates...</strong>. -In the dialog that appears, click the <strong>Available Software</strong> tab.</li> - <li>Click <strong>Add Site</strong>.</li> - <li>In the Add Site dialog that appears, enter this URL in the "Location" field: - <pre>https://dl-ssl.google.com/android/eclipse/</pre> - <p>Note: If you have trouble acquiring the plugin, you can try - using "http" in the URL, instead of "https" (https is preferred for - security reasons).</p> - <p>Click <strong>OK</strong>.</p> - </li> - <li>Back in the Available Software view, you should see the plugin listed by the URL, - with "Developer Tools" nested within it. Select the checkbox next to Developer Tools, - which will automatically select the nested tools. Then click - <strong>Install</strong></li> - <li>On the subsequent Install window, all of the included tools - should be checked. Click <strong>Next</strong>. </li> - <li>Read and accept the license agreements, then click <strong>Finish</strong>.</li> - <li>When the installation completes, restart Eclipse. </li> - -</ol> -</td> -</tr> -</table> - <h3 id="configuring">Configuring the ADT Plugin</h3> <p>Once you've successfully downloaded ADT as described above, the next step @@ -807,11 +775,6 @@ Eclipse Installed Software window using <strong>Help</strong> <p>Follow the steps below to check whether an update is available and, if so, to install it. </p> -<table style="font-size:100%"> -<tr><th>Eclipse 3.5 (Galileo) and 3.6 (Helios)</th><th>Eclipse 3.4 (Ganymede)</th></tr> -<tr> -<td> -<!-- 3.5+ steps --> <ol> <li>Select <strong>Help</strong> > <strong>Check for Updates</strong>. <p>If there are no updates available, a dialog will say so and you're done.</p></li> @@ -823,25 +786,6 @@ to install it. </p> Android Development Tools.</li> <li>Restart Eclipse.</li> </ol> -</td> - -<td width="50%"> -<!-- 3.4 steps --> -<ol> - <li>Select <strong>Help</strong> > <strong>Software Updates</strong>.</li> - <li>Select the <strong>Available Software</strong> tab.</li> - <li>If there are updates available, select Android DDMS, Android Development Tools, - and Android Hierarchy Viewer, then click <strong>Update</strong>.</li> - <li>In the resulting Available Updates dialog, ensure that each of the listed tools - are selected, then click <strong>Next</strong>.</li> - <li>Read and accept the license agreement and then click <strong>Finish</strong>. - This will download and install the latest version of Android DDMS and - Android Development Tools.</li> - <li>Restart Eclipse.</li> -</ol> -</td> -</tr> -</table> <p>If you encounter problems during the update, remove the existing ADT plugin from Eclipse, then diff --git a/docs/html/sdk/installing.jd b/docs/html/sdk/installing.jd index b0fd761..a1080c2 100644 --- a/docs/html/sdk/installing.jd +++ b/docs/html/sdk/installing.jd @@ -96,13 +96,14 @@ href="http://java.sun.com/javase/downloads/index.jsp">JDK</a>, if you don't have <p>If you will be developing in Eclipse with the Android Development Tools (ADT) Plugin—the recommended path if you are new to Android—make sure that you have a suitable version of Eclipse -installed on your computer (3.4 or newer is recommended). If you need -to install Eclipse, you can download it from this location: </p> +installed on your computer as described in the +<a href="requirements.html">System Requirements</a> document. +If you need to install Eclipse, you can download it from this location: </p> <p style="margin-left:2em;"><a href= "http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a></p> -<p>For Eclipse 3.5 or newer, the "Eclipse Classic" version is recommended. Otherwise, a Java or +<p>The "Eclipse Classic" version is recommended. Otherwise, a Java or RCP version of Eclipse is recommended.</p> diff --git a/docs/html/sdk/preview/features.jd b/docs/html/sdk/preview/features.jd index cd0dea1..d7ecc47 100644 --- a/docs/html/sdk/preview/features.jd +++ b/docs/html/sdk/preview/features.jd @@ -1,186 +1,8 @@ -page.title=Introduction to Honeycomb @jd:body -<p>Welcome to the Honeycomb preview SDK. Honeycomb is the next major release of the Android -platform and is optimized for tablet devices. This document provides an introduction to the new -platform features and APIs available in Honeycomb.</p> - - -<h2>Fragments</h2> - -<div class="figure" style="width:400px"> - <img src="{@docRoot}images/preview_hc/fragments_layout.png" alt="" /> - <p class="img-caption"><strong>Fragment Layout.</strong> An activity with two -fragments: one with a list view, on the left, and one that displays selected content on the -right. This demo is available in the samples package.</p> -</div> - - -<p>A new framework component that allows you to separate distinct elements of an activity into -self-contained modules that define their own UI and lifecycle—defining what may be -considered "sub-activities".</p> -<ul> - <li>Multiple fragments can be combined in a single activity to build a multi-pane UI in which -each pane manages its own lifecycle and user inputs</li> - <li>Fragments are self-contained and can be reused in multiple activities</li> - <li>Fragments can be added, removed, replaced and animated inside the activity</li> - <li>Fragment can be added to a back stack managed by the activity, preserving the state of -fragments as they are changed and allowing the user to navigate backward through the different -states</li> - <li>By <a -href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">providing -alternative resources</a>, you can mix and match fragments, based -on the screen size and orientation</li> - <li>Fragments have direct access to their container activity and can contribute items to the -activity's Options Menu</li> -</ul> - -<p>For more information, see the <a -href="{@docRoot}guide/topics/fragments/index.html">Fragments</a> developer guide.</p> - - -<h2>Action Bar</h2> - -<p>A replacement for the traditional title bar, which provides users quick access to global -actions and different navigation modes.</p> -<ul> - <li>Provides quick access to items from the Options Menu ("action items") and interactive -widgets ("action views")</li> - <li>Includes the application logo in the left corner, which can perform actions when tapped -and can be replaced with a custom logo</li> - <li>Provides breadcumbs for navigating backward through fragments</li> - <li>Offers built in navigation modes, including tabs and a drop-down list</li> - <li>Can be customized with themes and custom backgrounds</li> - <li>And more</li> -</ul> - -<img src="{@docRoot}images/preview_hc/actionbar.png" alt="" /> -<p class="img-caption"><strong>Action Bar.</strong> An action bar with a custom logo, -tabs, and Options Menu. This demo is available in the samples package.</p> - -<p>For more information, see the <a -href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer guide.</p> - - -<h2>System Clipboard</h2> - -<p>Applications can copy and paste data (beyond mere text) to and from the system-wide -clipboard.</p> - -<ul> - <li>Clipped data can be plain text, a URI, or an intent</li> - <li>The new {@link android.content.ClipData} class represents a complex data type for the -clipboard</li> - <li>The new {@link android.content.ClipboardManager} class allows apps to add {@link -android.content.ClipData} to the clipboard (copy) and read {@link -android.content.ClipData} from the clipboard (paste)</li> - <li>The {@link android.content.ContentProvider} class has been extended to generate byte -streams based on data types added to the clipboard and point to data hosted in a -content provider</li> -</ul> - -<p>See {@link android.content.ClipData} and {@link android.content.ClipboardManager} -for more information. You can also see an example implementation of copy/paste in an updated -version of the NotePad application (available in the samples package).</p> - - -<h2>Drag and Drop</h2> - -<p>New APIs to perform drag and drop operations, leveraging the system clipboard APIs to -transport data.</p> - -<ul> - <li>Any {@link android.view.View} can be used for a drag and drop event and a thumbnail of that -view is generated and used during the drag</li> - <li>{@link android.view.ViewGroup}s that can receive the object are notified during hover and drop -events</li> - <li>The new {@link android.view.DragEvent} class describes a drag event relating to a view, -including the item's current coordinates, the type of action (whether the drag has entered the -view, exited the view, started, dropped, etc.), and provides access to the {@link -android.content.ClipData} being carried</li> - <li>The new {@link android.view.View.OnDragListener} interface defines a callback that views -can register in order to be notified of drag events being dispatched to the view; view's can -register a drag listener with {@link android.view.View#setOnDragListener setOnDragListener()}</li> -</ul> - -<p>See {@link android.view.DragEvent} and {@link android.view.View.OnDragListener} for more -information.</p> - - -<h2>New Animations</h2> - -<p>An all new animation framework.</p> - -<ul> - <li>A flexible animation system that allows you to animate the properties of any object (View, -Drawable, Fragment, Object, anything)</li> -</ul> - -<p>See the {@link android.animation} package.</p> - - -<h2>Extended App Widgets</h2> - -<p>App widgets can now be more interactive and accept finger gestures.</p> - -<ul> - <li>The complete list of supported widgets for an app widget is now: {@link -android.widget.AnalogClock}, {@link android.widget.Button}, {@link android.widget.Chronometer}, -{@link android.widget.ImageButton}, {@link android.widget.ImageView}, {@link -android.widget.ProgressBar}, {@link android.widget.TextView}, {@link -android.widget.ViewFlipper}, {@link android.widget.AdapterViewFlipper}, {@link -android.widget.StackView}, {@link android.widget.ListView}, and {@link -android.widget.GridView}.</li> -</ul> - - -<h2>Extended Status Bar Notifications</h2> - -<p>The {@link android.app.Notification} class has been extended to support more content-rich -status bar notifications when on xlarge screens.</p> - -<ul> - <li>New {@link android.app.Notification.Builder} class helps you easily create new {@link -android.app.Notification} objects</li> - <li>Support for a title in the status bar ticker (in addition to the normal ticker text)</li> - <li>Support for a large "sender" icon in the notification—a second icon intended for -social applications to show the contact photo of the person who is the source of the -notification</li> - <li>Support for custom layouts in the status bar ticker</li> - <li>Support for buttons in the expanded notification that deliver custom intents -(such as to control ongoing music in the background)</li> -</ul> - - -<h2>Plus Android 2.3</h2> - -<p>Honeycomb includes all platform changes introduced for Android 2.3.</p> - -<p>To take full advantage of Honeycomb, you should also be aware of the new features -and APIs introduced for Android 2.3. To learn more, read the <a -href="{@docRoot}sdk/android-2.3.html">Android 2.3 release notes</a>.</p> - -<!-- -<div class="special"> -<p>To set up your preview SDK and start developing apps for Honeycomb, see the <a -href="{@docRoot}sdk/preview/installing.html">Getting Started</a> guide.</p> -</div> ---> - - - - - - - - - - - - - - - - - +<script type="text/javascript"> + document.location=toRoot+"sdk/android-3.0.html" +</script> +<p>You should have already been redirected by your browser. Please go to the +<a href="{@docRoot}sdk/android-3.0.html">Android 3.0 Platform</a>.</p>
\ No newline at end of file diff --git a/docs/html/sdk/preview/index.jd b/docs/html/sdk/preview/index.jd index edfa02b..ed8f7e0 100644 --- a/docs/html/sdk/preview/index.jd +++ b/docs/html/sdk/preview/index.jd @@ -1,183 +1,2 @@ -page.title=Android 3.0 Preview SDK +sdk.redirect=true @jd:body - -<p>Android 3.0 is the next major release of the Android platform and is optimized for tablet -devices. We're offering a Preview SDK so you can get a head-start developing -applications for it or simply optimize your existing application for upcoming -tablets.</p> - - -<h3>What is the Preview SDK?</h3> - -<p>The Android 3.0 Preview SDK is an early look at the upcoming version of Android 3.0, for -developers only. </p> - -<p>The Preview SDK includes:</p> -<ul> - <li>An early Android 3.0 system image for use in the Android emulator</li> - <li>An Android 3.0 library with non-final APIs</li> - <li>A new WXGA emulator skin for an extra large Android Virtual Device</li> - <li>New documentation for Android 3.0, including a complete API reference, new developer guides, -and an API differences report between Android 3.0 and 2.3.</li> -</ul> - -<div class="note"> -<p><strong>Be aware that:</strong></p> -<ul> - <li>The APIs in the Preview SDK are <strong>not final</strong>. Some APIs may change in behavior -or availability when the final SDK is made available.</li> - <li>You <strong>cannot</strong> publish an application that's built against the Preview -SDK—you can only run an application built against the Preview SDK on the Android -emulator.</li> - <li>The documentation on <a href="http://developer.android.com">developer.android.com</a> -does <strong>not</strong> include the Android 3.0 documentation—to read the API reference and -developer guides for Android 3.0, you must install the Android 3.0 Preview documentation from -the AVD and SDK Manager.</li> -</ul> -</div> - - -<p><b>About emulator performance</b></p> - -<p>Because the Android emulator must simulate the ARM instruction set architecture on your -computer and the WXGA screen is significantly larger than what the emulator -normally handles, emulator performance is much slower than usual. </p> - -<p>In particular, initializing the emulator can be slow and can take several -minutes, depending on your hardware. When the emulator is booting there is -limited user feedback, so please be patient and continue waiting until you see -the home screen appear. </p> - -<p>We're working hard to resolve the performance issues in the emulator and it will improve in -future releases. In the meantime, we wanted to give developers access to new APIs and an basic test -environment as early as possible. </p> - -<p>Keeping in mind that performance on the emulator does not reflect the speed or performance of -apps on actual devices running Android 3.0, developing and testing on the emulator is still an -important tool in evaluating your application's appearance and functionality on the new platform. -</p> - - - - - -<h3>What can I do with the preview?</h3> - -<p>The Preview SDK is intended for testing existing applications on the new platform and -developing new applications with new Android 3.0 APIs.</p> - -<p>If you have an existing Android application, you don't <em>have to</em> do anything. Android -applications are always forward-compatible. If your application is a good citizen of the Android -APIs, your app should work fine on devices running Android 3.0 without any additional work. However, -in order to ensure proper performance and provide users a better experience when running your -application on an Android 3.0 tablet, we recommend that you perform the following:</p> - -<ol> - <li><b>Test your application on Android 3.0</b> - <p>Simply install the Android 3.0 preview in your Android SDK, create an AVD using the -Android 3.0 system image, install your application, and run some tests.</p> - <p>As mentioned above, your application should perform as expected. You might, however, -discover that your activity layouts are less than ideal on a large screen or some other aspects -of your application don't behave the way you expect.</p> - </li> - <li><b>Inherit the new "Holographic" theme</b> - <p>Android 3.0 offers an updated set of UI widgets that are redesigned for use on larger screens -such as tablets and incorporate the new holographic theme. Your existing application can inherit -the new design simply by setting the <a -href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> -element's {@code android:targetSdkVersion} attribute to {@code "Honeycomb"}.</p> - <p>If you do not update the {@code android:targetSdkVersion} attribute and the {@code -android:minSdkVersion} is set to "9" or lower, then your application uses the widget designs -from Android 2.3 and does <em>not</em> inherit the holographic theme.</p> - <p>In order for your application to match the rest of the system UI, we highly recommend you -make this change to inherit the new widget styles and system theme. However, beware that doing so -might conflict with color or text designs you applied to your application based on the previous -system theme, so you should be sure to inspect your application UI when using the holographic -theme.</p> - </li> - <li><b>Provide alternative layouts for extra large screens</b> - <p>As discussed in the guide to <a -href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>, Android -2.3 and above support the <code>xlarge</code> resource qualifier, which you should use to supply -alternative layouts for extra large screens.</p> - <p>By providing alternative layouts for some of your activities when running on extra large -screens, you can improve the user experience of your application on a tablet without using any -new APIs.</p> - <p>For example, here are some things to consider when creating a new layout for tables:</p> - <ul> - <li>Landscape layout: The "normal" orientation for tablets is usually landscape (wide), so -you should be sure that your activities offer an appropriate layout for such a wide viewing -area.</li> - <li>Button position: Consider whether the position of the most common buttons in your UI are -easily accessible while holding a tablet with two hands.</li> - </ul> - <p class="note"><strong>Note:</strong> You can add alternative resources for <em>xlarge</em> -screens without changing your {@code minSdkVersion}. For example, if you add alternative layouts in -<code>res/layout-xlarge/</code> and your application is compatible with older versions, such -as Android 1.5—which doesn't support <em>xlarge</em> screens—this layout directory is -simply ignored by those devices.</p> - </li> -</ol> - - -<p>Otherwise, if you want to develop a new application or upgrade your existing application to -use APIs added in Android 3.0, we encourage you to get started by developing against the Android -3.0 preview platform. You can get started the same way as you would for any other version of -Android.</p> - - -<p>To get started—whether testing an existing application or creating a new one—follow -the procedure in the following section to install the Preview SDK.</p> - - - -<h3 id="Setup">How do I get it?</h3> - -<p>To get the Preview SDK, you can download it using the Android SDK and AVD Manager.</p> - -<p>If you're new to Android development, start by <a href="{@docRoot}sdk/index.html">downloading the -Android SDK starter package</a>.</p> - -<p><a href="{@docRoot}sdk/adding-components.html#launching">Launch the Android SDK and AVD -Manager</a> and install the following:</p> -<ul> - <li>SDK Platform Android Honeycomb Preview</li> - <li>Android SDK Tools, revision 9</li> - <li>Android SDK Platform-tools, revision 2</li> - <li>Documentation for Android 'Honeycomb' Preview</li> - <li>Samples for SDK API Honeycomb Preview</li> -</ul> - -<p class="note"><strong>Note:</strong> Be sure to install the documentation component for the -Honeycomb Preview SDK. The API reference for the Android 3.0 API is <strong>not</strong> available -online.</p> - -<p>Once you have installed these components, open your SDK directory and navigate to {@code -docs/sdk/} and open {@code index.html} in your browser. </p> - - - -<h3 id="Issues">Known issues</h3> - -<p>The following known issues occur for Android 3.0 AVDs that are loaded in the emulator:</p> - -<ul> - <li>The emulator displays a rotated portrait screen while in landscape -orientation. To view the screen correctly in landscape orientation, turn off the auto-rotate setting -in <strong>Settings > Screen > Auto-rotate screen</strong>. Then use Ctrl-F11 to rotate the -emulator.</li> - <li>You cannot take screenshots of an emulator screen. The Device Screen Capture window displays -<strong>Screen not available</strong>.</li> - <li>GPS emulation is currently not supported.</li> - <li>When rotating the emulator screen by pressing Ctrl-F11, the screen turns green momentarily, -then displays the normal interface.</li> - <li>The Dev Tools application sometimes crashes when trying to use the Package Browser -feature.</li> -</ul> - - -<div class="special"> - <p>For an overview of new features in Android 3.0, read the <a -href="{@docRoot}sdk/android-3.0-highlights.html">Platform Highlights</a>.</p> -</div> - diff --git a/docs/html/sdk/preview/installing.jd b/docs/html/sdk/preview/installing.jd index c835c49..94c6f2f 100644 --- a/docs/html/sdk/preview/installing.jd +++ b/docs/html/sdk/preview/installing.jd @@ -1,62 +1,8 @@ -page.title=Getting Started with Honeycomb @jd:body -<p>First, you need to set up your development environment with the new SDK Tools and preview -platform:</p> +<script type="text/javascript"> + document.location=toRoot+"sdk/installing.html" +</script> -<ol> - <li>Unpack the SDK Tools r8 package you've received. - <p>If you have an existing Android SDK directory, simply replace your existing {@code -tools/} directory with the one from the new package and add the {@code platform-tools/} -directory along side it (at the root of the SDK directory).</p></li> - <li>Unpack the platform package ({@code android-Froyo}) and place it in your SDK's {@code -platforms/} directory.</li> - <li>If you're using Eclipse, also update your Eclipse plugin using the provided archive file. - <ol> - <li>Select <strong>Help > Install new software</strong>.</li> - <li>Click <strong>Add</strong>.</li> - <li>Click <strong>Archive</strong>.</li> - <li>Locate and select the archive file. Click <strong>OK</strong>. - <p>Developer Tools now appear in the Available Software window and you can proceed -to install the plugin.</p> - </li> - </ol> - </li> -</ol> - -<p class="note"><strong>Note:</strong> Beginning with SDK Tools r8 (the version you've received), -the {@code adb} tool is now located in the {@code <sdk>/platform-tools/} directory (instead -of in {@code <sdk>/tools/}). Be sure to update your {@code PATH} environment variable and any -build/debugging scripts you have.</p> - - - -<h2 id="Setup">Set Up Your AVD and Application</h2> - -<p>With your SDK now set up, follow these steps to start developing an application for -Honeycomb.</p> - -<ol> - - <li>Create a new AVD targeted to "Android Froyo (Preview)" and with a custom skin resolution of -1280 x 800.</li> - - <li>Set the build target of your application to "Android Froyo (Preview)".</li> - <li>Set your manifest file's {@code <uses-sdk>} element to use {@code -android:minSdkVersion="Froyo"}. For example: -<pre> -<manifest> - <uses-sdk android:minSdkVersion="Froyo" /> - ... -</manifest> -</pre> -<p>"Froyo" is a provisional API Level for the Honeycomb release, used only during the preview -period. When the APIs are -finalized and the SDK is released publicly, you must update this with the appropriate API Level -integer.</p> -<p class="note"><strong>Note:</strong> By providing your {@code <uses-sdk>} element in the -manifest file <em>before</em> the {@code <application>} element, your application will -automatically apply the new Holographic theme.</p> -</li> - -</ol> +<p>You should have already been redirected by your browser. Please go to +<a href="{@docRoot}sdk/installing.html">Installing the SDK</a>.</p>
\ No newline at end of file diff --git a/docs/html/sdk/preview/requirements.jd b/docs/html/sdk/preview/requirements.jd index 1e6b26b..b5aed80 100644 --- a/docs/html/sdk/preview/requirements.jd +++ b/docs/html/sdk/preview/requirements.jd @@ -1,5 +1,8 @@ -sdk.redirect=true - @jd:body +<script type="text/javascript"> + document.location=toRoot+"sdk/requirements.html" +</script> +<p>You should have already been redirected by your browser. Please go to the +<a href="{@docRoot}sdk/requirements.html">SDK System Requirements</a>.</p>
\ No newline at end of file diff --git a/docs/html/sdk/preview/upgrading.jd b/docs/html/sdk/preview/upgrading.jd index 1e6b26b..1c53bdb 100644 --- a/docs/html/sdk/preview/upgrading.jd +++ b/docs/html/sdk/preview/upgrading.jd @@ -1,5 +1,8 @@ -sdk.redirect=true - @jd:body +<script type="text/javascript"> + document.location=toRoot+"sdk/index.html" +</script> +<p>You should have already been redirected by your browser. Please go to +<a href="{@docRoot}sdk/index.html">the Android SDK</a>.</p>
\ No newline at end of file diff --git a/docs/html/sdk/requirements.jd b/docs/html/sdk/requirements.jd index 3d62dd9..f12d0aa 100644 --- a/docs/html/sdk/requirements.jd +++ b/docs/html/sdk/requirements.jd @@ -24,7 +24,9 @@ Android applications using the Android SDK. </p> <h4 style="margin-top:.25em"><em>Eclipse IDE</em></h4> <ul> - <li>Eclipse 3.4 (Ganymede) or greater</li> + <li>Eclipse 3.5 (Galileo) or greater +<p class="note"><strong>Note:</strong> Eclipse 3.4 (Ganymede) is no longer +supported with the latest version of ADT.</p></li> <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included in most Eclipse IDE packages) </li> <li>If you need to install or update Eclipse, you can download it from <a diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp index ddbd220..696e305 100644 --- a/drm/common/IDrmManagerService.cpp +++ b/drm/common/IDrmManagerService.cpp @@ -596,7 +596,7 @@ DecryptHandle* BpDrmManagerService::openDecryptSession(int uniqueId, const char* handle->decryptInfo->decryptBufferLength = reply.readInt32(); } } else { - LOGE("no decryptHandle is generated in service side"); + LOGV("no decryptHandle is generated in service side"); } return handle; } @@ -1308,7 +1308,7 @@ status_t BnDrmManagerService::onTransact( delete handle->decryptInfo; handle->decryptInfo = NULL; } } else { - LOGE("NULL decryptHandle is returned"); + LOGV("NULL decryptHandle is returned"); } delete handle; handle = NULL; return DRM_NO_ERROR; diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp index ec400b7..305bafc 100644 --- a/drm/drmserver/DrmManager.cpp +++ b/drm/drmserver/DrmManager.cpp @@ -51,6 +51,7 @@ DrmManager::~DrmManager() { } int DrmManager::addUniqueId(int uniqueId) { + Mutex::Autolock _l(mLock); if (0 == uniqueId) { int temp = 0; bool foundUniqueId = false; @@ -78,6 +79,7 @@ int DrmManager::addUniqueId(int uniqueId) { } void DrmManager::removeUniqueId(int uniqueId) { + Mutex::Autolock _l(mLock); for (unsigned int i = 0; i < mUniqueIdVector.size(); i++) { if (uniqueId == mUniqueIdVector.itemAt(i)) { mUniqueIdVector.removeAt(i); @@ -107,6 +109,7 @@ status_t DrmManager::loadPlugIns(const String8& plugInDirPath) { } status_t DrmManager::unloadPlugIns() { + Mutex::Autolock _l(mLock); mConvertSessionMap.clear(); mDecryptSessionMap.clear(); mPlugInManager.unloadPlugIns(); @@ -126,6 +129,7 @@ status_t DrmManager::setDrmServiceListener( } void DrmManager::addClient(int uniqueId) { + Mutex::Autolock _l(mLock); if (!mSupportInfoToPlugInIdMap.isEmpty()) { Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); for (unsigned int index = 0; index < plugInIdList.size(); index++) { @@ -137,6 +141,7 @@ void DrmManager::addClient(int uniqueId) { } void DrmManager::removeClient(int uniqueId) { + Mutex::Autolock _l(mLock); Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); for (unsigned int index = 0; index < plugInIdList.size(); index++) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); @@ -145,6 +150,7 @@ void DrmManager::removeClient(int uniqueId) { } DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -154,6 +160,7 @@ DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, co } DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -163,6 +170,7 @@ DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) { } status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) { + Mutex::Autolock _l(mLock); mPlugInManager.loadPlugIn(absolutePath); IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(absolutePath); @@ -176,6 +184,7 @@ status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) } bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInId(mimeType); bool result = (EMPTY_STRING != plugInId) ? true : false; @@ -194,6 +203,7 @@ bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mim } DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType()); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -218,6 +228,7 @@ bool DrmManager::canHandle(int uniqueId, const String8& path) { } DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType()); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -228,6 +239,7 @@ DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoR status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights, const String8& rightsPath, const String8& contentPath) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType()); status_t result = DRM_ERROR_UNKNOWN; if (EMPTY_STRING != plugInId) { @@ -238,6 +250,7 @@ status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights, } String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -247,6 +260,7 @@ String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) { } int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -256,6 +270,7 @@ int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String } int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -267,6 +282,7 @@ int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) status_t DrmManager::consumeRights( int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { status_t result = DRM_ERROR_UNKNOWN; + Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve); @@ -277,6 +293,7 @@ status_t DrmManager::consumeRights( status_t DrmManager::setPlaybackStatus( int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { status_t result = DRM_ERROR_UNKNOWN; + Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); @@ -286,6 +303,7 @@ status_t DrmManager::setPlaybackStatus( bool DrmManager::validateAction( int uniqueId, const String8& path, int action, const ActionDescription& description) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); if (EMPTY_STRING != plugInId) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); @@ -295,6 +313,7 @@ bool DrmManager::validateAction( } status_t DrmManager::removeRights(int uniqueId, const String8& path) { + Mutex::Autolock _l(mLock); const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); status_t result = DRM_ERROR_UNKNOWN; if (EMPTY_STRING != plugInId) { @@ -318,6 +337,7 @@ status_t DrmManager::removeAllRights(int uniqueId) { } int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) { + Mutex::Autolock _l(mConvertLock); int convertId = -1; const String8 plugInId = getSupportedPlugInId(mimeType); @@ -325,7 +345,6 @@ int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) { - Mutex::Autolock _l(mConvertLock); ++mConvertId; convertId = mConvertId; mConvertSessionMap.add(convertId, &rDrmEngine); @@ -338,6 +357,7 @@ DrmConvertedStatus* DrmManager::convertData( int uniqueId, int convertId, const DrmBuffer* inputData) { DrmConvertedStatus *drmConvertedStatus = NULL; + Mutex::Autolock _l(mConvertLock); if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId); drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData); @@ -346,6 +366,7 @@ DrmConvertedStatus* DrmManager::convertData( } DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) { + Mutex::Autolock _l(mConvertLock); DrmConvertedStatus *drmConvertedStatus = NULL; if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) { @@ -358,6 +379,7 @@ DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) status_t DrmManager::getAllSupportInfo( int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) { + Mutex::Autolock _l(mLock); Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); int size = plugInPathList.size(); int validPlugins = 0; @@ -437,7 +459,7 @@ DecryptHandle* DrmManager::openDecryptSession(int uniqueId, const char* uri) { } if (DRM_NO_ERROR != result) { delete handle; handle = NULL; - LOGE("DrmManager::openDecryptSession: no capable plug-in found"); + LOGV("DrmManager::openDecryptSession: no capable plug-in found"); } return handle; } @@ -458,6 +480,7 @@ status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHan status_t DrmManager::initializeDecryptUnit( int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { status_t result = DRM_ERROR_UNKNOWN; + Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo); @@ -468,6 +491,8 @@ status_t DrmManager::initializeDecryptUnit( status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { status_t result = DRM_ERROR_UNKNOWN; + + Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); result = drmEngine->decrypt( @@ -479,6 +504,7 @@ status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int dec status_t DrmManager::finalizeDecryptUnit( int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { status_t result = DRM_ERROR_UNKNOWN; + Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); @@ -490,6 +516,7 @@ ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { ssize_t result = DECRYPT_FILE_ERROR; + Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset); diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java index c541456..782ffdb 100644 --- a/drm/java/android/drm/DrmManagerClient.java +++ b/drm/java/android/drm/DrmManagerClient.java @@ -735,6 +735,7 @@ public class DrmManagerClient { * This method expects uri in the following format * content://media/<table_name>/<row_index> (or) * file://sdcard/test.mp4 + * http://test.com/test.mp4 * * Here <table_name> shall be "video" or "audio" or "images" * <row_index> the index of the content in given table @@ -746,6 +747,10 @@ public class DrmManagerClient { if (null == scheme || scheme.equals("") || scheme.equals(ContentResolver.SCHEME_FILE)) { path = uri.getPath(); + + } else if (scheme.equals("http")) { + path = uri.toString(); + } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { String[] projection = new String[] {MediaStore.MediaColumns.DATA}; Cursor cursor = null; diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index 5f7cd90..293764d 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -346,12 +346,14 @@ private: }; bool processAudioBuffer(const sp<ClientRecordThread>& thread); - status_t openRecord(uint32_t sampleRate, + status_t openRecord_l(uint32_t sampleRate, int format, int channelCount, int frameCount, uint32_t flags, audio_io_handle_t input); + audio_io_handle_t getInput_l(); + status_t restoreRecord_l(audio_track_cblk_t*& cblk); sp<IAudioRecord> mAudioRecord; sp<IMemory> mCblkMemory; diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 813a905..3e346db 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -437,7 +437,7 @@ private: }; bool processAudioBuffer(const sp<AudioTrackThread>& thread); - status_t createTrack(int streamType, + status_t createTrack_l(int streamType, uint32_t sampleRate, int format, int channelCount, @@ -446,6 +446,10 @@ private: const sp<IMemory>& sharedBuffer, audio_io_handle_t output, bool enforceFrameCount); + void flush_l(); + status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount); + audio_io_handle_t getOutput_l(); + status_t restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart); sp<IAudioTrack> mAudioTrack; sp<IMemory> mCblkMemory; diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index f7d837a..93b5d24 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -50,6 +50,9 @@ struct OMXCodec : public MediaSource, // Only submit one input buffer at one time. kOnlySubmitOneInputBufferAtOneTime = 64, + + // Enable GRALLOC_USAGE_PROTECTED for output buffers from native window + kEnableGrallocUsageProtected = 128, }; static sp<MediaSource> Create( const sp<IOMX> &omx, @@ -197,6 +200,7 @@ private: bool mIsMetaDataStoredInVideoBuffers; bool mOnlySubmitOneBufferAtOneTime; + bool mEnableGrallocUsageProtected; OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks, bool isEncoder, const char *mime, const char *componentName, diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index c6990bf..4610135 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -31,6 +31,7 @@ namespace android { #define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP init time #define MAX_RUN_TIMEOUT_MS 1000 #define WAIT_PERIOD_MS 10 +#define RESTORE_TIMEOUT_MS 5000 // Maximum waiting time for a track to be restored #define CBLK_UNDERRUN_MSK 0x0001 #define CBLK_UNDERRUN_ON 0x0001 // underrun (out) or overrrun (in) indication @@ -47,6 +48,12 @@ namespace android { #define CBLK_DISABLED_MSK 0x0010 #define CBLK_DISABLED_ON 0x0010 // track disabled by AudioFlinger due to underrun: #define CBLK_DISABLED_OFF 0x0000 // must be re-started +#define CBLK_RESTORING_MSK 0x0020 +#define CBLK_RESTORING_ON 0x0020 // track is being restored after invalidation +#define CBLK_RESTORING_OFF 0x0000 // by AudioFlinger +#define CBLK_RESTORED_MSK 0x0040 +#define CBLK_RESTORED_ON 0x0040 // track has been restored after invalidation +#define CBLK_RESTORED_OFF 0x0040 // by AudioFlinger struct audio_track_cblk_t { diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 361e7dc..dea1b10 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -138,6 +138,10 @@ public: * This is an ASYNCHRONOUS call. */ virtual void signal() const = 0; + + /* verify that an ISurface was created by SurfaceFlinger. + */ + virtual bool authenticateSurface(const sp<ISurface>& surface) const = 0; }; // ---------------------------------------------------------------------------- @@ -161,7 +165,8 @@ public: SIGNAL, CAPTURE_SCREEN, TURN_ELECTRON_BEAM_OFF, - TURN_ELECTRON_BEAM_ON + TURN_ELECTRON_BEAM_ON, + AUTHENTICATE_SURFACE, }; virtual status_t onTransact( uint32_t code, diff --git a/include/ui/Input.h b/include/ui/Input.h index e92d7f5..d9d77c4 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -144,6 +144,14 @@ enum { }; /* + * Button state. + */ +enum { + // Primary button pressed (left mouse button). + BUTTON_STATE_PRIMARY = 1 << 0, +}; + +/* * Describes the basic configuration of input devices that are present. */ struct InputConfiguration { @@ -544,6 +552,8 @@ public: ~InputDeviceInfo(); struct MotionRange { + int32_t axis; + uint32_t source; float min; float max; float flat; @@ -556,16 +566,17 @@ public: inline const String8 getName() const { return mName; } inline uint32_t getSources() const { return mSources; } - const MotionRange* getMotionRange(int32_t axis) const; + const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; void addSource(uint32_t source); - void addMotionRange(int32_t axis, float min, float max, float flat, float fuzz); - void addMotionRange(int32_t axis, const MotionRange& range); + void addMotionRange(int32_t axis, uint32_t source, + float min, float max, float flat, float fuzz); + void addMotionRange(const MotionRange& range); inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } inline int32_t getKeyboardType() const { return mKeyboardType; } - inline const KeyedVector<int32_t, MotionRange> getMotionRanges() const { + inline const Vector<MotionRange>& getMotionRanges() const { return mMotionRanges; } @@ -575,7 +586,7 @@ private: uint32_t mSources; int32_t mKeyboardType; - KeyedVector<int32_t, MotionRange> mMotionRanges; + Vector<MotionRange> mMotionRanges; }; /* diff --git a/include/ui/KeyLayoutMap.h b/include/ui/KeyLayoutMap.h index 904c8f3..d82d0c8 100644 --- a/include/ui/KeyLayoutMap.h +++ b/include/ui/KeyLayoutMap.h @@ -24,6 +24,36 @@ namespace android { +struct AxisInfo { + enum Mode { + // Axis value is reported directly. + MODE_NORMAL = 0, + // Axis value should be inverted before reporting. + MODE_INVERT = 1, + // Axis value should be split into two axes + MODE_SPLIT = 2, + }; + + // Axis mode. + Mode mode; + + // Axis id. + // When split, this is the axis used for values smaller than the split position. + int32_t axis; + + // When split, this is the axis used for values after higher than the split position. + int32_t highAxis; + + // The split value, or 0 if not split. + int32_t splitValue; + + // The flat value, or -1 if none. + int32_t flatOverride; + + AxisInfo() : mode(MODE_NORMAL), axis(-1), highAxis(-1), splitValue(0), flatOverride(-1) { + } +}; + /** * Describes a mapping from keyboard scan codes and joystick axes to Android key codes and axes. */ @@ -36,7 +66,7 @@ public: status_t mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const; status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const; - status_t mapAxis(int32_t scanCode, int32_t* axis) const; + status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const; private: struct Key { @@ -45,7 +75,7 @@ private: }; KeyedVector<int32_t, Key> mKeys; - KeyedVector<int32_t, int32_t> mAxes; + KeyedVector<int32_t, AxisInfo> mAxes; KeyLayoutMap(); diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h index bdfbf7c..b912e9b 100755 --- a/include/ui/KeycodeLabels.h +++ b/include/ui/KeycodeLabels.h @@ -270,6 +270,11 @@ static const KeycodeLabel AXES[] = { { "HAT_Y", 16 }, { "LTRIGGER", 17 }, { "RTRIGGER", 18 }, + { "THROTTLE", 19 }, + { "RUDDER", 20 }, + { "WHEEL", 21 }, + { "GAS", 22 }, + { "BRAKE", 23 }, { "GENERIC_1", 32 }, { "GENERIC_2", 33 }, { "GENERIC_3", 34 }, diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index fd83f46..0ac34d0 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -95,6 +95,21 @@ enum { * 5. Queue, dequeue, queue, dequeue, ad infinitum */ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, + + /* Check whether queueBuffer operations on the ANativeWindow send the buffer + * to the window compositor. The query sets the returned 'value' argument + * to 1 if the ANativeWindow DOES send queued buffers directly to the window + * compositor and 0 if the buffers do not go directly to the window + * compositor. + * + * This can be used to determine whether protected buffer content should be + * sent to the ANativeWindow. Note, however, that a result of 1 does NOT + * indicate that queued buffers will be protected from applications or users + * capturing their contents. If that behavior is desired then some other + * mechanism (e.g. the GRALLOC_USAGE_PROTECTED flag) should be used in + * conjunction with this query. + */ + NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, }; /* valid operations for the (*perform)() hook */ diff --git a/include/utils/Functor.h b/include/utils/Functor.h index 3955bc3..565f4a3 100644 --- a/include/utils/Functor.h +++ b/include/utils/Functor.h @@ -26,6 +26,7 @@ public: Functor() {} virtual ~Functor() {} virtual status_t operator ()() { return true; } + virtual status_t operator ()(float* data, uint32_t len) { return true; } }; }; // namespace android diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 43b330c..a40fac9 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -156,6 +156,10 @@ int SurfaceTextureClient::query(int what, int* value) { case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: *value = MIN_UNDEQUEUED_BUFFERS; return NO_ERROR; + case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: + // SurfaceTextureClient currently never queues frames to SurfaceFlinger. + *value = 0; + return NO_ERROR; } return BAD_VALUE; } diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk new file mode 100644 index 0000000..1dd8885 --- /dev/null +++ b/libs/gui/tests/Android.mk @@ -0,0 +1,53 @@ +# Build the unit tests. +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +ifneq ($(TARGET_SIMULATOR),true) + +# Build the unit tests. +test_src_files := \ + SurfaceTextureClient_test.cpp \ + +shared_libraries := \ + libcutils \ + libutils \ + libbinder \ + libgui \ + libstlport \ + +static_libraries := \ + libgtest \ + libgtest_main \ + +c_includes := \ + bionic \ + bionic/libstdc++/include \ + external/gtest/include \ + external/stlport/stlport \ + +module_tags := tests + +$(foreach file,$(test_src_files), \ + $(eval include $(CLEAR_VARS)) \ + $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ + $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ + $(eval LOCAL_C_INCLUDES := $(c_includes)) \ + $(eval LOCAL_SRC_FILES := $(file)) \ + $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ + $(eval LOCAL_MODULE_TAGS := $(module_tags)) \ + $(eval include $(BUILD_EXECUTABLE)) \ +) + +# Build the manual test programs. +include $(call all-subdir-makefiles) + +endif + +# Include subdirectory makefiles +# ============================================================ + +# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework +# team really wants is to build the stuff defined by this makefile. +ifeq (,$(ONE_SHOT_MAKEFILE)) +include $(call first-makefiles-under,$(LOCAL_PATH)) +endif diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp new file mode 100644 index 0000000..0f140ff --- /dev/null +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/SurfaceTextureClient.h> +#include <gtest/gtest.h> + +namespace android { + +class SurfaceTextureClientTest : public ::testing::Test { +protected: + virtual void SetUp() { + mST = new SurfaceTexture(123); + mSTC = new SurfaceTextureClient(mST); + } + + virtual void TearDown() { + mST.clear(); + mSTC.clear(); + } + + sp<SurfaceTexture> mST; + sp<SurfaceTextureClient> mSTC; +}; + +TEST_F(SurfaceTextureClientTest, QueuesToWindowCompositorIsFalse) { + sp<ANativeWindow> anw(mSTC); + int result = -123; + int err = anw->query(anw.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, + &result); + EXPECT_EQ(NO_ERROR, err); + EXPECT_EQ(0, result); +} + +} diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 38e0848..f4a0161 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -15,7 +15,6 @@ ifeq ($(USE_OPENGL_RENDERER),true) LayerCache.cpp \ LayerRenderer.cpp \ Matrix.cpp \ - OpenGLDebugRenderer.cpp \ OpenGLRenderer.cpp \ Patch.cpp \ PatchCache.cpp \ diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index d5d2ba0..737fa02 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -166,7 +166,7 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde void DisplayList::init() { } -bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) { +bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) { bool needsInvalidate = false; TextContainer text; mReader.rewind(); @@ -189,7 +189,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) { case DrawGLFunction: { Functor *functor = (Functor *) getInt(); DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor); - needsInvalidate |= renderer.callDrawGLFunction(functor); + needsInvalidate |= renderer.callDrawGLFunction(functor, dirty); } break; case Save: { @@ -287,7 +287,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) { DisplayList* displayList = getDisplayList(); DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op], displayList, level + 1); - needsInvalidate |= renderer.drawDisplayList(displayList, level + 1); + needsInvalidate |= renderer.drawDisplayList(displayList, dirty, level + 1); } break; case DrawLayer: { @@ -589,7 +589,8 @@ void DisplayListRenderer::interrupt() { void DisplayListRenderer::resume() { } -bool DisplayListRenderer::callDrawGLFunction(Functor *functor) { +bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) { + // Ignore dirty during recording, it matters only when we replay addOp(DisplayList::DrawGLFunction); addInt((int) functor); return false; // No invalidate needed at record-time @@ -673,7 +674,9 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot return OpenGLRenderer::clipRect(left, top, right, bottom, op); } -bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) { +bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) { + // dirty is an out parameter and should not be recorded, + // it matters only when replaying the display list addOp(DisplayList::DrawDisplayList); addDisplayList(displayList); return false; diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index e8f189d..f24545d 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -103,7 +103,7 @@ public: void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); - bool replay(OpenGLRenderer& renderer, uint32_t level = 0); + bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0); private: void init(); @@ -214,7 +214,7 @@ public: void prepareDirty(float left, float top, float right, float bottom, bool opaque); void finish(); - bool callDrawGLFunction(Functor *functor); + bool callDrawGLFunction(Functor *functor, Rect& dirty); void interrupt(); void resume(); @@ -238,7 +238,7 @@ public: bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); - bool drawDisplayList(DisplayList* displayList, uint32_t level = 0); + bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0); void drawLayer(Layer* layer, float x, float y, SkPaint* paint); void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp deleted file mode 100644 index 05870bb..0000000 --- a/libs/hwui/OpenGLDebugRenderer.cpp +++ /dev/null @@ -1,156 +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. - */ - -#define LOG_TAG "OpenGLRenderer" - -#include <utils/StopWatch.h> - -#include "OpenGLDebugRenderer.h" - -namespace android { -namespace uirenderer { - -void OpenGLDebugRenderer::prepareDirty(float left, float top, - float right, float bottom, bool opaque) { - mPrimitivesCount = 0; - LOGD("========= Frame start ========="); - OpenGLRenderer::prepareDirty(left, top, right, bottom, opaque); -} - -void OpenGLDebugRenderer::finish() { - LOGD("========= Frame end ========="); - LOGD("Primitives draw count = %d", mPrimitivesCount); - OpenGLRenderer::finish(); -} - -void OpenGLDebugRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { - mPrimitivesCount++; - StopWatch w("composeLayer"); - return OpenGLRenderer::composeLayer(current, previous); -} - -int OpenGLDebugRenderer::saveLayer(float left, float top, float right, float bottom, - SkPaint* p, int flags) { - mPrimitivesCount++; - StopWatch w("saveLayer"); - return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags); -} - -bool OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) { - mPrimitivesCount++; - StopWatch w("drawDisplayList"); - return OpenGLRenderer::drawDisplayList(displayList); -} - -void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawLayer"); - OpenGLRenderer::drawLayer(layer, x, y, paint); -} - -void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, - SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawBitmap"); - OpenGLRenderer::drawBitmap(bitmap, left, top, paint); -} - -void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, - SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawBitmapMatrix"); - OpenGLRenderer::drawBitmap(bitmap, matrix, paint); -} - -void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, - float srcRight, float srcBottom, float dstLeft, float dstTop, - float dstRight, float dstBottom, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawBitmapRect"); - OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, - dstLeft, dstTop, dstRight, dstBottom, paint); -} - -void OpenGLDebugRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, - const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, - float left, float top, float right, float bottom, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawPatch"); - OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors, - left, top, right, bottom, paint); -} - -void OpenGLDebugRenderer::drawColor(int color, SkXfermode::Mode mode) { - mPrimitivesCount++; - StopWatch w("drawColor"); - OpenGLRenderer::drawColor(color, mode); -} - -void OpenGLDebugRenderer::drawRect(float left, float top, float right, float bottom, - SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawRect"); - OpenGLRenderer::drawRect(left, top, right, bottom, paint); -} - -void OpenGLDebugRenderer::drawRoundRect(float left, float top, float right, float bottom, - float rx, float ry, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawRoundRect"); - OpenGLRenderer::drawRoundRect(left, top, right, bottom, rx, ry, paint); -} - -void OpenGLDebugRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawCircle"); - OpenGLRenderer::drawCircle(x, y, radius, paint); -} - -void OpenGLDebugRenderer::drawOval(float left, float top, float right, float bottom, - SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawOval"); - OpenGLRenderer::drawOval(left, top, right, bottom, paint); -} - -void OpenGLDebugRenderer::drawArc(float left, float top, float right, float bottom, - float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawArc"); - OpenGLRenderer::drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint); -} - -void OpenGLDebugRenderer::drawPath(SkPath* path, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawPath"); - OpenGLRenderer::drawPath(path, paint); -} - -void OpenGLDebugRenderer::drawLines(float* points, int count, SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawLines"); - OpenGLRenderer::drawLines(points, count, paint); -} - -void OpenGLDebugRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, - SkPaint* paint) { - mPrimitivesCount++; - StopWatch w("drawText"); - OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint); -} - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h deleted file mode 100644 index 1a18a67..0000000 --- a/libs/hwui/OpenGLDebugRenderer.h +++ /dev/null @@ -1,77 +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 ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H -#define ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H - -#include "OpenGLRenderer.h" - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// Renderer -/////////////////////////////////////////////////////////////////////////////// - -class OpenGLDebugRenderer: public OpenGLRenderer { -public: - OpenGLDebugRenderer(): mPrimitivesCount(0) { - } - - ~OpenGLDebugRenderer() { - } - - void prepareDirty(float left, float top, float right, float bottom, bool opaque); - void finish(); - - int saveLayer(float left, float top, float right, float bottom, - SkPaint* p, int flags); - - bool drawDisplayList(DisplayList* displayList, uint32_t level = 0); - void drawLayer(Layer* layer, float x, float y, SkPaint* paint); - void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); - void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); - void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, - float srcRight, float srcBottom, float dstLeft, float dstTop, - float dstRight, float dstBottom, SkPaint* paint); - void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, - const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, - float left, float top, float right, float bottom, SkPaint* paint); - void drawColor(int color, SkXfermode::Mode mode); - void drawRect(float left, float top, float right, float bottom, SkPaint* paint); - void drawRoundRect(float left, float top, float right, float bottom, - float rx, float ry, SkPaint* paint); - void drawCircle(float x, float y, float radius, SkPaint* paint); - void drawOval(float left, float top, float right, float bottom, SkPaint* paint); - void drawArc(float left, float top, float right, float bottom, - float startAngle, float sweepAngle, bool useCenter, SkPaint* paint); - void drawPath(SkPath* path, SkPaint* paint); - void drawLines(float* points, int count, SkPaint* paint); - void drawText(const char* text, int bytesCount, int count, float x, float y, - SkPaint* paint); - -protected: - void composeLayer(sp<Snapshot> current, sp<Snapshot> previous); - -private: - uint32_t mPrimitivesCount; - -}; // class OpenGLDebugRenderer - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index dfca7eb..1f65201 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -210,7 +210,7 @@ void OpenGLRenderer::resume() { glBlendEquation(GL_FUNC_ADD); } -bool OpenGLRenderer::callDrawGLFunction(Functor *functor) { +bool OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) { interrupt(); if (mDirtyClip) { setScissorFromClip(); @@ -226,9 +226,16 @@ bool OpenGLRenderer::callDrawGLFunction(Functor *functor) { } #endif - status_t result = (*functor)(); + float bounds[4]; + status_t result = (*functor)(&bounds[0], 4); + + if (result != 0) { + Rect localDirty(bounds[0], bounds[1], bounds[2], bounds[3]); + dirty.unionWith(localDirty); + } + resume(); - return (result == 0) ? false : true; + return result != 0; } /////////////////////////////////////////////////////////////////////////////// @@ -1057,11 +1064,11 @@ void OpenGLRenderer::finishDrawTexture() { // Drawing /////////////////////////////////////////////////////////////////////////////// -bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) { +bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) { // All the usual checks and setup operations (quickReject, setupDraw, etc.) // will be performed by the display list itself if (displayList) { - return displayList->replay(*this, level); + return displayList->replay(*this, dirty, level); } return false; } @@ -1522,7 +1529,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, break; } - // TODO: Handle paint->getTextScaleX() const float oldX = x; const float oldY = y; const bool pureTranslate = mSnapshot->transform->isPureTranslate(); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 7bbf034..9d86388 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -70,7 +70,7 @@ public: virtual void interrupt(); virtual void resume(); - virtual bool callDrawGLFunction(Functor *functor); + virtual bool callDrawGLFunction(Functor *functor, Rect& dirty); int getSaveCount() const; virtual int save(int flags); @@ -96,7 +96,7 @@ public: bool quickReject(float left, float top, float right, float bottom); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); - virtual bool drawDisplayList(DisplayList* displayList, uint32_t level = 0); + virtual bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0); virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h index 62c4250..d46686d 100644 --- a/libs/hwui/TextDropShadowCache.h +++ b/libs/hwui/TextDropShadowCache.h @@ -42,6 +42,17 @@ struct ShadowText { textSize = paint->getTextSize(); typeface = paint->getTypeface(); + + flags = 0; + if (paint->isFakeBoldText()) { + flags |= Font::kFakeBold; + } + + const float skewX = paint->getTextSkewX(); + italicStyle = *(uint32_t*) &skewX; + + const float scaleXFloat = paint->getTextScaleX(); + scaleX = *(uint32_t*) &scaleXFloat; } ~ShadowText() { @@ -51,6 +62,9 @@ struct ShadowText { uint32_t len; float textSize; SkTypeface* typeface; + uint32_t flags; + uint32_t italicStyle; + uint32_t scaleX; const char16_t* text; String16 str; @@ -65,7 +79,13 @@ struct ShadowText { LTE_INT(radius) { LTE_FLOAT(textSize) { LTE_INT(typeface) { - return strncmp16(text, rhs.text, len >> 1) < 0; + LTE_INT(flags) { + LTE_INT(italicStyle) { + LTE_INT(scaleX) { + return strncmp16(text, rhs.text, len >> 1) < 0; + } + } + } } } } diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 4a5620d..f9e29f1 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -592,11 +592,11 @@ void * Context::helperThreadProc(void *vrsc) { void Context::launchThreads(WorkerCallback_t cbk, void *data) { mWorkers.mLaunchData = data; mWorkers.mLaunchCallback = cbk; - mWorkers.mRunningCount = (int)mWorkers.mCount; + android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount); for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { mWorkers.mLaunchSignals[ct].set(); } - while (mWorkers.mRunningCount) { + while (android_atomic_acquire_load(&mWorkers.mRunningCount) != 0) { mWorkers.mCompleteSignal.wait(); } } @@ -707,8 +707,8 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) { } mWorkers.mCompleteSignal.init(); - mWorkers.mRunningCount = 0; - mWorkers.mLaunchCount = 0; + android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount); + android_atomic_release_store(0, &mWorkers.mLaunchCount); for (uint32_t ct=0; ct < mWorkers.mCount; ct++) { status = pthread_create(&mWorkers.mThreadId[ct], &threadAttr, helperThreadProc, this); if (status) { @@ -717,6 +717,9 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) { break; } } + while (android_atomic_acquire_load(&mWorkers.mRunningCount) != 0) { + usleep(100); + } pthread_attr_destroy(&threadAttr); return true; } @@ -736,14 +739,14 @@ Context::~Context() { // Cleanup compute threads. mWorkers.mLaunchData = NULL; mWorkers.mLaunchCallback = NULL; - mWorkers.mRunningCount = (int)mWorkers.mCount; + android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount); for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { mWorkers.mLaunchSignals[ct].set(); } for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { status = pthread_join(mWorkers.mThreadId[ct], &res); } - rsAssert(!mWorkers.mRunningCount); + rsAssert(android_atomic_acquire_load(&mWorkers.mRunningCount) == 0); // Global structure cleanup. pthread_mutex_lock(&gInitMutex); diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp index 01ae23f..8951c3f 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp @@ -25,9 +25,11 @@ #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> +#include <surfaceflinger/ISurfaceComposer.h> + #include <ui/DisplayInfo.h> -#include <surfaceflinger/ISurfaceComposer.h> +#include <utils/Log.h> // --------------------------------------------------------------------------- @@ -178,6 +180,40 @@ public: data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY); } + + virtual bool authenticateSurface(const sp<ISurface>& surface) const + { + Parcel data, reply; + int err = NO_ERROR; + err = data.writeInterfaceToken( + ISurfaceComposer::getInterfaceDescriptor()); + if (err != NO_ERROR) { + LOGE("ISurfaceComposer::authenticateSurface: error writing " + "interface descriptor: %s (%d)", strerror(-err), -err); + return false; + } + err = data.writeStrongBinder(surface->asBinder()); + if (err != NO_ERROR) { + LOGE("ISurfaceComposer::authenticateSurface: error writing strong " + "binder to parcel: %s (%d)", strerror(-err), -err); + return false; + } + err = remote()->transact(BnSurfaceComposer::AUTHENTICATE_SURFACE, data, + &reply); + if (err != NO_ERROR) { + LOGE("ISurfaceComposer::authenticateSurface: error performing " + "transaction: %s (%d)", strerror(-err), -err); + return false; + } + int32_t result = 0; + err = reply.readInt32(&result); + if (err != NO_ERROR) { + LOGE("ISurfaceComposer::authenticateSurface: error retrieving " + "result: %s (%d)", strerror(-err), -err); + return false; + } + return result != 0; + } }; IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); @@ -273,6 +309,12 @@ status_t BnSurfaceComposer::onTransact( status_t res = turnElectronBeamOn(mode); reply->writeInt32(res); } break; + case AUTHENTICATE_SURFACE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder()); + int32_t result = authenticateSurface(surface) ? 1 : 0; + reply->writeInt32(result); + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 818114a..afabbf4 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -712,6 +712,10 @@ int Surface::query(int what, int* value) case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: *value = MIN_UNDEQUEUED_BUFFERS; return NO_ERROR; + case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: + sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + *value = sf->authenticateSurface(mSurface) ? 1 : 0; + return NO_ERROR; } return BAD_VALUE; } diff --git a/libs/surfaceflinger_client/tests/Android.mk b/libs/surfaceflinger_client/tests/Android.mk index 5053e7d..212b8e7 100644 --- a/libs/surfaceflinger_client/tests/Android.mk +++ b/libs/surfaceflinger_client/tests/Android.mk @@ -1 +1,53 @@ +# Build the unit tests. +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +ifneq ($(TARGET_SIMULATOR),true) + +# Build the unit tests. +test_src_files := \ + Surface_test.cpp \ + +shared_libraries := \ + libcutils \ + libutils \ + libbinder \ + libsurfaceflinger_client \ + libstlport \ + +static_libraries := \ + libgtest \ + libgtest_main \ + +c_includes := \ + bionic \ + bionic/libstdc++/include \ + external/gtest/include \ + external/stlport/stlport \ + +module_tags := tests + +$(foreach file,$(test_src_files), \ + $(eval include $(CLEAR_VARS)) \ + $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ + $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ + $(eval LOCAL_C_INCLUDES := $(c_includes)) \ + $(eval LOCAL_SRC_FILES := $(file)) \ + $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ + $(eval LOCAL_MODULE_TAGS := $(module_tags)) \ + $(eval include $(BUILD_EXECUTABLE)) \ +) + +# Build the manual test programs. include $(call all-subdir-makefiles) + +endif + +# Include subdirectory makefiles +# ============================================================ + +# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework +# team really wants is to build the stuff defined by this makefile. +ifeq (,$(ONE_SHOT_MAKEFILE)) +include $(call first-makefiles-under,$(LOCAL_PATH)) +endif diff --git a/libs/surfaceflinger_client/tests/Surface_test.cpp b/libs/surfaceflinger_client/tests/Surface_test.cpp new file mode 100644 index 0000000..74ebf4e --- /dev/null +++ b/libs/surfaceflinger_client/tests/Surface_test.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <binder/IMemory.h> +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/Surface.h> +#include <surfaceflinger/SurfaceComposerClient.h> +#include <utils/String8.h> + +namespace android { + +class SurfaceTest : public ::testing::Test { +protected: + virtual void SetUp() { + mComposerClient = new SurfaceComposerClient; + ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); + + mSurfaceControl = mComposerClient->createSurface(getpid(), + String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGB_888, 0); + + ASSERT_TRUE(mSurfaceControl != NULL); + ASSERT_TRUE(mSurfaceControl->isValid()); + + ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction()); + ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000)); + ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); + ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction()); + + mSurface = mSurfaceControl->getSurface(); + ASSERT_TRUE(mSurface != NULL); + } + + virtual void TearDown() { + mComposerClient->dispose(); + } + + sp<Surface> mSurface; + sp<SurfaceComposerClient> mComposerClient; + sp<SurfaceControl> mSurfaceControl; +}; + +TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenVisible) { + sp<ANativeWindow> anw(mSurface); + int result = -123; + int err = anw->query(anw.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, + &result); + EXPECT_EQ(NO_ERROR, err); + EXPECT_EQ(1, result); +} + +TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenPurgatorized) { + mSurfaceControl.clear(); + + sp<ANativeWindow> anw(mSurface); + int result = -123; + int err = anw->query(anw.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, + &result); + EXPECT_EQ(NO_ERROR, err); + EXPECT_EQ(1, result); +} + +// This test probably doesn't belong here. +TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { + sp<ANativeWindow> anw(mSurface); + + // Verify the screenshot works with no protected buffers. + sp<IMemoryHeap> heap; + uint32_t w=0, h=0; + PixelFormat fmt=0; + sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0, + 40000)); + ASSERT_TRUE(heap != NULL); + + // Set the PROTECTED usage bit and verify that the screenshot fails. Note + // that we need to dequeue a buffer in order for it to actually get + // allocated in SurfaceFlinger. + ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), + GRALLOC_USAGE_PROTECTED)); + ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); + android_native_buffer_t* buf = 0; + for (int i = 0; i < 4; i++) { + // Loop to make sure SurfaceFlinger has retired a protected buffer. + ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); + ASSERT_EQ(NO_ERROR, anw->lockBuffer(anw.get(), buf)); + ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf)); + } + heap = 0; + w = h = fmt = 0; + ASSERT_EQ(INVALID_OPERATION, sf->captureScreen(0, &heap, &w, &h, &fmt, + 64, 64, 0, 40000)); + ASSERT_TRUE(heap == NULL); + + // XXX: This should not be needed, but it seems that the new buffers don't + // correctly show up after the upcoming dequeue/lock/queue loop without it. + // We should look into this at some point. + ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); + + // Un-set the PROTECTED usage bit and verify that the screenshot works + // again. Note that we have to change the buffers geometry to ensure that + // the buffers get reallocated, as the new usage bits are a subset of the + // old. + ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(anw.get(), 32, 32, 0)); + for (int i = 0; i < 4; i++) { + // Loop to make sure SurfaceFlinger has retired a protected buffer. + ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); + ASSERT_EQ(NO_ERROR, anw->lockBuffer(anw.get(), buf)); + ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf)); + } + heap = 0; + w = h = fmt = 0; + ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0, + 40000)); + ASSERT_TRUE(heap != NULL); +} + +} diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp index 0ed0866..e2e698e 100644 --- a/libs/ui/Input.cpp +++ b/libs/ui/Input.cpp @@ -657,23 +657,30 @@ void InputDeviceInfo::initialize(int32_t id, const String8& name) { mMotionRanges.clear(); } -const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(int32_t axis) const { - ssize_t index = mMotionRanges.indexOfKey(axis); - return index >= 0 ? & mMotionRanges.valueAt(index) : NULL; +const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( + int32_t axis, uint32_t source) const { + size_t numRanges = mMotionRanges.size(); + for (size_t i = 0; i < numRanges; i++) { + const MotionRange& range = mMotionRanges.itemAt(i); + if (range.axis == axis && range.source == source) { + return ⦥ + } + } + return NULL; } void InputDeviceInfo::addSource(uint32_t source) { mSources |= source; } -void InputDeviceInfo::addMotionRange(int32_t axis, float min, float max, +void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, float flat, float fuzz) { - MotionRange range = { min, max, flat, fuzz }; - addMotionRange(axis, range); + MotionRange range = { axis, source, min, max, flat, fuzz }; + mMotionRanges.add(range); } -void InputDeviceInfo::addMotionRange(int32_t axis, const MotionRange& range) { - mMotionRanges.add(axis, range); +void InputDeviceInfo::addMotionRange(const MotionRange& range) { + mMotionRanges.add(range); } } // namespace android diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp index 2ed0e66..8626a03 100644 --- a/libs/ui/KeyLayoutMap.cpp +++ b/libs/ui/KeyLayoutMap.cpp @@ -113,20 +113,23 @@ status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* out return NO_ERROR; } -status_t KeyLayoutMap::mapAxis(int32_t scanCode, int32_t* axis) const { +status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const { ssize_t index = mAxes.indexOfKey(scanCode); if (index < 0) { #if DEBUG_MAPPING LOGD("mapAxis: scanCode=%d ~ Failed.", scanCode); #endif - *axis = -1; return NAME_NOT_FOUND; } - *axis = mAxes.valueAt(index); + *outAxisInfo = mAxes.valueAt(index); #if DEBUG_MAPPING - LOGD("mapAxis: scanCode=%d ~ Result axis=%d.", scanCode, *axis); + LOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, " + "splitValue=%d, flatOverride=%d.", + scanCode, + outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis, + outAxisInfo->splitValue, outAxisInfo->flatOverride); #endif return NO_ERROR; } @@ -249,19 +252,89 @@ status_t KeyLayoutMap::Parser::parseAxis() { return BAD_VALUE; } + AxisInfo axisInfo; + mTokenizer->skipDelimiters(WHITESPACE); - String8 axisToken = mTokenizer->nextToken(WHITESPACE); - int32_t axis = getAxisByLabel(axisToken.string()); - if (axis < 0) { - LOGE("%s: Expected axis label, got '%s'.", mTokenizer->getLocation().string(), - axisToken.string()); - return BAD_VALUE; + String8 token = mTokenizer->nextToken(WHITESPACE); + if (token == "invert") { + axisInfo.mode = AxisInfo::MODE_INVERT; + + mTokenizer->skipDelimiters(WHITESPACE); + String8 axisToken = mTokenizer->nextToken(WHITESPACE); + axisInfo.axis = getAxisByLabel(axisToken.string()); + if (axisInfo.axis < 0) { + LOGE("%s: Expected inverted axis label, got '%s'.", + mTokenizer->getLocation().string(), axisToken.string()); + return BAD_VALUE; + } + } else if (token == "split") { + axisInfo.mode = AxisInfo::MODE_SPLIT; + + mTokenizer->skipDelimiters(WHITESPACE); + String8 splitToken = mTokenizer->nextToken(WHITESPACE); + axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0)); + if (*end) { + LOGE("%s: Expected split value, got '%s'.", + mTokenizer->getLocation().string(), splitToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE); + axisInfo.axis = getAxisByLabel(lowAxisToken.string()); + if (axisInfo.axis < 0) { + LOGE("%s: Expected low axis label, got '%s'.", + mTokenizer->getLocation().string(), lowAxisToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 highAxisToken = mTokenizer->nextToken(WHITESPACE); + axisInfo.highAxis = getAxisByLabel(highAxisToken.string()); + if (axisInfo.highAxis < 0) { + LOGE("%s: Expected high axis label, got '%s'.", + mTokenizer->getLocation().string(), highAxisToken.string()); + return BAD_VALUE; + } + } else { + axisInfo.axis = getAxisByLabel(token.string()); + if (axisInfo.axis < 0) { + LOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.", + mTokenizer->getLocation().string(), token.string()); + return BAD_VALUE; + } + } + + for (;;) { + mTokenizer->skipDelimiters(WHITESPACE); + if (mTokenizer->isEol()) { + break; + } + String8 keywordToken = mTokenizer->nextToken(WHITESPACE); + if (keywordToken == "flat") { + mTokenizer->skipDelimiters(WHITESPACE); + String8 flatToken = mTokenizer->nextToken(WHITESPACE); + axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0)); + if (*end) { + LOGE("%s: Expected flat value, got '%s'.", + mTokenizer->getLocation().string(), flatToken.string()); + return BAD_VALUE; + } + } else { + LOGE("%s: Expected keyword 'flat', got '%s'.", + mTokenizer->getLocation().string(), keywordToken.string()); + return BAD_VALUE; + } } #if DEBUG_PARSER - LOGD("Parsed axis: scanCode=%d, axis=%d.", scanCode, axis); + LOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, " + "splitValue=%d, flatOverride=%d.", + scanCode, + axisInfo.mode, axisInfo.axis, axisInfo.highAxis, + axisInfo.splitValue, axisInfo.flatOverride); #endif - mMap->mAxes.add(scanCode, axis); + mMap->mAxes.add(scanCode, axisInfo); return NO_ERROR; } diff --git a/libs/usb/src/com/android/future/usb/UsbAccessory.java b/libs/usb/src/com/android/future/usb/UsbAccessory.java index cdd2b73..3d0707f 100644 --- a/libs/usb/src/com/android/future/usb/UsbAccessory.java +++ b/libs/usb/src/com/android/future/usb/UsbAccessory.java @@ -23,14 +23,16 @@ public final class UsbAccessory { private final String mManufacturer; private final String mModel; - private final String mType; + private final String mDescription; private final String mVersion; + private final String mUri; /* package */ UsbAccessory(android.hardware.usb.UsbAccessory accessory) { mManufacturer = accessory.getManufacturer(); mModel = accessory.getModel(); - mType = accessory.getType(); + mDescription = accessory.getDescription(); mVersion = accessory.getVersion(); + mUri = accessory.getUri(); } /** @@ -52,12 +54,12 @@ public final class UsbAccessory { } /** - * Returns the type of the accessory. + * Returns a user visible description of the accessory. * - * @return the accessory type + * @return the accessory description */ - public String getType() { - return mType; + public String getDescription() { + return mDescription; } /** @@ -69,6 +71,17 @@ public final class UsbAccessory { return mVersion; } + /** + * Returns the URI for the accessory. + * This is an optional URI that might show information about the accessory + * or provide the option to download an application for the accessory + * + * @return the accessory URI + */ + public String getUri() { + return mUri; + } + private static boolean compare(String s1, String s2) { if (s1 == null) return (s2 == null); return s1.equals(s2); @@ -80,17 +93,28 @@ public final class UsbAccessory { UsbAccessory accessory = (UsbAccessory)obj; return (compare(mManufacturer, accessory.getManufacturer()) && compare(mModel, accessory.getModel()) && - compare(mType, accessory.getType()) && - compare(mVersion, accessory.getVersion())); + compare(mDescription, accessory.getDescription()) && + compare(mVersion, accessory.getVersion()) && + compare(mUri, accessory.getUri())); } return false; } @Override + public int hashCode() { + return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^ + (mModel == null ? 0 : mModel.hashCode()) ^ + (mDescription == null ? 0 : mDescription.hashCode()) ^ + (mVersion == null ? 0 : mVersion.hashCode()) ^ + (mUri == null ? 0 : mUri.hashCode())); + } + + @Override public String toString() { return "UsbAccessory[mManufacturer=" + mManufacturer + ", mModel=" + mModel + - ", mType=" + mType + - ", mVersion=" + mVersion + "]"; + ", mDescription=" + mDescription + + ", mVersion=" + mVersion + + ", mUri=" + mUri + "]"; } } diff --git a/libs/usb/src/com/android/future/usb/UsbManager.java b/libs/usb/src/com/android/future/usb/UsbManager.java index f74b291..840e1e3 100644 --- a/libs/usb/src/com/android/future/usb/UsbManager.java +++ b/libs/usb/src/com/android/future/usb/UsbManager.java @@ -17,6 +17,7 @@ package com.android.future.usb; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.hardware.usb.IUsbManager; @@ -55,28 +56,39 @@ public class UsbManager { public static final String ACTION_USB_ACCESSORY_DETACHED = "android.hardware.usb.action.USB_ACCESSORY_DETACHED"; + /** + * Name of extra added to the {@link android.app.PendingIntent} + * passed into {#requestPermission} or {#requestPermission} + * containing a boolean value indicating whether the user granted permission or not. + */ + public static final String EXTRA_PERMISSION_GRANTED = "permission"; + + private final Context mContext; private final IUsbManager mService; - private UsbManager(IUsbManager service) { + private UsbManager(Context context, IUsbManager service) { + mContext = context; mService = service; } /** * Returns a new instance of this class. * + * @param context the caller's {@link android.content.Context} * @return UsbManager instance. */ - public static UsbManager getInstance() { + public static UsbManager getInstance(Context context) { IBinder b = ServiceManager.getService(Context.USB_SERVICE); - return new UsbManager(IUsbManager.Stub.asInterface(b)); + return new UsbManager(context, IUsbManager.Stub.asInterface(b)); } /** * Returns the {@link com.google.android.usb.UsbAccessory} for * a {@link #ACTION_USB_ACCESSORY_ATTACHED} or {@link #ACTION_USB_ACCESSORY_ATTACHED} - * broadcast Intent + * broadcast Intent. This can also be used to retrieve the accessory from the result + * of a call to {#requestPermission}. * - * @return UsbAccessory for the broadcast. + * @return UsbAccessory for the intent. */ public static UsbAccessory getAccessory(Intent intent) { android.hardware.usb.UsbAccessory accessory = @@ -118,10 +130,54 @@ public class UsbManager { try { return mService.openAccessory(new android.hardware.usb.UsbAccessory( accessory.getManufacturer(),accessory.getModel(), - accessory.getType(), accessory.getVersion())); + accessory.getDescription(), accessory.getVersion(), accessory.getUri())); } catch (RemoteException e) { Log.e(TAG, "RemoteException in openAccessory" , e); return null; } } + + /** + * Returns true if the caller has permission to access the accessory. + * Permission might have been granted temporarily via + * {@link #requestPermission(android.hardware.usb.UsbAccessory} or + * by the user choosing the caller as the default application for the accessory. + * + * @param accessory to check permissions for + * @return true if caller has permission + */ + public boolean hasPermission(UsbAccessory accessory) { + try { + return mService.hasAccessoryPermission(new android.hardware.usb.UsbAccessory( + accessory.getManufacturer(),accessory.getModel(), + accessory.getDescription(), accessory.getVersion(), accessory.getUri())); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in hasPermission", e); + return false; + } + } + + /** + * Requests temporary permission for the given package to access the accessory. + * This may result in a system dialog being displayed to the user + * if permission had not already been granted. + * Success or failure is returned via the {@link android.app.PendingIntent} pi. + * The boolean extra {@link #EXTRA_PERMISSION_GRANTED} will be attached to the + * PendingIntent to indicate success or failure. + * If successful, this grants the caller permission to access the device only + * until the device is disconnected. + * + * @param accessory to request permissions for + * @param pi PendingIntent for returning result + */ + public void requestPermission(UsbAccessory accessory, PendingIntent pi) { + try { + mService.requestAccessoryPermission(new android.hardware.usb.UsbAccessory( + accessory.getManufacturer(),accessory.getModel(), + accessory.getDescription(), accessory.getVersion(), accessory.getUri()), + mContext.getPackageName(), pi); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in requestPermission", e); + } + } } diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c index 94cc0ce..3c0de69 100644 --- a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c +++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c @@ -133,10 +133,19 @@ static int usb_device_added(const char *devname, void* client_data) { } else { printf("Found possible android device - attempting to switch to accessory mode\n"); + uint16_t protocol; + ret = usb_device_control_transfer(device, USB_DIR_IN | USB_TYPE_VENDOR, + ACCESSORY_GET_PROTOCOL, 0, 0, &protocol, sizeof(protocol), 0); + if (ret == 2) + printf("device supports protocol version %d\n", protocol); + else + fprintf(stderr, "failed to read protocol version\n"); + send_string(device, ACCESSORY_STRING_MANUFACTURER, "Google, Inc."); send_string(device, ACCESSORY_STRING_MODEL, "AccessoryChat"); - send_string(device, ACCESSORY_STRING_TYPE, "Sample Program"); + send_string(device, ACCESSORY_STRING_DESCRIPTION, "Sample Program"); send_string(device, ACCESSORY_STRING_VERSION, "1.0"); + send_string(device, ACCESSORY_STRING_URI, "http://www.android.com"); ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR, ACCESSORY_START, 0, 0, 0, 0, 0); diff --git a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java index 5cf02c7..f9a5bf4 100644 --- a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java +++ b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java @@ -17,9 +17,11 @@ package com.android.accessorychat; import android.app.Activity; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -42,18 +44,47 @@ import java.io.IOException; public class AccessoryChat extends Activity implements Runnable, TextView.OnEditorActionListener { private static final String TAG = "AccessoryChat"; - TextView mLog; - EditText mEditText; - ParcelFileDescriptor mFileDescriptor; - FileInputStream mInputStream; - FileOutputStream mOutputStream; + + private static final String ACTION_USB_PERMISSION = + "com.android.accessorychat.action.USB_PERMISSION"; + + private TextView mLog; + private EditText mEditText; + private ParcelFileDescriptor mFileDescriptor; + private FileInputStream mInputStream; + private FileOutputStream mOutputStream; + private UsbManager mUsbManager; + private PendingIntent mPermissionIntent; + private boolean mPermissionRequestPending; private static final int MESSAGE_LOG = 1; + private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_USB_PERMISSION.equals(intent.getAction())) { + synchronized (this) { + UsbAccessory accessory = UsbManager.getAccessory(intent); + if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { + openAccessory(accessory); + } else { + Log.d(TAG, "permission denied for accessory " + accessory); + } + mPermissionRequestPending = false; + } + } + } + }; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mUsbManager = UsbManager.getInstance(this); + mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); + IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); + registerReceiver(mUsbReceiver, filter); + setContentView(R.layout.accessory_chat); mLog = (TextView)findViewById(R.id.log); mEditText = (EditText)findViewById(R.id.message); @@ -66,21 +97,20 @@ public class AccessoryChat extends Activity implements Runnable, TextView.OnEdit Intent intent = getIntent(); Log.d(TAG, "intent: " + intent); - UsbManager manager = UsbManager.getInstance(); - UsbAccessory[] accessories = manager.getAccessoryList(); + UsbAccessory[] accessories = mUsbManager.getAccessoryList(); UsbAccessory accessory = (accessories == null ? null : accessories[0]); if (accessory != null) { - mFileDescriptor = manager.openAccessory(accessory); - if (mFileDescriptor != null) { - FileDescriptor fd = mFileDescriptor.getFileDescriptor(); - mInputStream = new FileInputStream(fd); - mOutputStream = new FileOutputStream(fd); - Thread thread = new Thread(null, this, "AccessoryChat"); - thread.start(); + if (mUsbManager.hasPermission(accessory)) { + openAccessory(accessory); } else { - Log.d(TAG, "openAccessory fail"); + synchronized (mUsbReceiver) { + if (!mPermissionRequestPending) { + mUsbManager.requestPermission(accessory, mPermissionIntent); + mPermissionRequestPending = true; + } + } } - } else { + } else { Log.d(TAG, "mAccessory is null"); } } @@ -100,9 +130,24 @@ public class AccessoryChat extends Activity implements Runnable, TextView.OnEdit @Override public void onDestroy() { + unregisterReceiver(mUsbReceiver); super.onDestroy(); } + private void openAccessory(UsbAccessory accessory) { + mFileDescriptor = mUsbManager.openAccessory(accessory); + if (mFileDescriptor != null) { + FileDescriptor fd = mFileDescriptor.getFileDescriptor(); + mInputStream = new FileInputStream(fd); + mOutputStream = new FileOutputStream(fd); + Thread thread = new Thread(null, this, "AccessoryChat"); + thread.start(); + Log.d(TAG, "openAccessory succeeded"); + } else { + Log.d(TAG, "openAccessory fail"); + } + } + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE && mOutputStream != null) { try { diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 5a73d2d..fd12e19 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -805,7 +805,7 @@ public class AudioService extends IAudioService.Stub { if (mode != mMode) { // automatically handle audio focus for mode changes - handleFocusForCalls(mMode, mode); + handleFocusForCalls(mMode, mode, cb); if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) { mMode = mode; @@ -864,7 +864,7 @@ public class AudioService extends IAudioService.Stub { } /** pre-condition: oldMode != newMode */ - private void handleFocusForCalls(int oldMode, int newMode) { + private void handleFocusForCalls(int oldMode, int newMode, IBinder cb) { // if ringing if (newMode == AudioSystem.MODE_RINGTONE) { // if not ringing silently @@ -872,8 +872,8 @@ public class AudioService extends IAudioService.Stub { if (ringVolume > 0) { // request audio focus for the communication focus entry requestAudioFocus(AudioManager.STREAM_RING, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, - null, null /* both allowed to be null only for this clientId */, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, cb, + null /* IAudioFocusDispatcher allowed to be null only for this clientId */, IN_VOICE_COMM_FOCUS_ID /*clientId*/); } @@ -884,8 +884,8 @@ public class AudioService extends IAudioService.Stub { // request audio focus for the communication focus entry // (it's ok if focus was already requested during ringing) requestAudioFocus(AudioManager.STREAM_RING, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, - null, null /* both allowed to be null only for this clientId */, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, cb, + null /* IAudioFocusDispatcher allowed to be null only for this clientId */, IN_VOICE_COMM_FOCUS_ID /*clientId*/); } // if exiting call @@ -2547,10 +2547,9 @@ public class AudioService extends IAudioService.Stub { // the main stream type for the audio focus request is currently not used. It may // potentially be used to handle multiple stream type-dependent audio focuses. - // we need a valid binder callback for clients other than the AudioService's phone - // state listener - if (!IN_VOICE_COMM_FOCUS_ID.equals(clientId) && ((cb == null) || !cb.pingBinder())) { - Log.i(TAG, " AudioFocus DOA client for requestAudioFocus(), exiting"); + // we need a valid binder callback for clients + if (!cb.pingBinder()) { + Log.e(TAG, " AudioFocus DOA client for requestAudioFocus(), aborting."); return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } @@ -2591,17 +2590,14 @@ public class AudioService extends IAudioService.Stub { }//synchronized(mAudioFocusLock) // handle the potential premature death of the new holder of the focus - // (premature death == death before abandoning focus) for a client which is not the - // AudioService's phone state listener - if (!IN_VOICE_COMM_FOCUS_ID.equals(clientId)) { - // Register for client death notification - AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb); - try { - cb.linkToDeath(afdh, 0); - } catch (RemoteException e) { - // client has already died! - Log.w(TAG, "AudioFocus requestAudioFocus() could not link to "+cb+" binder death"); - } + // (premature death == death before abandoning focus) + // Register for client death notification + AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb); + try { + cb.linkToDeath(afdh, 0); + } catch (RemoteException e) { + // client has already died! + Log.w(TAG, "AudioFocus requestAudioFocus() could not link to "+cb+" binder death"); } return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java index b2f547b..7069b23 100755 --- a/media/java/android/media/videoeditor/AudioTrack.java +++ b/media/java/android/media/videoeditor/AudioTrack.java @@ -140,7 +140,7 @@ public class AudioTrack { try { properties = mMANativeHelper.getMediaProperties(filename); } catch (Exception e) { - throw new IllegalArgumentException("Unsupported file or file not found"); + throw new IllegalArgumentException(e.getMessage() + " : " + filename); } switch (mMANativeHelper.getFileType(properties.fileType)) { case MediaProperties.FILE_3GP: diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java index c91d796..4758de6 100755 --- a/media/java/android/media/videoeditor/MediaVideoItem.java +++ b/media/java/android/media/videoeditor/MediaVideoItem.java @@ -115,7 +115,7 @@ public class MediaVideoItem extends MediaItem { try { properties = mMANativeHelper.getMediaProperties(filename); } catch ( Exception e) { - throw new IllegalArgumentException("Unsupported file or file not found: " + filename); + throw new IllegalArgumentException(e.getMessage() + " : " + filename); } switch (mMANativeHelper.getFileType(properties.fileType)) { diff --git a/media/java/android/media/videoeditor/Transition.java b/media/java/android/media/videoeditor/Transition.java index 3e8fe94..fa9d26d 100755 --- a/media/java/android/media/videoeditor/Transition.java +++ b/media/java/android/media/videoeditor/Transition.java @@ -131,6 +131,11 @@ public abstract class Transition { if (durationMs > getMaximumDuration()) { throw new IllegalArgumentException("The duration is too large"); } + if (afterMediaItem != null) { + mNativeHelper = afterMediaItem.getNativeContext(); + }else { + mNativeHelper = beforeMediaItem.getNativeContext(); + } } /** diff --git a/media/java/android/media/videoeditor/TransitionAlpha.java b/media/java/android/media/videoeditor/TransitionAlpha.java index f7d17cb..22788d4 100755 --- a/media/java/android/media/videoeditor/TransitionAlpha.java +++ b/media/java/android/media/videoeditor/TransitionAlpha.java @@ -104,13 +104,6 @@ public class TransitionAlpha extends Transition { mWidth = dbo.outWidth; mHeight = dbo.outHeight; - if (afterMediaItem != null) { - mNativeHelper = afterMediaItem.getNativeContext(); - }else { - mNativeHelper = beforeMediaItem.getNativeContext(); - } - - mRGBMaskFile = String.format(mNativeHelper.getProjectPath() + "/" + "mask" + transitionId+ ".rgb"); diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index 98de2f7..b4a4689 100644 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.ContentValues; import android.content.IContentProvider; import android.content.Intent; +import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.media.MediaScanner; @@ -62,8 +63,8 @@ public class MtpDatabase { // true if the database has been modified in the current MTP session private boolean mDatabaseModified; - // database for writable MTP device properties - private SQLiteDatabase mDevicePropDb; + // SharedPreferences for writable MTP device properties + private SharedPreferences mDeviceProperties; private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1; // FIXME - this should be passed in via the constructor @@ -96,9 +97,6 @@ public class MtpDatabase { private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " + Files.FileColumns.FORMAT + "=?"; - private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" }; - private static final String DEVICE_PROPERTY_WHERE = "code=?"; - private final MediaScanner mMediaScanner; static { @@ -114,7 +112,7 @@ public class MtpDatabase { mMediaStoragePath = storagePath; mObjectsUri = Files.getMtpObjectsUri(volumeName); mMediaScanner = new MediaScanner(context); - openDevicePropertiesDatabase(context); + initDeviceProperties(context); } @Override @@ -126,19 +124,38 @@ public class MtpDatabase { } } - private void openDevicePropertiesDatabase(Context context) { - mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null); - int version = mDevicePropDb.getVersion(); - - // initialize if necessary - if (version != DEVICE_PROPERTIES_DATABASE_VERSION) { - mDevicePropDb.execSQL("CREATE TABLE properties (" + - "_id INTEGER PRIMARY KEY AUTOINCREMENT," + - "code INTEGER UNIQUE ON CONFLICT REPLACE," + - "value TEXT" + - ");"); - mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);"); - mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION); + private void initDeviceProperties(Context context) { + final String devicePropertiesName = "device-properties"; + mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE); + File databaseFile = context.getDatabasePath(devicePropertiesName); + + if (databaseFile.exists()) { + // for backward compatibility - read device properties from sqlite database + // and migrate them to shared prefs + SQLiteDatabase db = null; + Cursor c = null; + try { + db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null); + if (db != null) { + c = db.query("properties", new String[] { "_id", "code", "value" }, + null, null, null, null, null); + if (c != null) { + SharedPreferences.Editor e = mDeviceProperties.edit(); + while (c.moveToNext()) { + String name = c.getString(1); + String value = c.getString(2); + e.putString(name, value); + } + e.commit(); + } + } + } catch (Exception e) { + Log.e(TAG, "failed to migrate device properties", e); + } finally { + if (c != null) c.close(); + if (db != null) db.close(); + } + databaseFile.delete(); } } @@ -567,30 +584,15 @@ public class MtpDatabase { switch (property) { case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: - // writable string properties kept in our device property database - Cursor c = null; - try { - c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION, - DEVICE_PROPERTY_WHERE, new String[] { Integer.toString(property) }, - null, null, null); - - if (c != null && c.moveToNext()) { - String value = c.getString(1); - int length = value.length(); - if (length > 255) { - length = 255; - } - value.getChars(0, length, outStringValue, 0); - outStringValue[length] = 0; - } else { - outStringValue[0] = 0; - } - return MtpConstants.RESPONSE_OK; - } finally { - if (c != null) { - c.close(); - } + // writable string properties kept in shared preferences + String value = mDeviceProperties.getString(Integer.toString(property), ""); + int length = value.length(); + if (length > 255) { + length = 255; } + value.getChars(0, length, outStringValue, 0); + outStringValue[length] = 0; + return MtpConstants.RESPONSE_OK; case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE: // use screen size as max image size @@ -612,16 +614,11 @@ public class MtpDatabase { switch (property) { case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: - // writable string properties kept in our device property database - try { - ContentValues values = new ContentValues(); - values.put("code", property); - values.put("value", stringValue); - mDevicePropDb.insert("properties", "code", values); - return MtpConstants.RESPONSE_OK; - } catch (Exception e) { - return MtpConstants.RESPONSE_GENERAL_ERROR; - } + // writable string properties kept in shared prefs + SharedPreferences.Editor e = mDeviceProperties.edit(); + e.putString(Integer.toString(property), stringValue); + return (e.commit() ? MtpConstants.RESPONSE_OK + : MtpConstants.RESPONSE_GENERAL_ERROR); } return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED; diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java index 22961d7f..db2cebd 100644 --- a/media/java/android/mtp/MtpDevice.java +++ b/media/java/android/mtp/MtpDevice.java @@ -17,7 +17,7 @@ package android.mtp; import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; +import android.hardware.usb.UsbDeviceConnection; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -44,17 +44,20 @@ public final class MtpDevice { } /** - * Opens the MTP or PTP device and return an {@link android.mtp.MtpDevice} for it. + * Opens the MTP device. Once the device is open it takes ownership of the + * {@link android.hardware.usb.UsbDeviceConnection}. + * The connection will be closed when you call {@link #close()} + * The connection will also be closed if this method fails. * - * @param manager reference to {@link android.hardware.usb.UsbManager} + * @param connection an open {@link android.hardware.usb.UsbDeviceConnection} for the device * @return true if the device was successfully opened. */ - public boolean open(UsbManager manager) { - if (manager.openDevice(mDevice)) { - return native_open(mDevice.getDeviceName(), mDevice.getFileDescriptor()); - } else { - return false; + public boolean open(UsbDeviceConnection connection) { + boolean result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor()); + if (!result) { + connection.close(); } + return result; } /** diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp index fd32665..f5fcb4e 100644 --- a/media/jni/android_mtp_MtpDevice.cpp +++ b/media/jni/android_mtp_MtpDevice.cpp @@ -311,9 +311,9 @@ android_mtp_MtpDevice_get_object_info(JNIEnv *env, jobject thiz, jint objectID) if (objectInfo->mName) env->SetObjectField(info, field_objectInfo_name, env->NewStringUTF(objectInfo->mName)); if (objectInfo->mDateCreated) - env->SetLongField(info, field_objectInfo_dateCreated, objectInfo->mDateCreated); + env->SetLongField(info, field_objectInfo_dateCreated, objectInfo->mDateCreated * 1000LL); if (objectInfo->mDateModified) - env->SetLongField(info, field_objectInfo_dateModified, objectInfo->mDateModified); + env->SetLongField(info, field_objectInfo_dateModified, objectInfo->mDateModified * 1000LL); if (objectInfo->mKeywords) env->SetObjectField(info, field_objectInfo_keywords, env->NewStringUTF(objectInfo->mKeywords)); diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp index 423e93f..035f59a 100755 --- a/media/jni/mediaeditor/VideoEditorOsal.cpp +++ b/media/jni/mediaeditor/VideoEditorOsal.cpp @@ -207,6 +207,7 @@ static const VideoEdit_Osal_Result gkRESULTS[] = VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIOBITRATE_TOO_HIGH ), VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL ), VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_NOMORE_SPACE ), + VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_FILE_DRM_PROTECTED ), // M4READER_Common.h VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_READER_UNKNOWN_STREAM_TYPE ), diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp index 73a7c9c..3b795ce 100755 --- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp +++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp @@ -204,10 +204,17 @@ jobject videoEditProp_getProperties( result = getClipProperties( pEnv, thiz, pFile, clipType, pClipProperties); - // Check if the creation succeeded. - videoEditJava_checkAndThrowIllegalArgumentException( - &gotten, pEnv,(M4NO_ERROR != result), - "Invalid File or File not found"); + if (M4MCS_ERR_FILE_DRM_PROTECTED == result) { + // Check if the creation succeeded. + videoEditJava_checkAndThrowIllegalArgumentException( + &gotten, pEnv,(M4NO_ERROR != result), + "Invalid File - DRM Protected "); + } else { + // Check if the creation succeeded. + videoEditJava_checkAndThrowIllegalArgumentException( + &gotten, pEnv,(M4NO_ERROR != result), + "Invalid File or File not found "); + } /** * Max resolution supported is 1280 x 720. diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 1d6ffa0..a18bedb 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -128,6 +128,9 @@ status_t AudioRecord::set( { LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount); + + AutoMutex lock(mLock); + if (mAudioRecord != 0) { return INVALID_OPERATION; } @@ -183,7 +186,7 @@ status_t AudioRecord::set( mSessionId = sessionId; // create the IAudioRecord - status = openRecord(sampleRate, format, channelCount, + status = openRecord_l(sampleRate, format, channelCount, frameCount, flags, input); if (status != NO_ERROR) { return status; @@ -282,21 +285,31 @@ status_t AudioRecord::start() } AutoMutex lock(mLock); + // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed + // while we are accessing the cblk + sp <IAudioRecord> audioRecord = mAudioRecord; + sp <IMemory> iMem = mCblkMemory; + audio_track_cblk_t* cblk = mCblk; if (mActive == 0) { mActive = 1; - ret = mAudioRecord->start(); - if (ret == DEAD_OBJECT) { - LOGV("start() dead IAudioRecord: creating a new one"); - ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount, - mFrameCount, mFlags, getInput()); - if (ret == NO_ERROR) { - ret = mAudioRecord->start(); + + cblk->lock.lock(); + if (!(cblk->flags & CBLK_INVALID_MSK)) { + cblk->lock.unlock(); + ret = mAudioRecord->start(); + cblk->lock.lock(); + if (ret == DEAD_OBJECT) { + cblk->flags |= CBLK_INVALID_MSK; } } + if (cblk->flags & CBLK_INVALID_MSK) { + ret = restoreRecord_l(cblk); + } + cblk->lock.unlock(); if (ret == NO_ERROR) { - mNewPosition = mCblk->user + mUpdatePeriod; - mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; - mCblk->waitTimeMs = 0; + mNewPosition = cblk->user + mUpdatePeriod; + cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + cblk->waitTimeMs = 0; if (t != 0) { t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT); } else { @@ -353,6 +366,7 @@ bool AudioRecord::stopped() const uint32_t AudioRecord::getSampleRate() { + AutoMutex lock(mLock); return mCblk->sampleRate; } @@ -400,6 +414,7 @@ status_t AudioRecord::getPosition(uint32_t *position) { if (position == 0) return BAD_VALUE; + AutoMutex lock(mLock); *position = mCblk->user; return NO_ERROR; @@ -415,7 +430,8 @@ unsigned int AudioRecord::getInputFramesLost() // ------------------------------------------------------------------------- -status_t AudioRecord::openRecord( +// must be called with mLock held +status_t AudioRecord::openRecord_l( uint32_t sampleRate, int format, int channelCount, @@ -459,6 +475,7 @@ status_t AudioRecord::openRecord( status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { + AutoMutex lock(mLock); int active; status_t result; audio_track_cblk_t* cblk = mCblk; @@ -483,7 +500,19 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) cblk->lock.unlock(); return WOULD_BLOCK; } - result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); + if (!(cblk->flags & CBLK_INVALID_MSK)) { + mLock.unlock(); + result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); + cblk->lock.unlock(); + mLock.lock(); + if (mActive == 0) { + return status_t(STOPPED); + } + cblk->lock.lock(); + } + if (cblk->flags & CBLK_INVALID_MSK) { + goto create_new_record; + } if (__builtin_expect(result!=NO_ERROR, false)) { cblk->waitTimeMs += waitTimeMs; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { @@ -491,16 +520,17 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) "user=%08x, server=%08x", cblk->user, cblk->server); cblk->lock.unlock(); result = mAudioRecord->start(); + cblk->lock.lock(); if (result == DEAD_OBJECT) { - LOGW("obtainBuffer() dead IAudioRecord: creating a new one"); - result = openRecord(cblk->sampleRate, mFormat, mChannelCount, - mFrameCount, mFlags, getInput()); - if (result == NO_ERROR) { - cblk = mCblk; - mAudioRecord->start(); - } + cblk->flags |= CBLK_INVALID_MSK; +create_new_record: + result = AudioRecord::restoreRecord_l(cblk); + } + if (result != NO_ERROR) { + LOGW("obtainBuffer create Track error %d", result); + cblk->lock.unlock(); + return result; } - cblk->lock.lock(); cblk->waitTimeMs = 0; } if (--waitCount == 0) { @@ -540,12 +570,19 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) void AudioRecord::releaseBuffer(Buffer* audioBuffer) { - audio_track_cblk_t* cblk = mCblk; - cblk->stepUser(audioBuffer->frameCount); + AutoMutex lock(mLock); + mCblk->stepUser(audioBuffer->frameCount); } audio_io_handle_t AudioRecord::getInput() { + AutoMutex lock(mLock); + return getInput_l(); +} + +// must be called with mLock held +audio_io_handle_t AudioRecord::getInput_l() +{ mInput = AudioSystem::getInput(mInputSource, mCblk->sampleRate, mFormat, mChannels, @@ -573,6 +610,12 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize) return BAD_VALUE; } + mLock.lock(); + // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed + // while we are accessing the cblk + sp <IAudioRecord> audioRecord = mAudioRecord; + sp <IMemory> iMem = mCblkMemory; + mLock.unlock(); do { @@ -613,9 +656,17 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) uint32_t frames = mRemainingFrames; size_t readSize; + mLock.lock(); + // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed + // while we are accessing the cblk + sp <IAudioRecord> audioRecord = mAudioRecord; + sp <IMemory> iMem = mCblkMemory; + audio_track_cblk_t* cblk = mCblk; + mLock.unlock(); + // Manage marker callback if (!mMarkerReached && (mMarkerPosition > 0)) { - if (mCblk->user >= mMarkerPosition) { + if (cblk->user >= mMarkerPosition) { mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); mMarkerReached = true; } @@ -623,7 +674,7 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) // Manage new position callback if (mUpdatePeriod > 0) { - while (mCblk->user >= mNewPosition) { + while (cblk->user >= mNewPosition) { mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); mNewPosition += mUpdatePeriod; } @@ -669,11 +720,11 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) // Manage overrun callback - if (mActive && (mCblk->framesAvailable_l() == 0)) { - LOGV("Overrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags); - if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { + if (mActive && (cblk->framesAvailable() == 0)) { + LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); + if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { mCbf(EVENT_OVERRUN, mUserData, 0); - mCblk->flags |= CBLK_UNDERRUN_ON; + cblk->flags |= CBLK_UNDERRUN_ON; } } @@ -685,6 +736,69 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) return true; } +// must be called with mLock and cblk.lock held. Callers must also hold strong references on +// the IAudioRecord and IMemory in case they are recreated here. +// If the IAudioRecord is successfully restored, the cblk pointer is updated +status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) +{ + status_t result; + + if (!(cblk->flags & CBLK_RESTORING_MSK)) { + LOGW("dead IAudioRecord, creating a new one"); + + cblk->flags |= CBLK_RESTORING_ON; + // signal old cblk condition so that other threads waiting for available buffers stop + // waiting now + cblk->cv.broadcast(); + cblk->lock.unlock(); + + // if the new IAudioRecord is created, openRecord_l() will modify the + // following member variables: mAudioRecord, mCblkMemory and mCblk. + // It will also delete the strong references on previous IAudioRecord and IMemory + result = openRecord_l(cblk->sampleRate, mFormat, mChannelCount, + mFrameCount, mFlags, getInput_l()); + if (result == NO_ERROR) { + result = mAudioRecord->start(); + } + if (result != NO_ERROR) { + mActive = false; + } + + // signal old cblk condition for other threads waiting for restore completion + cblk->lock.lock(); + cblk->flags |= CBLK_RESTORED_MSK; + cblk->cv.broadcast(); + cblk->lock.unlock(); + } else { + if (!(cblk->flags & CBLK_RESTORED_MSK)) { + LOGW("dead IAudioRecord, waiting for a new one to be created"); + mLock.unlock(); + result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); + cblk->lock.unlock(); + mLock.lock(); + } else { + LOGW("dead IAudioRecord, already restored"); + result = NO_ERROR; + cblk->lock.unlock(); + } + if (result != NO_ERROR || mActive == 0) { + result = status_t(STOPPED); + } + } + LOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", + result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); + + if (result == NO_ERROR) { + // from now on we switch to the newly created cblk + cblk = mCblk; + } + cblk->lock.lock(); + + LOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result); + + return result; +} + // ========================================================================= AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index c1bed59..8d8f67b 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -148,6 +148,7 @@ status_t AudioTrack::set( LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); + AutoMutex lock(mLock); if (mAudioTrack != 0) { LOGE("Track already in use"); return INVALID_OPERATION; @@ -211,8 +212,15 @@ status_t AudioTrack::set( mAuxEffectId = 0; // create the IAudioTrack - status_t status = createTrack(streamType, sampleRate, format, channelCount, - frameCount, flags, sharedBuffer, output, true); + status_t status = createTrack_l(streamType, + sampleRate, + format, + channelCount, + frameCount, + flags, + sharedBuffer, + output, + true); if (status != NO_ERROR) { return status; @@ -312,37 +320,38 @@ void AudioTrack::start() } AutoMutex lock(mLock); + // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed + // while we are accessing the cblk + sp <IAudioTrack> audioTrack = mAudioTrack; + sp <IMemory> iMem = mCblkMemory; + audio_track_cblk_t* cblk = mCblk; + if (mActive == 0) { mActive = 1; - mNewPosition = mCblk->server + mUpdatePeriod; - mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; - mCblk->waitTimeMs = 0; - mCblk->flags &= ~CBLK_DISABLED_ON; + mNewPosition = cblk->server + mUpdatePeriod; + cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; + cblk->waitTimeMs = 0; + cblk->flags &= ~CBLK_DISABLED_ON; if (t != 0) { t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); } else { setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); } - if (mCblk->flags & CBLK_INVALID_MSK) { - LOGW("start() track %p invalidated, creating a new one", this); - // no need to clear the invalid flag as this cblk will not be used anymore - // force new track creation - status = DEAD_OBJECT; - } else { + LOGV("start %p before lock cblk %p", this, mCblk); + cblk->lock.lock(); + if (!(cblk->flags & CBLK_INVALID_MSK)) { + cblk->lock.unlock(); status = mAudioTrack->start(); - } - if (status == DEAD_OBJECT) { - LOGV("start() dead IAudioTrack: creating a new one"); - status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount, - mFrameCount, mFlags, mSharedBuffer, getOutput(), false); - if (status == NO_ERROR) { - status = mAudioTrack->start(); - if (status == NO_ERROR) { - mNewPosition = mCblk->server + mUpdatePeriod; - } + cblk->lock.lock(); + if (status == DEAD_OBJECT) { + cblk->flags |= CBLK_INVALID_MSK; } } + if (cblk->flags & CBLK_INVALID_MSK) { + status = restoreTrack_l(cblk, true); + } + cblk->lock.unlock(); if (status != NO_ERROR) { LOGV("start() failed"); mActive = 0; @@ -375,14 +384,14 @@ void AudioTrack::stop() mAudioTrack->stop(); // Cancel loops (If we are in the middle of a loop, playback // would not stop until loopCount reaches 0). - setLoop(0, 0, 0); + setLoop_l(0, 0, 0); // the playback head position will reset to 0, so if a marker is set, we need // to activate it again mMarkerReached = false; // Force flush if a shared buffer is used otherwise audioflinger // will not stop before end of buffer is reached. if (mSharedBuffer != 0) { - flush(); + flush_l(); } if (t != 0) { t->requestExit(); @@ -403,6 +412,13 @@ bool AudioTrack::stopped() const void AudioTrack::flush() { + AutoMutex lock(mLock); + flush_l(); +} + +// must be called with mLock held +void AudioTrack::flush_l() +{ LOGV("flush"); // clear playback marker and periodic update counter @@ -445,6 +461,7 @@ status_t AudioTrack::setVolume(float left, float right) return BAD_VALUE; } + AutoMutex lock(mLock); mVolume[LEFT] = left; mVolume[RIGHT] = right; @@ -470,6 +487,7 @@ status_t AudioTrack::setAuxEffectSendLevel(float level) if (level > 1.0f) { return BAD_VALUE; } + AutoMutex lock(mLock); mSendLevel = level; @@ -495,17 +513,26 @@ status_t AudioTrack::setSampleRate(int rate) // Resampler implementation limits input sampling rate to 2 x output sampling rate. if (rate <= 0 || rate > afSamplingRate*2 ) return BAD_VALUE; + AutoMutex lock(mLock); mCblk->sampleRate = rate; return NO_ERROR; } uint32_t AudioTrack::getSampleRate() { + AutoMutex lock(mLock); return mCblk->sampleRate; } status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) { + AutoMutex lock(mLock); + return setLoop_l(loopStart, loopEnd, loopCount); +} + +// must be called with mLock held +status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount) +{ audio_track_cblk_t* cblk = mCblk; Mutex::Autolock _l(cblk->lock); @@ -540,6 +567,7 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount status_t AudioTrack::getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount) { + AutoMutex lock(mLock); if (loopStart != 0) { *loopStart = mCblk->loopStart; } @@ -599,6 +627,7 @@ status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) status_t AudioTrack::setPosition(uint32_t position) { + AutoMutex lock(mLock); Mutex::Autolock _l(mCblk->lock); if (!stopped()) return INVALID_OPERATION; @@ -614,7 +643,7 @@ status_t AudioTrack::setPosition(uint32_t position) status_t AudioTrack::getPosition(uint32_t *position) { if (position == 0) return BAD_VALUE; - + AutoMutex lock(mLock); *position = mCblk->server; return NO_ERROR; @@ -622,9 +651,11 @@ status_t AudioTrack::getPosition(uint32_t *position) status_t AudioTrack::reload() { + AutoMutex lock(mLock); + if (!stopped()) return INVALID_OPERATION; - flush(); + flush_l(); mCblk->stepUser(mCblk->frameCount); @@ -633,6 +664,13 @@ status_t AudioTrack::reload() audio_io_handle_t AudioTrack::getOutput() { + AutoMutex lock(mLock); + return getOutput_l(); +} + +// must be called with mLock held +audio_io_handle_t AudioTrack::getOutput_l() +{ return AudioSystem::getOutput((AudioSystem::stream_type)mStreamType, mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags); } @@ -654,7 +692,8 @@ status_t AudioTrack::attachAuxEffect(int effectId) // ------------------------------------------------------------------------- -status_t AudioTrack::createTrack( +// must be called with mLock held +status_t AudioTrack::createTrack_l( int streamType, uint32_t sampleRate, int format, @@ -774,6 +813,7 @@ status_t AudioTrack::createTrack( status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { + AutoMutex lock(mLock); int active; status_t result; audio_track_cblk_t* cblk = mCblk; @@ -800,12 +840,17 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) return WOULD_BLOCK; } if (!(cblk->flags & CBLK_INVALID_MSK)) { + mLock.unlock(); result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); + cblk->lock.unlock(); + mLock.lock(); + if (mActive == 0) { + return status_t(STOPPED); + } + cblk->lock.lock(); } + if (cblk->flags & CBLK_INVALID_MSK) { - LOGW("obtainBuffer() track %p invalidated, creating a new one", this); - // no need to clear the invalid flag as this cblk will not be used anymore - cblk->lock.unlock(); goto create_new_track; } if (__builtin_expect(result!=NO_ERROR, false)) { @@ -819,18 +864,17 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) cblk->lock.unlock(); result = mAudioTrack->start(); + cblk->lock.lock(); if (result == DEAD_OBJECT) { - LOGW("obtainBuffer() dead IAudioTrack: creating a new one"); + cblk->flags |= CBLK_INVALID_MSK; create_new_track: - result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount, - mFrameCount, mFlags, mSharedBuffer, getOutput(), false); - if (result == NO_ERROR) { - cblk = mCblk; - cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; - mAudioTrack->start(); - } + result = restoreTrack_l(cblk, false); + } + if (result != NO_ERROR) { + LOGW("obtainBuffer create Track error %d", result); + cblk->lock.unlock(); + return result; } - cblk->lock.lock(); } cblk->waitTimeMs = 0; } @@ -848,7 +892,7 @@ create_new_track: } // restart track if it was disabled by audioflinger due to previous underrun - if (cblk->flags & CBLK_DISABLED_MSK) { + if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) { cblk->flags &= ~CBLK_DISABLED_ON; LOGW("obtainBuffer() track %p disabled, restarting", this); mAudioTrack->start(); @@ -883,8 +927,8 @@ create_new_track: void AudioTrack::releaseBuffer(Buffer* audioBuffer) { - audio_track_cblk_t* cblk = mCblk; - cblk->stepUser(audioBuffer->frameCount); + AutoMutex lock(mLock); + mCblk->stepUser(audioBuffer->frameCount); } // ------------------------------------------------------------------------- @@ -903,6 +947,13 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) LOGV("write %p: %d bytes, mActive=%d", this, userSize, mActive); + // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed + // while we are accessing the cblk + mLock.lock(); + sp <IAudioTrack> audioTrack = mAudioTrack; + sp <IMemory> iMem = mCblkMemory; + mLock.unlock(); + ssize_t written = 0; const int8_t *src = (const int8_t *)buffer; Buffer audioBuffer; @@ -953,21 +1004,29 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) uint32_t frames; size_t writtenSize; + mLock.lock(); + // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed + // while we are accessing the cblk + sp <IAudioTrack> audioTrack = mAudioTrack; + sp <IMemory> iMem = mCblkMemory; + audio_track_cblk_t* cblk = mCblk; + mLock.unlock(); + // Manage underrun callback - if (mActive && (mCblk->framesReady() == 0)) { - LOGV("Underrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags); - if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { + if (mActive && (cblk->framesReady() == 0)) { + LOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); + if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { mCbf(EVENT_UNDERRUN, mUserData, 0); - if (mCblk->server == mCblk->frameCount) { + if (cblk->server == cblk->frameCount) { mCbf(EVENT_BUFFER_END, mUserData, 0); } - mCblk->flags |= CBLK_UNDERRUN_ON; + cblk->flags |= CBLK_UNDERRUN_ON; if (mSharedBuffer != 0) return false; } } // Manage loop end callback - while (mLoopCount > mCblk->loopCount) { + while (mLoopCount > cblk->loopCount) { int loopCount = -1; mLoopCount--; if (mLoopCount >= 0) loopCount = mLoopCount; @@ -977,7 +1036,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Manage marker callback if (!mMarkerReached && (mMarkerPosition > 0)) { - if (mCblk->server >= mMarkerPosition) { + if (cblk->server >= mMarkerPosition) { mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); mMarkerReached = true; } @@ -985,7 +1044,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Manage new position callback if (mUpdatePeriod > 0) { - while (mCblk->server >= mNewPosition) { + while (cblk->server >= mNewPosition) { mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); mNewPosition += mUpdatePeriod; } @@ -1068,6 +1127,84 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) return true; } +// must be called with mLock and cblk.lock held. Callers must also hold strong references on +// the IAudioTrack and IMemory in case they are recreated here. +// If the IAudioTrack is successfully restored, the cblk pointer is updated +status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart) +{ + status_t result; + + if (!(cblk->flags & CBLK_RESTORING_MSK)) { + LOGW("dead IAudioTrack, creating a new one from %s", + fromStart ? "start()" : "obtainBuffer()"); + + cblk->flags |= CBLK_RESTORING_ON; + // signal old cblk condition so that other threads waiting for available buffers stop + // waiting now + cblk->cv.broadcast(); + cblk->lock.unlock(); + + // if the new IAudioTrack is created, createTrack_l() will modify the + // following member variables: mAudioTrack, mCblkMemory and mCblk. + // It will also delete the strong references on previous IAudioTrack and IMemory + result = createTrack_l(mStreamType, + cblk->sampleRate, + mFormat, + mChannelCount, + mFrameCount, + mFlags, + mSharedBuffer, + getOutput_l(), + false); + + if (result == NO_ERROR) { + if (!fromStart) { + mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + } + result = mAudioTrack->start(); + if (fromStart && result == NO_ERROR) { + mNewPosition = mCblk->server + mUpdatePeriod; + } + } + if (result != NO_ERROR) { + mActive = false; + } + + // signal old cblk condition for other threads waiting for restore completion + cblk->lock.lock(); + cblk->flags |= CBLK_RESTORED_MSK; + cblk->cv.broadcast(); + cblk->lock.unlock(); + } else { + if (!(cblk->flags & CBLK_RESTORED_MSK)) { + LOGW("dead IAudioTrack, waiting for a new one"); + mLock.unlock(); + result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); + cblk->lock.unlock(); + mLock.lock(); + } else { + LOGW("dead IAudioTrack, already restored"); + result = NO_ERROR; + cblk->lock.unlock(); + } + if (result != NO_ERROR || mActive == 0) { + result = status_t(STOPPED); + } + } + LOGV("restoreTrack_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", + result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); + + if (result == NO_ERROR) { + // from now on we switch to the newly created cblk + cblk = mCblk; + } + cblk->lock.lock(); + + LOGW_IF(result != NO_ERROR, "restoreTrack_l() error %d", result); + + return result; +} + status_t AudioTrack::dump(int fd, const Vector<String16>& args) const { @@ -1197,7 +1334,9 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) this->server = s; - cv.signal(); + if (!(flags & CBLK_INVALID_MSK)) { + cv.signal(); + } lock.unlock(); return true; } diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 4c744bd..5734c7e 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -45,6 +45,7 @@ #include <surfaceflinger/Surface.h> #include <gui/ISurfaceTexture.h> #include <gui/SurfaceTextureClient.h> +#include <surfaceflinger/ISurfaceComposer.h> #include <media/stagefright/foundation/ALooper.h> #include <media/stagefright/foundation/AMessage.h> @@ -1189,6 +1190,19 @@ void AwesomePlayer::setVideoSource(sp<MediaSource> source) { } status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { + + // Either the application or the DRM system can independently say + // that there must be a hardware-protected path to an external video sink. + // For now we always require a hardware-protected path to external video sink + // if content is DRMed, but eventually this could be optional per DRM agent. + // When the application wants protection, then + // (USE_SURFACE_ALLOC && (mSurface != 0) && + // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp)) + // will be true, but that part is already handled by SurfaceFlinger. + if (mDecryptHandle != NULL) { + flags |= OMXCodec::kEnableGrallocUsageProtected; + } + LOGV("initVideoDecoder flags=0x%x", flags); mVideoSource = OMXCodec::Create( mClient.interface(), mVideoTrack->getFormat(), false, // createEncoder diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp index eb4c68d..03ce202 100644 --- a/media/libstagefright/MP3Extractor.cpp +++ b/media/libstagefright/MP3Extractor.cpp @@ -39,10 +39,10 @@ namespace android { // Everything must match except for -// protection, bitrate, padding, private bits, mode extension, +// protection, bitrate, padding, private bits, mode, mode extension, // copyright bit, original bit and emphasis. // Yes ... there are things that must indeed match... -static const uint32_t kMask = 0xfffe0cc0; +static const uint32_t kMask = 0xfffe0c00; // static bool MP3Extractor::get_mp3_frame_size( diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp index dbbf3b4..b24343f 100644 --- a/media/libstagefright/NuHTTPDataSource.cpp +++ b/media/libstagefright/NuHTTPDataSource.cpp @@ -1,3 +1,19 @@ +/* + * 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. + */ + //#define LOG_NDEBUG 0 #define LOG_TAG "NuHTTPDataSource" #include <utils/Log.h> diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 4a94e0d..3e26a95 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -528,6 +528,12 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta, uint32_t flags) { mOnlySubmitOneBufferAtOneTime = true; } + mEnableGrallocUsageProtected = false; + if (flags & kEnableGrallocUsageProtected) { + mEnableGrallocUsageProtected = true; + } + LOGV("configureCodec protected=%d", mEnableGrallocUsageProtected); + if (!(flags & kIgnoreCodecSpecificData)) { uint32_t type; const void *data; @@ -1751,7 +1757,11 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() { // XXX: Currently this error is logged, but not fatal. usage = 0; } + if (mEnableGrallocUsageProtected) { + usage |= GRALLOC_USAGE_PROTECTED; + } + LOGV("native_window_set_usage usage=0x%x", usage); err = native_window_set_usage( mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); if (err != 0) { diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp index a8b1292..e4ff128 100644 --- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp +++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp @@ -189,6 +189,9 @@ status_t AACEncoder::stop() { delete mApiHandle; mApiHandle = NULL; + delete mMemOperator; + mMemOperator = NULL; + mStarted = false; return OK; diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h index 082b589..2569568 100644 --- a/media/libstagefright/include/NuHTTPDataSource.h +++ b/media/libstagefright/include/NuHTTPDataSource.h @@ -1,3 +1,19 @@ +/* + * 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 NU_HTTP_DATA_SOURCE_H_ #define NU_HTTP_DATA_SOURCE_H_ diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk index 1d81129..46596a7 100644 --- a/media/tests/CameraBrowser/Android.mk +++ b/media/tests/CameraBrowser/Android.mk @@ -7,4 +7,6 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := CameraBrowser +LOCAL_SDK_VERSION := current + include $(BUILD_PACKAGE) diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java index f642d93..af17ded 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java @@ -20,7 +20,6 @@ import android.app.ListActivity; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.mtp.MtpClient; import android.mtp.MtpDevice; import android.mtp.MtpDeviceInfo; import android.os.Bundle; @@ -79,8 +78,8 @@ public class CameraBrowser extends ListActivity implements MtpClient.Listener { view = (TwoLineListItem)convertView; } - TextView textView1 = (TextView)view.findViewById(com.android.internal.R.id.text1); - TextView textView2 = (TextView)view.findViewById(com.android.internal.R.id.text2); + TextView textView1 = (TextView)view.findViewById(android.R.id.text1); + TextView textView2 = (TextView)view.findViewById(android.R.id.text2); MtpDevice device = mDeviceList.get(position); MtpDeviceInfo info = device.getDeviceInfo(); if (info != null) { diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java index 6f1edfea..8075862 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java @@ -17,8 +17,6 @@ package com.android.camerabrowser; import android.app.Application; -import android.mtp.MtpClient; - public class CameraBrowserApplication extends Application { diff --git a/media/java/android/mtp/MtpClient.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/MtpClient.java index c4ee19e..edb5e37 100644 --- a/media/java/android/mtp/MtpClient.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/MtpClient.java @@ -14,21 +14,28 @@ * limitations under the License. */ -package android.mtp; +package com.android.camerabrowser; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; +import android.mtp.MtpDevice; +import android.mtp.MtpDeviceInfo; +import android.mtp.MtpObjectInfo; +import android.mtp.MtpStorageInfo; import android.os.ParcelFileDescriptor; import android.util.Log; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; /** @@ -40,34 +47,58 @@ public class MtpClient { private static final String TAG = "MtpClient"; + private static final String ACTION_USB_PERMISSION = + "android.mtp.MtpClient.action.USB_PERMISSION"; + private final Context mContext; private final UsbManager mUsbManager; private final ArrayList<Listener> mListeners = new ArrayList<Listener>(); - private final ArrayList<MtpDevice> mDeviceList = new ArrayList<MtpDevice>(); + // mDevices contains all MtpDevices that have been seen by our client, + // so we can inform when the device has been detached. + // mDevices is also used for synchronization in this class. + private final HashMap<String, MtpDevice> mDevices = new HashMap<String, MtpDevice>(); + + private final PendingIntent mPermissionIntent; private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); UsbDevice usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); String deviceName = usbDevice.getDeviceName(); - synchronized (mDeviceList) { - MtpDevice mtpDevice = getDeviceLocked(deviceName); + synchronized (mDevices) { + MtpDevice mtpDevice = mDevices.get(deviceName); - if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { + if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { if (mtpDevice == null) { - mtpDevice = openDevice(usbDevice); + mtpDevice = openDeviceLocked(usbDevice); } if (mtpDevice != null) { - mDeviceList.add(mtpDevice); for (Listener listener : mListeners) { listener.deviceAdded(mtpDevice); } } - } else if (mtpDevice != null) { - mDeviceList.remove(mtpDevice); - for (Listener listener : mListeners) { - listener.deviceRemoved(mtpDevice); + } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { + if (mtpDevice != null) { + mDevices.remove(deviceName); + for (Listener listener : mListeners) { + listener.deviceRemoved(mtpDevice); + } + } + } else if (ACTION_USB_PERMISSION.equals(action)) { + boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, + false); + Log.d(TAG, "ACTION_USB_PERMISSION: " + permission); + if (permission) { + if (mtpDevice == null) { + mtpDevice = openDeviceLocked(usbDevice); + } + if (mtpDevice != null) { + for (Listener listener : mListeners) { + listener.deviceAdded(mtpDevice); + } + } } } } @@ -122,21 +153,12 @@ public class MtpClient { public MtpClient(Context context) { mContext = context; mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE); - + mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); + filter.addAction(ACTION_USB_PERMISSION); context.registerReceiver(mUsbReceiver, filter); - - for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) { - MtpDevice mtpDevice = getDeviceLocked(usbDevice.getDeviceName()); - if (mtpDevice == null) { - mtpDevice = openDevice(usbDevice); - } - if (mtpDevice != null) { - mDeviceList.add(mtpDevice); - } - } } /** @@ -146,11 +168,19 @@ public class MtpClient { * @param device the device to open * @return an MtpDevice for the device. */ - private MtpDevice openDevice(UsbDevice usbDevice) { + private MtpDevice openDeviceLocked(UsbDevice usbDevice) { if (isCamera(usbDevice)) { - MtpDevice mtpDevice = new MtpDevice(usbDevice); - if (mtpDevice.open(mUsbManager)) { - return mtpDevice; + if (!mUsbManager.hasPermission(usbDevice)) { + mUsbManager.requestPermission(usbDevice, mPermissionIntent); + } else { + UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice); + if (connection != null) { + MtpDevice mtpDevice = new MtpDevice(usbDevice); + if (mtpDevice.open(connection)) { + mDevices.put(usbDevice.getDeviceName(), mtpDevice); + return mtpDevice; + } + } } } return null; @@ -170,7 +200,7 @@ public class MtpClient { * @param listener the listener to register */ public void addListener(Listener listener) { - synchronized (mDeviceList) { + synchronized (mDevices) { if (!mListeners.contains(listener)) { mListeners.add(listener); } @@ -183,7 +213,7 @@ public class MtpClient { * @param listener the listener to unregister */ public void removeListener(Listener listener) { - synchronized (mDeviceList) { + synchronized (mDevices) { mListeners.remove(listener); } } @@ -196,8 +226,8 @@ public class MtpClient { * @return the MtpDevice, or null if it does not exist */ public MtpDevice getDevice(String deviceName) { - synchronized (mDeviceList) { - return getDeviceLocked(deviceName); + synchronized (mDevices) { + return mDevices.get(deviceName); } } @@ -209,18 +239,9 @@ public class MtpClient { * @return the MtpDevice, or null if it does not exist */ public MtpDevice getDevice(int id) { - synchronized (mDeviceList) { - return getDeviceLocked(UsbDevice.getDeviceName(id)); - } - } - - private MtpDevice getDeviceLocked(String deviceName) { - for (MtpDevice device : mDeviceList) { - if (device.getDeviceName().equals(deviceName)) { - return device; - } + synchronized (mDevices) { + return mDevices.get(UsbDevice.getDeviceName(id)); } - return null; } /** @@ -229,8 +250,16 @@ public class MtpClient { * @return the list of MtpDevices */ public List<MtpDevice> getDeviceList() { - synchronized (mDeviceList) { - return new ArrayList<MtpDevice>(mDeviceList); + synchronized (mDevices) { + // Query the USB manager since devices might have attached + // before we added our listener. + for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) { + if (mDevices.get(usbDevice.getDeviceName()) == null) { + openDeviceLocked(usbDevice); + } + } + + return new ArrayList<MtpDevice>(mDevices.values()); } } diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java index 82251d9..68fed7b 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java @@ -22,7 +22,6 @@ import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.mtp.MtpClient; import android.mtp.MtpConstants; import android.mtp.MtpDevice; import android.mtp.MtpObjectInfo; diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java index e9ea9f3..ef69c44 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java @@ -23,7 +23,6 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.MediaScannerConnection; import android.media.MediaScannerConnection.MediaScannerConnectionClient; -import android.mtp.MtpClient; import android.mtp.MtpConstants; import android.mtp.MtpObjectInfo; import android.net.Uri; diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java index 7d5a5da..64320fe 100644 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java +++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java @@ -19,7 +19,6 @@ package com.android.camerabrowser; import android.app.ListActivity; import android.content.Context; import android.content.Intent; -import android.mtp.MtpClient; import android.mtp.MtpDevice; import android.mtp.MtpStorageInfo; import android.os.Bundle; diff --git a/native/include/android/input.h b/native/include/android/input.h index f19e8be..86be54a 100644 --- a/native/include/android/input.h +++ b/native/include/android/input.h @@ -359,6 +359,11 @@ enum { AMOTION_EVENT_AXIS_HAT_Y = 16, AMOTION_EVENT_AXIS_LTRIGGER = 17, AMOTION_EVENT_AXIS_RTRIGGER = 18, + AMOTION_EVENT_AXIS_THROTTLE = 19, + AMOTION_EVENT_AXIS_RUDDER = 20, + AMOTION_EVENT_AXIS_WHEEL = 21, + AMOTION_EVENT_AXIS_GAS = 22, + AMOTION_EVENT_AXIS_BRAKE = 23, AMOTION_EVENT_AXIS_GENERIC_1 = 32, AMOTION_EVENT_AXIS_GENERIC_2 = 33, AMOTION_EVENT_AXIS_GENERIC_3 = 34, diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java index 9cf5de7..cd36099 100644 --- a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java +++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java @@ -32,4 +32,19 @@ public class EGLContextImpl extends EGLContext { public GL getGL() { return mGLContext; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + EGLContextImpl that = (EGLContextImpl) o; + + return mEGLContext == that.mEGLContext; + } + + @Override + public int hashCode() { + return mEGLContext; + } } diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java index cb94888..e6c9817 100644 --- a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java +++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java @@ -24,4 +24,20 @@ public class EGLDisplayImpl extends EGLDisplay { public EGLDisplayImpl(int dpy) { mEGLDisplay = dpy; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + EGLDisplayImpl that = (EGLDisplayImpl) o; + + return mEGLDisplay == that.mEGLDisplay; + + } + + @Override + public int hashCode() { + return mEGLDisplay; + } } diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java index f6b90ab..e7f15dc 100644 --- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java +++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java @@ -29,4 +29,20 @@ public class EGLSurfaceImpl extends EGLSurface { mEGLSurface = surface; mNativePixelRef = 0; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + EGLSurfaceImpl that = (EGLSurfaceImpl) o; + + return mEGLSurface == that.mEGLSurface; + + } + + @Override + public int hashCode() { + return mEGLSurface; + } } diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index d3d1750..ecd6fb6 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -8,6 +8,7 @@ <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.GET_TASKS" /> + <uses-permission android:name="android.permission.MANAGE_USB" /> <application android:persistent="true" @@ -39,5 +40,31 @@ android:exported="true"> </activity> + <!-- started from UsbDeviceSettingsManager --> + <activity android:name=".usb.UsbPermissionActivity" + android:exported="true" + android:permission="android.permission.MANAGE_USB" + android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true"> + </activity> + + <!-- started from UsbDeviceSettingsManager --> + <activity android:name=".usb.UsbResolverActivity" + android:exported="true" + android:permission="android.permission.MANAGE_USB" + android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true"> + </activity> + + <!-- started from UsbDeviceSettingsManager --> + <activity android:name=".usb.UsbAccessoryUriActivity" + android:exported="true" + android:permission="android.permission.MANAGE_USB" + android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true"> + </activity> </application> </manifest> diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png Binary files differnew file mode 100644 index 0000000..0c40c73 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png Binary files differindex 51b4f3f..4ec771a 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png Binary files differindex 170178c..2ea2609 100755 --- a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png Binary files differindex 61f65bf..765cdd7 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png Binary files differindex ff74c35..6ff0899 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png Binary files differindex 6375b1b..6dcdefb 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png Binary files differindex ef886b8..5ee9e0a 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png Binary files differindex 92882bd..a74e731 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png Binary files differindex cf5c4c3..441739a 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png Binary files differindex 24b6d25..a666c75 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png Binary files differindex b147583..2045c0c 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png Binary files differindex 594ad6a..063a86c 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png Binary files differindex 2879550..1e4aebb 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png Binary files differindex c763976..52e8a8e 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png Binary files differindex 883808a..c69c44f 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png Binary files differnew file mode 100644 index 0000000..0413ae3 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png Binary files differindex 8ea42c7..61e7772a 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png Binary files differindex 71429ae..74b018a 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png Binary files differindex 5c34554..d3364bc 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png Binary files differindex 44e7072..e65d6ed 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png Binary files differindex 7cd2893..f5b07e6 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png Binary files differindex 23eb1d6..fbb31b8 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png Binary files differindex ad28667..c1f2f97 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png Binary files differindex 048dfd1..8721d5c 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png Binary files differindex 224ae1f..b8feac6 100755 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png Binary files differindex b85859b..6854a2b 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png Binary files differindex d7f3960..efff76c 100755 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png Binary files differindex 54915b9..3a5c7e2 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png Binary files differindex bd44b52..dc1ce8e 100755 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png Binary files differindex 4fc6b46..4fb1cf1 100644 --- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png +++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png Binary files differindex d846afe..3a50987 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png Binary files differindex 9b28252..5bde4e5 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png Binary files differindex 3a0fce0..c9da7b9 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png Binary files differindex 8654aa0..35056d3 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png Binary files differindex c10629f..dcfcc00 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png Binary files differindex 753c9f9..e61b6ba 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png Binary files differindex 65a886a..f0f86e5 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png Binary files differindex 6e90ce4..1025e81 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png Binary files differindex cce7d9b..c4cc59f 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png Binary files differindex c4e33bd..4976752 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png Binary files differindex 433a2c5..380a5f4 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png Binary files differindex 81401b2..d97b1de 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png Binary files differindex a1a9794..174d65c 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png Binary files differindex e429ea1..abbdbc0 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png Binary files differindex e3bcaf9..f1f4c1c 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png Binary files differindex 26db91e..f767994 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png Binary files differindex 957c5ba..7c97a01 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png Binary files differindex aec6050..c0665c4 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png Binary files differindex bb8eea0..8746388 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png Binary files differindex 75906a2..150a6c7 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png Binary files differindex 528e4ce..76f86dc 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png Binary files differindex 1eb5aad..1f0dd89 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png Binary files differindex 5f2c230..5e7ae35 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png Binary files differindex 2c27620..b861bc9 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png Binary files differindex 4cb06be..8f16376 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png Binary files differindex fd9c350..67f46d3 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png Binary files differindex e8aed95..165348c 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png Binary files differindex c629387..d53d3bc 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png Binary files differindex 8e039ce..1629575 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png Binary files differindex 0cb0a08..e87bcec 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png Binary files differindex c3cd10b..fd44002 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png Binary files differindex 650f67b..e455ad6 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png Binary files differindex f5b1618..6613585 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png Binary files differindex eddc487..7502a54 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png Binary files differindex 1eb0142..1309176 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png Binary files differindex 4c8e7c3..810714e 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png Binary files differindex 657dc04..72176ba 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png Binary files differindex 359e8f8..82a2bf0 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png Binary files differindex e5b0841..1e6c604 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png Binary files differindex 4fe8df3..13aee06 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png Binary files differindex a7a7bea..76c48a8 100644 --- a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png Binary files differindex 2cbec7b..73cdabe 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png Binary files differindex 0efb9c9..b5a39cc 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png Binary files differindex 2eae1e1..6de880c 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png Binary files differindex 7e82c4c..2dbbfc0 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png Binary files differindex d37f1e5..a45f011 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png Binary files differindex 5f7349e..517a6bb 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png Binary files differindex 31358ec..5226c1c 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png Binary files differindex e5a3484..a845648 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png Binary files differindex 2a3a5dc..1d15587 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png Binary files differindex 5dbd1ab..52d5736 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png Binary files differindex 51d1f76..79a2a05 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png Binary files differindex 10d81ca..b032594 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png Binary files differindex 1d9bda0..c4abcc9 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml index 1afb2e3..543f4ed 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml @@ -22,7 +22,6 @@ android:layout_height="0dp" android:orientation="vertical" android:background="@drawable/notify_panel_clock_bg" - android:clickable="true" > <LinearLayout android:id="@+id/icons" diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml index bfa6c36..3f172e6 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml @@ -38,8 +38,8 @@ android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" - android:layout_marginLeft="123dip" - android:layout_marginTop="16dip" + android:layout_marginLeft="131dip" + android:layout_marginTop="13dip" android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width" android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height" android:adjustViewBounds="true" diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml index eda19b7..42940be 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml @@ -51,7 +51,7 @@ android:stackFromBottom="true" android:fadingEdge="vertical" android:scrollbars="none" - android:fadingEdgeLength="30dip" + android:fadingEdgeLength="20dip" android:listSelector="@drawable/recents_thumbnail_bg_selector" /> diff --git a/packages/SystemUI/res/values-ar-xlarge/strings.xml b/packages/SystemUI/res/values-ar-xlarge/strings.xml index af0eed0..d4fb873 100644 --- a/packages/SystemUI/res/values-ar-xlarge/strings.xml +++ b/packages/SystemUI/res/values-ar-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"جارٍ البحث عن GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"تم تعيين الموقع بواسطة GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"إيقاف التنبيهات"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"انقر هنا لإعادة تشغيل التنبيهات."</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 2b22302..530704b 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"تم إنشاء الاتصال بالإنترنت عن طريق البلوتوث."</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"تهيئة طرق الإدخال"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"استخدام لوحة المفاتيح الفعلية"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-bg-xlarge/strings.xml b/packages/SystemUI/res/values-bg-xlarge/strings.xml index d44366d..4e730ae 100644 --- a/packages/SystemUI/res/values-bg-xlarge/strings.xml +++ b/packages/SystemUI/res/values-bg-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: има връзка"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Търси се GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Местоположението е зададено от GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Известията са изключени"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Докоснете тук, за да включите отново известията."</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index faf802b..cc4395f 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth има връзка с тетъринг"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Конфигуриране на въвеждането"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Използване на физ. клав."</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ca-xlarge/strings.xml b/packages/SystemUI/res/values-ca-xlarge/strings.xml index a0ace2c..9fc74d0 100644 --- a/packages/SystemUI/res/values-ca-xlarge/strings.xml +++ b/packages/SystemUI/res/values-ca-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: connectat"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"S\'està cercant un GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"S\'ha establert la ubicació per GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notificacions desactivades"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Pica aquí per tornar a activar les notificacions."</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 73ef49e..af78e07 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth sense fil"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configura mètodes d\'entrada"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilitza un teclat físic"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-cs-xlarge/strings.xml b/packages/SystemUI/res/values-cs-xlarge/strings.xml index 5fe365c..05b1248 100644 --- a/packages/SystemUI/res/values-cs-xlarge/strings.xml +++ b/packages/SystemUI/res/values-cs-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: připojeno"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Vyhledávání satelitů GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Poloha nastavena pomocí GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Oznámení jsou vypnuta"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Chcete-li oznámení znovu zapnout, klepněte sem."</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 66eecd6..37def5e 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Datové připojení Bluetooth se sdílí"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Nakonfigurovat metody vstupu"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Použít fyz. klávesnici"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-da-xlarge/strings.xml b/packages/SystemUI/res/values-da-xlarge/strings.xml index ae430b3..dd20e64 100644 --- a/packages/SystemUI/res/values-da-xlarge/strings.xml +++ b/packages/SystemUI/res/values-da-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi er forbundet"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Søger efter GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Placeringen er angivet ved hjælp af GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Meddelelser: Fra"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Tryk her for at slå meddelelser til igen."</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 15f370b..a0875d3 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-tethering anvendt"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurer inputmetoder"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Brug fysisk tastatur"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-de-xlarge/strings.xml b/packages/SystemUI/res/values-de-xlarge/strings.xml index 825cd0d..cc782da 100644 --- a/packages/SystemUI/res/values-de-xlarge/strings.xml +++ b/packages/SystemUI/res/values-de-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Mit WLAN verbunden"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Suche nach GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Standort durch GPS festgelegt"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Benachrichtigungen aus"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Tippen Sie hier, um Benachrichtigungen wieder einzuschalten."</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index e13f723..a9d2e79 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-Tethering aktiv"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Eingabemethoden konfigurieren"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Physische Tastatur"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-el-xlarge/strings.xml b/packages/SystemUI/res/values-el-xlarge/strings.xml index 4902bb5..4f7814a 100644 --- a/packages/SystemUI/res/values-el-xlarge/strings.xml +++ b/packages/SystemUI/res/values-el-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: συνδέθηκε"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Αναζήτηση για GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Ρύθμιση τοποθεσίας με GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Ειδοποιήσεις ανενεργές"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Πατήστε εδώ για να ενεργοποιήσετε τις ειδοποιήσεις"</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 069277d..2370c26 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Έγινε σύνδεση μέσω Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Διαμόρφωση μεθόδων εισαγωγής"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Χρήση κανονικού πληκτρολ."</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml b/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml index de1eb52..68986f0 100644 --- a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml +++ b/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi connected"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Searching for GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Location set by GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notifications off"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Tap here to turn notifications back on."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 9efd6b2..2a7a7eb 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tethered"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configure input methods"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Use physical keyboard"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml b/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml index 2ace144..fa9b762 100644 --- a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml +++ b/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"WiFi conectado"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Buscando GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"La ubicación se estableció por GPS."</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notificaciones desactivadas"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Presiona aquí para volver a activar las notificaciones."</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 7ec089f..60beb13 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -19,7 +19,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="7164937344850004466">"Sistema UI"</string> + <string name="app_label" msgid="7164937344850004466">"IU del sistema"</string> <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string> <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molestar"</string> <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificaciones"</string> @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de entrada"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Usar teclado físico"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-es-xlarge/strings.xml b/packages/SystemUI/res/values-es-xlarge/strings.xml index dd490fb..a7588da 100644 --- a/packages/SystemUI/res/values-es-xlarge/strings.xml +++ b/packages/SystemUI/res/values-es-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Con conexión WiFi"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Buscando GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Ubicación definida por GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notificaciones desactivadas"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Toca aquí para volver a activar las notificaciones."</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 25465d9..8d39377 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de introducción"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizar teclado físico"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-fa-xlarge/strings.xml b/packages/SystemUI/res/values-fa-xlarge/strings.xml index 6e0654d..a8e2543 100644 --- a/packages/SystemUI/res/values-fa-xlarge/strings.xml +++ b/packages/SystemUI/res/values-fa-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل شد"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"جستجوی GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"مکان تنظیم شده توسط GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"اعلان ها خاموش"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"برای روشن کردن مجدد اعلان ها، اینجا را ضربه بزنید."</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 4e15435..1474340 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"اتصال اینترنتی با بلوتوث تلفن همراه"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"پیکربندی روش های ورودی"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"از صفحه کلید فیزیکی استفاده کنید"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-fi-xlarge/strings.xml b/packages/SystemUI/res/values-fi-xlarge/strings.xml index 7d49e9b..754c577 100644 --- a/packages/SystemUI/res/values-fi-xlarge/strings.xml +++ b/packages/SystemUI/res/values-fi-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wifi yhdistetty"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Haetaan GPS-yhteyttä"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Sijainti määritetty GPS:n avulla"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Ilmoitukset pois käytöstä"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Ota ilmoitukset uudelleen käyttöön napauttamalla tätä."</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 252b97f..12d74e6 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth yhdistetty"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Määritä syöttötavat"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Käytä fyysistä näppäimistöä"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-fr-xlarge/strings.xml b/packages/SystemUI/res/values-fr-xlarge/strings.xml index 98dc6c0..08f673d 100644 --- a/packages/SystemUI/res/values-fr-xlarge/strings.xml +++ b/packages/SystemUI/res/values-fr-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Connecté au Wi-Fi"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Recherche de GPS en cours"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Position définie par GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notifications désactivées"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Appuyez ici pour réactiver les notifications."</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index b903452..b507c98 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Connexion Bluetooth partagée"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurer les modes de saisie"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utiliser clavier physique"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-hr-xlarge/strings.xml b/packages/SystemUI/res/values-hr-xlarge/strings.xml index 08adaf0..b6e15dc 100644 --- a/packages/SystemUI/res/values-hr-xlarge/strings.xml +++ b/packages/SystemUI/res/values-hr-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: povezano"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Pretraživanje GPS-a"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokaciju utvrdio GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Obavijesti isključene"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Dotaknite ovdje da biste ponovo uključili obavijesti."</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 916f2c3..f568310 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth posredno povezan"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfiguriraj načine ulaza"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Rabi fizičku tipkovnicu"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-hu-xlarge/strings.xml b/packages/SystemUI/res/values-hu-xlarge/strings.xml index 41d60fc..fe2e5ee 100644 --- a/packages/SystemUI/res/values-hu-xlarge/strings.xml +++ b/packages/SystemUI/res/values-hu-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi csatlakozva"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS keresése"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"A GPS beállította a helyet"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Értesítések kikapcsolva"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Itt érintse meg az értesítések bekapcsolásához."</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index f41c89c..1299991 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth megosztva"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Beviteli módok konfigurálása"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Valódi bill. használata"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-in-xlarge/strings.xml b/packages/SystemUI/res/values-in-xlarge/strings.xml index 8d95060..a4ca341 100644 --- a/packages/SystemUI/res/values-in-xlarge/strings.xml +++ b/packages/SystemUI/res/values-in-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi tersambung"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Menelusuri GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokasi yang disetel oleh GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Pemberitahuan mati"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Ketuk di sini untuk menghidupkan lagi pemberitahuan."</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 0d5b411..259a358 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tertambat"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurasikan metode masukan"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Gunakan keyboard fisik"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-it-xlarge/strings.xml b/packages/SystemUI/res/values-it-xlarge/strings.xml index 68393fb..24d88744 100644 --- a/packages/SystemUI/res/values-it-xlarge/strings.xml +++ b/packages/SystemUI/res/values-it-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: connesso"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Ricerca del GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Posizione stabilita dal GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notifiche disattivate"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Tocca qui per riattivare le notifiche."</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index c94dbb5..99f321d 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth con tethering"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configura metodi di input"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizza tastiera fisica"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-iw-xlarge/strings.xml b/packages/SystemUI/res/values-iw-xlarge/strings.xml index fd3ce0e..97172b8 100644 --- a/packages/SystemUI/res/values-iw-xlarge/strings.xml +++ b/packages/SystemUI/res/values-iw-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi מחובר"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"מחפש GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"מיקום מוגדר על ידי GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"מצב התראות כבוי"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"הקש כאן כדי להפעיל מחדש את ההתראות."</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 85beeb3..ff7114a 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth קשור"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"הגדר שיטות קלט"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"השתמש במקלדת הפיזית"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ja-xlarge/strings.xml b/packages/SystemUI/res/values-ja-xlarge/strings.xml index c7c0824..e67e0e1 100644 --- a/packages/SystemUI/res/values-ja-xlarge/strings.xml +++ b/packages/SystemUI/res/values-ja-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi接続済み"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"GPSで検索中"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"GPSにより現在地が設定されました"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"通知OFF"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"通知を有効にするにはここをタップします。"</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 9cb8189..90708a1 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetoothテザリング接続"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"入力方法の設定"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"物理キーボードを使用"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ko-xlarge/strings.xml b/packages/SystemUI/res/values-ko-xlarge/strings.xml index 3777154..e28ac63 100644 --- a/packages/SystemUI/res/values-ko-xlarge/strings.xml +++ b/packages/SystemUI/res/values-ko-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 연결됨"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS 검색"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS에서 설정한 위치"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"알림 사용 안함"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"알림을 다시 사용하려면 여기를 누르세요."</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 4504f61..97847f1 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"블루투스 테더링됨"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"입력 방법 구성"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"물리적 키보드 사용"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-lt-xlarge/strings.xml b/packages/SystemUI/res/values-lt-xlarge/strings.xml index 90dd501..12e8bb3 100644 --- a/packages/SystemUI/res/values-lt-xlarge/strings.xml +++ b/packages/SystemUI/res/values-lt-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Prisijungta prie „Wi-Fi“"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Ieškoma GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS nustatyta vieta"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Pranešimai išjungti"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Palieskite čia, kad vėl įjungtumėte pranešimus."</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 5985ee6..60cd207 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"„Bluetooth“ susieta"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigūruoti įvesties metodus"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Naudoti fizinę klaviatūrą"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-lv-xlarge/strings.xml b/packages/SystemUI/res/values-lv-xlarge/strings.xml index c533ecb..aecb471 100644 --- a/packages/SystemUI/res/values-lv-xlarge/strings.xml +++ b/packages/SystemUI/res/values-lv-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Izv. sav. ar Wi-Fi"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Notiek GPS meklēšana..."</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS iestatītā atrašanās vieta"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Paziņojumi ir izslēgti."</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Pieskarieties šeit, lai vēlreiz ieslēgtu paziņojumus."</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 808d374..634ce19 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth piesaiste"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurēt ievades metodes"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Izmantot fizisku tastatūru"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-nb-xlarge/strings.xml b/packages/SystemUI/res/values-nb-xlarge/strings.xml index 2bf63e8..717ee79 100644 --- a/packages/SystemUI/res/values-nb-xlarge/strings.xml +++ b/packages/SystemUI/res/values-nb-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: tilkoblet"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Søker etter GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Posisjon angitt av GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Varslinger er slått av"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Trykk her for å slå på varslinger igjen."</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index e23a17f..e9c267e 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tilknyttet"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurer inndatametoder"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Bruk fysisk tastatur"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-nl-xlarge/strings.xml b/packages/SystemUI/res/values-nl-xlarge/strings.xml index 7a63401..7c84a7a 100644 --- a/packages/SystemUI/res/values-nl-xlarge/strings.xml +++ b/packages/SystemUI/res/values-nl-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Verbonden via Wi-Fi"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Zoeken naar GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Locatie bepaald met GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Meldingen uit"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Tik hier om meldingen weer in te schakelen."</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 56136fa..e879592 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth getetherd"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Invoermethoden configureren"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Fysiek toetsenbord gebruiken"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-pl-xlarge/strings.xml b/packages/SystemUI/res/values-pl-xlarge/strings.xml index 1334b70..9db1cab 100644 --- a/packages/SystemUI/res/values-pl-xlarge/strings.xml +++ b/packages/SystemUI/res/values-pl-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: połączono"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Wyszukiwanie sygnału GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokalizacja ustawiona wg GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Powiadomienia wyłączone"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Dotknij tutaj, aby z powrotem włączyć powiadomienia."</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 7ccb037..d6c138b 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth – podłączono"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfiguruj metody wprowadzania"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Używaj klawiatury fizycznej"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml b/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml index a5d6bac..7860208 100644 --- a/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi ligado"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"A procurar GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Localização definida por GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notificações desativadas"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Toque aqui para voltar a ativar as notificações."</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 088240c..506b072 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ligado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de entrada"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizar teclado físico"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-pt-xlarge/strings.xml b/packages/SystemUI/res/values-pt-xlarge/strings.xml index 5209ab9..2a1786d 100644 --- a/packages/SystemUI/res/values-pt-xlarge/strings.xml +++ b/packages/SystemUI/res/values-pt-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi conectado"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Procurando GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Localização definida por GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notificações desativadas"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Toque aqui para ativar novamente as notificações."</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 7636aed..5db5277 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth vinculado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de entrada"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Usar o teclado físico"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml index debba7a..fd350cb 100644 --- a/packages/SystemUI/res/values-rm/strings.xml +++ b/packages/SystemUI/res/values-rm/strings.xml @@ -61,4 +61,8 @@ <skip /> <!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) --> <skip /> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ro-xlarge/strings.xml b/packages/SystemUI/res/values-ro-xlarge/strings.xml index 2dedd3b..21fd0ad 100644 --- a/packages/SystemUI/res/values-ro-xlarge/strings.xml +++ b/packages/SystemUI/res/values-ro-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi conectat"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Se caută dispozitivul GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Locaţie setată prin GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Notificările sunt dezactivate"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Apăsaţi aici pentru a reactiva notificările."</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index e62eb6e..98d68b5 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Conectat prin tethering prin Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configuraţi metode de intrare"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizaţi tastat. fizică"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ru-xlarge/strings.xml b/packages/SystemUI/res/values-ru-xlarge/strings.xml index 212fa83..bc31fb1 100644 --- a/packages/SystemUI/res/values-ru-xlarge/strings.xml +++ b/packages/SystemUI/res/values-ru-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi подкл."</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Выполняется поиск при помощи GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Местоположение установлено при помощи GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Показ уведомлений отключен"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Нажмите здесь, чтобы снова включить показ уведомлений."</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index d57289e..9306274 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Общий модем доступен через Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Настроить способ ввода"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Использовать физическую клавиатуру"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sk-xlarge/strings.xml b/packages/SystemUI/res/values-sk-xlarge/strings.xml index 0fcdd4a..ee9e613 100644 --- a/packages/SystemUI/res/values-sk-xlarge/strings.xml +++ b/packages/SystemUI/res/values-sk-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: pripojené"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Hľadanie signálu GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Poloha určená pomocou GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Upozornenia sú vypnuté"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Klepnutím tu upozornenia znova povolíte."</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 78a7149..a3475ac 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Zdieľané dátové pripojenie cez Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurovať metódy vstupu"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Použiť fyzickú klávesnicu"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sl-xlarge/strings.xml b/packages/SystemUI/res/values-sl-xlarge/strings.xml index 615c565..57ed9a7 100644 --- a/packages/SystemUI/res/values-sl-xlarge/strings.xml +++ b/packages/SystemUI/res/values-sl-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi – povezano"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Iskanje GPS-a"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokacija nastavljena z GPS-om"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Obvestila izklopljena"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Tapnite tukaj, da spet vklopite obvestila."</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index be77583..80a5674 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetna povezava prek Bluetootha"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Nastavitev načinov vnosa"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Uporabi fizično tipkovn."</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sr-xlarge/strings.xml b/packages/SystemUI/res/values-sr-xlarge/strings.xml index d66765b..95fbc2f 100644 --- a/packages/SystemUI/res/values-sr-xlarge/strings.xml +++ b/packages/SystemUI/res/values-sr-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi је повезан"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Тражи се GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Локацију је подесио GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Обавештења су искључена"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Додирните овде да бисте поново укључили обавештења."</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 2e9a18b..427b0d9 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Веза преко Bluetooth-а"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Конфигуриши методе уноса"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Користи физичку тастатуру"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sv-xlarge/strings.xml b/packages/SystemUI/res/values-sv-xlarge/strings.xml index b53269e..ce608c2 100644 --- a/packages/SystemUI/res/values-sv-xlarge/strings.xml +++ b/packages/SystemUI/res/values-sv-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi-ansluten"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Sökning efter GPS pågår"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Platsen har identifierats av GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Aviseringar inaktiverade"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Knacka lätt här om du vill aktivera aviseringar igen."</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 041d309..5612457 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetdelning via Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurera inmatningsmetoder"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Använd fysiska tangenter"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-th-xlarge/strings.xml b/packages/SystemUI/res/values-th-xlarge/strings.xml index 8222140..824de38 100644 --- a/packages/SystemUI/res/values-th-xlarge/strings.xml +++ b/packages/SystemUI/res/values-th-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"เชื่อมต่อ Wi-Fi แล้ว"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"การค้นหาสำหรับ GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"ตำแหน่งที่กำหนดโดย GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"การแจ้งเตือนปิดอยู่"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 4cac345..8ee8ee5 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"บลูทูธที่ปล่อยสัญญาณ"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"กำหนดค่าวิธีการป้อนข้อมูล"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"ใช้แป้นพิมพ์จริง"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-tl-xlarge/strings.xml b/packages/SystemUI/res/values-tl-xlarge/strings.xml index 0eef090..582adbc 100644 --- a/packages/SystemUI/res/values-tl-xlarge/strings.xml +++ b/packages/SystemUI/res/values-tl-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Konektado ang WiFi"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Naghahanap ng GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokasyon na itinatakda ng GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Naka-off ang mga notification"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Mag-tap dito upang i-on muli ang mga notification."</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 8d10afd..22ddda7 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Na-tether ang bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"I-configure paraan ng input"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Gamitin ang pisikal na keyboard"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-tr-xlarge/strings.xml b/packages/SystemUI/res/values-tr-xlarge/strings.xml index 8c382fb..6db515f 100644 --- a/packages/SystemUI/res/values-tr-xlarge/strings.xml +++ b/packages/SystemUI/res/values-tr-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Kablosuz bağlandı"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS aranıyor"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Konum GPS ile belirlendi"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Bildirimler kapalı"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Bildirimleri tekrar açmak için buraya hafifçe vurun."</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index d6f1482..a7c9d4c 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth paylaşımı tamam"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Giriş yöntemlerini yapılandır"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Fiziksel klavyeyi kullan"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-uk-xlarge/strings.xml b/packages/SystemUI/res/values-uk-xlarge/strings.xml index 6b1b193..81e50c0 100644 --- a/packages/SystemUI/res/values-uk-xlarge/strings.xml +++ b/packages/SystemUI/res/values-uk-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi під\'єднано"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Виконується пошук за допомогою GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Місцезнаходження встановлено за допомогою GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Сповіщення вимкнено"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Торкніться тут, щоб знову ввімкнути сповіщення."</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 1d4694b..56f4c06 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Створено прив\'язку Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Налаштувати методи введення"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Викор. реальну клавіатуру"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-vi-xlarge/strings.xml b/packages/SystemUI/res/values-vi-xlarge/strings.xml index b44e1c3..6382fae 100644 --- a/packages/SystemUI/res/values-vi-xlarge/strings.xml +++ b/packages/SystemUI/res/values-vi-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Đã kết nối Wi-Fi"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"Tìm kiếm GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"Vị trí đặt bởi GPS"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"Tắt thông báo"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"Chạm vào đây để bật lại thông báo."</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index b1eaa8b..8678b6c 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth được dùng làm điểm truy cập Internet"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Định cấu hình phương pháp nhập liệu"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Sử dụng bàn phím vật lý"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml b/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml index f599dca..207ebe4 100644 --- a/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 已连接"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"正在搜索 GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS 设置的位置"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"通知已关闭"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"点按此处可以重新打开通知。"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 3a5f88b..c8753f1 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"蓝牙已绑定"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"配置输入法"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"使用物理键盘"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml b/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml index 2191db7..14a10f2 100644 --- a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml @@ -24,8 +24,6 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 已連線"</string> <string name="gps_notification_searching_text" msgid="894185519046488403">"正在搜尋 GPS"</string> <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS 已定位"</string> - <!-- no translation found for notifications_off_title (2297252328026582111) --> - <skip /> - <!-- no translation found for notifications_off_text (3754847213329718358) --> - <skip /> + <string name="notifications_off_title" msgid="2297252328026582111">"關閉通知"</string> + <string name="notifications_off_text" msgid="3754847213329718358">"輕觸這裡即可重新開啟通知。"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 203cd08..3ab5bcf 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -45,4 +45,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"已透過藍牙進行網際網路共用"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"設定輸入方式"</string> <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"使用實體鍵盤"</string> + <!-- no translation found for usb_device_permission_prompt (5340926456453429244) --> + <skip /> + <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index ebd48e7..06c8ed9 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -115,4 +115,23 @@ <!-- Label of a toggle switch to disable use of the physical keyboard in favor of the IME. [CHAR LIMIT=25] --> <string name="status_bar_use_physical_keyboard">Use physical keyboard</string> + + <!-- Prompt for the USB device permission dialog [CHAR LIMIT=80] --> + <string name="usb_device_permission_prompt">Allow the application %1$s to access the USB device?</string> + + <!-- Prompt for the USB accessory permission dialog [CHAR LIMIT=80] --> + <string name="usb_accessory_permission_prompt">Allow the application %1$s to access the USB accessory?</string> + + <!-- Prompt for the USB accessory URI dialog [CHAR LIMIT=80] --> + <string name="usb_accessory_uri_prompt">Additional information for this device may be found at: %1$s</string> + + <!-- Title for USB accessory dialog. Used when the name of the accessory cannot be determined. [CHAR LIMIT=50] --> + <string name="title_usb_accessory">USB accessory</string> + + <!-- View button label for USB dialogs. [CHAR LIMIT=15] --> + <string name="label_view">View</string> + + <!-- Ignore button label for USB dialogs. [CHAR LIMIT=15] --> + <string name="label_ignore">Ignore</string> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index b17e41b..69585ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -94,6 +94,7 @@ public class NetworkController extends BroadcastReceiver { int mWifiLevel; String mWifiSsid; int mWifiIconId = 0; + int mWifiActivity = WifiManager.DATA_ACTIVITY_NONE; // bluetooth private boolean mBluetoothTethered = false; @@ -153,9 +154,7 @@ public class NetworkController extends BroadcastReceiver { // wifi mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - HandlerThread handlerThread = new HandlerThread("WifiServiceThread"); - handlerThread.start(); - Handler handler = new WifiHandler(handlerThread.getLooper()); + Handler handler = new WifiHandler(); mWifiChannel = new AsyncChannel(); Messenger wifiMessenger = mWifiManager.getMessenger(); if (wifiMessenger != null) { @@ -549,11 +548,6 @@ public class NetworkController extends BroadcastReceiver { // ===== Wifi =================================================================== class WifiHandler extends Handler { - - WifiHandler(Looper looper) { - super(looper); - } - @Override public void handleMessage(Message msg) { switch (msg.what) { @@ -566,17 +560,9 @@ public class NetworkController extends BroadcastReceiver { } break; case WifiManager.DATA_ACTIVITY_NOTIFICATION: - int dataActivity = msg.arg1; - /* TODO: update icons based on data activity */ - switch (dataActivity) { - case WifiManager.DATA_ACTIVITY_IN: - break; - case WifiManager.DATA_ACTIVITY_OUT: - break; - case WifiManager.DATA_ACTIVITY_INOUT: - break; - case WifiManager.DATA_ACTIVITY_NONE: - break; + if (msg.arg1 != mWifiActivity) { + mWifiActivity = msg.arg1; + refreshViews(); } break; default: @@ -697,6 +683,19 @@ public class NetworkController extends BroadcastReceiver { label = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid); } else { label = mWifiSsid; + switch (mWifiActivity) { + case WifiManager.DATA_ACTIVITY_IN: + dataDirectionOverlayIconId = R.drawable.stat_sys_wifi_in; + break; + case WifiManager.DATA_ACTIVITY_OUT: + dataDirectionOverlayIconId = R.drawable.stat_sys_wifi_out; + break; + case WifiManager.DATA_ACTIVITY_INOUT: + dataDirectionOverlayIconId = R.drawable.stat_sys_wifi_inout; + break; + case WifiManager.DATA_ACTIVITY_NONE: + break; + } } combinedSignalIconId = mWifiIconId; dataTypeIconId = 0; @@ -884,6 +883,9 @@ public class NetworkController extends BroadcastReceiver { pw.println(mWifiSsid); pw.print(" mWifiIconId="); pw.println(mWifiIconId); + pw.print(" mWifiActivity="); + pw.println(mWifiActivity); + pw.println(" - Bluetooth ----"); pw.print(" mBtReverseTethered="); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java index 744f667..8b68240 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java @@ -18,11 +18,15 @@ package com.android.systemui.statusbar.tablet; import android.content.Context; import android.util.AttributeSet; +import android.util.Slog; +import android.view.MotionEvent; import android.widget.RelativeLayout; import com.android.systemui.R; public class NotificationPeekPanel extends RelativeLayout implements StatusBarPanel { + TabletStatusBar mBar; + public NotificationPeekPanel(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -39,5 +43,16 @@ public class NotificationPeekPanel extends RelativeLayout implements StatusBarPa return x >= l && x < r && y >= t && y < b; } + public void setBar(TabletStatusBar bar) { + mBar = bar; + } + + // We don't really want to intercept the touch event, but we *do* want to reset the fade timer + // in case the user is interacting with some custom controls or something. + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + mBar.resetNotificationPeekFadeTimer(); + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java index 737a52b..c5a7df2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java @@ -513,9 +513,7 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O paint.setFilterBitmap(true); paint.setAlpha(255); final int srcWidth = thumbnail.getWidth(); - final int height = thumbnail.getHeight(); - final int srcHeight = srcWidth > height ? height - : (height - height * srcWidth / height); + final int srcHeight = thumbnail.getHeight(); canvas.drawBitmap(thumbnail, new Rect(0, 0, srcWidth-1, srcHeight-1), new RectF(GLOW_PADDING, 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 4557105..58c4d5a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -217,6 +217,8 @@ public class TabletStatusBar extends StatusBar implements // Notification preview window mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context, R.layout.status_bar_notification_peek, null); + mNotificationPeekWindow.setBar(this); + mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content); mNotificationPeekWindow.setVisibility(View.GONE); mNotificationPeekWindow.setOnTouchListener( @@ -1211,10 +1213,20 @@ public class TabletStatusBar extends StatusBar implements } } - private class NotificationIconTouchListener implements View.OnTouchListener { - final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms - final static int NOTIFICATION_PEEK_FADE_DELAY = 5000; // ms + final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms + final static int NOTIFICATION_PEEK_FADE_DELAY = 3000; // ms + + public void resetNotificationPeekFadeTimer() { + if (DEBUG) { + Slog.d(TAG, "setting peek fade timer for " + NOTIFICATION_PEEK_FADE_DELAY + + "ms from now"); + } + mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK); + mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK, + NOTIFICATION_PEEK_FADE_DELAY); + } + private class NotificationIconTouchListener implements View.OnTouchListener { VelocityTracker mVT; int mPeekIndex; float mInitialTouchX, mInitialTouchY; @@ -1303,8 +1315,7 @@ public class TabletStatusBar extends StatusBar implements } if (peeking) { - mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK, - NOTIFICATION_PEEK_FADE_DELAY); + resetNotificationPeekFadeTimer(); } mVT.recycle(); diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java new file mode 100644 index 0000000..eefb1c6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.usb; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.hardware.usb.UsbAccessory; +import android.hardware.usb.UsbManager; +import android.os.Bundle; +import android.util.Log; + +import com.android.internal.app.AlertActivity; +import com.android.internal.app.AlertController; + +import com.android.systemui.R; + +/** + * If the attached USB accessory has a URL associated with it, and that URL is valid, + * show this dialog to the user to allow them to optionally visit that URL for more + * information or software downloads. + * Otherwise (no valid URL) this activity does nothing at all, finishing immediately. + */ +public class UsbAccessoryUriActivity extends AlertActivity + implements DialogInterface.OnClickListener { + + private static final String TAG = "UsbAccessoryUriActivity"; + + private UsbAccessory mAccessory; + private Uri mUri; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + Intent intent = getIntent(); + mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); + String uriString = intent.getStringExtra("uri"); + mUri = (uriString == null ? null : Uri.parse(uriString)); + + // sanity check before displaying dialog + if (mUri == null) { + Log.e(TAG, "could not parse Uri " + uriString); + finish(); + return; + } + String scheme = mUri.getScheme(); + if (!"http".equals(scheme) && !"https".equals(scheme)) { + Log.e(TAG, "Uri not http or https: " + mUri); + finish(); + return; + } + + final AlertController.AlertParams ap = mAlertParams; + ap.mTitle = mAccessory.getDescription(); + if (ap.mTitle == null || ap.mTitle.length() == 0) { + ap.mTitle = getString(R.string.title_usb_accessory); + } + ap.mMessage = getString(R.string.usb_accessory_uri_prompt, mUri); + ap.mPositiveButtonText = getString(R.string.label_view); + ap.mNegativeButtonText = getString(R.string.label_ignore); + ap.mPositiveButtonListener = this; + ap.mNegativeButtonListener = this; + + setupAlert(); + } + + public void onClick(DialogInterface dialog, int which) { + if (which == AlertDialog.BUTTON_POSITIVE) { + // launch the browser + Intent intent = new Intent(Intent.ACTION_VIEW, mUri); + intent.addCategory(Intent.CATEGORY_BROWSABLE); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "startActivity failed for " + mUri); + } + } + finish(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java new file mode 100644 index 0000000..1edebbb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java @@ -0,0 +1,67 @@ +/* + * 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.systemui.usb; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbAccessory; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; + +// This class is used to close UsbPermissionsActivity and UsbResolverActivity +// if their device/accessory is disconnected while the dialog is still open +class UsbDisconnectedReceiver extends BroadcastReceiver { + private final Activity mActivity; + private UsbDevice mDevice; + private UsbAccessory mAccessory; + + public UsbDisconnectedReceiver(Activity activity, UsbDevice device) { + mActivity = activity; + mDevice = device; + + IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED); + activity.registerReceiver(this, filter); + } + + public UsbDisconnectedReceiver(Activity activity, UsbAccessory accessory) { + mActivity = activity; + mAccessory = accessory; + + IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED); + activity.registerReceiver(this, filter); + } + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { + UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (device != null && device.equals(mDevice)) { + mActivity.finish(); + } + } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) { + UsbAccessory accessory = + (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); + if (accessory != null && accessory.equals(mAccessory)) { + mActivity.finish(); + } + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java new file mode 100644 index 0000000..f1784df --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.usb; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.PendingIntent; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.hardware.usb.IUsbManager; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbAccessory; +import android.hardware.usb.UsbManager; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; + +import com.android.internal.app.AlertActivity; +import com.android.internal.app.AlertController; + +import com.android.systemui.R; + +public class UsbPermissionActivity extends AlertActivity + implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener { + + private static final String TAG = "UsbPermissionActivity"; + + private CheckBox mAlwaysCheck; + private TextView mClearDefaultHint; + private UsbDevice mDevice; + private UsbAccessory mAccessory; + private PendingIntent mPendingIntent; + private String mPackageName; + private int mUid; + private boolean mPermissionGranted; + private UsbDisconnectedReceiver mDisconnectedReceiver; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + Intent intent = getIntent(); + mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); + mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT); + mUid = intent.getIntExtra("uid", 0); + mPackageName = intent.getStringExtra("package"); + + PackageManager packageManager = getPackageManager(); + ApplicationInfo aInfo; + try { + aInfo = packageManager.getApplicationInfo(mPackageName, 0); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "unable to look up package name", e); + finish(); + return; + } + String appName = aInfo.loadLabel(packageManager).toString(); + + final AlertController.AlertParams ap = mAlertParams; + ap.mIcon = aInfo.loadIcon(packageManager); + ap.mTitle = appName; + if (mDevice == null) { + ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName); + mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory); + } else { + ap.mMessage = getString(R.string.usb_device_permission_prompt, appName); + mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); + } + ap.mPositiveButtonText = getString(com.android.internal.R.string.ok); + ap.mNegativeButtonText = getString(com.android.internal.R.string.cancel); + ap.mPositiveButtonListener = this; + ap.mNegativeButtonListener = this; + + // add "always use" checkbox + LayoutInflater inflater = (LayoutInflater)getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); + mAlwaysCheck = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse); + mAlwaysCheck.setText(com.android.internal.R.string.alwaysUse); + mAlwaysCheck.setOnCheckedChangeListener(this); + mClearDefaultHint = (TextView)ap.mView.findViewById( + com.android.internal.R.id.clearDefaultHint); + mClearDefaultHint.setVisibility(View.GONE); + + setupAlert(); + + } + + @Override + public void onDestroy() { + IBinder b = ServiceManager.getService(USB_SERVICE); + IUsbManager service = IUsbManager.Stub.asInterface(b); + + // send response via pending intent + Intent intent = new Intent(); + try { + if (mDevice != null) { + intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice); + if (mPermissionGranted) { + service.grantDevicePermission(mDevice, mUid); + if (mAlwaysCheck.isChecked()) { + service.setDevicePackage(mDevice, mPackageName); + } + } + } + if (mAccessory != null) { + intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory); + if (mPermissionGranted) { + service.grantAccessoryPermission(mAccessory, mUid); + if (mAlwaysCheck.isChecked()) { + service.setAccessoryPackage(mAccessory, mPackageName); + } + } + } + intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, mPermissionGranted); + mPendingIntent.send(this, 0, intent); + } catch (PendingIntent.CanceledException e) { + Log.w(TAG, "PendingIntent was cancelled"); + } catch (RemoteException e) { + Log.e(TAG, "IUsbService connection failed", e); + } + + if (mDisconnectedReceiver != null) { + unregisterReceiver(mDisconnectedReceiver); + } + super.onDestroy(); + } + + public void onClick(DialogInterface dialog, int which) { + if (which == AlertDialog.BUTTON_POSITIVE) { + mPermissionGranted = true; + } + finish(); + } + + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (mClearDefaultHint == null) return; + + if(isChecked) { + mClearDefaultHint.setVisibility(View.VISIBLE); + } else { + mClearDefaultHint.setVisibility(View.GONE); + } + } +} diff --git a/services/java/com/android/server/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java index e8a09a5..84d73dd 100644 --- a/services/java/com/android/server/usb/UsbResolverActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.usb; +package com.android.systemui.usb; import com.android.internal.app.ResolverActivity; @@ -39,6 +39,10 @@ public class UsbResolverActivity extends ResolverActivity { public static final String TAG = "UsbResolverActivity"; public static final String EXTRA_RESOLVE_INFOS = "rlist"; + private UsbDevice mDevice; + private UsbAccessory mAccessory; + private UsbDisconnectedReceiver mDisconnectedReceiver; + @Override protected void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); @@ -50,7 +54,6 @@ public class UsbResolverActivity extends ResolverActivity { } Intent target = (Intent)targetParcelable; ArrayList<ResolveInfo> rList = intent.getParcelableArrayListExtra(EXTRA_RESOLVE_INFOS); - Log.d(TAG, "rList.size() " + rList.size()); CharSequence title = getResources().getText(com.android.internal.R.string.chooseUsbActivity); super.onCreate(savedInstanceState, target, title, null, rList, true, /* Set alwaysUseOption to true to enable "always use this app" checkbox. */ @@ -58,6 +61,27 @@ public class UsbResolverActivity extends ResolverActivity { This is necessary because this activity is needed for the user to allow the application permission to access the device */ ); + + mDevice = (UsbDevice)target.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (mDevice != null) { + mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); + } else { + mAccessory = (UsbAccessory)target.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); + if (mAccessory == null) { + Log.e(TAG, "no device or accessory"); + finish(); + return; + } + mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory); + } + } + + @Override + protected void onDestroy() { + if (mDisconnectedReceiver != null) { + unregisterReceiver(mDisconnectedReceiver); + } + super.onDestroy(); } protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) { @@ -65,28 +89,24 @@ public class UsbResolverActivity extends ResolverActivity { IBinder b = ServiceManager.getService(USB_SERVICE); IUsbManager service = IUsbManager.Stub.asInterface(b); int uid = ri.activityInfo.applicationInfo.uid; - String action = intent.getAction(); - if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { - UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (mDevice != null) { // grant permission for the device - service.grantDevicePermission(device, uid); + service.grantDevicePermission(mDevice, uid); // set or clear default setting if (alwaysCheck) { - service.setDevicePackage(device, ri.activityInfo.packageName); + service.setDevicePackage(mDevice, ri.activityInfo.packageName); } else { - service.setDevicePackage(device, null); + service.setDevicePackage(mDevice, null); } - } else if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) { - UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra( - UsbManager.EXTRA_ACCESSORY); + } else if (mAccessory != null) { // grant permission for the accessory - service.grantAccessoryPermission(accessory, uid); + service.grantAccessoryPermission(mAccessory, uid); // set or clear default setting if (alwaysCheck) { - service.setAccessoryPackage(accessory, ri.activityInfo.packageName); + service.setAccessoryPackage(mAccessory, ri.activityInfo.packageName); } else { - service.setAccessoryPackage(accessory, null); + service.setAccessoryPackage(mAccessory, null); } } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index 8d70a7b..ae23df6 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -103,6 +103,8 @@ public class KeyguardViewManager implements KeyguardWindowController { int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED_SYSTEM /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ; if (!mNeedsInput) { @@ -142,7 +144,7 @@ public class KeyguardViewManager implements KeyguardWindowController { mKeyguardView.onScreenTurnedOn(); } } - + mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); mKeyguardHost.setVisibility(View.VISIBLE); mKeyguardView.requestFocus(); } diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 2bc57b5..a9d5ce4 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -232,6 +232,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen, /** {@inheritDoc} */ public void onGrabbedStateChange(View v, int grabbedState) { + if (DBG) Log.v(TAG, "*** LockScreen accel is " + + (mEnergyWave.isHardwareAccelerated() ? "on":"off")); // Don't poke the wake lock when returning to a state where the handle is // not grabbed since that can happen when the system (instead of the user) // cancels the grab. diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index ec89db3..64857ed 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -2187,7 +2187,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { super.onDetachedFromWindow(); final Callback cb = getCallback(); - if (cb != null && !isDestroyed() && mFeatureId < 0) { + if (cb != null && mFeatureId < 0) { cb.onDetachedFromWindow(); } diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index 2fe5980..e2da740 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -352,14 +352,13 @@ status_t EventHub::mapKey(int32_t deviceId, int scancode, return NAME_NOT_FOUND; } -status_t EventHub::mapAxis(int32_t deviceId, int scancode, - int32_t* outAxis) const +status_t EventHub::mapAxis(int32_t deviceId, int scancode, AxisInfo* outAxisInfo) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis); + status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo); if (err == NO_ERROR) { return NO_ERROR; } @@ -369,14 +368,13 @@ status_t EventHub::mapAxis(int32_t deviceId, int scancode, device = getDeviceLocked(mBuiltInKeyboardId); if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis); + status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo); if (err == NO_ERROR) { return NO_ERROR; } } } - *outAxis = -1; return NAME_NOT_FOUND; } @@ -822,8 +820,10 @@ int EventHub::openDevice(const char *devicePath) { bool haveKeyboardKeys = containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC)) || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK), sizeof_bit_array(KEY_MAX + 1)); - bool haveGamepadButtons =containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_JOYSTICK), - sizeof_bit_array(BTN_DIGI)); + bool haveGamepadButtons = containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_MISC), + sizeof_bit_array(BTN_MOUSE)) + || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_JOYSTICK), + sizeof_bit_array(BTN_DIGI)); if (haveKeyboardKeys || haveGamepadButtons) { device->classes |= INPUT_DEVICE_CLASS_KEYBOARD; } @@ -852,6 +852,16 @@ int EventHub::openDevice(const char *devicePath) { device->classes |= INPUT_DEVICE_CLASS_TOUCH; } + // See if this device is a joystick. + // Ignore touchscreens because they use the same absolute axes for other purposes. + // Assumes that joysticks always have gamepad buttons in order to distinguish them + // from other devices such as accelerometers that also have absolute axes. + if (haveGamepadButtons + && !(device->classes & INPUT_DEVICE_CLASS_TOUCH) + && containsNonZeroByte(abs_bitmask, 0, sizeof_bit_array(ABS_MAX + 1))) { + device->classes |= INPUT_DEVICE_CLASS_JOYSTICK; + } + // figure out the switches this device reports bool haveSwitches = false; for (int i=0; i<EV_SW; i++) { @@ -876,15 +886,21 @@ int EventHub::openDevice(const char *devicePath) { } } - if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) { + // Load the key map. + // We need to do this for joysticks too because the key layout may specify axes. + status_t keyMapStatus = NAME_NOT_FOUND; + if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) { // Load the keymap for the device. - status_t status = loadKeyMap(device); + keyMapStatus = loadKeyMap(device); + } + // Configure the keyboard, gamepad or virtual keyboard. + if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) { // Set system properties for the keyboard. setKeyboardProperties(device, false); // Register the keyboard as a built-in keyboard if it is eligible. - if (!status + if (!keyMapStatus && mBuiltInKeyboardId == -1 && isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) { @@ -915,16 +931,6 @@ int EventHub::openDevice(const char *devicePath) { } } - // See if this device is a joystick. - // Ignore touchscreens because they use the same absolute axes for other purposes. - // Assumes that joysticks always have buttons and the keymap has been loaded. - if (device->classes & INPUT_DEVICE_CLASS_GAMEPAD - && !(device->classes & INPUT_DEVICE_CLASS_TOUCH)) { - if (containsNonZeroByte(abs_bitmask, 0, sizeof_bit_array(ABS_MAX + 1))) { - device->classes |= INPUT_DEVICE_CLASS_JOYSTICK; - } - } - // If the device isn't recognized as something we handle, don't monitor it. if (device->classes == 0) { LOGV("Dropping device: id=%d, path='%s', name='%s'", diff --git a/services/input/EventHub.h b/services/input/EventHub.h index 445c04b..7053a94 100644 --- a/services/input/EventHub.h +++ b/services/input/EventHub.h @@ -85,8 +85,6 @@ struct RawAbsoluteAxisInfo { int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8 int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise - inline int32_t getRange() const { return maxValue - minValue; } - inline void clear() { valid = false; minValue = 0; @@ -176,7 +174,7 @@ public: int32_t* outKeycode, uint32_t* outFlags) const = 0; virtual status_t mapAxis(int32_t deviceId, int scancode, - int32_t* outAxis) const = 0; + AxisInfo* outAxisInfo) const = 0; // exclude a particular device from opening // this can be used to ignore input devices for sensors @@ -235,7 +233,7 @@ public: int32_t* outKeycode, uint32_t* outFlags) const; virtual status_t mapAxis(int32_t deviceId, int scancode, - int32_t* outAxis) const; + AxisInfo* outAxisInfo) const; virtual void addExcludedDevice(const char* deviceName); diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index e614e81..19295e6 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -2245,6 +2245,21 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so policyFlags |= POLICY_FLAG_VIRTUAL; flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; } + if (policyFlags & POLICY_FLAG_ALT) { + metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON; + } + if (policyFlags & POLICY_FLAG_ALT_GR) { + metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON; + } + if (policyFlags & POLICY_FLAG_SHIFT) { + metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON; + } + if (policyFlags & POLICY_FLAG_CAPS_LOCK) { + metaState |= AMETA_CAPS_LOCK_ON; + } + if (policyFlags & POLICY_FLAG_FUNCTION) { + metaState |= AMETA_FUNCTION_ON; + } policyFlags |= POLICY_FLAG_TRUSTED; @@ -2328,17 +2343,17 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t } MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); - if (motionEntry->deviceId != deviceId) { - // Keep looking for this device. + if (motionEntry->deviceId != deviceId + || motionEntry->source != source) { + // Keep looking for this device and source. continue; } if (motionEntry->action != action - || motionEntry->source != source || motionEntry->pointerCount != pointerCount || motionEntry->isInjected()) { - // Last motion event in the queue for this device is not compatible for - // appending new samples. Stop here. + // Last motion event in the queue for this device and source is + // not compatible for appending new samples. Stop here. goto NoBatchingOrStreaming; } diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index b92c3b5..3029028 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -33,6 +33,7 @@ // Log debug messages about pointer assignment calculations. #define DEBUG_POINTER_ASSIGNMENT 0 + #include "InputReader.h" #include <cutils/log.h> @@ -88,6 +89,18 @@ static inline const char* toString(bool value) { return value ? "true" : "false"; } +static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation, + const int32_t map[][4], size_t mapSize) { + if (orientation != DISPLAY_ORIENTATION_0) { + for (size_t i = 0; i < mapSize; i++) { + if (value == map[i][0]) { + return map[i][orientation]; + } + } + } + return value; +} + static const int32_t keyCodeRotationMap[][4] = { // key codes enumerated counter-clockwise with the original (unrotated) key first // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation @@ -96,24 +109,80 @@ static const int32_t keyCodeRotationMap[][4] = { { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT }, { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP }, }; -static const int keyCodeRotationMapSize = +static const size_t keyCodeRotationMapSize = sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]); int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { - if (orientation != DISPLAY_ORIENTATION_0) { - for (int i = 0; i < keyCodeRotationMapSize; i++) { - if (keyCode == keyCodeRotationMap[i][0]) { - return keyCodeRotationMap[i][orientation]; - } - } - } - return keyCode; + return rotateValueUsingRotationMap(keyCode, orientation, + keyCodeRotationMap, keyCodeRotationMapSize); +} + +static const int32_t edgeFlagRotationMap[][4] = { + // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first + // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation + { AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT, + AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT }, + { AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP, + AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM }, + { AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT, + AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT }, + { AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM, + AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP }, +}; +static const size_t edgeFlagRotationMapSize = + sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]); + +static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) { + return rotateValueUsingRotationMap(edgeFlag, orientation, + edgeFlagRotationMap, edgeFlagRotationMapSize); } static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) { return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0; } +static uint32_t getButtonStateForScanCode(int32_t scanCode) { + // Currently all buttons are mapped to the primary button. + switch (scanCode) { + case BTN_LEFT: + case BTN_RIGHT: + case BTN_MIDDLE: + case BTN_SIDE: + case BTN_EXTRA: + case BTN_FORWARD: + case BTN_BACK: + case BTN_TASK: + return BUTTON_STATE_PRIMARY; + default: + return 0; + } +} + +// Returns true if the pointer should be reported as being down given the specified +// button states. +static bool isPointerDown(uint32_t buttonState) { + return buttonState & BUTTON_STATE_PRIMARY; +} + +static int32_t calculateEdgeFlagsUsingPointerBounds( + const sp<PointerControllerInterface>& pointerController, float x, float y) { + int32_t edgeFlags = 0; + float minX, minY, maxX, maxY; + if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) { + if (x <= minX) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT; + } else if (x >= maxX) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT; + } + if (y <= minY) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP; + } else if (y >= maxY) { + edgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM; + } + } + return edgeFlags; +} + // --- InputReader --- @@ -244,23 +313,23 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui } // Keyboard-like devices. - uint32_t keyboardSources = 0; + uint32_t keyboardSource = 0; int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC; if (classes & INPUT_DEVICE_CLASS_KEYBOARD) { - keyboardSources |= AINPUT_SOURCE_KEYBOARD; + keyboardSource |= AINPUT_SOURCE_KEYBOARD; } if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) { keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC; } if (classes & INPUT_DEVICE_CLASS_DPAD) { - keyboardSources |= AINPUT_SOURCE_DPAD; + keyboardSource |= AINPUT_SOURCE_DPAD; } if (classes & INPUT_DEVICE_CLASS_GAMEPAD) { - keyboardSources |= AINPUT_SOURCE_GAMEPAD; + keyboardSource |= AINPUT_SOURCE_GAMEPAD; } - if (keyboardSources != 0) { - device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType)); + if (keyboardSource != 0) { + device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType)); } // Cursor-like devices. @@ -591,22 +660,22 @@ void InputDevice::dump(String8& dump) { dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources()); dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType()); - const KeyedVector<int32_t, InputDeviceInfo::MotionRange> ranges = deviceInfo.getMotionRanges(); + const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); if (!ranges.isEmpty()) { dump.append(INDENT2 "Motion Ranges:\n"); for (size_t i = 0; i < ranges.size(); i++) { - int32_t axis = ranges.keyAt(i); - const char* label = getAxisLabel(axis); + const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); + const char* label = getAxisLabel(range.axis); char name[32]; if (label) { strncpy(name, label, sizeof(name)); name[sizeof(name) - 1] = '\0'; } else { - snprintf(name, sizeof(name), "%d", axis); + snprintf(name, sizeof(name), "%d", range.axis); } - const InputDeviceInfo::MotionRange& range = ranges.valueAt(i); - dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n", - name, range.min, range.max, range.flat, range.fuzz); + dump.appendFormat(INDENT3 "%s: source=0x%08x, " + "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n", + name, range.source, range.min, range.max, range.flat, range.fuzz); } } @@ -811,8 +880,8 @@ int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCod // --- KeyboardInputMapper --- KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, - uint32_t sources, int32_t keyboardType) : - InputMapper(device), mSources(sources), + uint32_t source, int32_t keyboardType) : + InputMapper(device), mSource(source), mKeyboardType(keyboardType) { initializeLocked(); } @@ -826,7 +895,7 @@ void KeyboardInputMapper::initializeLocked() { } uint32_t KeyboardInputMapper::getSources() { - return mSources; + return mSource; } void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { @@ -919,6 +988,7 @@ void KeyboardInputMapper::process(const RawEvent* rawEvent) { bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) { return scanCode < BTN_MOUSE || scanCode >= KEY_OK + || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI); } @@ -1009,10 +1079,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, getContext()->fadePointer(); } - if (policyFlags & POLICY_FLAG_FUNCTION) { - newMetaState |= AMETA_FUNCTION_ON; - } - getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags, + getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); } @@ -1092,7 +1159,7 @@ CursorInputMapper::~CursorInputMapper() { } uint32_t CursorInputMapper::getSources() { - return mSources; + return mSource; } void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { @@ -1101,20 +1168,20 @@ void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { if (mParameters.mode == Parameters::MODE_POINTER) { float minX, minY, maxX, maxY; if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) { - info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f); } } else { - info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale); + info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale); + info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale); } - info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f); if (mHaveVWheel) { - info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f); } if (mHaveHWheel) { - info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f); + info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f); } } @@ -1131,7 +1198,8 @@ void CursorInputMapper::dump(String8& dump) { dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel)); dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale); dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale); - dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down)); + dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState); + dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState))); dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime); } // release lock } @@ -1145,7 +1213,7 @@ void CursorInputMapper::configure() { // Configure device mode. switch (mParameters.mode) { case Parameters::MODE_POINTER: - mSources = AINPUT_SOURCE_MOUSE; + mSource = AINPUT_SOURCE_MOUSE; mXPrecision = 1.0f; mYPrecision = 1.0f; mXScale = 1.0f; @@ -1153,7 +1221,7 @@ void CursorInputMapper::configure() { mPointerController = getPolicy()->obtainPointerController(getDeviceId()); break; case Parameters::MODE_NAVIGATION: - mSources = AINPUT_SOURCE_TRACKBALL; + mSource = AINPUT_SOURCE_TRACKBALL; mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; @@ -1210,16 +1278,18 @@ void CursorInputMapper::dumpParameters(String8& dump) { void CursorInputMapper::initializeLocked() { mAccumulator.clear(); - mLocked.down = false; + mLocked.buttonState = 0; mLocked.downTime = 0; } void CursorInputMapper::reset() { for (;;) { + uint32_t buttonState; { // acquire lock AutoMutex _l(mLock); - if (! mLocked.down) { + buttonState = mLocked.buttonState; + if (!buttonState) { initializeLocked(); break; // done } @@ -1227,8 +1297,10 @@ void CursorInputMapper::reset() { // Synthesize button up event on reset. nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); - mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE; - mAccumulator.btnMouse = false; + mAccumulator.clear(); + mAccumulator.buttonDown = 0; + mAccumulator.buttonUp = buttonState; + mAccumulator.fields = Accumulator::FIELD_BUTTONS; sync(when); } @@ -1237,24 +1309,25 @@ void CursorInputMapper::reset() { void CursorInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { - case EV_KEY: - switch (rawEvent->scanCode) { - case BTN_LEFT: - case BTN_RIGHT: - case BTN_MIDDLE: - case BTN_SIDE: - case BTN_EXTRA: - case BTN_FORWARD: - case BTN_BACK: - case BTN_TASK: - mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE; - mAccumulator.btnMouse = rawEvent->value != 0; + case EV_KEY: { + uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode); + if (buttonState) { + if (rawEvent->value) { + mAccumulator.buttonDown = buttonState; + mAccumulator.buttonUp = 0; + } else { + mAccumulator.buttonDown = 0; + mAccumulator.buttonUp = buttonState; + } + mAccumulator.fields |= Accumulator::FIELD_BUTTONS; + // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and // we need to ensure that we report the up/down promptly. sync(rawEvent->when); break; } break; + } case EV_REL: switch (rawEvent->scanCode) { @@ -1293,30 +1366,34 @@ void CursorInputMapper::sync(nsecs_t when) { return; // no new state changes, so nothing to do } - int motionEventAction; + int32_t motionEventAction; + int32_t motionEventEdgeFlags; PointerCoords pointerCoords; nsecs_t downTime; float vscroll, hscroll; { // acquire lock AutoMutex _l(mLock); - bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE; + bool down, downChanged; + bool wasDown = isPointerDown(mLocked.buttonState); + bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS; + if (buttonsChanged) { + mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown) + & ~mAccumulator.buttonUp; - if (downChanged) { - if (mAccumulator.btnMouse) { - if (!mLocked.down) { - mLocked.down = true; - mLocked.downTime = when; - } else { - downChanged = false; - } + down = isPointerDown(mLocked.buttonState); + + if (!wasDown && down) { + mLocked.downTime = when; + downChanged = true; + } else if (wasDown && !down) { + downChanged = true; } else { - if (mLocked.down) { - mLocked.down = false; - } else { - downChanged = false; - } + downChanged = false; } + } else { + down = wasDown; + downChanged = false; } downTime = mLocked.downTime; @@ -1324,8 +1401,8 @@ void CursorInputMapper::sync(nsecs_t when) { float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f; if (downChanged) { - motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; - } else if (mLocked.down || mPointerController == NULL) { + motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; + } else if (down || mPointerController == NULL) { motionEventAction = AMOTION_EVENT_ACTION_MOVE; } else { motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE; @@ -1364,21 +1441,29 @@ void CursorInputMapper::sync(nsecs_t when) { pointerCoords.clear(); + motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE; + if (mPointerController != NULL) { mPointerController->move(deltaX, deltaY); - if (downChanged) { - mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0); + if (buttonsChanged) { + mPointerController->setButtonState(mLocked.buttonState); } + float x, y; mPointerController->getPosition(&x, &y); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); + + if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) { + motionEventEdgeFlags = calculateEdgeFlagsUsingPointerBounds( + mPointerController, x, y); + } } else { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); } - pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f); + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) { vscroll = mAccumulator.relWheel; @@ -1406,8 +1491,8 @@ void CursorInputMapper::sync(nsecs_t when) { int32_t metaState = mContext->getGlobalMetaState(); int32_t pointerId = 0; - getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags, - motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE, + getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags, + motionEventAction, 0, metaState, motionEventEdgeFlags, 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime); mAccumulator.clear(); @@ -1416,7 +1501,7 @@ void CursorInputMapper::sync(nsecs_t when) { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags, + getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime); } @@ -1433,7 +1518,9 @@ int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCod void CursorInputMapper::fadePointer() { { // acquire lock AutoMutex _l(mLock); - mPointerController->fade(); + if (mPointerController != NULL) { + mPointerController->fade(); + } } // release lock } @@ -1453,7 +1540,7 @@ TouchInputMapper::~TouchInputMapper() { } uint32_t TouchInputMapper::getSources() { - return mSources; + return mTouchSource; } void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { @@ -1464,38 +1551,33 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { // Ensure surface information is up to date so that orientation changes are // noticed immediately. - configureSurfaceLocked(); + if (!configureSurfaceLocked()) { + return; + } - info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x); - info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y); + info->addMotionRange(mLocked.orientedRanges.x); + info->addMotionRange(mLocked.orientedRanges.y); if (mLocked.orientedRanges.havePressure) { - info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, - mLocked.orientedRanges.pressure); + info->addMotionRange(mLocked.orientedRanges.pressure); } if (mLocked.orientedRanges.haveSize) { - info->addMotionRange(AMOTION_EVENT_AXIS_SIZE, - mLocked.orientedRanges.size); + info->addMotionRange(mLocked.orientedRanges.size); } if (mLocked.orientedRanges.haveTouchSize) { - info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR, - mLocked.orientedRanges.touchMajor); - info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR, - mLocked.orientedRanges.touchMinor); + info->addMotionRange(mLocked.orientedRanges.touchMajor); + info->addMotionRange(mLocked.orientedRanges.touchMinor); } if (mLocked.orientedRanges.haveToolSize) { - info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR, - mLocked.orientedRanges.toolMajor); - info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR, - mLocked.orientedRanges.toolMinor); + info->addMotionRange(mLocked.orientedRanges.toolMajor); + info->addMotionRange(mLocked.orientedRanges.toolMinor); } if (mLocked.orientedRanges.haveOrientation) { - info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, - mLocked.orientedRanges.orientation); + info->addMotionRange(mLocked.orientedRanges.orientation); } } // release lock } @@ -1509,9 +1591,8 @@ void TouchInputMapper::dump(String8& dump) { dumpRawAxes(dump); dumpCalibration(dump); dumpSurfaceLocked(dump); + dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); - dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin); - dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin); dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale); dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale); dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision); @@ -1523,7 +1604,10 @@ void TouchInputMapper::dump(String8& dump) { dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias); dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale); dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale); - dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale); + dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale); + + dump.appendFormat(INDENT3 "Last Touch:\n"); + dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount); } // release lock } @@ -1557,10 +1641,10 @@ void TouchInputMapper::configure() { // Configure sources. switch (mParameters.deviceType) { case Parameters::DEVICE_TYPE_TOUCH_SCREEN: - mSources = AINPUT_SOURCE_TOUCHSCREEN; + mTouchSource = AINPUT_SOURCE_TOUCHSCREEN; break; case Parameters::DEVICE_TYPE_TOUCH_PAD: - mSources = AINPUT_SOURCE_TOUCHPAD; + mTouchSource = AINPUT_SOURCE_TOUCHPAD; break; default: assert(false); @@ -1593,17 +1677,20 @@ void TouchInputMapper::configureParameters() { deviceTypeString)) { if (deviceTypeString == "touchScreen") { mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN; - } else if (deviceTypeString != "touchPad") { + } else if (deviceTypeString == "touchPad") { + mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD; + } else { LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string()); } } - bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; - mParameters.orientationAware = isTouchScreen; + mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"), mParameters.orientationAware); - mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1; + mParameters.associatedDisplayId = mParameters.orientationAware + || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN + ? 0 : -1; } void TouchInputMapper::dumpParameters(String8& dump) { @@ -1657,21 +1744,36 @@ void TouchInputMapper::dumpRawAxes(String8& dump) { } bool TouchInputMapper::configureSurfaceLocked() { + // Ensure we have valid X and Y axes. + if (!mRawAxes.x.valid || !mRawAxes.y.valid) { + LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! " + "The device will be inoperable.", getDeviceName().string()); + return false; + } + // Update orientation and dimensions if needed. int32_t orientation = DISPLAY_ORIENTATION_0; - int32_t width = mRawAxes.x.getRange(); - int32_t height = mRawAxes.y.getRange(); + int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1; + int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1; if (mParameters.associatedDisplayId >= 0) { - bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; - bool wantOrientation = mParameters.orientationAware; - // Note: getDisplayInfo is non-reentrant so we can continue holding the lock. if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId, - wantSize ? &width : NULL, wantSize ? &height : NULL, - wantOrientation ? &orientation : NULL)) { + &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight, + &mLocked.associatedDisplayOrientation)) { return false; } + + // A touch screen inherits the dimensions of the display. + if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { + width = mLocked.associatedDisplayWidth; + height = mLocked.associatedDisplayHeight; + } + + // The device inherits the orientation of the display if it is orientation aware. + if (mParameters.orientationAware) { + orientation = mLocked.associatedDisplayOrientation; + } } bool orientationChanged = mLocked.surfaceOrientation != orientation; @@ -1681,39 +1783,24 @@ bool TouchInputMapper::configureSurfaceLocked() { bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height; if (sizeChanged) { - LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d", + LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d", getDeviceId(), getDeviceName().string(), width, height); mLocked.surfaceWidth = width; mLocked.surfaceHeight = height; // Configure X and Y factors. - if (mRawAxes.x.valid && mRawAxes.y.valid) { - mLocked.xOrigin = mCalibration.haveXOrigin - ? mCalibration.xOrigin - : mRawAxes.x.minValue; - mLocked.yOrigin = mCalibration.haveYOrigin - ? mCalibration.yOrigin - : mRawAxes.y.minValue; - mLocked.xScale = mCalibration.haveXScale - ? mCalibration.xScale - : float(width) / mRawAxes.x.getRange(); - mLocked.yScale = mCalibration.haveYScale - ? mCalibration.yScale - : float(height) / mRawAxes.y.getRange(); - mLocked.xPrecision = 1.0f / mLocked.xScale; - mLocked.yPrecision = 1.0f / mLocked.yScale; - - configureVirtualKeysLocked(); - } else { - LOGW(INDENT "Touch device did not report support for X or Y axis!"); - mLocked.xOrigin = 0; - mLocked.yOrigin = 0; - mLocked.xScale = 1.0f; - mLocked.yScale = 1.0f; - mLocked.xPrecision = 1.0f; - mLocked.yPrecision = 1.0f; - } + mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1); + mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1); + mLocked.xPrecision = 1.0f / mLocked.xScale; + mLocked.yPrecision = 1.0f / mLocked.yScale; + + mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X; + mLocked.orientedRanges.x.source = mTouchSource; + mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y; + mLocked.orientedRanges.y.source = mTouchSource; + + configureVirtualKeysLocked(); // Scale factor for terms that are not oriented in a particular axis. // If the pixels are square then xScale == yScale otherwise we fake it @@ -1726,11 +1813,16 @@ bool TouchInputMapper::configureSurfaceLocked() { // TouchMajor and TouchMinor factors. if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) { mLocked.orientedRanges.haveTouchSize = true; + + mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR; + mLocked.orientedRanges.touchMajor.source = mTouchSource; mLocked.orientedRanges.touchMajor.min = 0; mLocked.orientedRanges.touchMajor.max = diagonalSize; mLocked.orientedRanges.touchMajor.flat = 0; mLocked.orientedRanges.touchMajor.fuzz = 0; + mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor; + mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; } // ToolMajor and ToolMinor factors. @@ -1774,11 +1866,16 @@ bool TouchInputMapper::configureSurfaceLocked() { } mLocked.orientedRanges.haveToolSize = true; + + mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR; + mLocked.orientedRanges.toolMajor.source = mTouchSource; mLocked.orientedRanges.toolMajor.min = 0; mLocked.orientedRanges.toolMajor.max = diagonalSize; mLocked.orientedRanges.toolMajor.flat = 0; mLocked.orientedRanges.toolMajor.fuzz = 0; + mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor; + mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR; } // Pressure factors. @@ -1807,6 +1904,9 @@ bool TouchInputMapper::configureSurfaceLocked() { } mLocked.orientedRanges.havePressure = true; + + mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE; + mLocked.orientedRanges.pressure.source = mTouchSource; mLocked.orientedRanges.pressure.min = 0; mLocked.orientedRanges.pressure.max = 1.0; mLocked.orientedRanges.pressure.flat = 0; @@ -1823,6 +1923,9 @@ bool TouchInputMapper::configureSurfaceLocked() { } mLocked.orientedRanges.haveSize = true; + + mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE; + mLocked.orientedRanges.size.source = mTouchSource; mLocked.orientedRanges.size.min = 0; mLocked.orientedRanges.size.max = 1.0; mLocked.orientedRanges.size.flat = 0; @@ -1839,6 +1942,8 @@ bool TouchInputMapper::configureSurfaceLocked() { } } + mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; + mLocked.orientedRanges.orientation.source = mTouchSource; mLocked.orientedRanges.orientation.min = - M_PI_2; mLocked.orientedRanges.orientation.max = M_PI_2; mLocked.orientedRanges.orientation.flat = 0; @@ -1847,38 +1952,51 @@ bool TouchInputMapper::configureSurfaceLocked() { } if (orientationChanged || sizeChanged) { - // Compute oriented surface dimensions, precision, and scales. - float orientedXScale, orientedYScale; + // Compute oriented surface dimensions, precision, scales and ranges. + // Note that the maximum value reported is an inclusive maximum value so it is one + // unit less than the total width or height of surface. switch (mLocked.surfaceOrientation) { case DISPLAY_ORIENTATION_90: case DISPLAY_ORIENTATION_270: mLocked.orientedSurfaceWidth = mLocked.surfaceHeight; mLocked.orientedSurfaceHeight = mLocked.surfaceWidth; + mLocked.orientedXPrecision = mLocked.yPrecision; mLocked.orientedYPrecision = mLocked.xPrecision; - orientedXScale = mLocked.yScale; - orientedYScale = mLocked.xScale; + + mLocked.orientedRanges.x.min = 0; + mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue) + * mLocked.yScale; + mLocked.orientedRanges.x.flat = 0; + mLocked.orientedRanges.x.fuzz = mLocked.yScale; + + mLocked.orientedRanges.y.min = 0; + mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue) + * mLocked.xScale; + mLocked.orientedRanges.y.flat = 0; + mLocked.orientedRanges.y.fuzz = mLocked.xScale; break; + default: mLocked.orientedSurfaceWidth = mLocked.surfaceWidth; mLocked.orientedSurfaceHeight = mLocked.surfaceHeight; + mLocked.orientedXPrecision = mLocked.xPrecision; mLocked.orientedYPrecision = mLocked.yPrecision; - orientedXScale = mLocked.xScale; - orientedYScale = mLocked.yScale; + + mLocked.orientedRanges.x.min = 0; + mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue) + * mLocked.xScale; + mLocked.orientedRanges.x.flat = 0; + mLocked.orientedRanges.x.fuzz = mLocked.xScale; + + mLocked.orientedRanges.y.min = 0; + mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue) + * mLocked.yScale; + mLocked.orientedRanges.y.flat = 0; + mLocked.orientedRanges.y.fuzz = mLocked.yScale; break; } - - // Configure position ranges. - mLocked.orientedRanges.x.min = 0; - mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth; - mLocked.orientedRanges.x.flat = 0; - mLocked.orientedRanges.x.fuzz = orientedXScale; - - mLocked.orientedRanges.y.min = 0; - mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight; - mLocked.orientedRanges.y.flat = 0; - mLocked.orientedRanges.y.fuzz = orientedYScale; } return true; @@ -1891,8 +2009,6 @@ void TouchInputMapper::dumpSurfaceLocked(String8& dump) { } void TouchInputMapper::configureVirtualKeysLocked() { - assert(mRawAxes.x.valid && mRawAxes.y.valid); - Vector<VirtualKeyDefinition> virtualKeyDefinitions; getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions); @@ -1906,8 +2022,8 @@ void TouchInputMapper::configureVirtualKeysLocked() { int32_t touchScreenLeft = mRawAxes.x.minValue; int32_t touchScreenTop = mRawAxes.y.minValue; - int32_t touchScreenWidth = mRawAxes.x.getRange(); - int32_t touchScreenHeight = mRawAxes.y.getRange(); + int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1; + int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1; for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) { const VirtualKeyDefinition& virtualKeyDefinition = @@ -1942,7 +2058,6 @@ void TouchInputMapper::configureVirtualKeysLocked() { * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop; virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop; - } } @@ -1965,12 +2080,6 @@ void TouchInputMapper::parseCalibration() { const PropertyMap& in = getDevice()->getConfiguration(); Calibration& out = mCalibration; - // Position - out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin); - out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin); - out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale); - out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale); - // Touch Size out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT; String8 touchSizeCalibrationString; @@ -2182,20 +2291,6 @@ void TouchInputMapper::resolveCalibration() { void TouchInputMapper::dumpCalibration(String8& dump) { dump.append(INDENT3 "Calibration:\n"); - // Position - if (mCalibration.haveXOrigin) { - dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin); - } - if (mCalibration.haveYOrigin) { - dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin); - } - if (mCalibration.haveXScale) { - dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale); - } - if (mCalibration.haveYScale) { - dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale); - } - // Touch Size switch (mCalibration.touchSizeCalibration) { case Calibration::TOUCH_SIZE_CALIBRATION_NONE: @@ -2363,8 +2458,10 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { uint32_t policyFlags = 0; if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) { - // Hide the pointer on an initial down. - getContext()->fadePointer(); + if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) { + // If this is a touch screen, hide the pointer on an initial down. + getContext()->fadePointer(); + } // Initial downs on external touch devices should wake the device. // We don't do this for internal touch screens to prevent them from waking @@ -2378,7 +2475,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { // Process touches and virtual keys. TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { - detectGestures(when); + suppressSwipeOntoVirtualKeys(when); dispatchTouches(when, policyFlags); } @@ -2505,7 +2602,7 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( return touchResult; } -void TouchInputMapper::detectGestures(nsecs_t when) { +void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) { // Disable all virtual key touches that happen within a short time interval of the // most recent touch. The idea is to filter out stray virtual key presses when // interacting with the touch screen. @@ -2623,14 +2720,14 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, int32_t motionEventAction) { int32_t pointerIds[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; - int32_t motionEventEdgeFlags = 0; + int32_t motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE; float xPrecision, yPrecision; { // acquire lock AutoMutex _l(mLock); // Walk through the the active pointers and map touch screen coordinates (TouchData) into - // display coordinates (PointerCoords) and adjust for display orientation. + // display or surface coordinates (PointerCoords) and adjust for display orientation. for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) { uint32_t id = idBits.firstMarkedBit(); idBits.clearBit(id); @@ -2638,10 +2735,6 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, const PointerData& in = touch->pointers[inIndex]; - // X and Y - float x = float(in.x - mLocked.xOrigin) * mLocked.xScale; - float y = float(in.y - mLocked.yOrigin) * mLocked.yScale; - // ToolMajor and ToolMinor float toolMajor, toolMinor; switch (mCalibration.toolSizeCalibration) { @@ -2779,33 +2872,34 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, orientation = 0; } - // Adjust coords for orientation. + // X and Y + // Adjust coords for surface orientation. + float x, y; switch (mLocked.surfaceOrientation) { - case DISPLAY_ORIENTATION_90: { - float xTemp = x; - x = y; - y = mLocked.surfaceWidth - xTemp; + case DISPLAY_ORIENTATION_90: + x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale; + y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale; orientation -= M_PI_2; if (orientation < - M_PI_2) { orientation += M_PI; } break; - } - case DISPLAY_ORIENTATION_180: { - x = mLocked.surfaceWidth - x; - y = mLocked.surfaceHeight - y; + case DISPLAY_ORIENTATION_180: + x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale; + y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale; break; - } - case DISPLAY_ORIENTATION_270: { - float xTemp = x; - x = mLocked.surfaceHeight - y; - y = xTemp; + case DISPLAY_ORIENTATION_270: + x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale; + y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale; orientation += M_PI_2; if (orientation > M_PI_2) { orientation -= M_PI; } break; - } + default: + x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale; + y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale; + break; } // Write output coords. @@ -2831,18 +2925,22 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, // Check edge flags by looking only at the first pointer since the flags are // global to the event. if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) { - float x = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X); - float y = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y); + uint32_t inIndex = touch->idToIndex[pointerIds[0]]; + const PointerData& in = touch->pointers[inIndex]; - if (x <= 0) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT; - } else if (x >= mLocked.orientedSurfaceWidth) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT; + if (in.x <= mRawAxes.x.minValue) { + motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT, + mLocked.surfaceOrientation); + } else if (in.x >= mRawAxes.x.maxValue) { + motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT, + mLocked.surfaceOrientation); } - if (y <= 0) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP; - } else if (y >= mLocked.orientedSurfaceHeight) { - motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM; + if (in.y <= mRawAxes.y.minValue) { + motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP, + mLocked.surfaceOrientation); + } else if (in.y >= mRawAxes.y.maxValue) { + motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM, + mLocked.surfaceOrientation); } } @@ -2850,18 +2948,15 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, yPrecision = mLocked.orientedYPrecision; } // release lock - getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags, + getDispatcher()->notifyMotion(when, getDeviceId(), mTouchSource, policyFlags, motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags, pointerCount, pointerIds, pointerCoords, xPrecision, yPrecision, mDownTime); } bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) { - if (mRawAxes.x.valid && mRawAxes.y.valid) { - return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue - && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue; - } - return true; + return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue + && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue; } const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked( @@ -3069,11 +3164,6 @@ void TouchInputMapper::calculatePointerIds() { * points has moved more than a screen height from the last position, * then drop it. */ bool TouchInputMapper::applyBadTouchFilter() { - // This hack requires valid axis parameters. - if (! mRawAxes.y.valid) { - return false; - } - uint32_t pointerCount = mCurrentTouch.pointerCount; // Nothing to do if there are no points. @@ -3092,7 +3182,7 @@ bool TouchInputMapper::applyBadTouchFilter() { // the long size of the screen to be bad. This was a magic value // determined by looking at the maximum distance it is feasible // to actually move in one sample. - int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16; + int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16; // XXX The original code in InputDevice.java included commented out // code for testing the X axis. Note that when we drop a point @@ -3153,11 +3243,6 @@ bool TouchInputMapper::applyBadTouchFilter() { * the coordinate value for one axis has jumped to the other pointer's location. */ bool TouchInputMapper::applyJumpyTouchFilter() { - // This hack requires valid axis parameters. - if (! mRawAxes.y.valid) { - return false; - } - uint32_t pointerCount = mCurrentTouch.pointerCount; if (mLastTouch.pointerCount != pointerCount) { #if DEBUG_HACKS @@ -3214,7 +3299,7 @@ bool TouchInputMapper::applyJumpyTouchFilter() { } if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) { - int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR; + int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR; // We only replace the single worst jumpy point as characterized by pointer distance // in a single axis. @@ -3854,7 +3939,12 @@ void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) { for (size_t i = 0; i < mAxes.size(); i++) { const Axis& axis = mAxes.valueAt(i); - info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz); + info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK, + axis.min, axis.max, axis.flat, axis.fuzz); + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { + info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK, + axis.min, axis.max, axis.flat, axis.fuzz); + } } } @@ -3865,18 +3955,29 @@ void JoystickInputMapper::dump(String8& dump) { size_t numAxes = mAxes.size(); for (size_t i = 0; i < numAxes; i++) { const Axis& axis = mAxes.valueAt(i); - const char* label = getAxisLabel(axis.axis); - char name[32]; + const char* label = getAxisLabel(axis.axisInfo.axis); if (label) { - strncpy(name, label, sizeof(name)); - name[sizeof(name) - 1] = '\0'; + dump.appendFormat(INDENT4 "%s", label); } else { - snprintf(name, sizeof(name), "%d", axis.axis); + dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis); + } + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { + label = getAxisLabel(axis.axisInfo.highAxis); + if (label) { + dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue); + } else { + dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis, + axis.axisInfo.splitValue); + } + } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) { + dump.append(" (invert)"); } - dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, " - "scale=%0.3f, offset=%0.3f\n", - name, axis.min, axis.max, axis.flat, axis.fuzz, - axis.scale, axis.offset); + + dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n", + axis.min, axis.max, axis.flat, axis.fuzz); + dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, " + "highScale=%0.5f, highOffset=%0.5f\n", + axis.scale, axis.offset, axis.highScale, axis.highOffset); dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n", mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue, axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz); @@ -3891,25 +3992,38 @@ void JoystickInputMapper::configure() { RawAbsoluteAxisInfo rawAxisInfo; getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo); if (rawAxisInfo.valid) { - int32_t axisId; - bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId); + // Map axis. + AxisInfo axisInfo; + bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo); if (!explicitlyMapped) { // Axis is not explicitly mapped, will choose a generic axis later. - axisId = -1; + axisInfo.mode = AxisInfo::MODE_NORMAL; + axisInfo.axis = -1; } + // Apply flat override. + int32_t rawFlat = axisInfo.flatOverride < 0 + ? rawAxisInfo.flat : axisInfo.flatOverride; + + // Calculate scaling factors and limits. Axis axis; - if (isCenteredAxis(axisId)) { + if (axisInfo.mode == AxisInfo::MODE_SPLIT) { + float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue); + float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue); + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, + scale, 0.0f, highScale, 0.0f, + 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); + } else if (isCenteredAxis(axisInfo.axis)) { float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale; - axis.initialize(rawAxisInfo, axisId, explicitlyMapped, - scale, offset, -1.0f, 1.0f, - rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale); + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, + scale, offset, scale, offset, + -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); } else { float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); - axis.initialize(rawAxisInfo, axisId, explicitlyMapped, - scale, 0.0f, 0.0f, 1.0f, - rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale); + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, + scale, 0.0f, scale, 0.0f, + 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); } // To eliminate noise while the joystick is at rest, filter out small variations @@ -3934,14 +4048,14 @@ void JoystickInputMapper::configure() { size_t numAxes = mAxes.size(); for (size_t i = 0; i < numAxes; i++) { Axis& axis = mAxes.editValueAt(i); - if (axis.axis < 0) { + if (axis.axisInfo.axis < 0) { while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16 && haveAxis(nextGenericAxisId)) { nextGenericAxisId += 1; } if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) { - axis.axis = nextGenericAxisId; + axis.axisInfo.axis = nextGenericAxisId; nextGenericAxisId += 1; } else { LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids " @@ -3954,10 +4068,13 @@ void JoystickInputMapper::configure() { } } -bool JoystickInputMapper::haveAxis(int32_t axis) { +bool JoystickInputMapper::haveAxis(int32_t axisId) { size_t numAxes = mAxes.size(); for (size_t i = 0; i < numAxes; i++) { - if (mAxes.valueAt(i).axis == axis) { + const Axis& axis = mAxes.valueAt(i); + if (axis.axisInfo.axis == axisId + || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT + && axis.axisInfo.highAxis == axisId)) { return true; } } @@ -3987,6 +4104,8 @@ bool JoystickInputMapper::isCenteredAxis(int32_t axis) { case AMOTION_EVENT_AXIS_HAT_X: case AMOTION_EVENT_AXIS_HAT_Y: case AMOTION_EVENT_AXIS_ORIENTATION: + case AMOTION_EVENT_AXIS_RUDDER: + case AMOTION_EVENT_AXIS_WHEEL: return true; default: return false; @@ -4000,7 +4119,7 @@ void JoystickInputMapper::reset() { size_t numAxes = mAxes.size(); for (size_t i = 0; i < numAxes; i++) { Axis& axis = mAxes.editValueAt(i); - axis.newValue = 0; + axis.resetValue(); } sync(when, true /*force*/); @@ -4014,10 +4133,34 @@ void JoystickInputMapper::process(const RawEvent* rawEvent) { ssize_t index = mAxes.indexOfKey(rawEvent->scanCode); if (index >= 0) { Axis& axis = mAxes.editValueAt(index); - float newValue = rawEvent->value * axis.scale + axis.offset; - if (newValue != axis.newValue) { - axis.newValue = newValue; + float newValue, highNewValue; + switch (axis.axisInfo.mode) { + case AxisInfo::MODE_INVERT: + newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) + * axis.scale + axis.offset; + highNewValue = 0.0f; + break; + case AxisInfo::MODE_SPLIT: + if (rawEvent->value < axis.axisInfo.splitValue) { + newValue = (axis.axisInfo.splitValue - rawEvent->value) + * axis.scale + axis.offset; + highNewValue = 0.0f; + } else if (rawEvent->value > axis.axisInfo.splitValue) { + newValue = 0.0f; + highNewValue = (rawEvent->value - axis.axisInfo.splitValue) + * axis.highScale + axis.highOffset; + } else { + newValue = 0.0f; + highNewValue = 0.0f; + } + break; + default: + newValue = rawEvent->value * axis.scale + axis.offset; + highNewValue = 0.0f; + break; } + axis.newValue = newValue; + axis.highNewValue = highNewValue; } break; } @@ -4033,7 +4176,7 @@ void JoystickInputMapper::process(const RawEvent* rawEvent) { } void JoystickInputMapper::sync(nsecs_t when, bool force) { - if (!force && !haveAxesChangedSignificantly()) { + if (!filterAxes(force)) { return; } @@ -4044,9 +4187,11 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { size_t numAxes = mAxes.size(); for (size_t i = 0; i < numAxes; i++) { - Axis& axis = mAxes.editValueAt(i); - pointerCoords.setAxisValue(axis.axis, axis.newValue); - axis.oldValue = axis.newValue; + const Axis& axis = mAxes.valueAt(i); + pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue); + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { + pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue); + } } // Moving a joystick axis should not wake the devide because joysticks can @@ -4061,12 +4206,49 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { 1, &pointerId, &pointerCoords, 0, 0, 0); } -bool JoystickInputMapper::haveAxesChangedSignificantly() { +bool JoystickInputMapper::filterAxes(bool force) { + bool atLeastOneSignificantChange = force; size_t numAxes = mAxes.size(); for (size_t i = 0; i < numAxes; i++) { - const Axis& axis = mAxes.valueAt(i); - if (axis.newValue != axis.oldValue - && fabs(axis.newValue - axis.oldValue) > axis.filter) { + Axis& axis = mAxes.editValueAt(i); + if (force || hasValueChangedSignificantly(axis.filter, + axis.newValue, axis.currentValue, axis.min, axis.max)) { + axis.currentValue = axis.newValue; + atLeastOneSignificantChange = true; + } + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { + if (force || hasValueChangedSignificantly(axis.filter, + axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) { + axis.highCurrentValue = axis.highNewValue; + atLeastOneSignificantChange = true; + } + } + } + return atLeastOneSignificantChange; +} + +bool JoystickInputMapper::hasValueChangedSignificantly( + float filter, float newValue, float currentValue, float min, float max) { + if (newValue != currentValue) { + // Filter out small changes in value unless the value is converging on the axis + // bounds or center point. This is intended to reduce the amount of information + // sent to applications by particularly noisy joysticks (such as PS3). + if (fabs(newValue - currentValue) > filter + || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min) + || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max) + || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) { + return true; + } + } + return false; +} + +bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange( + float filter, float newValue, float currentValue, float thresholdValue) { + float newDistance = fabs(newValue - thresholdValue); + if (newDistance < filter) { + float oldDistance = fabs(currentValue - thresholdValue); + if (newDistance < oldDistance) { return true; } } diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 655f0f0..68002ca 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -389,7 +389,7 @@ private: class KeyboardInputMapper : public InputMapper { public: - KeyboardInputMapper(InputDevice* device, uint32_t sources, int32_t keyboardType); + KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType); virtual ~KeyboardInputMapper(); virtual uint32_t getSources(); @@ -414,7 +414,7 @@ private: int32_t scanCode; }; - uint32_t mSources; + uint32_t mSource; int32_t mKeyboardType; // Immutable configuration parameters. @@ -493,7 +493,7 @@ private: struct Accumulator { enum { - FIELD_BTN_MOUSE = 1, + FIELD_BUTTONS = 1, FIELD_REL_X = 2, FIELD_REL_Y = 4, FIELD_REL_WHEEL = 8, @@ -502,7 +502,9 @@ private: uint32_t fields; - bool btnMouse; + uint32_t buttonDown; + uint32_t buttonUp; + int32_t relX; int32_t relY; int32_t relWheel; @@ -513,7 +515,7 @@ private: } } mAccumulator; - int32_t mSources; + int32_t mSource; float mXScale; float mYScale; float mXPrecision; @@ -527,7 +529,7 @@ private: sp<PointerControllerInterface> mPointerController; struct LockedState { - bool down; + uint32_t buttonState; nsecs_t downTime; } mLocked; @@ -629,7 +631,7 @@ protected: }; // Input sources supported by the device. - int32_t mSources; + uint32_t mTouchSource; // sources when reporting touch data // Immutable configuration parameters. struct Parameters { @@ -650,16 +652,6 @@ protected: // Immutable calibration parameters in parsed form. struct Calibration { - // Position - bool haveXOrigin; - int32_t xOrigin; - bool haveYOrigin; - int32_t yOrigin; - bool haveXScale; - float xScale; - bool haveYScale; - float yScale; - // Touch Size enum TouchSizeCalibration { TOUCH_SIZE_CALIBRATION_DEFAULT, @@ -755,12 +747,14 @@ protected: int32_t surfaceOrientation; int32_t surfaceWidth, surfaceHeight; + // The associated display orientation and width and height set by configureSurfaceLocked(). + int32_t associatedDisplayOrientation; + int32_t associatedDisplayWidth, associatedDisplayHeight; + // Translation and scaling factors, orientation-independent. - int32_t xOrigin; float xScale; float xPrecision; - int32_t yOrigin; float yScale; float yPrecision; @@ -882,7 +876,7 @@ private: void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount, int32_t motionEventAction); - void detectGestures(nsecs_t when); + void suppressSwipeOntoVirtualKeys(nsecs_t when); bool isPointInsideSurfaceLocked(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); @@ -912,7 +906,7 @@ private: FIELD_ABS_X = 2, FIELD_ABS_Y = 4, FIELD_ABS_PRESSURE = 8, - FIELD_ABS_TOOL_WIDTH = 16 + FIELD_ABS_TOOL_WIDTH = 16, }; uint32_t fields; @@ -1011,38 +1005,50 @@ public: private: struct Axis { RawAbsoluteAxisInfo rawAxisInfo; + AxisInfo axisInfo; - int32_t axis; // axis id bool explicitlyMapped; // true if the axis was explicitly assigned an axis id float scale; // scale factor from raw to normalized values float offset; // offset to add after scaling for normalization + float highScale; // scale factor from raw to normalized values of high split + float highOffset; // offset to add after scaling for normalization of high split float min; // normalized inclusive minimum float max; // normalized inclusive maximum float flat; // normalized flat region size float fuzz; // normalized error tolerance - float oldValue; // previous value - float newValue; // most recent value - float filter; // filter out small variations of this size + float currentValue; // current value + float newValue; // most recent value + float highCurrentValue; // current value of high split + float highNewValue; // most recent value of high split - void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, - int32_t axis, bool explicitlyMapped, float scale, float offset, + void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo, + bool explicitlyMapped, float scale, float offset, + float highScale, float highOffset, float min, float max, float flat, float fuzz) { this->rawAxisInfo = rawAxisInfo; - this->axis = axis; + this->axisInfo = axisInfo; this->explicitlyMapped = explicitlyMapped; this->scale = scale; this->offset = offset; + this->highScale = highScale; + this->highOffset = highOffset; this->min = min; this->max = max; this->flat = flat; this->fuzz = fuzz; this->filter = 0; - this->oldValue = 0; + resetValue(); + } + + void resetValue() { + this->currentValue = 0; this->newValue = 0; + this->highCurrentValue = 0; + this->highNewValue = 0; } }; @@ -1051,9 +1057,14 @@ private: void sync(nsecs_t when, bool force); - bool haveAxis(int32_t axis); + bool haveAxis(int32_t axisId); void pruneAxes(bool ignoreExplicitlyMappedAxes); - bool haveAxesChangedSignificantly(); + bool filterAxes(bool force); + + static bool hasValueChangedSignificantly(float filter, + float newValue, float currentValue, float min, float max); + static bool hasMovedNearerToValueWithinFilteredRange(float filter, + float newValue, float currentValue, float thresholdValue); static bool isCenteredAxis(int32_t axis); }; diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp index 954872b..a4ee295 100644 --- a/services/input/PointerController.cpp +++ b/services/input/PointerController.cpp @@ -109,12 +109,12 @@ bool PointerController::getBoundsLocked(float* outMinX, float* outMinY, switch (mLocked.displayOrientation) { case DISPLAY_ORIENTATION_90: case DISPLAY_ORIENTATION_270: - *outMaxX = mLocked.displayHeight; - *outMaxY = mLocked.displayWidth; + *outMaxX = mLocked.displayHeight - 1; + *outMaxY = mLocked.displayWidth - 1; break; default: - *outMaxX = mLocked.displayWidth; - *outMaxY = mLocked.displayHeight; + *outMaxX = mLocked.displayWidth - 1; + *outMaxY = mLocked.displayHeight - 1; break; } return true; @@ -309,48 +309,53 @@ void PointerController::setDisplayOrientation(int32_t orientation) { AutoMutex _l(mLock); if (mLocked.displayOrientation != orientation) { - float absoluteX, absoluteY; - - // Map from oriented display coordinates to absolute display coordinates. + // Apply offsets to convert from the pixel top-left corner position to the pixel center. + // This creates an invariant frame of reference that we can easily rotate when + // taking into account that the pointer may be located at fractional pixel offsets. + float x = mLocked.pointerX + 0.5f; + float y = mLocked.pointerY + 0.5f; + float temp; + + // Undo the previous rotation. switch (mLocked.displayOrientation) { case DISPLAY_ORIENTATION_90: - absoluteX = mLocked.displayWidth - mLocked.pointerY; - absoluteY = mLocked.pointerX; + temp = x; + x = mLocked.displayWidth - y; + y = temp; break; case DISPLAY_ORIENTATION_180: - absoluteX = mLocked.displayWidth - mLocked.pointerX; - absoluteY = mLocked.displayHeight - mLocked.pointerY; + x = mLocked.displayWidth - x; + y = mLocked.displayHeight - y; break; case DISPLAY_ORIENTATION_270: - absoluteX = mLocked.pointerY; - absoluteY = mLocked.displayHeight - mLocked.pointerX; - break; - default: - absoluteX = mLocked.pointerX; - absoluteY = mLocked.pointerY; + temp = x; + x = y; + y = mLocked.displayHeight - temp; break; } - // Map from absolute display coordinates to oriented display coordinates. + // Perform the new rotation. switch (orientation) { case DISPLAY_ORIENTATION_90: - mLocked.pointerX = absoluteY; - mLocked.pointerY = mLocked.displayWidth - absoluteX; + temp = x; + x = y; + y = mLocked.displayWidth - x; break; case DISPLAY_ORIENTATION_180: - mLocked.pointerX = mLocked.displayWidth - absoluteX; - mLocked.pointerY = mLocked.displayHeight - absoluteY; + x = mLocked.displayWidth - x; + y = mLocked.displayHeight - y; break; case DISPLAY_ORIENTATION_270: - mLocked.pointerX = mLocked.displayHeight - absoluteY; - mLocked.pointerY = absoluteX; - break; - default: - mLocked.pointerX = absoluteX; - mLocked.pointerY = absoluteY; + temp = x; + x = mLocked.displayHeight - y; + y = temp; break; } + // Apply offsets to convert from the pixel center to the pixel top-left corner position + // and save the results. + mLocked.pointerX = x - 0.5f; + mLocked.pointerY = y - 0.5f; mLocked.displayOrientation = orientation; updateLocked(); diff --git a/services/input/PointerController.h b/services/input/PointerController.h index e28dd7d..e1dab5c 100644 --- a/services/input/PointerController.h +++ b/services/input/PointerController.h @@ -31,10 +31,6 @@ namespace android { -enum { - POINTER_BUTTON_1 = 1 << 0, -}; - /** * Interface for tracking a single (mouse) pointer. * diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 8404b3a..67a2e21 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -405,7 +405,8 @@ class FakeEventHub : public EventHubInterface { String8 name; uint32_t classes; PropertyMap configuration; - KeyedVector<int, RawAbsoluteAxisInfo> axes; + KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes; + KeyedVector<int, bool> relativeAxes; KeyedVector<int32_t, int32_t> keyCodeStates; KeyedVector<int32_t, int32_t> scanCodeStates; KeyedVector<int32_t, int32_t> switchStates; @@ -460,7 +461,7 @@ public: device->configuration.addAll(configuration); } - void addAxis(int32_t deviceId, int axis, + void addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, int32_t maxValue, int flat, int fuzz) { Device* device = getDevice(deviceId); @@ -470,7 +471,12 @@ public: info.maxValue = maxValue; info.flat = flat; info.fuzz = fuzz; - device->axes.add(axis, info); + device->absoluteAxes.add(axis, info); + } + + void addRelativeAxis(int32_t deviceId, int32_t axis) { + Device* device = getDevice(deviceId); + device->relativeAxes.add(axis, true); } void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) { @@ -560,9 +566,9 @@ private: RawAbsoluteAxisInfo* outAxisInfo) const { Device* device = getDevice(deviceId); if (device) { - ssize_t index = device->axes.indexOfKey(axis); + ssize_t index = device->absoluteAxes.indexOfKey(axis); if (index >= 0) { - *outAxisInfo = device->axes.valueAt(index); + *outAxisInfo = device->absoluteAxes.valueAt(index); return OK; } } @@ -570,6 +576,10 @@ private: } virtual bool hasRelativeAxis(int32_t deviceId, int axis) const { + Device* device = getDevice(deviceId); + if (device) { + return device->relativeAxes.indexOfKey(axis) >= 0; + } return false; } @@ -592,7 +602,7 @@ private: } virtual status_t mapAxis(int32_t deviceId, int scancode, - int32_t* outAxis) const { + AxisInfo* outAxisInfo) const { return NAME_NOT_FOUND; } @@ -1487,13 +1497,15 @@ protected: } static void assertMotionRange(const InputDeviceInfo& info, - int32_t rangeType, float min, float max, float flat, float fuzz) { - const InputDeviceInfo::MotionRange* range = info.getMotionRange(rangeType); - ASSERT_TRUE(range != NULL) << "Range: " << rangeType; - ASSERT_NEAR(min, range->min, EPSILON) << "Range: " << rangeType; - ASSERT_NEAR(max, range->max, EPSILON) << "Range: " << rangeType; - ASSERT_NEAR(flat, range->flat, EPSILON) << "Range: " << rangeType; - ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Range: " << rangeType; + int32_t axis, uint32_t source, float min, float max, float flat, float fuzz) { + const InputDeviceInfo::MotionRange* range = info.getMotionRange(axis, source); + ASSERT_TRUE(range != NULL) << "Axis: " << axis << " Source: " << source; + ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source; + ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(max, range->max, EPSILON) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(flat, range->flat, EPSILON) << "Axis: " << axis << " Source: " << source; + ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Axis: " << axis << " Source: " << source; } static void assertPointerCoords(const PointerCoords& coords, @@ -2001,22 +2013,25 @@ TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeF mapper->populateDeviceInfo(&info); // Initially there may not be a valid motion range. - ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X)); - ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE, - 0.0f, 1.0f, 0.0f, 0.0f)); + ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE)); + ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE)); + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f)); // When the bounds are set, then there should be a valid motion range. - mFakePointerController->setBounds(1, 2, 800, 480); + mFakePointerController->setBounds(1, 2, 800 - 1, 480 - 1); InputDeviceInfo info2; mapper->populateDeviceInfo(&info2); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_X, - 1, 800, 0.0f, 0.0f)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_Y, - 2, 480, 0.0f, 0.0f)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_PRESSURE, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, + AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE, + 1, 800 - 1, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, + AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE, + 2, 480 - 1, 0.0f, 0.0f)); + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, + AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f)); } @@ -2028,11 +2043,14 @@ TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsSca InputDeviceInfo info; mapper->populateDeviceInfo(&info); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_TRACKBALL, -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_TRACKBALL, -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD)); - ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE, + ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, + AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TRACKBALL, 0.0f, 1.0f, 0.0f, 0.0f)); } @@ -2320,9 +2338,9 @@ protected: }; const int32_t TouchInputMapperTest::RAW_X_MIN = 25; -const int32_t TouchInputMapperTest::RAW_X_MAX = 1020; +const int32_t TouchInputMapperTest::RAW_X_MAX = 1019; const int32_t TouchInputMapperTest::RAW_Y_MIN = 30; -const int32_t TouchInputMapperTest::RAW_Y_MAX = 1010; +const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009; const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0; const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31; const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0; @@ -2333,8 +2351,8 @@ const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7; const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7; const int32_t TouchInputMapperTest::RAW_ID_MIN = 0; const int32_t TouchInputMapperTest::RAW_ID_MAX = 9; -const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH; -const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT; +const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH; +const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT; const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = { { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 }, @@ -2353,19 +2371,19 @@ void TouchInputMapperTest::prepareVirtualKeys() { } int32_t TouchInputMapperTest::toRawX(float displayX) { - return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH + RAW_X_MIN); + return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN); } int32_t TouchInputMapperTest::toRawY(float displayY) { - return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT + RAW_Y_MIN); + return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN); } float TouchInputMapperTest::toDisplayX(int32_t rawX) { - return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN); + return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN + 1); } float TouchInputMapperTest::toDisplayY(int32_t rawY) { - return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN); + return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN + 1); } @@ -2385,14 +2403,18 @@ protected: void SingleTouchInputMapperTest::prepareAxes(int axes) { if (axes & POSITION) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0); - mFakeEventHub->addAxis(DEVICE_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X, + RAW_X_MIN, RAW_X_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_Y, + RAW_Y_MIN, RAW_Y_MAX, 0, 0); } if (axes & PRESSURE) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_PRESSURE, + RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0); } if (axes & TOOL) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TOOL_WIDTH, + RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); } } @@ -2950,12 +2972,12 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) // Rotation 90. prepareDisplay(DISPLAY_ORIENTATION_90); - processDown(mapper, toRawX(50), toRawY(75)); + processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50)); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); - ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); + ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); + ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); @@ -2963,12 +2985,12 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) // Rotation 180. prepareDisplay(DISPLAY_ORIENTATION_180); - processDown(mapper, toRawX(50), toRawY(75)); + processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); - ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); + ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); + ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); @@ -2976,12 +2998,12 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) // Rotation 270. prepareDisplay(DISPLAY_ORIENTATION_270); - processDown(mapper, toRawX(50), toRawY(75)); + processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); - ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); + ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1); + ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1); processUp(mapper); processSync(mapper); @@ -3040,33 +3062,37 @@ protected: void MultiTouchInputMapperTest::prepareAxes(int axes) { if (axes & POSITION) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0); - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_X, + RAW_X_MIN, RAW_X_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_Y, + RAW_Y_MIN, RAW_Y_MAX, 0, 0); } if (axes & TOUCH) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, + RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0); if (axes & MINOR) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0); } } if (axes & TOOL) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, + RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0); if (axes & MINOR) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0); } } if (axes & ORIENTATION) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_ORIENTATION, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0); } if (axes & PRESSURE) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_PRESSURE, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0); } if (axes & ID) { - mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TRACKING_ID, + mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0, 0); } } @@ -3601,8 +3627,8 @@ TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) float y = toDisplayY(rawY); float pressure = float(rawTouchMajor) / RAW_TOUCH_MAX; float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX; - float scale = avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN), - float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN)); + float scale = avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1), + float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1)); float toolMajor = float(rawToolMajor) * scale; float toolMinor = float(rawToolMinor) * scale; float touchMajor = min(float(rawTouchMajor) * scale, toolMajor); diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index adc49ae..3c6c427 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -62,6 +62,7 @@ import android.util.Slog; import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicBoolean; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -99,9 +100,6 @@ public class WifiService extends IWifiManager.Stub { /* Chipset supports background scan */ private final boolean mBackgroundScanSupported; - // true if the user enabled Wifi while in airplane mode - private AtomicBoolean mAirplaneModeOverwridden = new AtomicBoolean(false); - private final LockList mLocks = new LockList(); // some wifi lock statistics private int mFullHighPerfLocksAcquired; @@ -144,6 +142,14 @@ public class WifiService extends IWifiManager.Stub { private static final String ACTION_DEVICE_IDLE = "com.android.server.WifiManager.action.DEVICE_IDLE"; + private static final int WIFI_DISABLED = 0; + private static final int WIFI_ENABLED = 1; + /* Wifi enabled while in airplane mode */ + private static final int WIFI_ENABLED_AIRPLANE_OVERRIDE = 2; + + private AtomicInteger mWifiState = new AtomicInteger(WIFI_DISABLED); + private AtomicBoolean mAirplaneModeOn = new AtomicBoolean(false); + private boolean mIsReceiverRegistered = false; @@ -338,11 +344,11 @@ public class WifiService extends IWifiManager.Stub { new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // clear our flag indicating the user has overwridden airplane mode - mAirplaneModeOverwridden.set(false); - // on airplane disable, restore Wifi if the saved state indicates so - if (!isAirplaneModeOn() && testAndClearWifiSavedState()) { - persistWifiEnabled(true); + mAirplaneModeOn.set(isAirplaneModeOn()); + /* On airplane mode disable, restore wifi state if necessary */ + if (!mAirplaneModeOn.get() && (testAndClearWifiSavedState() || + mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE)) { + persistWifiEnabled(true); } updateWifiState(); } @@ -402,9 +408,10 @@ public class WifiService extends IWifiManager.Stub { * This function is used only at boot time */ public void checkAndStartWifi() { - /* Start if Wi-Fi is enabled or the saved state indicates Wi-Fi was on */ - boolean wifiEnabled = !isAirplaneModeOn() - && (getPersistedWifiEnabled() || testAndClearWifiSavedState()); + mAirplaneModeOn.set(isAirplaneModeOn()); + mWifiState.set(getPersistedWifiState()); + /* Start if Wi-Fi should be enabled or the saved state indicates Wi-Fi was on */ + boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState(); Slog.i(TAG, "WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled")); setWifiEnabled(wifiEnabled); @@ -423,21 +430,39 @@ public class WifiService extends IWifiManager.Stub { return (wifiSavedState == 1); } - private boolean getPersistedWifiEnabled() { + private int getPersistedWifiState() { final ContentResolver cr = mContext.getContentResolver(); try { - return Settings.Secure.getInt(cr, Settings.Secure.WIFI_ON) == 1; + return Settings.Secure.getInt(cr, Settings.Secure.WIFI_ON); } catch (Settings.SettingNotFoundException e) { - Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, 0); - return false; + Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, WIFI_DISABLED); + return WIFI_DISABLED; + } + } + + private boolean shouldWifiBeEnabled() { + if (mAirplaneModeOn.get()) { + return mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE; + } else { + return mWifiState.get() != WIFI_DISABLED; } } private void persistWifiEnabled(boolean enabled) { final ContentResolver cr = mContext.getContentResolver(); - Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, enabled ? 1 : 0); + if (enabled) { + if (isAirplaneModeOn() && isAirplaneToggleable()) { + mWifiState.set(WIFI_ENABLED_AIRPLANE_OVERRIDE); + } else { + mWifiState.set(WIFI_ENABLED); + } + } else { + mWifiState.set(WIFI_DISABLED); + } + Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, mWifiState.get()); } + /** * see {@link android.net.wifi.WifiManager#pingSupplicant()} * @return {@code true} if the operation succeeds, {@code false} otherwise @@ -490,11 +515,6 @@ public class WifiService extends IWifiManager.Stub { Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n"); } - // set a flag if the user is enabling Wifi while in airplane mode - if (enable && isAirplaneModeOn() && isAirplaneToggleable()) { - mAirplaneModeOverwridden.set(true); - } - if (enable) { reportStartWorkSource(); } @@ -1037,11 +1057,8 @@ public class WifiService extends IWifiManager.Stub { } private void updateWifiState() { - boolean wifiEnabled = getPersistedWifiEnabled(); - boolean airplaneMode = isAirplaneModeOn() && !mAirplaneModeOverwridden.get(); boolean lockHeld = mLocks.hasLocks(); int strongestLockMode = WifiManager.WIFI_MODE_FULL; - boolean wifiShouldBeEnabled = wifiEnabled && !airplaneMode; boolean wifiShouldBeStarted = !mDeviceIdle || lockHeld; if (lockHeld) { @@ -1053,11 +1070,11 @@ public class WifiService extends IWifiManager.Stub { } /* Disable tethering when airplane mode is enabled */ - if (airplaneMode) { + if (mAirplaneModeOn.get()) { mWifiStateMachine.setWifiApEnabled(null, false); } - if (wifiShouldBeEnabled) { + if (shouldWifiBeEnabled()) { if (wifiShouldBeStarted) { reportStartWorkSource(); mWifiStateMachine.setWifiEnabled(true); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 0fab964..267c76a 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3151,6 +3151,9 @@ public final class ActivityManagerService extends ActivityManagerNative try { pm.setPackageStoppedState(packageName, true); } catch (RemoteException e) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + packageName + ": " + e); } } } finally { @@ -5559,6 +5562,9 @@ public final class ActivityManagerService extends ActivityManagerNative AppGlobals.getPackageManager().setPackageStoppedState( cpr.appInfo.packageName, false); } catch (RemoteException e) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + cpr.appInfo.packageName + ": " + e); } ProcessRecord proc = startProcessLocked(cpi.processName, @@ -5840,6 +5846,9 @@ public final class ActivityManagerService extends ActivityManagerNative AppGlobals.getPackageManager().setPackageStoppedState( info.packageName, false); } catch (RemoteException e) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + info.packageName + ": " + e); } if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) @@ -6673,8 +6682,10 @@ public final class ActivityManagerService extends ActivityManagerNative mProcessCrashTimes.remove(app.info.processName, app.info.uid); app.removed = true; removeProcessLocked(app, false); + mMainStack.resumeTopActivityLocked(null); return false; } + mMainStack.resumeTopActivityLocked(null); } else { ActivityRecord r = mMainStack.topRunningActivityLocked(null); if (r.app == app) { @@ -6780,7 +6791,7 @@ public final class ActivityManagerService extends ActivityManagerNative * @param crashInfo describing the exception */ public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) { - ProcessRecord r = findAppProcess(app); + ProcessRecord r = findAppProcess(app, "Crash"); EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(), app == null ? "system" : (r == null ? "unknown" : r.processName), @@ -6799,7 +6810,10 @@ public final class ActivityManagerService extends ActivityManagerNative IBinder app, int violationMask, StrictMode.ViolationInfo info) { - ProcessRecord r = findAppProcess(app); + ProcessRecord r = findAppProcess(app, "StrictMode"); + if (r == null) { + return; + } if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) { Integer stackFingerprint = info.hashCode(); @@ -6973,7 +6987,7 @@ public final class ActivityManagerService extends ActivityManagerNative */ public boolean handleApplicationWtf(IBinder app, String tag, ApplicationErrorReport.CrashInfo crashInfo) { - ProcessRecord r = findAppProcess(app); + ProcessRecord r = findAppProcess(app, "WTF"); EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(), app == null ? "system" : (r == null ? "unknown" : r.processName), @@ -6995,7 +7009,7 @@ public final class ActivityManagerService extends ActivityManagerNative * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit}) * @return the corresponding {@link ProcessRecord} object, or null if none could be found */ - private ProcessRecord findAppProcess(IBinder app) { + private ProcessRecord findAppProcess(IBinder app, String reason) { if (app == null) { return null; } @@ -7011,7 +7025,9 @@ public final class ActivityManagerService extends ActivityManagerNative } } - Slog.w(TAG, "Can't find mystery application: " + app); + Slog.w(TAG, "Can't find mystery application for " + reason + + " from pid=" + Binder.getCallingPid() + + " uid=" + Binder.getCallingUid() + ": " + app); return null; } } @@ -9396,6 +9412,9 @@ public final class ActivityManagerService extends ActivityManagerNative AppGlobals.getPackageManager().setPackageStoppedState( r.packageName, false); } catch (RemoteException e) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + r.packageName + ": " + e); } final String appName = r.processName; @@ -10297,6 +10316,9 @@ public final class ActivityManagerService extends ActivityManagerNative AppGlobals.getPackageManager().setPackageStoppedState( app.packageName, false); } catch (RemoteException e) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + app.packageName + ": " + e); } BackupRecord r = new BackupRecord(ss, app, backupMode); @@ -11625,6 +11647,9 @@ public final class ActivityManagerService extends ActivityManagerNative AppGlobals.getPackageManager().setPackageStoppedState( r.curComponent.getPackageName(), false); } catch (RemoteException e) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + r.curComponent.getPackageName() + ": " + e); } // Is this receiver's application already running? diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 3a613bb..c087aec 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1299,6 +1299,9 @@ public class ActivityStack { AppGlobals.getPackageManager().setPackageStoppedState( next.packageName, false); } catch (RemoteException e1) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + next.packageName + ": " + e); } // We are starting up the next activity, so tell the window manager diff --git a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java index 2f22fe1..c40ce76 100644 --- a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java +++ b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java @@ -16,11 +16,14 @@ package com.android.server.usb; +import android.app.PendingIntent; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; @@ -33,7 +36,7 @@ import android.os.Binder; import android.os.FileUtils; import android.os.Process; import android.util.Log; -import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.Xml; import com.android.internal.content.PackageMonitor; @@ -62,17 +65,18 @@ class UsbDeviceSettingsManager { private static final File sSettingsFile = new File("/data/system/usb_device_manager.xml"); private final Context mContext; - - // maps UID to user approved USB devices - private final SparseArray<ArrayList<DeviceFilter>> mDevicePermissionMap = - new SparseArray<ArrayList<DeviceFilter>>(); - // maps UID to user approved USB accessories - private final SparseArray<ArrayList<AccessoryFilter>> mAccessoryPermissionMap = - new SparseArray<ArrayList<AccessoryFilter>>(); + private final PackageManager mPackageManager; + + // Temporary mapping USB device name to list of UIDs with permissions for the device + private final HashMap<String, SparseBooleanArray> mDevicePermissionMap = + new HashMap<String, SparseBooleanArray>(); + // Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory + private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap = + new HashMap<UsbAccessory, SparseBooleanArray>(); // Maps DeviceFilter to user preferred application package private final HashMap<DeviceFilter, String> mDevicePreferenceMap = new HashMap<DeviceFilter, String>(); - // Maps DeviceFilter to user preferred application package + // Maps AccessoryFilter to user preferred application package private final HashMap<AccessoryFilter, String> mAccessoryPreferenceMap = new HashMap<AccessoryFilter, String>(); @@ -185,6 +189,14 @@ class UsbDeviceSettingsManager { return false; } + public boolean matches(DeviceFilter f) { + if (mVendorId != -1 && f.mVendorId != mVendorId) return false; + if (mProductId != -1 && f.mProductId != mProductId) return false; + + // check device class/subclass/protocol + return matches(f.mClass, f.mSubclass, f.mProtocol); + } + @Override public boolean equals(Object obj) { // can't compare if we have wildcard strings @@ -234,22 +246,18 @@ class UsbDeviceSettingsManager { public final String mManufacturer; // USB accessory model (or null for unspecified) public final String mModel; - // USB accessory type (or null for unspecified) - public final String mType; // USB accessory version (or null for unspecified) public final String mVersion; - public AccessoryFilter(String manufacturer, String model, String type, String version) { + public AccessoryFilter(String manufacturer, String model, String version) { mManufacturer = manufacturer; mModel = model; - mType = type; mVersion = version; } public AccessoryFilter(UsbAccessory accessory) { mManufacturer = accessory.getManufacturer(); mModel = accessory.getModel(); - mType = accessory.getType(); mVersion = accessory.getVersion(); } @@ -257,7 +265,6 @@ class UsbDeviceSettingsManager { throws XmlPullParserException, IOException { String manufacturer = null; String model = null; - String type = null; String version = null; int count = parser.getAttributeCount(); @@ -269,13 +276,11 @@ class UsbDeviceSettingsManager { manufacturer = value; } else if ("model".equals(name)) { model = value; - } else if ("type".equals(name)) { - type = value; } else if ("version".equals(name)) { version = value; } } - return new AccessoryFilter(manufacturer, model, type, version); + return new AccessoryFilter(manufacturer, model, version); } public void write(XmlSerializer serializer)throws IOException { @@ -286,9 +291,6 @@ class UsbDeviceSettingsManager { if (mModel != null) { serializer.attribute(null, "model", mModel); } - if (mType != null) { - serializer.attribute(null, "type", mType); - } if (mVersion != null) { serializer.attribute(null, "version", mVersion); } @@ -298,29 +300,33 @@ class UsbDeviceSettingsManager { public boolean matches(UsbAccessory acc) { if (mManufacturer != null && !acc.getManufacturer().equals(mManufacturer)) return false; if (mModel != null && !acc.getModel().equals(mModel)) return false; - if (mType != null && !acc.getType().equals(mType)) return false; if (mVersion != null && !acc.getVersion().equals(mVersion)) return false; return true; } + public boolean matches(AccessoryFilter f) { + if (mManufacturer != null && !f.mManufacturer.equals(mManufacturer)) return false; + if (mModel != null && !f.mModel.equals(mModel)) return false; + if (mVersion != null && !f.mVersion.equals(mVersion)) return false; + return true; + } + @Override public boolean equals(Object obj) { // can't compare if we have wildcard strings - if (mManufacturer == null || mModel == null || mType == null || mVersion == null) { + if (mManufacturer == null || mModel == null || mVersion == null) { return false; } if (obj instanceof AccessoryFilter) { AccessoryFilter filter = (AccessoryFilter)obj; return (mManufacturer.equals(filter.mManufacturer) && mModel.equals(filter.mModel) && - mType.equals(filter.mType) && mVersion.equals(filter.mVersion)); } if (obj instanceof UsbAccessory) { UsbAccessory accessory = (UsbAccessory)obj; return (mManufacturer.equals(accessory.getManufacturer()) && mModel.equals(accessory.getModel()) && - mType.equals(accessory.getType()) && mVersion.equals(accessory.getVersion())); } return false; @@ -330,7 +336,6 @@ class UsbDeviceSettingsManager { public int hashCode() { return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^ (mModel == null ? 0 : mModel.hashCode()) ^ - (mType == null ? 0 : mType.hashCode()) ^ (mVersion == null ? 0 : mVersion.hashCode())); } @@ -338,78 +343,35 @@ class UsbDeviceSettingsManager { public String toString() { return "AccessoryFilter[mManufacturer=\"" + mManufacturer + "\", mModel=\"" + mModel + - "\", mType=\"" + mType + "\", mVersion=\"" + mVersion + "\"]"; } } private class MyPackageMonitor extends PackageMonitor { - public void onPackageRemoved(String packageName, int uid) { - synchronized (mLock) { - // clear all activity preferences for the package - if (clearPackageDefaultsLocked(packageName)) { - writeSettingsLocked(); - } - } + + public void onPackageAdded(String packageName, int uid) { + handlePackageUpdate(packageName); } - public void onUidRemoved(int uid) { - synchronized (mLock) { - // clear all permissions for the UID - if (clearUidDefaultsLocked(uid)) { - writeSettingsLocked(); - } - } + public void onPackageChanged(String packageName, int uid, String[] components) { + handlePackageUpdate(packageName); + } + + public void onPackageRemoved(String packageName, int uid) { + clearDefaults(packageName); } } MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); public UsbDeviceSettingsManager(Context context) { mContext = context; + mPackageManager = context.getPackageManager(); synchronized (mLock) { readSettingsLocked(); } mPackageMonitor.register(context, true); } - private void readDevicePermission(XmlPullParser parser) - throws XmlPullParserException, IOException { - int uid = -1; - ArrayList<DeviceFilter> filters = new ArrayList<DeviceFilter>(); - int count = parser.getAttributeCount(); - for (int i = 0; i < count; i++) { - if ("uid".equals(parser.getAttributeName(i))) { - uid = Integer.parseInt(parser.getAttributeValue(i)); - break; - } - } - XmlUtils.nextElement(parser); - while ("usb-device".equals(parser.getName())) { - filters.add(DeviceFilter.read(parser)); - XmlUtils.nextElement(parser); - } - mDevicePermissionMap.put(uid, filters); - } - - private void readAccessoryPermission(XmlPullParser parser) - throws XmlPullParserException, IOException { - int uid = -1; - ArrayList<AccessoryFilter> filters = new ArrayList<AccessoryFilter>(); - int count = parser.getAttributeCount(); - for (int i = 0; i < count; i++) { - if ("uid".equals(parser.getAttributeName(i))) { - uid = Integer.parseInt(parser.getAttributeValue(i)); - break; - } - } - XmlUtils.nextElement(parser); - while ("usb-accessory".equals(parser.getName())) { - filters.add(AccessoryFilter.read(parser)); - XmlUtils.nextElement(parser); - } - mAccessoryPermissionMap.put(uid, filters); - } - private void readPreference(XmlPullParser parser) throws XmlPullParserException, IOException { String packageName = null; @@ -441,11 +403,7 @@ class UsbDeviceSettingsManager { XmlUtils.nextElement(parser); while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { String tagName = parser.getName(); - if ("device-permission".equals(tagName)) { - readDevicePermission(parser); - } else if ("accessory-permission".equals(tagName)) { - readAccessoryPermission(parser); - } else if ("preference".equals(tagName)) { + if ("preference".equals(tagName)) { readPreference(parser); } else { XmlUtils.nextElement(parser); @@ -478,32 +436,6 @@ class UsbDeviceSettingsManager { serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startTag(null, "settings"); - int count = mDevicePermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mDevicePermissionMap.keyAt(i); - ArrayList<DeviceFilter> filters = mDevicePermissionMap.valueAt(i); - serializer.startTag(null, "device-permission"); - serializer.attribute(null, "uid", Integer.toString(uid)); - int filterCount = filters.size(); - for (int j = 0; j < filterCount; j++) { - filters.get(j).write(serializer); - } - serializer.endTag(null, "device-permission"); - } - - count = mAccessoryPermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mAccessoryPermissionMap.keyAt(i); - ArrayList<AccessoryFilter> filters = mAccessoryPermissionMap.valueAt(i); - serializer.startTag(null, "accessory-permission"); - serializer.attribute(null, "uid", Integer.toString(uid)); - int filterCount = filters.size(); - for (int j = 0; j < filterCount; j++) { - filters.get(j).write(serializer); - } - serializer.endTag(null, "accessory-permission"); - } - for (DeviceFilter filter : mDevicePreferenceMap.keySet()) { serializer.startTag(null, "preference"); serializer.attribute(null, "package", mDevicePreferenceMap.get(filter)); @@ -535,11 +467,10 @@ class UsbDeviceSettingsManager { private boolean packageMatchesLocked(ResolveInfo info, String metaDataName, UsbDevice device, UsbAccessory accessory) { ActivityInfo ai = info.activityInfo; - PackageManager pm = mContext.getPackageManager(); XmlResourceParser parser = null; try { - parser = ai.loadXmlMetaData(pm, metaDataName); + parser = ai.loadXmlMetaData(mPackageManager, metaDataName); if (parser == null) { Log.w(TAG, "no meta-data for " + info); return false; @@ -572,8 +503,7 @@ class UsbDeviceSettingsManager { private final ArrayList<ResolveInfo> getDeviceMatchesLocked(UsbDevice device, Intent intent) { ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>(); - PackageManager pm = mContext.getPackageManager(); - List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, + List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(intent, PackageManager.GET_META_DATA); int count = resolveInfos.size(); for (int i = 0; i < count; i++) { @@ -588,8 +518,7 @@ class UsbDeviceSettingsManager { private final ArrayList<ResolveInfo> getAccessoryMatchesLocked( UsbAccessory accessory, Intent intent) { ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>(); - PackageManager pm = mContext.getPackageManager(); - List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, + List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(intent, PackageManager.GET_META_DATA); int count = resolveInfos.size(); for (int i = 0; i < count; i++) { @@ -602,53 +531,26 @@ class UsbDeviceSettingsManager { } public void deviceAttached(UsbDevice device) { - Intent deviceIntent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); - deviceIntent.putExtra(UsbManager.EXTRA_DEVICE, device); - deviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); + intent.putExtra(UsbManager.EXTRA_DEVICE, device); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ArrayList<ResolveInfo> matches; String defaultPackage; synchronized (mLock) { - matches = getDeviceMatchesLocked(device, deviceIntent); + matches = getDeviceMatchesLocked(device, intent); // Launch our default activity directly, if we have one. // Otherwise we will start the UsbResolverActivity to allow the user to choose. defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device)); } - int count = matches.size(); - // don't show the resolver activity if there are no choices available - if (count == 0) return; - - if (defaultPackage != null) { - for (int i = 0; i < count; i++) { - ResolveInfo rInfo = matches.get(i); - if (rInfo.activityInfo != null && - defaultPackage.equals(rInfo.activityInfo.packageName)) { - try { - deviceIntent.setComponent(new ComponentName( - defaultPackage, rInfo.activityInfo.name)); - mContext.startActivity(deviceIntent); - } catch (ActivityNotFoundException e) { - Log.e(TAG, "startActivity failed", e); - } - return; - } - } - } - - Intent intent = new Intent(mContext, UsbResolverActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - intent.putExtra(Intent.EXTRA_INTENT, deviceIntent); - intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, matches); - try { - mContext.startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.w(TAG, "unable to start UsbResolverActivity"); - } + resolveActivity(intent, matches, defaultPackage, device, null); } public void deviceDetached(UsbDevice device) { + // clear temporary permissions for the device + mDevicePermissionMap.remove(device.getDeviceName()); + Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); intent.putExtra(UsbManager.EXTRA_DEVICE, device); Log.d(TAG, "usbDeviceRemoved, sending " + intent); @@ -656,93 +558,308 @@ class UsbDeviceSettingsManager { } public void accessoryAttached(UsbAccessory accessory) { - Intent accessoryIntent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); - accessoryIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - accessoryIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ArrayList<ResolveInfo> matches; String defaultPackage; synchronized (mLock) { - matches = getAccessoryMatchesLocked(accessory, accessoryIntent); + matches = getAccessoryMatchesLocked(accessory, intent); // Launch our default activity directly, if we have one. // Otherwise we will start the UsbResolverActivity to allow the user to choose. defaultPackage = mAccessoryPreferenceMap.get(new AccessoryFilter(accessory)); } + resolveActivity(intent, matches, defaultPackage, null, accessory); + } + + public void accessoryDetached(UsbAccessory accessory) { + // clear temporary permissions for the accessory + mAccessoryPermissionMap.remove(accessory); + + Intent intent = new Intent( + UsbManager.ACTION_USB_ACCESSORY_DETACHED); + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + mContext.sendBroadcast(intent); + } + + private void resolveActivity(Intent intent, ArrayList<ResolveInfo> matches, + String defaultPackage, UsbDevice device, UsbAccessory accessory) { int count = matches.size(); + // don't show the resolver activity if there are no choices available - if (count == 0) return; + if (count == 0) { + if (accessory != null) { + String uri = accessory.getUri(); + if (uri != null && uri.length() > 0) { + // display URI to user + // start UsbResolverActivity so user can choose an activity + Intent dialogIntent = new Intent(); + dialogIntent.setClassName("com.android.systemui", + "com.android.systemui.usb.UsbAccessoryUriActivity"); + dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + dialogIntent.putExtra("uri", uri); + try { + mContext.startActivity(dialogIntent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "unable to start UsbAccessoryUriActivity"); + } + } + } + + // do nothing + return; + } + + ResolveInfo defaultRI = null; + if (count == 1 && defaultPackage == null) { + // Check to see if our single choice is on the system partition. + // If so, treat it as our default without calling UsbResolverActivity + ResolveInfo rInfo = matches.get(0); + if (rInfo.activityInfo != null && + rInfo.activityInfo.applicationInfo != null && + (rInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + defaultRI = rInfo; + } + } - if (defaultPackage != null) { + if (defaultRI == null && defaultPackage != null) { + // look for default activity for (int i = 0; i < count; i++) { ResolveInfo rInfo = matches.get(i); if (rInfo.activityInfo != null && defaultPackage.equals(rInfo.activityInfo.packageName)) { - try { - accessoryIntent.setComponent(new ComponentName( - defaultPackage, rInfo.activityInfo.name)); - mContext.startActivity(accessoryIntent); - } catch (ActivityNotFoundException e) { - Log.e(TAG, "startActivity failed", e); - } - return; + defaultRI = rInfo; + break; } } } - Intent intent = new Intent(mContext, UsbResolverActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (defaultRI != null) { + // grant permission for default activity + if (device != null) { + grantDevicePermission(device, defaultRI.activityInfo.applicationInfo.uid); + } else if (accessory != null) { + grantAccessoryPermission(accessory, defaultRI.activityInfo.applicationInfo.uid); + } - intent.putExtra(Intent.EXTRA_INTENT, accessoryIntent); - intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, matches); - try { - mContext.startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.w(TAG, "unable to start UsbResolverActivity"); + // start default activity directly + try { + intent.setComponent( + new ComponentName(defaultRI.activityInfo.packageName, + defaultRI.activityInfo.name)); + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "startActivity failed", e); + } + } else { + // start UsbResolverActivity so user can choose an activity + Intent resolverIntent = new Intent(); + resolverIntent.setClassName("com.android.systemui", + "com.android.systemui.usb.UsbResolverActivity"); + resolverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + resolverIntent.putExtra(Intent.EXTRA_INTENT, intent); + resolverIntent.putParcelableArrayListExtra("rlist", matches); + try { + mContext.startActivity(resolverIntent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "unable to start UsbResolverActivity"); + } } } - public void accessoryDetached(UsbAccessory accessory) { - Intent intent = new Intent( - UsbManager.ACTION_USB_ACCESSORY_DETACHED); - intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - mContext.sendBroadcast(intent); + private boolean clearCompatibleMatchesLocked(String packageName, DeviceFilter filter) { + boolean changed = false; + for (DeviceFilter test : mDevicePreferenceMap.keySet()) { + if (filter.matches(test)) { + mDevicePreferenceMap.remove(test); + changed = true; + } + } + return changed; } - public void checkPermission(UsbDevice device) { - if (device == null) return; - synchronized (mLock) { - ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(Binder.getCallingUid()); - if (filterList != null) { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - DeviceFilter filter = filterList.get(i); - if (filter.equals(device)) { - // permission allowed - return; + private boolean clearCompatibleMatchesLocked(String packageName, AccessoryFilter filter) { + boolean changed = false; + for (AccessoryFilter test : mAccessoryPreferenceMap.keySet()) { + if (filter.matches(test)) { + mAccessoryPreferenceMap.remove(test); + changed = true; + } + } + return changed; + } + + private boolean handlePackageUpdateLocked(String packageName, ActivityInfo aInfo, + String metaDataName) { + XmlResourceParser parser = null; + boolean changed = false; + + try { + parser = aInfo.loadXmlMetaData(mPackageManager, metaDataName); + if (parser == null) return false; + + XmlUtils.nextElement(parser); + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + String tagName = parser.getName(); + if ("usb-device".equals(tagName)) { + DeviceFilter filter = DeviceFilter.read(parser); + if (clearCompatibleMatchesLocked(packageName, filter)) { + changed = true; } } + else if ("usb-accessory".equals(tagName)) { + AccessoryFilter filter = AccessoryFilter.read(parser); + if (clearCompatibleMatchesLocked(packageName, filter)) { + changed = true; + } + } + XmlUtils.nextElement(parser); } + } catch (Exception e) { + Log.w(TAG, "Unable to load component info " + aInfo.toString(), e); + } finally { + if (parser != null) parser.close(); } - throw new SecurityException("User has not given permission to device " + device); + return changed; } - public void checkPermission(UsbAccessory accessory) { - if (accessory == null) return; + // Check to see if the package supports any USB devices or accessories. + // If so, clear any non-matching preferences for matching devices/accessories. + private void handlePackageUpdate(String packageName) { synchronized (mLock) { - ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(Binder.getCallingUid()); - if (filterList != null) { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - AccessoryFilter filter = filterList.get(i); - if (filter.equals(accessory)) { - // permission allowed - return; - } + PackageInfo info; + boolean changed = false; + + try { + info = mPackageManager.getPackageInfo(packageName, + PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA); + } catch (NameNotFoundException e) { + Log.e(TAG, "handlePackageUpdate could not find package " + packageName, e); + return; + } + + ActivityInfo[] activities = info.activities; + if (activities == null) return; + for (int i = 0; i < activities.length; i++) { + // check for meta-data, both for devices and accessories + if (handlePackageUpdateLocked(packageName, activities[i], + UsbManager.ACTION_USB_DEVICE_ATTACHED)) { + changed = true; } + if (handlePackageUpdateLocked(packageName, activities[i], + UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) { + changed = true; + } + } + + if (changed) { + writeSettingsLocked(); } } - throw new SecurityException("User has not given permission to accessory " + accessory); + } + + public boolean hasPermission(UsbDevice device) { + synchronized (mLock) { + SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName()); + if (uidList == null) { + return false; + } + return uidList.get(Binder.getCallingUid()); + } + } + + public boolean hasPermission(UsbAccessory accessory) { + synchronized (mLock) { + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + if (uidList == null) { + return false; + } + return uidList.get(Binder.getCallingUid()); + } + } + + public void checkPermission(UsbDevice device) { + if (!hasPermission(device)) { + throw new SecurityException("User has not given permission to device " + device); + } + } + + public void checkPermission(UsbAccessory accessory) { + if (!hasPermission(accessory)) { + throw new SecurityException("User has not given permission to accessory " + accessory); + } + } + + private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) { + int uid = Binder.getCallingUid(); + + // compare uid with packageName to foil apps pretending to be someone else + try { + ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0); + if (aInfo.uid != uid) { + throw new IllegalArgumentException("package " + packageName + + " does not match caller's uid " + uid); + } + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalArgumentException("package " + packageName + " not found"); + } + + long identity = Binder.clearCallingIdentity(); + intent.setClassName("com.android.systemui", + "com.android.systemui.usb.UsbPermissionActivity"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Intent.EXTRA_INTENT, pi); + intent.putExtra("package", packageName); + intent.putExtra("uid", uid); + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "unable to start UsbPermissionActivity"); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + public void requestPermission(UsbDevice device, String packageName, PendingIntent pi) { + Intent intent = new Intent(); + + // respond immediately if permission has already been granted + if (hasPermission(device)) { + intent.putExtra(UsbManager.EXTRA_DEVICE, device); + intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); + try { + pi.send(mContext, 0, intent); + } catch (PendingIntent.CanceledException e) { + Log.w(TAG, "requestPermission PendingIntent was cancelled"); + } + return; + } + + // start UsbPermissionActivity so user can choose an activity + intent.putExtra(UsbManager.EXTRA_DEVICE, device); + requestPermissionDialog(intent, packageName, pi); + } + + public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) { + Intent intent = new Intent(); + + // respond immediately if permission has already been granted + if (hasPermission(accessory)) { + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); + try { + pi.send(mContext, 0, intent); + } catch (PendingIntent.CanceledException e) { + Log.w(TAG, "requestPermission PendingIntent was cancelled"); + } + return; + } + + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + requestPermissionDialog(intent, packageName, pi); } public void setDevicePackage(UsbDevice device, String packageName) { @@ -783,73 +900,43 @@ class UsbDeviceSettingsManager { public void grantDevicePermission(UsbDevice device, int uid) { synchronized (mLock) { - ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(uid); - if (filterList == null) { - filterList = new ArrayList<DeviceFilter>(); - mDevicePermissionMap.put(uid, filterList); - } else { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - if (filterList.get(i).equals(device)) return; - } + String deviceName = device.getDeviceName(); + SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); + if (uidList == null) { + uidList = new SparseBooleanArray(1); + mDevicePermissionMap.put(deviceName, uidList); } - filterList.add(new DeviceFilter(device)); - writeSettingsLocked(); + uidList.put(uid, true); } } public void grantAccessoryPermission(UsbAccessory accessory, int uid) { synchronized (mLock) { - ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(uid); - if (filterList == null) { - filterList = new ArrayList<AccessoryFilter>(); - mAccessoryPermissionMap.put(uid, filterList); - } else { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - if (filterList.get(i).equals(accessory)) return; - } + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + if (uidList == null) { + uidList = new SparseBooleanArray(1); + mAccessoryPermissionMap.put(accessory, uidList); } - filterList.add(new AccessoryFilter(accessory)); - writeSettingsLocked(); + uidList.put(uid, true); } } - public boolean hasDefaults(String packageName, int uid) { + public boolean hasDefaults(String packageName) { synchronized (mLock) { - if (mDevicePermissionMap.get(uid) != null) return true; - if (mAccessoryPermissionMap.get(uid) != null) return true; if (mDevicePreferenceMap.values().contains(packageName)) return true; if (mAccessoryPreferenceMap.values().contains(packageName)) return true; return false; } } - public void clearDefaults(String packageName, int uid) { + public void clearDefaults(String packageName) { synchronized (mLock) { - boolean packageCleared = clearPackageDefaultsLocked(packageName); - boolean uidCleared = clearUidDefaultsLocked(uid); - if (packageCleared || uidCleared) { + if (clearPackageDefaultsLocked(packageName)) { writeSettingsLocked(); } } } - private boolean clearUidDefaultsLocked(int uid) { - boolean cleared = false; - int index = mDevicePermissionMap.indexOfKey(uid); - if (index >= 0) { - mDevicePermissionMap.removeAt(index); - cleared = true; - } - index = mAccessoryPermissionMap.indexOfKey(uid); - if (index >= 0) { - mAccessoryPermissionMap.removeAt(index); - cleared = true; - } - return cleared; - } - private boolean clearPackageDefaultsLocked(String packageName) { boolean cleared = false; synchronized (mLock) { @@ -882,24 +969,24 @@ class UsbDeviceSettingsManager { public void dump(FileDescriptor fd, PrintWriter pw) { synchronized (mLock) { pw.println(" Device permissions:"); - int count = mDevicePermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mDevicePermissionMap.keyAt(i); - pw.println(" " + "uid " + uid + ":"); - ArrayList<DeviceFilter> filters = mDevicePermissionMap.valueAt(i); - for (DeviceFilter filter : filters) { - pw.println(" " + filter); + for (String deviceName : mDevicePermissionMap.keySet()) { + pw.print(" " + deviceName + ": "); + SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); + int count = uidList.size(); + for (int i = 0; i < count; i++) { + pw.print(Integer.toString(uidList.keyAt(i)) + " "); } + pw.println(""); } pw.println(" Accessory permissions:"); - count = mAccessoryPermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mAccessoryPermissionMap.keyAt(i); - pw.println(" " + "uid " + uid + ":"); - ArrayList<AccessoryFilter> filters = mAccessoryPermissionMap.valueAt(i); - for (AccessoryFilter filter : filters) { - pw.println(" " + filter); + for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) { + pw.print(" " + accessory + ": "); + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + int count = uidList.size(); + for (int i = 0; i < count; i++) { + pw.print(Integer.toString(uidList.keyAt(i)) + " "); } + pw.println(""); } pw.println(" Device preferences:"); for (DeviceFilter filter : mDevicePreferenceMap.keySet()) { diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java index 8170c61..8b419f3 100644 --- a/services/java/com/android/server/usb/UsbService.java +++ b/services/java/com/android/server/usb/UsbService.java @@ -16,6 +16,7 @@ package com.android.server.usb; +import android.app.PendingIntent; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -422,10 +423,7 @@ public class UsbService extends IUsbManager.Stub { /* returns the currently attached USB accessory (device mode) */ public UsbAccessory getCurrentAccessory() { - synchronized (mLock) { - mDeviceManager.checkPermission(mCurrentAccessory); - return mCurrentAccessory; - } + return mCurrentAccessory; } /* opens the currently attached USB accessory (device mode) */ @@ -454,6 +452,24 @@ public class UsbService extends IUsbManager.Stub { mDeviceManager.setAccessoryPackage(accessory, packageName); } + public boolean hasDevicePermission(UsbDevice device) { + return mDeviceManager.hasPermission(device); + } + + public boolean hasAccessoryPermission(UsbAccessory accessory) { + return mDeviceManager.hasPermission(accessory); + } + + public void requestDevicePermission(UsbDevice device, String packageName, + PendingIntent pi) { + mDeviceManager.requestPermission(device, packageName, pi); + } + + public void requestAccessoryPermission(UsbAccessory accessory, String packageName, + PendingIntent pi) { + mDeviceManager.requestPermission(accessory, packageName, pi); + } + public void grantDevicePermission(UsbDevice device, int uid) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); mDeviceManager.grantDevicePermission(device, uid); @@ -464,14 +480,14 @@ public class UsbService extends IUsbManager.Stub { mDeviceManager.grantAccessoryPermission(accessory, uid); } - public boolean hasDefaults(String packageName, int uid) { + public boolean hasDefaults(String packageName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); - return mDeviceManager.hasDefaults(packageName, uid); + return mDeviceManager.hasDefaults(packageName); } - public void clearDefaults(String packageName, int uid) { + public void clearDefaults(String packageName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); - mDeviceManager.clearDefaults(packageName, uid); + mDeviceManager.clearDefaults(packageName); } /* diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index eed41a0..33e6a36 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -4727,7 +4727,15 @@ public class WindowManagerService extends IWindowManager.Stub SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); } - public Bitmap screenshotApplications(IBinder appToken, int maxWidth, int maxHeight) { + /** + * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. + * In portrait mode, it grabs the upper region of the screen based on the vertical dimension + * of the target image. + * + * @param width the width of the target bitmap + * @param height the height of the target bitmap + */ + public Bitmap screenshotApplications(IBinder appToken, int width, int height) { if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, "screenshotApplications()")) { throw new SecurityException("Requires READ_FRAME_BUFFER permission"); @@ -4739,7 +4747,7 @@ public class WindowManagerService extends IWindowManager.Stub final Rect frame = new Rect(); float scale; - int sw, sh, dw, dh; + int dw, dh; int rot; synchronized(mWindowMap) { @@ -4791,19 +4799,23 @@ public class WindowManagerService extends IWindowManager.Stub if (maxLayer < ws.mAnimLayer) { maxLayer = ws.mAnimLayer; } - final Rect wf = ws.mFrame; - final Rect cr = ws.mContentInsets; - int left = wf.left + cr.left; - int top = wf.top + cr.top; - int right = wf.right - cr.right; - int bottom = wf.bottom - cr.bottom; - frame.union(left, top, right, bottom); + + // Don't include wallpaper in bounds calculation + if (!ws.mIsWallpaper) { + final Rect wf = ws.mFrame; + final Rect cr = ws.mContentInsets; + int left = wf.left + cr.left; + int top = wf.top + cr.top; + int right = wf.right - cr.right; + int bottom = wf.bottom - cr.bottom; + frame.union(left, top, right, bottom); + } } Binder.restoreCallingIdentity(ident); // Constrain frame to the screen size. frame.intersect(0, 0, dw, dh); - + if (frame.isEmpty() || maxLayer == 0) { return null; } @@ -4814,15 +4826,7 @@ public class WindowManagerService extends IWindowManager.Stub int fh = frame.height(); // First try reducing to fit in x dimension. - scale = maxWidth/(float)fw; - sw = maxWidth; - sh = (int)(fh*scale); - if (sh > maxHeight) { - // y dimension became too long; constrain by that. - scale = maxHeight/(float)fh; - sw = (int)(fw*scale); - sh = maxHeight; - } + scale = width/(float)fw; // The screen shot will contain the entire screen. dw = (int)(dw*scale); @@ -4841,8 +4845,8 @@ public class WindowManagerService extends IWindowManager.Stub + ") to layer " + maxLayer); return null; } - - Bitmap bm = Bitmap.createBitmap(sw, sh, rawss.getConfig()); + + Bitmap bm = Bitmap.createBitmap(width, height, rawss.getConfig()); Matrix matrix = new Matrix(); ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); matrix.postTranslate(-(int)(frame.left*scale), -(int)(frame.top*scale)); @@ -5460,8 +5464,9 @@ public class WindowManagerService extends IWindowManager.Stub shortSize = (int)(shortSize/dm.density); // These semi-magic numbers define our compatibility modes for - // applications with different screens. Don't change unless you - // make sure to test lots and lots of apps! + // applications with different screens. These are guarantees to + // app developers about the space they can expect for a particular + // configuration. DO NOT CHANGE! if (longSize < 470) { // This is shorter than an HVGA normal density screen (which // is 480 pixels on its long side). @@ -5469,12 +5474,12 @@ public class WindowManagerService extends IWindowManager.Stub | Configuration.SCREENLAYOUT_LONG_NO; } else { // What size is this screen screen? - if (longSize >= 800 && shortSize >= 600) { - // SVGA or larger screens at medium density are the point + if (longSize >= 960 && shortSize >= 720) { + // 1.5xVGA or larger screens at medium density are the point // at which we consider it to be an extra large screen. mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE; - } else if (longSize >= 530 && shortSize >= 400) { - // SVGA or larger screens at high density are the point + } else if (longSize >= 640 && shortSize >= 480) { + // VGA or larger screens at medium density are the point // at which we consider it to be a large screen. mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE; } else { diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 3be3b1b..80dddc2 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -727,14 +727,14 @@ void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, }; if (wmActions & WM_ACTION_GO_TO_SLEEP) { -#ifdef DEBUG_INPUT_DISPATCHER_POLICY +#if DEBUG_INPUT_DISPATCHER_POLICY LOGD("handleInterceptActions: Going to sleep."); #endif android_server_PowerManagerService_goToSleep(when); } if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) { -#ifdef DEBUG_INPUT_DISPATCHER_POLICY +#if DEBUG_INPUT_DISPATCHER_POLICY LOGD("handleInterceptActions: Poking user activity."); #endif android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT); @@ -743,7 +743,7 @@ void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, if (wmActions & WM_ACTION_PASS_TO_USER) { policyFlags |= POLICY_FLAG_PASS_TO_USER; } else { -#ifdef DEBUG_INPUT_DISPATCHER_POLICY +#if DEBUG_INPUT_DISPATCHER_POLICY LOGD("handleInterceptActions: Not passing key to user."); #endif } @@ -1103,12 +1103,11 @@ static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env, env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources()); env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType()); - const KeyedVector<int, InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); + const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); for (size_t i = 0; i < ranges.size(); i++) { - int rangeType = ranges.keyAt(i); - const InputDeviceInfo::MotionRange& range = ranges.valueAt(i); + const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); env->CallVoidMethod(deviceObj, gInputDeviceClassInfo.addMotionRange, - rangeType, range.min, range.max, range.flat, range.fuzz); + range.axis, range.source, range.min, range.max, range.flat, range.fuzz); if (env->ExceptionCheck()) { return NULL; } @@ -1321,7 +1320,7 @@ int register_android_server_InputManager(JNIEnv* env) { "<init>", "()V"); GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz, - "addMotionRange", "(IFFFF)V"); + "addMotionRange", "(IIFFFF)V"); GET_FIELD_ID(gInputDeviceClassInfo.mId, gInputDeviceClassInfo.clazz, "mId", "I"); diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp index 3c49e54..c66f181 100644 --- a/services/jni/com_android_server_UsbService.cpp +++ b/services/jni/com_android_server_UsbService.cpp @@ -193,12 +193,13 @@ static jobjectArray android_server_UsbService_getAccessoryStrings(JNIEnv *env, j return NULL; } jclass stringClass = env->FindClass("java/lang/String"); - jobjectArray strArray = env->NewObjectArray(4, stringClass, NULL); + jobjectArray strArray = env->NewObjectArray(5, stringClass, NULL); if (!strArray) goto out; set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0); set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1); - set_accessory_string(env, fd, ACCESSORY_GET_STRING_TYPE, strArray, 2); + set_accessory_string(env, fd, ACCESSORY_GET_STRING_DESCRIPTION, strArray, 2); set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3); + set_accessory_string(env, fd, ACCESSORY_GET_STRING_URI, strArray, 4); out: close(fd); diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 697e879..ce1ab3d 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -340,11 +340,14 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (rec->addConnection(connection)) { // this sensor is already activated, but we are adding a // connection that uses it. Immediately send down the last - // known value of the requested sensor. - sensors_event_t scratch; - sensors_event_t& event(mLastEventSeen.editValueFor(handle)); - if (event.version == sizeof(sensors_event_t)) { - connection->sendEvents(&event, 1); + // known value of the requested sensor if it's not a + // "continuous" sensor. + if (sensor->getSensor().getMinDelay() == 0) { + sensors_event_t scratch; + sensors_event_t& event(mLastEventSeen.editValueFor(handle)); + if (event.version == sizeof(sensors_event_t)) { + connection->sendEvents(&event, 1); + } } } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 57af001..1297363 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -57,7 +57,6 @@ Layer::Layer(SurfaceFlinger* flinger, mNeedsDithering(false), mSecure(false), mProtectedByApp(false), - mProtectedByDRM(false), mTextureManager(), mBufferManager(mTextureManager), mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false) @@ -191,7 +190,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false; - mProtectedByDRM = (flags & ISurfaceComposer::eProtectedByDRM) ? true : false; mNeedsBlending = (info.h_alpha - info.l_alpha) > 0 && (flags & ISurfaceComposer::eOpaque) == 0; @@ -392,6 +390,12 @@ bool Layer::needsFiltering() const return LayerBase::needsFiltering(); } +bool Layer::isProtected() const +{ + sp<GraphicBuffer> activeBuffer(mBufferManager.getActiveBuffer()); + return (activeBuffer != 0) && + (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); +} status_t Layer::setBufferCount(int bufferCount) { @@ -515,7 +519,7 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const // request EGLImage for all buffers usage |= GraphicBuffer::USAGE_HW_TEXTURE; } - if (mProtectedByApp || mProtectedByDRM) { + if (mProtectedByApp) { // need a hardware-protected path to external video sink usage |= GraphicBuffer::USAGE_PROTECTED; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index bccc900..128f93d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -80,8 +80,7 @@ public: virtual bool needsDithering() const { return mNeedsDithering; } virtual bool needsFiltering() const; virtual bool isSecure() const { return mSecure; } - virtual bool isProtectedByApp() const { return mProtectedByApp; } - virtual bool isProtectedByDRM() const { return mProtectedByDRM; } + virtual bool isProtected() const; virtual sp<Surface> createSurface() const; virtual status_t ditch(); virtual void onRemoved(); @@ -222,7 +221,6 @@ private: // page-flip thread (currently main thread) bool mSecure; // no screenshots bool mProtectedByApp; // application requires protected path to external sink - bool mProtectedByDRM; // DRM agent requires protected path to external sink Region mPostedDirtyRegion; // page-flip thread and transaction thread (currently main thread) diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index bfe92e6..7162e47 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -197,16 +197,10 @@ public: virtual bool isSecure() const { return false; } /** - * isProtectedByApp - true if application says this surface is protected, that - * is if it requires a hardware-protected data path to an external sink. + * isProtected - true if the layer may contain protected content in the + * GRALLOC_USAGE_PROTECTED sense. */ - virtual bool isProtectedByApp() const { return false; } - - /** - * isProtectedByDRM - true if DRM agent says this surface is protected, that - * is if it requires a hardware-protected data path to an external sink. - */ - virtual bool isProtectedByDRM() const { return false; } + virtual bool isProtected() const { return false; } /** Called from the main thread, when the surface is removed from the * draw list */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 554fa43..a9fa1ef 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -327,6 +327,40 @@ void SurfaceFlinger::signal() const { const_cast<SurfaceFlinger*>(this)->signalEvent(); } +bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const { + Mutex::Autolock _l(mStateLock); + sp<IBinder> surfBinder(surface->asBinder()); + + // Check the visible layer list for the ISurface + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + size_t count = currentLayers.size(); + for (size_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(currentLayers[i]); + sp<LayerBaseClient> lbc(layer->getLayerBaseClient()); + if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) { + return true; + } + } + + // Check the layers in the purgatory. This check is here so that if a + // Surface gets destroyed before all the clients are done using it, the + // error will not be reported as "surface XYZ is not authenticated", but + // will instead fail later on when the client tries to use the surface, + // which should be reported as "surface XYZ returned an -ENODEV". The + // purgatorized layers are no less authentic than the visible ones, so this + // should not cause any harm. + size_t purgatorySize = mLayerPurgatory.size(); + for (size_t i=0 ; i<purgatorySize ; i++) { + const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i)); + sp<LayerBaseClient> lbc(layer->getLayerBaseClient()); + if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) { + return true; + } + } + + return false; +} + status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime, uint32_t flags) { @@ -2135,6 +2169,19 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) return BAD_VALUE; + // make sure none of the layers are protected + const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); + const size_t count = layers.size(); + for (size_t i=0 ; i<count ; ++i) { + const sp<LayerBase>& layer(layers[i]); + const uint32_t z = layer->drawingState().z; + if (z >= minLayerZ && z <= maxLayerZ) { + if (layer->isProtected()) { + return INVALID_OPERATION; + } + } + } + if (!GLExtensions::getInstance().haveFramebufferObject()) return INVALID_OPERATION; @@ -2183,8 +2230,6 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); - const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); - const size_t count = layers.size(); for (size_t i=0 ; i<count ; ++i) { const sp<LayerBase>& layer(layers[i]); const uint32_t z = layer->drawingState().z; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6dd91ac..9566819 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -209,6 +209,7 @@ public: virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); virtual void signal() const; + virtual bool authenticateSurface(const sp<ISurface>& surface) const; virtual status_t captureScreen(DisplayID dpy, sp<IMemoryHeap>* heap, diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java index e7f431c..3c8432e 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java @@ -58,10 +58,12 @@ public class TextActivity extends Activity { mScaledPaint = new Paint(); mScaledPaint.setAntiAlias(true); mScaledPaint.setTextSize(16.0f); + mScaledPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff00ff00); mSkewPaint = new Paint(); mSkewPaint.setAntiAlias(true); - mSkewPaint.setTextSize(16.0f); + mSkewPaint.setTextSize(16.0f); + mSkewPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff000000); } @Override @@ -106,11 +108,11 @@ public class TextActivity extends Activity { mStrikePaint.setUnderlineText(true); mSkewPaint.setTextSkewX(-0.25f); - canvas.drawText("Hello OpenGL renderer!", 680, 200, mSkewPaint); + canvas.drawText("Hello OpenGL renderer!", 980, 200, mSkewPaint); mSkewPaint.setTextSkewX(0.5f); - canvas.drawText("Hello OpenGL renderer!", 680, 230, mSkewPaint); + canvas.drawText("Hello OpenGL renderer!", 980, 230, mSkewPaint); mSkewPaint.setTextSkewX(0.0f); - canvas.drawText("Hello OpenGL renderer!", 680, 260, mSkewPaint); + canvas.drawText("Hello OpenGL renderer!", 980, 260, mSkewPaint); mScaledPaint.setTextScaleX(0.5f); canvas.drawText("Hello OpenGL renderer!", 500, 200, mScaledPaint); @@ -125,4 +127,4 @@ public class TextActivity extends Activity { canvas.restore(); } } -}
\ No newline at end of file +} diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java index 6c9f48f..db14e53 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java @@ -28,10 +28,12 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; /** * Delegate implementing the native methods of android.graphics.Path @@ -331,58 +333,91 @@ public final class Path_Delegate { @LayoutlibDelegate /*package*/ static void native_addOval(int nPath, RectF oval, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addOval is not supported.", null, null /*data*/); + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + pathDelegate.mPath.append(new Ellipse2D.Float( + oval.left, oval.top, oval.width(), oval.height()), false); } @LayoutlibDelegate /*package*/ static void native_addCircle(int nPath, float x, float y, float radius, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addCircle is not supported.", null, null /*data*/); + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + // because x/y is the center of the circle, need to offset this by the radius + pathDelegate.mPath.append(new Ellipse2D.Float( + x - radius, y - radius, radius * 2, radius * 2), false); } @LayoutlibDelegate /*package*/ static void native_addArc(int nPath, RectF oval, float startAngle, float sweepAngle) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addArc is not supported.", null, null /*data*/); + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + // because x/y is the center of the circle, need to offset this by the radius + pathDelegate.mPath.append(new Arc2D.Float( + oval.left, oval.top, oval.width(), oval.height(), + startAngle, sweepAngle, Arc2D.OPEN), false); } @LayoutlibDelegate - /*package*/ static void native_addRoundRect(int nPath, RectF rect, - float rx, float ry, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addRoundRect is not supported.", null, null /*data*/); + /*package*/ static void native_addRoundRect( + int nPath, RectF rect, float rx, float ry, int dir) { + + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + pathDelegate.mPath.append(new RoundRectangle2D.Float( + rect.left, rect.top, rect.width(), rect.height(), rx * 2, ry * 2), false); } @LayoutlibDelegate - /*package*/ static void native_addRoundRect(int nPath, RectF r, float[] radii, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addRoundRect is not supported.", null, null /*data*/); + /*package*/ static void native_addRoundRect(int nPath, RectF rect, float[] radii, int dir) { + // Java2D doesn't support different rounded corners in each corner, so just use the + // first value. + native_addRoundRect(nPath, rect, radii[0], radii[1], dir); + + // there can be a case where this API is used but with similar values for all corners, so + // in that case we don't warn. + // we only care if 2 corners are different so just compare to the next one. + for (int i = 0 ; i < 3 ; i++) { + if (radii[i * 2] != radii[(i + 1) * 2] || radii[i * 2 + 1] != radii[(i + 1) * 2 + 1]) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "Different corner sizes are not supported in Path.addRoundRect.", + null, null /*data*/); + break; + } + } } @LayoutlibDelegate /*package*/ static void native_addPath(int nPath, int src, float dx, float dy) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addPath is not supported.", null, null /*data*/); + addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy)); } @LayoutlibDelegate /*package*/ static void native_addPath(int nPath, int src) { - native_addPath(nPath, src, 0, 0); + addPath(nPath, src, null /*transform*/); } @LayoutlibDelegate /*package*/ static void native_addPath(int nPath, int src, int matrix) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addPath is not supported.", null, null /*data*/); + Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); + if (matrixDelegate == null) { + return; + } + + addPath(nPath, src, matrixDelegate.getAffineTransform()); } @LayoutlibDelegate @@ -487,6 +522,26 @@ public final class Path_Delegate { return null; } + private static void addPath(int destPath, int srcPath, AffineTransform transform) { + Path_Delegate destPathDelegate = sManager.getDelegate(destPath); + if (destPathDelegate == null) { + return; + } + + Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath); + if (srcPathDelegate == null) { + return; + } + + if (transform != null) { + destPathDelegate.mPath.append( + srcPathDelegate.mPath.getPathIterator(transform), false); + } else { + destPathDelegate.mPath.append(srcPathDelegate.mPath, false); + } + } + + /** * Returns whether the path is empty. * @return true if the path is empty. 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 acc7379..e6e9647 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -192,7 +192,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge { Capability.UNBOUND_RENDERING, Capability.CUSTOM_BACKGROUND_COLOR, Capability.RENDER, - Capability.LAYOUT_ONLY, + //Capability.LAYOUT_ONLY, // disable to run on ADT 10.0 which doesn't include this. Capability.EMBEDDED_LAYOUT, Capability.VIEW_MANIPULATION, Capability.PLAY_ANIMATION, diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java index c1d7600..138a455 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java @@ -412,9 +412,7 @@ public final class BridgeTypedArray extends TypedArray { return LayoutParams.MATCH_PARENT; } else if (s.equals(BridgeConstants.WRAP_CONTENT)) { return LayoutParams.WRAP_CONTENT; - } - - if (RenderResources.REFERENCE_NULL.equals(s)) { + } else if (RenderResources.REFERENCE_NULL.equals(s)) { return defValue; } @@ -486,23 +484,32 @@ public final class BridgeTypedArray extends TypedArray { return LayoutParams.MATCH_PARENT; } else if (s.equals(BridgeConstants.WRAP_CONTENT)) { return LayoutParams.WRAP_CONTENT; - } - - if (RenderResources.REFERENCE_NULL.equals(s)) { + } else if (RenderResources.REFERENCE_NULL.equals(s)) { return defValue; } - // FIXME huh? + if (ResourceHelper.stringToFloat(s, mValue)) { + float f = mValue.getDimension(mBridgeResources.mMetrics); - float f = getDimension(index, defValue); - final int res = (int)(f+0.5f); - if (res != 0) return res; - if (f == 0) return 0; - if (f > 0) return 1; + if (f < 0) { + // negative values are not allowed in pixel dimensions + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Negative pixel dimension: " + s, + null, null /*data*/); + return defValue; + } - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Can't convert to dimension: " + Integer.toString(index), - null, null /*data*/); + if (f == 0) return 0; + if (f < 1) return 1; + + return (int)(f+0.5f); + } + + // looks like we were unable to resolve the dimension value + Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, + String.format( + "\"%1$s\" in attribute \"%2$s\" is not a valid format.", + s, mNames[index]), null /*data*/); return defValue; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java index 69f46e6..649160e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java @@ -377,7 +377,7 @@ public final class ResourceHelper { } // check the first character - if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.') { + if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.' && buf[0] != '-') { return false; } diff --git a/voip/java/android/net/rtp/AudioCodec.java b/voip/java/android/net/rtp/AudioCodec.java index 3877aeb..85255c8 100644 --- a/voip/java/android/net/rtp/AudioCodec.java +++ b/voip/java/android/net/rtp/AudioCodec.java @@ -33,7 +33,6 @@ import java.util.Arrays; * </pre> * * @see AudioStream - * @hide */ public class AudioCodec { /** diff --git a/voip/java/android/net/rtp/AudioGroup.java b/voip/java/android/net/rtp/AudioGroup.java index 20c8969..3e7ace8 100644 --- a/voip/java/android/net/rtp/AudioGroup.java +++ b/voip/java/android/net/rtp/AudioGroup.java @@ -59,7 +59,6 @@ import java.util.Map; * the AudioGroups is in use.</p> * * @see AudioStream - * @hide */ public class AudioGroup { /** diff --git a/voip/java/android/net/rtp/AudioStream.java b/voip/java/android/net/rtp/AudioStream.java index b45cc5e..d761214 100644 --- a/voip/java/android/net/rtp/AudioStream.java +++ b/voip/java/android/net/rtp/AudioStream.java @@ -41,7 +41,6 @@ import java.net.SocketException; * * @see RtpStream * @see AudioGroup - * @hide */ public class AudioStream extends RtpStream { private AudioCodec mCodec; diff --git a/voip/java/android/net/rtp/RtpStream.java b/voip/java/android/net/rtp/RtpStream.java index 87d8bc6..e94ac42 100644 --- a/voip/java/android/net/rtp/RtpStream.java +++ b/voip/java/android/net/rtp/RtpStream.java @@ -27,7 +27,6 @@ import java.net.SocketException; * * <p class="note">Using this class requires * {@link android.Manifest.permission#INTERNET} permission.</p> - * @hide */ public class RtpStream { /** |