summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/dhcp/DhcpAckPacket.java110
-rw-r--r--core/java/android/net/dhcp/DhcpDeclinePacket.java65
-rw-r--r--core/java/android/net/dhcp/DhcpDiscoverPacket.java71
-rw-r--r--core/java/android/net/dhcp/DhcpInformPacket.java76
-rw-r--r--core/java/android/net/dhcp/DhcpNakPacket.java72
-rw-r--r--core/java/android/net/dhcp/DhcpOfferPacket.java101
-rw-r--r--core/java/android/net/dhcp/DhcpPacket.java899
-rw-r--r--core/java/android/net/dhcp/DhcpRequestPacket.java86
-rw-r--r--core/java/android/net/dhcp/DhcpStateMachine.java75
-rw-r--r--core/java/android/os/Vibrator.java18
-rw-r--r--core/java/android/view/ViewRoot.java3
-rw-r--r--core/java/android/widget/Switch.java6
-rw-r--r--core/java/android/widget/TextView.java32
-rw-r--r--core/java/com/android/internal/view/menu/MenuPopupHelper.java4
-rw-r--r--core/res/res/drawable-hdpi/spinner_active_holo_dark.9.pngbin522 -> 383 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_active_holo_light.9.pngbin527 -> 383 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.pngbin508 -> 364 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.pngbin517 -> 364 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.pngbin502 -> 364 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.pngbin517 -> 364 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.pngbin634 -> 505 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.pngbin522 -> 509 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_default_holo_dark.9.pngbin513 -> 378 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_default_holo_light.9.pngbin528 -> 378 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.pngbin656 -> 530 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_active_holo_dark.9.pngbin463 -> 306 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_active_holo_light.9.pngbin468 -> 305 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.pngbin399 -> 290 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.pngbin403 -> 290 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.pngbin388 -> 287 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.pngbin401 -> 288 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.pngbin455 -> 402 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.pngbin402 -> 416 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_default_holo_dark.9.pngbin456 -> 302 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_default_holo_light.9.pngbin467 -> 301 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.pngbin519 -> 420 bytes
-rwxr-xr-xcore/res/res/values/attrs.xml10
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java21
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java86
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java52
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java17
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java52
44 files changed, 1742 insertions, 117 deletions
diff --git a/core/java/android/net/dhcp/DhcpAckPacket.java b/core/java/android/net/dhcp/DhcpAckPacket.java
new file mode 100644
index 000000000000..900a0e6987c5
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpAckPacket.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * This class implements the DHCP-ACK packet.
+ */
+class DhcpAckPacket extends DhcpPacket {
+
+ /**
+ * The address of the server which sent this packet.
+ */
+ private final InetAddress mSrcIp;
+
+ DhcpAckPacket(int transId, boolean broadcast, InetAddress serverAddress,
+ InetAddress clientIp, byte[] clientMac) {
+ super(transId, Inet4Address.ANY, clientIp, Inet4Address.ANY,
+ Inet4Address.ANY, clientMac, broadcast);
+ mBroadcast = broadcast;
+ mSrcIp = serverAddress;
+ }
+
+ public String toString() {
+ String s = super.toString();
+ String dnsServers = " DNS servers: ";
+
+ for (InetAddress dnsServer: mDnsServers) {
+ dnsServers += dnsServer.toString() + " ";
+ }
+
+ return s + " ACK: your new IP " + mYourIp +
+ ", netmask " + mSubnetMask +
+ ", gateway " + mGateway + dnsServers +
+ ", lease time " + mLeaseTime;
+ }
+
+ /**
+ * Fills in a packet with the requested ACK parameters.
+ */
+ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+ ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+ InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp;
+ InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp;
+
+ fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
+ DHCP_BOOTREPLY, mBroadcast);
+ result.flip();
+ return result;
+ }
+
+ /**
+ * Adds the optional parameters to the client-generated ACK packet.
+ */
+ void finishPacket(ByteBuffer buffer) {
+ addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_ACK);
+ addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+ addTlv(buffer, DHCP_LEASE_TIME, mLeaseTime);
+
+ // the client should renew at 1/2 the lease-expiry interval
+ if (mLeaseTime != null) {
+ addTlv(buffer, DHCP_RENEWAL_TIME,
+ Integer.valueOf(mLeaseTime.intValue() / 2));
+ }
+
+ addTlv(buffer, DHCP_SUBNET_MASK, mSubnetMask);
+ addTlv(buffer, DHCP_ROUTER, mGateway);
+ addTlv(buffer, DHCP_DOMAIN_NAME, mDomainName);
+ addTlv(buffer, DHCP_BROADCAST_ADDRESS, mBroadcastAddress);
+ addTlv(buffer, DHCP_DNS_SERVER, mDnsServers);
+ addTlvEnd(buffer);
+ }
+
+ /**
+ * Un-boxes an Integer, returning 0 if a null reference is supplied.
+ */
+ private static final int getInt(Integer v) {
+ if (v == null) {
+ return 0;
+ } else {
+ return v.intValue();
+ }
+ }
+
+ /**
+ * Notifies the specified state machine of the ACK packet parameters.
+ */
+ public void doNextOp(DhcpStateMachine machine) {
+ machine.onAckReceived(mYourIp, mSubnetMask, mGateway, mDnsServers,
+ mServerIdentifier, getInt(mLeaseTime));
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpDeclinePacket.java b/core/java/android/net/dhcp/DhcpDeclinePacket.java
new file mode 100644
index 000000000000..7646eb46999f
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpDeclinePacket.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+
+/**
+ * This class implements the DHCP-DECLINE packet.
+ */
+class DhcpDeclinePacket extends DhcpPacket {
+ /**
+ * Generates a DECLINE packet with the specified parameters.
+ */
+ DhcpDeclinePacket(int transId, InetAddress clientIp, InetAddress yourIp,
+ InetAddress nextIp, InetAddress relayIp,
+ byte[] clientMac) {
+ super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
+ }
+
+ public String toString() {
+ String s = super.toString();
+ return s + " DECLINE";
+ }
+
+ /**
+ * Fills in a packet with the requested DECLINE attributes.
+ */
+ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+ ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+
+ fillInPacket(encap, mClientIp, mYourIp, destUdp, srcUdp, result,
+ DHCP_BOOTREQUEST, false);
+ result.flip();
+ return result;
+ }
+
+ /**
+ * Adds optional parameters to the DECLINE packet.
+ */
+ void finishPacket(ByteBuffer buffer) {
+ // None needed
+ }
+
+ /**
+ * Informs the state machine of the arrival of a DECLINE packet.
+ */
+ public void doNextOp(DhcpStateMachine machine) {
+ machine.onDeclineReceived(mClientMac, mRequestedIp);
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpDiscoverPacket.java b/core/java/android/net/dhcp/DhcpDiscoverPacket.java
new file mode 100644
index 000000000000..0e2d39be7183
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpDiscoverPacket.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+
+/**
+ * This class implements the DHCP-DISCOVER packet.
+ */
+class DhcpDiscoverPacket extends DhcpPacket {
+ /**
+ * Generates a DISCOVER packet with the specified parameters.
+ */
+ DhcpDiscoverPacket(int transId, byte[] clientMac, boolean broadcast) {
+ super(transId, Inet4Address.ANY, Inet4Address.ANY, Inet4Address.ANY,
+ Inet4Address.ANY, clientMac, broadcast);
+ }
+
+ public String toString() {
+ String s = super.toString();
+ return s + " DISCOVER " +
+ (mBroadcast ? "broadcast " : "unicast ");
+ }
+
+ /**
+ * Fills in a packet with the requested DISCOVER parameters.
+ */
+ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+ ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+ InetAddress destIp = Inet4Address.ALL;
+
+ fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp,
+ result, DHCP_BOOTREQUEST, true);
+ result.flip();
+ return result;
+ }
+
+ /**
+ * Adds optional parameters to a DISCOVER packet.
+ */
+ void finishPacket(ByteBuffer buffer) {
+ addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_DISCOVER);
+ addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
+ addTlvEnd(buffer);
+ }
+
+ /**
+ * Informs the state machine of the arrival of a DISCOVER packet.
+ */
+ public void doNextOp(DhcpStateMachine machine) {
+ // currently omitted: host name
+ machine.onDiscoverReceived(mBroadcast, mTransId, mClientMac,
+ mRequestedParams);
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpInformPacket.java b/core/java/android/net/dhcp/DhcpInformPacket.java
new file mode 100644
index 000000000000..da73216caaa9
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpInformPacket.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+
+/**
+ * This class implements the (unused) DHCP-INFORM packet.
+ */
+class DhcpInformPacket extends DhcpPacket {
+ /**
+ * Generates an INFORM packet with the specified parameters.
+ */
+ DhcpInformPacket(int transId, InetAddress clientIp, InetAddress yourIp,
+ InetAddress nextIp, InetAddress relayIp,
+ byte[] clientMac) {
+ super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
+ }
+
+ public String toString() {
+ String s = super.toString();
+ return s + " INFORM";
+ }
+
+ /**
+ * Builds an INFORM packet.
+ */
+ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+ ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+
+ fillInPacket(encap, mClientIp, mYourIp, destUdp, srcUdp, result,
+ DHCP_BOOTREQUEST, false);
+ result.flip();
+ return result;
+ }
+
+ /**
+ * Adds additional parameters to the INFORM packet.
+ */
+ void finishPacket(ByteBuffer buffer) {
+ byte[] clientId = new byte[7];
+
+ clientId[0] = CLIENT_ID_ETHER;
+ System.arraycopy(mClientMac, 0, clientId, 1, 6);
+
+ addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_REQUEST);
+ addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
+ addTlvEnd(buffer);
+ }
+
+ /**
+ * Informs the state machine of the arrival of an INFORM packet. Not
+ * used currently.
+ */
+ public void doNextOp(DhcpStateMachine machine) {
+ InetAddress clientRequest =
+ mRequestedIp == null ? mClientIp : mRequestedIp;
+ machine.onInformReceived(mTransId, mClientMac, clientRequest,
+ mRequestedParams);
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpNakPacket.java b/core/java/android/net/dhcp/DhcpNakPacket.java
new file mode 100644
index 000000000000..1f340ad4f098
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpNakPacket.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+
+/**
+ * This class implements the DHCP-NAK packet.
+ */
+class DhcpNakPacket extends DhcpPacket {
+ /**
+ * Generates a NAK packet with the specified parameters.
+ */
+ DhcpNakPacket(int transId, InetAddress clientIp, InetAddress yourIp,
+ InetAddress nextIp, InetAddress relayIp,
+ byte[] clientMac) {
+ super(transId, Inet4Address.ANY, Inet4Address.ANY, nextIp, relayIp,
+ clientMac, false);
+ }
+
+ public String toString() {
+ String s = super.toString();
+ return s + " NAK, reason " + (mMessage == null ? "(none)" : mMessage);
+ }
+
+ /**
+ * Fills in a packet with the requested NAK attributes.
+ */
+ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+ ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+ InetAddress destIp = mClientIp;
+ InetAddress srcIp = mYourIp;
+
+ fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
+ DHCP_BOOTREPLY, mBroadcast);
+ result.flip();
+ return result;
+ }
+
+ /**
+ * Adds the optional parameters to the client-generated NAK packet.
+ */
+ void finishPacket(ByteBuffer buffer) {
+ addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_NAK);
+ addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+ addTlv(buffer, DHCP_MESSAGE, mMessage);
+ addTlvEnd(buffer);
+ }
+
+ /**
+ * Notifies the specified state machine of the newly-arrived NAK packet.
+ */
+ public void doNextOp(DhcpStateMachine machine) {
+ machine.onNakReceived();
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpOfferPacket.java b/core/java/android/net/dhcp/DhcpOfferPacket.java
new file mode 100644
index 000000000000..3d79f4dd774f
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpOfferPacket.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * This class implements the DHCP-OFFER packet.
+ */
+class DhcpOfferPacket extends DhcpPacket {
+ /**
+ * The IP address of the server which sent this packet.
+ */
+ private final InetAddress mSrcIp;
+
+ /**
+ * Generates a OFFER packet with the specified parameters.
+ */
+ DhcpOfferPacket(int transId, boolean broadcast, InetAddress serverAddress,
+ InetAddress clientIp, byte[] clientMac) {
+ super(transId, Inet4Address.ANY, clientIp, Inet4Address.ANY,
+ Inet4Address.ANY, clientMac, broadcast);
+ mSrcIp = serverAddress;
+ }
+
+ public String toString() {
+ String s = super.toString();
+ String dnsServers = ", DNS servers: ";
+
+ if (mDnsServers != null) {
+ for (InetAddress dnsServer: mDnsServers) {
+ dnsServers += dnsServer + " ";
+ }
+ }
+
+ return s + " OFFER, ip " + mYourIp + ", mask " + mSubnetMask +
+ dnsServers + ", gateway " + mGateway +
+ " lease time " + mLeaseTime + ", domain " + mDomainName;
+ }
+
+ /**
+ * Fills in a packet with the specified OFFER attributes.
+ */
+ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+ ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+ InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp;
+ InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp;
+
+ fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
+ DHCP_BOOTREPLY, mBroadcast);
+ result.flip();
+ return result;
+ }
+
+ /**
+ * Adds the optional parameters to the server-generated OFFER packet.
+ */
+ void finishPacket(ByteBuffer buffer) {
+ addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_OFFER);
+ addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+ addTlv(buffer, DHCP_LEASE_TIME, mLeaseTime);
+
+ // the client should renew at 1/2 the lease-expiry interval
+ if (mLeaseTime != null) {
+ addTlv(buffer, DHCP_RENEWAL_TIME,
+ Integer.valueOf(mLeaseTime.intValue() / 2));
+ }
+
+ addTlv(buffer, DHCP_SUBNET_MASK, mSubnetMask);
+ addTlv(buffer, DHCP_ROUTER, mGateway);
+ addTlv(buffer, DHCP_DOMAIN_NAME, mDomainName);
+ addTlv(buffer, DHCP_BROADCAST_ADDRESS, mBroadcastAddress);
+ addTlv(buffer, DHCP_DNS_SERVER, mDnsServers);
+ addTlvEnd(buffer);
+ }
+
+ /**
+ * Notifies the state machine of the OFFER packet parameters.
+ */
+ public void doNextOp(DhcpStateMachine machine) {
+ machine.onOfferReceived(mBroadcast, mTransId, mClientMac, mYourIp,
+ mServerIdentifier);
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpPacket.java b/core/java/android/net/dhcp/DhcpPacket.java
new file mode 100644
index 000000000000..e009f70c339a
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpPacket.java
@@ -0,0 +1,899 @@
+package android.net.dhcp;
+
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charsets;
+import java.nio.ShortBuffer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Defines basic data and operations needed to build and use packets for the
+ * DHCP protocol. Subclasses create the specific packets used at each
+ * stage of the negotiation.
+ */
+abstract class DhcpPacket {
+ protected static final String TAG = "DhcpPacket";
+
+ /**
+ * Packet encapsulations.
+ */
+ public static final int ENCAP_L2 = 0; // EthernetII header included
+ public static final int ENCAP_L3 = 1; // IP/UDP header included
+ public static final int ENCAP_BOOTP = 2; // BOOTP contents only
+
+ /**
+ * IP layer definitions.
+ */
+ private static final byte IP_TYPE_UDP = (byte) 0x11;
+
+ /**
+ * IP: Version 4, Header Length 20 bytes
+ */
+ private static final byte IP_VERSION_HEADER_LEN = (byte) 0x45;
+
+ /**
+ * IP: Flags 0, Fragment Offset 0, Don't Fragment
+ */
+ private static final short IP_FLAGS_OFFSET = (short) 0x4000;
+
+ /**
+ * IP: TOS
+ */
+ private static final byte IP_TOS_LOWDELAY = (byte) 0x10;
+
+ /**
+ * IP: TTL -- use default 64 from RFC1340
+ */
+ private static final byte IP_TTL = (byte) 0x40;
+
+ /**
+ * The client DHCP port.
+ */
+ static final short DHCP_CLIENT = (short) 68;
+
+ /**
+ * The server DHCP port.
+ */
+ static final short DHCP_SERVER = (short) 67;
+
+ /**
+ * The message op code indicating a request from a client.
+ */
+ protected static final byte DHCP_BOOTREQUEST = (byte) 1;
+
+ /**
+ * The message op code indicating a response from the server.
+ */
+ protected static final byte DHCP_BOOTREPLY = (byte) 2;
+
+ /**
+ * The code type used to identify an Ethernet MAC address in the
+ * Client-ID field.
+ */
+ protected static final byte CLIENT_ID_ETHER = (byte) 1;
+
+ /**
+ * The maximum length of a packet that can be constructed.
+ */
+ protected static final int MAX_LENGTH = 1500;
+
+ /**
+ * DHCP Optional Type: DHCP Subnet Mask
+ */
+ protected static final byte DHCP_SUBNET_MASK = 1;
+ protected InetAddress mSubnetMask;
+
+ /**
+ * DHCP Optional Type: DHCP Router
+ */
+ protected static final byte DHCP_ROUTER = 3;
+ protected InetAddress mGateway;
+
+ /**
+ * DHCP Optional Type: DHCP DNS Server
+ */
+ protected static final byte DHCP_DNS_SERVER = 6;
+ protected List<InetAddress> mDnsServers;
+
+ /**
+ * DHCP Optional Type: DHCP Host Name
+ */
+ protected static final byte DHCP_HOST_NAME = 12;
+ protected String mHostName;
+
+ /**
+ * DHCP Optional Type: DHCP DOMAIN NAME
+ */
+ protected static final byte DHCP_DOMAIN_NAME = 15;
+ protected String mDomainName;
+
+ /**
+ * DHCP Optional Type: DHCP BROADCAST ADDRESS
+ */
+ protected static final byte DHCP_BROADCAST_ADDRESS = 28;
+ protected InetAddress mBroadcastAddress;
+
+ /**
+ * DHCP Optional Type: DHCP Requested IP Address
+ */
+ protected static final byte DHCP_REQUESTED_IP = 50;
+ protected InetAddress mRequestedIp;
+
+ /**
+ * DHCP Optional Type: DHCP Lease Time
+ */
+ protected static final byte DHCP_LEASE_TIME = 51;
+ protected Integer mLeaseTime;
+
+ /**
+ * DHCP Optional Type: DHCP Message Type
+ */
+ protected static final byte DHCP_MESSAGE_TYPE = 53;
+ // the actual type values
+ protected static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1;
+ protected static final byte DHCP_MESSAGE_TYPE_OFFER = 2;
+ protected static final byte DHCP_MESSAGE_TYPE_REQUEST = 3;
+ protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4;
+ protected static final byte DHCP_MESSAGE_TYPE_ACK = 5;
+ protected static final byte DHCP_MESSAGE_TYPE_NAK = 6;
+ protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8;
+
+ /**
+ * DHCP Optional Type: DHCP Server Identifier
+ */
+ protected static final byte DHCP_SERVER_IDENTIFIER = 54;
+ protected InetAddress mServerIdentifier;
+
+ /**
+ * DHCP Optional Type: DHCP Parameter List
+ */
+ protected static final byte DHCP_PARAMETER_LIST = 55;
+ protected byte[] mRequestedParams;
+
+ /**
+ * DHCP Optional Type: DHCP MESSAGE
+ */
+ protected static final byte DHCP_MESSAGE = 56;
+ protected String mMessage;
+
+ /**
+ * DHCP Optional Type: DHCP Renewal Time Value
+ */
+ protected static final byte DHCP_RENEWAL_TIME = 58;
+
+ /**
+ * DHCP Optional Type: Vendor Class Identifier
+ */
+ protected static final byte DHCP_VENDOR_CLASS_ID = 60;
+
+ /**
+ * DHCP Optional Type: DHCP Client Identifier
+ */
+ protected static final byte DHCP_CLIENT_IDENTIFIER = 61;
+
+ /**
+ * The transaction identifier used in this particular DHCP negotiation
+ */
+ protected final int mTransId;
+
+ /**
+ * The IP address of the client host. This address is typically
+ * proposed by the client (from an earlier DHCP negotiation) or
+ * supplied by the server.
+ */
+ protected final InetAddress mClientIp;
+ protected final InetAddress mYourIp;
+ private final InetAddress mNextIp;
+ private final InetAddress mRelayIp;
+
+ /**
+ * Does the client request a broadcast response?
+ */
+ protected boolean mBroadcast;
+
+ /**
+ * The six-octet MAC of the client.
+ */
+ protected final byte[] mClientMac;
+
+ /**
+ * Asks the packet object to signal the next operation in the DHCP
+ * protocol. The available actions are methods defined in the
+ * DhcpStateMachine interface.
+ */
+ public abstract void doNextOp(DhcpStateMachine stateMachine);
+
+ /**
+ * Asks the packet object to create a ByteBuffer serialization of
+ * the packet for transmission.
+ */
+ public abstract ByteBuffer buildPacket(int encap, short destUdp,
+ short srcUdp);
+
+ /**
+ * Allows the concrete class to fill in packet-type-specific details,
+ * typically optional parameters at the end of the packet.
+ */
+ abstract void finishPacket(ByteBuffer buffer);
+
+ protected DhcpPacket(int transId, InetAddress clientIp, InetAddress yourIp,
+ InetAddress nextIp, InetAddress relayIp,
+ byte[] clientMac, boolean broadcast) {
+ mTransId = transId;
+ mClientIp = clientIp;
+ mYourIp = yourIp;
+ mNextIp = nextIp;
+ mRelayIp = relayIp;
+ mClientMac = clientMac;
+ mBroadcast = broadcast;
+ }
+
+ /**
+ * Returns the transaction ID.
+ */
+ public int getTransactionId() {
+ return mTransId;
+ }
+
+ /**
+ * Creates a new L3 packet (including IP header) containing the
+ * DHCP udp packet. This method relies upon the delegated method
+ * finishPacket() to insert the per-packet contents.
+ */
+ protected void fillInPacket(int encap, InetAddress destIp,
+ InetAddress srcIp, short destUdp, short srcUdp, ByteBuffer buf,
+ byte requestCode, boolean broadcast) {
+ byte[] destIpArray = destIp.getAddress();
+ byte[] srcIpArray = srcIp.getAddress();
+ int ipLengthOffset = 0;
+ int ipChecksumOffset = 0;
+ int endIpHeader = 0;
+ int udpHeaderOffset = 0;
+ int udpLengthOffset = 0;
+ int udpChecksumOffset = 0;
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+
+ // if a full IP packet needs to be generated, put the IP & UDP
+ // headers in place, and pre-populate with artificial values
+ // needed to seed the IP checksum.
+ if (encap == ENCAP_L3) {
+ // fake IP header, used in the IP-header checksum
+ buf.put(IP_VERSION_HEADER_LEN);
+ buf.put(IP_TOS_LOWDELAY); // tos: IPTOS_LOWDELAY
+ ipLengthOffset = buf.position();
+ buf.putShort((short)0); // length
+ buf.putShort((short)0); // id
+ buf.putShort(IP_FLAGS_OFFSET); // ip offset: don't fragment
+ buf.put(IP_TTL); // TTL: use default 64 from RFC1340
+ buf.put(IP_TYPE_UDP);
+ ipChecksumOffset = buf.position();
+ buf.putShort((short) 0); // checksum
+
+ buf.put(srcIpArray);
+ buf.put(destIpArray);
+ endIpHeader = buf.position();
+
+ // UDP header
+ udpHeaderOffset = buf.position();
+ buf.putShort(srcUdp);
+ buf.putShort(destUdp);
+ udpLengthOffset = buf.position();
+ buf.putShort((short) 0); // length
+ udpChecksumOffset = buf.position();
+ buf.putShort((short) 0); // UDP checksum -- initially zero
+ }
+
+ // DHCP payload
+ buf.put(requestCode);
+ buf.put((byte) 1); // Hardware Type: Ethernet
+ buf.put((byte) mClientMac.length); // Hardware Address Length
+ buf.put((byte) 0); // Hop Count
+ buf.putInt(mTransId); // Transaction ID
+ buf.putShort((short) 0); // Elapsed Seconds
+
+ if (broadcast) {
+ buf.putShort((short) 0x8000); // Flags
+ } else {
+ buf.putShort((short) 0x0000); // Flags
+ }
+
+ buf.put(mClientIp.getAddress());
+ buf.put(mYourIp.getAddress());
+ buf.put(mNextIp.getAddress());
+ buf.put(mRelayIp.getAddress());
+ buf.put(mClientMac);
+ buf.position(buf.position() +
+ (16 - mClientMac.length) // pad addr to 16 bytes
+ + 64 // empty server host name (64 bytes)
+ + 128); // empty boot file name (128 bytes)
+ buf.putInt(0x63825363); // magic number
+ finishPacket(buf);
+
+ // round up to an even number of octets
+ if ((buf.position() & 1) == 1) {
+ buf.put((byte) 0);
+ }
+
+ // If an IP packet is being built, the IP & UDP checksums must be
+ // computed.
+ if (encap == ENCAP_L3) {
+ // fix UDP header: insert length
+ short udpLen = (short)(buf.position() - udpHeaderOffset);
+ buf.putShort(udpLengthOffset, udpLen);
+ // fix UDP header: checksum
+ // checksum for UDP at udpChecksumOffset
+ int udpSeed = 0;
+
+ // apply IPv4 pseudo-header. Read IP address src and destination
+ // values from the IP header and accumulate checksum.
+ udpSeed += intAbs(buf.getShort(ipChecksumOffset + 2));
+ udpSeed += intAbs(buf.getShort(ipChecksumOffset + 4));
+ udpSeed += intAbs(buf.getShort(ipChecksumOffset + 6));
+ udpSeed += intAbs(buf.getShort(ipChecksumOffset + 8));
+
+ // accumulate extra data for the pseudo-header
+ udpSeed += IP_TYPE_UDP;
+ udpSeed += udpLen;
+ // and compute UDP checksum
+ buf.putShort(udpChecksumOffset, (short) checksum(buf, udpSeed,
+ udpHeaderOffset,
+ buf.position()));
+ // fix IP header: insert length
+ buf.putShort(ipLengthOffset, (short)buf.position());
+ // fixup IP-header checksum
+ buf.putShort(ipChecksumOffset,
+ (short) checksum(buf, 0, 0, endIpHeader));
+ }
+ }
+
+ /**
+ * Converts a signed short value to an unsigned int value. Needed
+ * because Java does not have unsigned types.
+ */
+ private int intAbs(short v) {
+ if (v < 0) {
+ int r = v + 65536;
+ return r;
+ } else {
+ return(v);
+ }
+ }
+
+ /**
+ * Performs an IP checksum (used in IP header and across UDP
+ * payload) on the specified portion of a ByteBuffer. The seed
+ * allows the checksum to commence with a specified value.
+ */
+ private int checksum(ByteBuffer buf, int seed, int start, int end) {
+ int sum = seed;
+ int bufPosition = buf.position();
+
+ // set position of original ByteBuffer, so that the ShortBuffer
+ // will be correctly initialized
+ buf.position(start);
+ ShortBuffer shortBuf = buf.asShortBuffer();
+
+ // re-set ByteBuffer position
+ buf.position(bufPosition);
+
+ short[] shortArray = new short[(end - start) / 2];
+ shortBuf.get(shortArray);
+
+ for (short s : shortArray) {
+ sum += intAbs(s);
+ }
+
+ start += shortArray.length * 2;
+
+ // see if a singleton byte remains
+ if (end != start) {
+ short b = buf.get(start);
+
+ // make it unsigned
+ if (b < 0) {
+ b += 256;
+ }
+
+ sum += b * 256;
+ }
+
+ sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF);
+ sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF);
+ int negated = ~sum;
+ return intAbs((short) negated);
+ }
+
+ /**
+ * Adds an optional parameter containing a single byte value.
+ */
+ protected void addTlv(ByteBuffer buf, byte type, byte value) {
+ buf.put(type);
+ buf.put((byte) 1);
+ buf.put(value);
+ }
+
+ /**
+ * Adds an optional parameter containing an array of bytes.
+ */
+ protected void addTlv(ByteBuffer buf, byte type, byte[] payload) {
+ if (payload != null) {
+ buf.put(type);
+ buf.put((byte) payload.length);
+ buf.put(payload);
+ }
+ }
+
+ /**
+ * Adds an optional parameter containing an IP address.
+ */
+ protected void addTlv(ByteBuffer buf, byte type, InetAddress addr) {
+ if (addr != null) {
+ addTlv(buf, type, addr.getAddress());
+ }
+ }
+
+ /**
+ * Adds an optional parameter containing a list of IP addresses.
+ */
+ protected void addTlv(ByteBuffer buf, byte type, List<InetAddress> addrs) {
+ if (addrs != null && addrs.size() > 0) {
+ buf.put(type);
+ buf.put((byte)(4 * addrs.size()));
+
+ for (InetAddress addr : addrs) {
+ buf.put(addr.getAddress());
+ }
+ }
+ }
+
+ /**
+ * Adds an optional parameter containing a simple integer
+ */
+ protected void addTlv(ByteBuffer buf, byte type, Integer value) {
+ if (value != null) {
+ buf.put(type);
+ buf.put((byte) 4);
+ buf.putInt(value.intValue());
+ }
+ }
+
+ /**
+ * Adds an optional parameter containing and ASCII string.
+ */
+ protected void addTlv(ByteBuffer buf, byte type, String str) {
+ if (str != null) {
+ buf.put(type);
+ buf.put((byte) str.length());
+
+ for (int i = 0; i < str.length(); i++) {
+ buf.put((byte) str.charAt(i));
+ }
+ }
+ }
+
+ /**
+ * Adds the special end-of-optional-parameters indicator.
+ */
+ protected void addTlvEnd(ByteBuffer buf) {
+ buf.put((byte) 0xFF);
+ }
+
+ /**
+ * Converts a MAC from an array of octets to an ASCII string.
+ */
+ public static String macToString(byte[] mac) {
+ String macAddr = "";
+
+ for (int i = 0; i < mac.length; i++) {
+ String hexString = "0" + Integer.toHexString(mac[i]);
+
+ // substring operation grabs the last 2 digits: this
+ // allows signed bytes to be converted correctly.
+ macAddr += hexString.substring(hexString.length() - 2);
+
+ if (i != (mac.length - 1)) {
+ macAddr += ":";
+ }
+ }
+
+ return macAddr;
+ }
+
+ public String toString() {
+ String macAddr = macToString(mClientMac);
+
+ return macAddr;
+ }
+
+ /**
+ * Reads a four-octet value from a ByteBuffer and construct
+ * an IPv4 address from that value.
+ */
+ private static InetAddress readIpAddress(ByteBuffer packet) {
+ InetAddress result = null;
+ byte[] ipAddr = new byte[4];
+ packet.get(ipAddr);
+
+ try {
+ result = InetAddress.getByAddress(ipAddr);
+ } catch (UnknownHostException ex) {
+ // ipAddr is numeric, so this should not be
+ // triggered. However, if it is, just nullify
+ result = null;
+ }
+
+ return result;
+ }
+
+ /**
+ * Reads a string of specified length from the buffer.
+ */
+ private static String readAsciiString(ByteBuffer buf, int byteCount) {
+ byte[] bytes = new byte[byteCount];
+ buf.get(bytes);
+ return new String(bytes, 0, bytes.length, Charsets.US_ASCII);
+ }
+
+ /**
+ * Creates a concrete DhcpPacket from the supplied ByteBuffer. The
+ * buffer may have an L2 encapsulation (which is the full EthernetII
+ * format starting with the source-address MAC) or an L3 encapsulation
+ * (which starts with the IP header).
+ * <br>
+ * A subset of the optional parameters are parsed and are stored
+ * in object fields.
+ */
+ public static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType)
+ {
+ // bootp parameters
+ int transactionId;
+ InetAddress clientIp;
+ InetAddress yourIp;
+ InetAddress nextIp;
+ InetAddress relayIp;
+ byte[] clientMac;
+ List<InetAddress> dnsServers = null;
+ InetAddress gateway = null; // aka router
+ Integer leaseTime = null;
+ InetAddress serverIdentifier = null;
+ InetAddress netMask = null;
+ String message = null;
+ String vendorId = null;
+ byte[] expectedParams = null;
+ String hostName = null;
+ String domainName = null;
+ InetAddress ipSrc = null;
+ InetAddress ipDst = null;
+ InetAddress bcAddr = null;
+ InetAddress requestedIp = null;
+
+ // dhcp options
+ byte dhcpType = (byte) 0xFF;
+
+ packet.order(ByteOrder.BIG_ENDIAN);
+
+ // check to see if we need to parse L2, IP, and UDP encaps
+ if (pktType == ENCAP_L2) {
+ // System.out.println("buffer len " + packet.limit());
+ byte[] l2dst = new byte[6];
+ byte[] l2src = new byte[6];
+
+ packet.get(l2dst);
+ packet.get(l2src);
+
+ short l2type = packet.getShort();
+
+ if (l2type != 0x0800)
+ return null;
+ }
+
+ if ((pktType == ENCAP_L2) || (pktType == ENCAP_L3)) {
+ // assume l2type is 0x0800, i.e. IP
+ byte ipType = packet.get();
+ // System.out.println("ipType is " + ipType);
+ byte ipDiffServicesField = packet.get();
+ short ipTotalLength = packet.getShort();
+ short ipIdentification = packet.getShort();
+ byte ipFlags = packet.get();
+ byte ipFragOffset = packet.get();
+ byte ipTTL = packet.get();
+ byte ipProto = packet.get();
+ short ipChksm = packet.getShort();
+
+ ipSrc = readIpAddress(packet);
+ ipDst = readIpAddress(packet);
+
+ if (ipProto != IP_TYPE_UDP) // UDP
+ return null;
+
+ // assume UDP
+ short udpSrcPort = packet.getShort();
+ short udpDstPort = packet.getShort();
+ short udpLen = packet.getShort();
+ short udpChkSum = packet.getShort();
+
+ if ((udpSrcPort != DHCP_SERVER) && (udpSrcPort != DHCP_CLIENT))
+ return null;
+ }
+
+ // assume bootp
+ byte type = packet.get();
+ byte hwType = packet.get();
+ byte addrLen = packet.get();
+ byte hops = packet.get();
+ transactionId = packet.getInt();
+ short elapsed = packet.getShort();
+ short bootpFlags = packet.getShort();
+ boolean broadcast = (bootpFlags & 0x8000) != 0;
+ byte[] ipv4addr = new byte[4];
+
+ try {
+ packet.get(ipv4addr);
+ clientIp = InetAddress.getByAddress(ipv4addr);
+ packet.get(ipv4addr);
+ yourIp = InetAddress.getByAddress(ipv4addr);
+ packet.get(ipv4addr);
+ nextIp = InetAddress.getByAddress(ipv4addr);
+ packet.get(ipv4addr);
+ relayIp = InetAddress.getByAddress(ipv4addr);
+ } catch (UnknownHostException ex) {
+ return null;
+ }
+
+ clientMac = new byte[addrLen];
+ packet.get(clientMac);
+
+ // skip over address padding (16 octets allocated)
+ packet.position(packet.position() + (16 - addrLen)
+ + 64 // skip server host name (64 chars)
+ + 128); // skip boot file name (128 chars)
+
+ int dhcpMagicCookie = packet.getInt();
+
+ if (dhcpMagicCookie != 0x63825363)
+ return null;
+
+ // parse options
+ boolean notFinishedOptions = true;
+
+ while ((packet.position() < packet.limit()) && notFinishedOptions) {
+ byte optionType = packet.get();
+
+ if (optionType == (byte) 0xFF) {
+ notFinishedOptions = false;
+ } else {
+ byte optionLen = packet.get();
+ int expectedLen = 0;
+
+ switch(optionType) {
+ case DHCP_SUBNET_MASK:
+ netMask = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_ROUTER:
+ gateway = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_DNS_SERVER:
+ dnsServers = new ArrayList<InetAddress>();
+ expectedLen = 0;
+
+ for (expectedLen = 0; expectedLen < optionLen;
+ expectedLen += 4) {
+ dnsServers.add(readIpAddress(packet));
+ }
+ break;
+ case DHCP_HOST_NAME:
+ expectedLen = optionLen;
+ hostName = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_DOMAIN_NAME:
+ expectedLen = optionLen;
+ domainName = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_BROADCAST_ADDRESS:
+ bcAddr = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_REQUESTED_IP:
+ requestedIp = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_LEASE_TIME:
+ leaseTime = Integer.valueOf(packet.getInt());
+ expectedLen = 4;
+ break;
+ case DHCP_MESSAGE_TYPE:
+ dhcpType = packet.get();
+ expectedLen = 1;
+ break;
+ case DHCP_SERVER_IDENTIFIER:
+ serverIdentifier = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_PARAMETER_LIST:
+ expectedParams = new byte[optionLen];
+ packet.get(expectedParams);
+ expectedLen = optionLen;
+ break;
+ case DHCP_MESSAGE:
+ expectedLen = optionLen;
+ message = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_VENDOR_CLASS_ID:
+ expectedLen = optionLen;
+ vendorId = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_CLIENT_IDENTIFIER: { // Client identifier
+ byte[] id = new byte[optionLen];
+ packet.get(id);
+ expectedLen = optionLen;
+ } break;
+ default:
+ // ignore any other parameters
+ for (int i = 0; i < optionLen; i++) {
+ expectedLen++;
+ byte throwaway = packet.get();
+ }
+ }
+
+ if (expectedLen != optionLen) {
+ return null;
+ }
+ }
+ }
+
+ DhcpPacket newPacket;
+
+ switch(dhcpType) {
+ case -1: return null;
+ case DHCP_MESSAGE_TYPE_DISCOVER:
+ newPacket = new DhcpDiscoverPacket(
+ transactionId, clientMac, broadcast);
+ break;
+ case DHCP_MESSAGE_TYPE_OFFER:
+ newPacket = new DhcpOfferPacket(
+ transactionId, broadcast, ipSrc, yourIp, clientMac);
+ break;
+ case DHCP_MESSAGE_TYPE_REQUEST:
+ newPacket = new DhcpRequestPacket(
+ transactionId, clientIp, clientMac, broadcast);
+ break;
+ case DHCP_MESSAGE_TYPE_DECLINE:
+ newPacket = new DhcpDeclinePacket(
+ transactionId, clientIp, yourIp, nextIp, relayIp,
+ clientMac);
+ break;
+ case DHCP_MESSAGE_TYPE_ACK:
+ newPacket = new DhcpAckPacket(
+ transactionId, broadcast, ipSrc, yourIp, clientMac);
+ break;
+ case DHCP_MESSAGE_TYPE_NAK:
+ newPacket = new DhcpNakPacket(
+ transactionId, clientIp, yourIp, nextIp, relayIp,
+ clientMac);
+ break;
+ case DHCP_MESSAGE_TYPE_INFORM:
+ newPacket = new DhcpInformPacket(
+ transactionId, clientIp, yourIp, nextIp, relayIp,
+ clientMac);
+ break;
+ default:
+ System.out.println("Unimplemented type: " + dhcpType);
+ return null;
+ }
+
+ newPacket.mBroadcastAddress = bcAddr;
+ newPacket.mDnsServers = dnsServers;
+ newPacket.mDomainName = domainName;
+ newPacket.mGateway = gateway;
+ newPacket.mHostName = hostName;
+ newPacket.mLeaseTime = leaseTime;
+ newPacket.mMessage = message;
+ newPacket.mRequestedIp = requestedIp;
+ newPacket.mRequestedParams = expectedParams;
+ newPacket.mServerIdentifier = serverIdentifier;
+ newPacket.mSubnetMask = netMask;
+ return newPacket;
+ }
+
+ /**
+ * Parse a packet from an array of bytes.
+ */
+ public static DhcpPacket decodeFullPacket(byte[] packet, int pktType)
+ {
+ ByteBuffer buffer = ByteBuffer.wrap(packet).order(ByteOrder.BIG_ENDIAN);
+ return decodeFullPacket(buffer, pktType);
+ }
+
+ /**
+ * Builds a DHCP-DISCOVER packet from the required specified
+ * parameters.
+ */
+ public static ByteBuffer buildDiscoverPacket(int encap, int transactionId,
+ byte[] clientMac, boolean broadcast, byte[] expectedParams) {
+ DhcpPacket pkt = new DhcpDiscoverPacket(
+ transactionId, clientMac, broadcast);
+ pkt.mRequestedParams = expectedParams;
+ return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
+ }
+
+ /**
+ * Builds a DHCP-OFFER packet from the required specified
+ * parameters.
+ */
+ public static ByteBuffer buildOfferPacket(int encap, int transactionId,
+ boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
+ byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
+ InetAddress gateway, List<InetAddress> dnsServers,
+ InetAddress dhcpServerIdentifier, String domainName) {
+ DhcpPacket pkt = new DhcpOfferPacket(
+ transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
+ pkt.mGateway = gateway;
+ pkt.mDnsServers = dnsServers;
+ pkt.mLeaseTime = timeout;
+ pkt.mDomainName = domainName;
+ pkt.mServerIdentifier = dhcpServerIdentifier;
+ pkt.mSubnetMask = netMask;
+ pkt.mBroadcastAddress = bcAddr;
+ return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
+ }
+
+ /**
+ * Builds a DHCP-ACK packet from the required specified parameters.
+ */
+ public static ByteBuffer buildAckPacket(int encap, int transactionId,
+ boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
+ byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
+ InetAddress gateway, List<InetAddress> dnsServers,
+ InetAddress dhcpServerIdentifier, String domainName) {
+ DhcpPacket pkt = new DhcpAckPacket(
+ transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
+ pkt.mGateway = gateway;
+ pkt.mDnsServers = dnsServers;
+ pkt.mLeaseTime = timeout;
+ pkt.mDomainName = domainName;
+ pkt.mSubnetMask = netMask;
+ pkt.mServerIdentifier = dhcpServerIdentifier;
+ pkt.mBroadcastAddress = bcAddr;
+ return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
+ }
+
+ /**
+ * Builds a DHCP-NAK packet from the required specified parameters.
+ */
+ public static ByteBuffer buildNakPacket(int encap, int transactionId,
+ InetAddress serverIpAddr, InetAddress clientIpAddr, byte[] mac) {
+ DhcpPacket pkt = new DhcpNakPacket(transactionId, clientIpAddr,
+ serverIpAddr, serverIpAddr, serverIpAddr, mac);
+ pkt.mMessage = "requested address not available";
+ pkt.mRequestedIp = clientIpAddr;
+ return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
+ }
+
+ /**
+ * Builds a DHCP-REQUEST packet from the required specified parameters.
+ */
+ public static ByteBuffer buildRequestPacket(int encap,
+ int transactionId, InetAddress clientIp, boolean broadcast,
+ byte[] clientMac, InetAddress requestedIpAddress,
+ InetAddress serverIdentifier, byte[] requestedParams, String hostName) {
+ DhcpPacket pkt = new DhcpRequestPacket(transactionId, clientIp,
+ clientMac, broadcast);
+ pkt.mRequestedIp = requestedIpAddress;
+ pkt.mServerIdentifier = serverIdentifier;
+ pkt.mHostName = hostName;
+ pkt.mRequestedParams = requestedParams;
+ ByteBuffer result = pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
+ return result;
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpRequestPacket.java b/core/java/android/net/dhcp/DhcpRequestPacket.java
new file mode 100644
index 000000000000..cf32957fd3bd
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpRequestPacket.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+
+/**
+ * This class implements the DHCP-REQUEST packet.
+ */
+class DhcpRequestPacket extends DhcpPacket {
+ /**
+ * Generates a REQUEST packet with the specified parameters.
+ */
+ DhcpRequestPacket(int transId, InetAddress clientIp, byte[] clientMac,
+ boolean broadcast) {
+ super(transId, clientIp, Inet4Address.ANY, Inet4Address.ANY,
+ Inet4Address.ANY, clientMac, broadcast);
+ }
+
+ public String toString() {
+ String s = super.toString();
+ return s + " REQUEST, desired IP " + mRequestedIp + " from host '"
+ + mHostName + "', param list length "
+ + (mRequestedParams == null ? 0 : mRequestedParams.length);
+ }
+
+ /**
+ * Fills in a packet with the requested REQUEST attributes.
+ */
+ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+ ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+
+ fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp,
+ result, DHCP_BOOTREQUEST, mBroadcast);
+ result.flip();
+ return result;
+ }
+
+ /**
+ * Adds the optional parameters to the client-generated REQUEST packet.
+ */
+ void finishPacket(ByteBuffer buffer) {
+ byte[] clientId = new byte[7];
+
+ // assemble client identifier
+ clientId[0] = CLIENT_ID_ETHER;
+ System.arraycopy(mClientMac, 0, clientId, 1, 6);
+
+ addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_REQUEST);
+ addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
+ addTlv(buffer, DHCP_REQUESTED_IP, mRequestedIp);
+ addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+ addTlv(buffer, DHCP_CLIENT_IDENTIFIER, clientId);
+ addTlvEnd(buffer);
+ }
+
+ /**
+ * Notifies the specified state machine of the REQUEST packet parameters.
+ */
+ public void doNextOp(DhcpStateMachine machine) {
+ InetAddress clientRequest =
+ mRequestedIp == null ? mClientIp : mRequestedIp;
+ Log.v(TAG, "requested IP is " + mRequestedIp + " and client IP is " +
+ mClientIp);
+ machine.onRequestReceived(mBroadcast, mTransId, mClientMac,
+ clientRequest, mRequestedParams, mHostName);
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpStateMachine.java b/core/java/android/net/dhcp/DhcpStateMachine.java
new file mode 100644
index 000000000000..b6c384de70b0
--- /dev/null
+++ b/core/java/android/net/dhcp/DhcpStateMachine.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * This class defines the "next steps" which occur after a given DHCP
+ * packet has been received.
+ */
+interface DhcpStateMachine {
+ /**
+ * Signals that an offer packet has been received with the specified
+ * parameters.
+ */
+ public void onOfferReceived(boolean broadcast, int transactionId,
+ byte[] myMac, InetAddress offeredIpAddress,
+ InetAddress serverIpAddress);
+
+ /**
+ * Signals that a NAK packet has been received.
+ */
+ public void onNakReceived();
+
+ /**
+ * Signals that the final ACK has been received from the server.
+ */
+ public void onAckReceived(InetAddress myIpAddress, InetAddress myNetMask,
+ InetAddress myGateway, List<InetAddress> myDnsServers,
+ InetAddress myDhcpServer, int leaseTime);
+
+ /**
+ * Signals that a client's DISCOVER packet has been received with the
+ * specified parameters.
+ */
+ public void onDiscoverReceived(boolean broadcast, int transactionId,
+ byte[] clientMac, byte[] requestedParameterList);
+
+ /**
+ * Signals that a client's REQUEST packet has been received with the
+ * specified parameters.
+ */
+ public void onRequestReceived(boolean broadcast, int transactionId,
+ byte[] clientMac, InetAddress requestedIp, byte[] requestedParams,
+ String clientHostName);
+
+ /**
+ * Signals that a client's INFORM packet has been received with the
+ * specified parameters.
+ */
+ public void onInformReceived(int transactionId, byte[] clientMac,
+ InetAddress preassignedIp, byte[] requestedParams);
+
+ /**
+ * Signals that a client's DECLINE packet has been received with the
+ * specified parameters.
+ */
+ public void onDeclineReceived(byte[] clientMac, InetAddress declinedIp);
+}
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index e9428f7eb609..3769cfe9df0d 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -22,6 +22,7 @@ import android.util.Log;
* Class that operates the vibrator on the device.
* <p>
* If your process exits, any vibration you started with will stop.
+ * </p>
*/
public class Vibrator
{
@@ -56,7 +57,7 @@ public class Vibrator
/**
* Turn the vibrator on.
*
- * @param milliseconds How long to vibrate for.
+ * @param milliseconds The number of milliseconds to vibrate.
*/
public void vibrate(long milliseconds)
{
@@ -75,12 +76,17 @@ public class Vibrator
* Vibrate with a given pattern.
*
* <p>
- * Pass in an array of ints that are the times at which to turn on or off
- * the vibrator. The first one is how long to wait before turning it on,
- * and then after that it alternates. If you want to repeat, pass the
- * index into the pattern at which to start the repeat.
+ * Pass in an array of ints that are the durations for which to turn on or off
+ * the vibrator in milliseconds. The first value indicates the number of milliseconds
+ * to wait before turning the vibrator on. The next value indicates the number of milliseconds
+ * for which to keep the vibrator on before turning it off. Subsequent values alternate
+ * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
+ * </p><p>
+ * To cause the pattern to repeat, pass the index into the pattern array at which
+ * to start the repeat, or -1 to disable repeating.
+ * </p>
*
- * @param pattern an array of longs of times to turn the vibrator on or off.
+ * @param pattern an array of longs of times for which to turn the vibrator on or off.
* @param repeat the index into pattern at which to repeat, or -1 if
* you don't want to repeat.
*/
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 9bda637c2268..95949b98a05e 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -865,6 +865,9 @@ public final class ViewRoot extends Handler implements ViewParent,
childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
+ windowSizeMayChange = true;
+ }
}
if (DBG) {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 4223040ae0a4..8fb6fa38e464 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -192,12 +192,6 @@ public class Switch extends CompoundButton {
setSwitchTypefaceByIndex(typefaceIndex, styleIndex);
- int lineHeight = appearance.getDimensionPixelSize(
- com.android.internal.R.styleable.TextAppearance_textLineHeight, 0);
- if (lineHeight != 0) {
- setLineHeight(lineHeight);
- }
-
appearance.recycle();
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7fc7e541b469..c7ee57b2bbb7 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -766,13 +766,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mEditTextMultilineBackground = a.getDrawable(attr);
break;
- case com.android.internal.R.styleable.TextView_textLineHeight:
- int lineHeight = a.getDimensionPixelSize(attr, 0);
- if (lineHeight != 0) {
- setLineHeight(lineHeight);
- }
- break;
-
case com.android.internal.R.styleable.TextView_textIsSelectable:
mTextIsSelectable = a.getBoolean(attr, false);
break;
@@ -1133,15 +1126,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* within the text can cause individual lines to be taller or shorter
* than this height, and the layout may contain additional first-
* or last-line padding.
- *
- * @attr ref android.R.styleable#TextView_textLineHeight
*/
public int getLineHeight() {
- if (mLineHeight != 0) {
- return mLineHeight;
- }
- return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult
- + mSpacingAdd);
+ return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult + mSpacingAdd);
}
/**
@@ -1728,26 +1715,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setTypefaceByIndex(typefaceIndex, styleIndex);
- int lineHeight = appearance.getDimensionPixelSize(
- com.android.internal.R.styleable.TextAppearance_textLineHeight, 0);
- if (lineHeight != 0) {
- setLineHeight(lineHeight);
- }
-
appearance.recycle();
}
/**
- * Set the height of a line of text in pixels. This value will override line height
- * values stored in the font modified by lineSpacingExtra and lineSpacingMultiplier.
- *
- * @param lineHeight Desired height of a single line of text in pixels
- */
- public void setLineHeight(int lineHeight) {
- mLineHeight = lineHeight;
- }
-
- /**
* @return the size (in pixels) of the default text size in this TextView.
*/
public float getTextSize() {
@@ -9393,7 +9364,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private float mSpacingMult = 1;
private float mSpacingAdd = 0;
- private int mLineHeight = 0;
private boolean mTextIsSelectable = false;
private static final int LINES = 1;
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 2cb78a58c49b..a5fd38e94b39 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -96,6 +96,7 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
}
mPopup.setContentWidth(Math.min(measureContentWidth(adapter), mPopupMaxWidth));
+ mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
mPopup.show();
mPopup.getListView().setOnKeyListener(this);
}
@@ -163,6 +164,9 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
final View anchor = mAnchorView != null ? mAnchorView.get() : null;
if (anchor != null && !anchor.isShown()) {
dismiss();
+ } else {
+ // Recompute window size and position
+ mPopup.show();
}
}
}
diff --git a/core/res/res/drawable-hdpi/spinner_active_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_active_holo_dark.9.png
index bbf28615b274..752b41636609 100644
--- a/core/res/res/drawable-hdpi/spinner_active_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_active_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_active_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_active_holo_light.9.png
index a10098df8b92..afc0c57d65b6 100644
--- a/core/res/res/drawable-hdpi/spinner_active_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_active_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.png
index ffae7e7251b1..7cad0c93dda7 100644
--- a/core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.png
index eaa38e241eb2..7cad0c93dda7 100644
--- a/core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.png
index 869371095b37..b3f3cf757cc6 100644
--- a/core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.png
index 941739e02a76..af46631d9f3b 100644
--- a/core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.png
index dc236ec71ef8..8b6f9dd9f76a 100644
--- a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.png
index 17e3a2767978..4f0c476364f8 100644
--- a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
index 7189c6d57268..ac36c068c3da 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
index 996ef154925b..68215998b58d 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
index 5428b0a3a2c6..3b260170c683 100644
--- a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_active_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_active_holo_dark.9.png
index c235501537ed..1f0521a612f0 100644
--- a/core/res/res/drawable-mdpi/spinner_active_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_active_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_active_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_active_holo_light.9.png
index 06e2bded2a9d..9604e1fc4afc 100644
--- a/core/res/res/drawable-mdpi/spinner_active_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_active_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.png
index bb57d8d94c26..617c379142eb 100644
--- a/core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.png
index 4e3edff5afb3..617c379142eb 100644
--- a/core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.png
index 62d2f6efc416..d76b1232129d 100644
--- a/core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.png
index df80aa67abbd..ee910444e315 100644
--- a/core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.png
index 9b8a54b58423..df0a935ebb72 100644
--- a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.png
index 6d4fa54db464..b43177b053fc 100644
--- a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
index 3dba23529331..99b16056b139 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
index 4614cfa0387e..c820e40a1fa5 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
index 25aaed2d0159..083194a6fa11 100644
--- a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 181bbcc50aa6..f10e90f7468c 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -722,9 +722,6 @@
<!-- Color of link text (URLs). -->
<attr name="textColorLink" format="reference|color" />
- <!-- Height of a line of text. -->
- <attr name="textLineHeight" format="dimension" />
-
<!-- Indicates that the content of a non-editable TextView can be selected.
Default value is false. EditText content is always selectable. -->
<attr name="textIsSelectable" format="boolean" />
@@ -2429,8 +2426,6 @@
<attr name="textColorHint" />
<!-- Color of the links. -->
<attr name="textColorLink" />
- <!-- Height of a single line of text. -->
- <attr name="textLineHeight" />
</declare-styleable>
<declare-styleable name="TextSwitcher">
</declare-styleable>
@@ -2672,10 +2667,7 @@
<attr name="textEditPasteWindowLayout" />
<!-- Variation of textEditPasteWindowLayout displayed when the clipboard is empty. -->
<attr name="textEditNoPasteWindowLayout" />
-
- <!-- Height of a line of text. -->
- <attr name="textLineHeight" />
- <!-- Indicates that a non-editable text can be selected. -->
+ <!-- Indicates that the content of a non-editable text can be selected. -->
<attr name="textIsSelectable" />
<!-- A specific background drawable used by multi-line EditText only. -->
<attr name="multilineBackground" format="reference"/>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index dcc88f0b0d30..3a5b238d6d0c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1358,7 +1358,6 @@
<public type="attr" name="loopViews" />
<public type="attr" name="dialogTheme" />
<public type="attr" name="alertDialogTheme" />
- <public type="attr" name="textLineHeight" />
<public type="attr" name="dividerVertical" />
<public type="attr" name="homeAsUpIndicator" />
<public type="attr" name="enterFadeDuration" />
diff --git a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
index 042d55759c6c..bc4ccd2e3db4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
@@ -119,20 +119,23 @@ public abstract class Gradient_Delegate extends Shader_Delegate {
pos = 0.f;
break;
case REPEAT:
- // remove the integer part to stay in the [0,1] range
- // careful: this is a negative value, so use ceil instead of floor
- pos = pos - (float)Math.ceil(pos);
+ // remove the integer part to stay in the [0,1] range.
+ // we also need to invert the value from [-1,0] to [0, 1]
+ pos = pos - (float)Math.floor(pos);
break;
case MIRROR:
+ // this is the same as the positive side, just make the value positive
+ // first.
+ pos = Math.abs(pos);
+
// get the integer and the decimal part
- // careful: this is a negative value, so use ceil instead of floor
- int intPart = (int)Math.ceil(pos);
+ int intPart = (int)Math.floor(pos);
pos = pos - intPart;
- // 0 -> -1 : mirrored order
- // -1 -> -2: normal order
+ // 0 -> 1 : normal order
+ // 1 -> 2: mirrored
// etc..
- // this means if the intpart is even we invert
- if ((intPart % 2) == 0) {
+ // this means if the intpart is odd we invert
+ if ((intPart % 2) == 1) {
pos = 1.f - pos;
}
break;
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index 7573dc136966..862b4544a060 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -16,11 +16,14 @@
package android.graphics;
+import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Shader.TileMode;
import java.awt.Paint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
/**
* Delegate implementing the native methods of android.graphics.LinearGradient
@@ -115,7 +118,7 @@ public class LinearGradient_Delegate extends Gradient_Delegate {
* {@link java.awt.GradientPaint} only supports 2 points and does not support Android's tile
* modes.
*/
- private static class LinearGradientPaint extends GradientPaint {
+ private class LinearGradientPaint extends GradientPaint {
private final float mX0;
private final float mY0;
@@ -126,11 +129,11 @@ public class LinearGradient_Delegate extends Gradient_Delegate {
public LinearGradientPaint(float x0, float y0, float x1, float y1, int colors[],
float positions[], TileMode tile) {
super(colors, positions, tile);
- mX0 = x0;
- mY0 = y0;
- mDx = x1 - x0;
- mDy = y1 - y0;
- mDSize2 = mDx * mDx + mDy * mDy;
+ mX0 = x0;
+ mY0 = y0;
+ mDx = x1 - x0;
+ mDy = y1 - y0;
+ mDSize2 = mDx * mDx + mDy * mDy;
}
public java.awt.PaintContext createContext(
@@ -140,16 +143,37 @@ public class LinearGradient_Delegate extends Gradient_Delegate {
java.awt.geom.AffineTransform xform,
java.awt.RenderingHints hints) {
precomputeGradientColors();
- return new LinearGradientPaintContext(colorModel);
+
+ AffineTransform canvasMatrix;
+ try {
+ canvasMatrix = xform.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ Bridge.getLog().error(null, "Unable to inverse matrix in LinearGradient", e);
+ canvasMatrix = new AffineTransform();
+ }
+
+ AffineTransform localMatrix = getLocalMatrix();
+ try {
+ localMatrix = localMatrix.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ Bridge.getLog().error(null, "Unable to inverse matrix in LinearGradient", e);
+ localMatrix = new AffineTransform();
+ }
+
+ return new LinearGradientPaintContext(canvasMatrix, localMatrix, colorModel);
}
private class LinearGradientPaintContext implements java.awt.PaintContext {
+ private final AffineTransform mCanvasMatrix;
+ private final AffineTransform mLocalMatrix;
private final java.awt.image.ColorModel mColorModel;
- public LinearGradientPaintContext(java.awt.image.ColorModel colorModel) {
+ public LinearGradientPaintContext(AffineTransform canvasMatrix,
+ AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+ mCanvasMatrix = canvasMatrix;
+ mLocalMatrix = localMatrix;
mColorModel = colorModel;
- // FIXME: so far all this is always the same rect gotten in getRaster with an identity matrix?
}
public void dispose() {
@@ -165,31 +189,22 @@ public class LinearGradient_Delegate extends Gradient_Delegate {
int[] data = new int[w*h];
- if (mDx == 0) { // vertical gradient
- // compute first column and copy to all other columns
- int index = 0;
- for (int iy = 0 ; iy < h ; iy++) {
- int color = getColor(iy + y, mY0, mDy);
- for (int ix = 0 ; ix < w ; ix++) {
- data[index++] = color;
- }
- }
- } else if (mDy == 0) { // horizontal
- // compute first line in a tmp array and copy to all lines
- int[] line = new int[w];
+ int index = 0;
+ float[] pt1 = new float[2];
+ float[] pt2 = new float[2];
+ for (int iy = 0 ; iy < h ; iy++) {
for (int ix = 0 ; ix < w ; ix++) {
- line[ix] = getColor(ix + x, mX0, mDx);
- }
+ // handle the canvas transform
+ pt1[0] = x + ix;
+ pt1[1] = y + iy;
+ mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
- for (int iy = 0 ; iy < h ; iy++) {
- System.arraycopy(line, 0, data, iy*w, line.length);
- }
- } else {
- int index = 0;
- for (int iy = 0 ; iy < h ; iy++) {
- for (int ix = 0 ; ix < w ; ix++) {
- data[index++] = getColor(ix + x, iy + y);
- }
+ // handle the local matrix.
+ pt1[0] = pt2[0];
+ pt1[1] = pt2[1];
+ mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
+
+ data[index++] = getColor(pt2[0], pt2[1]);
}
}
@@ -199,13 +214,6 @@ public class LinearGradient_Delegate extends Gradient_Delegate {
}
}
- /** Returns a color for the easy vertical/horizontal mode */
- private int getColor(float absPos, float refPos, float refSize) {
- float pos = (absPos - refPos) / refSize;
-
- return getGradientColor(pos);
- }
-
/**
* Returns a color for an arbitrary point.
*/
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index bef8c8cbc246..6b43544f19df 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -471,7 +471,7 @@ public final class Matrix_Delegate {
return false;
}
- d.preTransform(getRotate(degrees, px, py));
+ d.postTransform(getRotate(degrees, px, py));
return true;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index c36ce530beb2..eebf378060b6 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -16,11 +16,14 @@
package android.graphics;
+import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Shader.TileMode;
import java.awt.Paint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
/**
* Delegate implementing the native methods of android.graphics.RadialGradient
@@ -105,18 +108,17 @@ public class RadialGradient_Delegate extends Gradient_Delegate {
private RadialGradient_Delegate(float x, float y, float radius, int colors[], float positions[],
TileMode tile) {
super(colors, positions);
-
mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile);
}
- private static class RadialGradientPaint extends GradientPaint {
+ private class RadialGradientPaint extends GradientPaint {
private final float mX;
private final float mY;
private final float mRadius;
- public RadialGradientPaint(float x, float y, float radius, int[] colors, float[] positions,
- TileMode mode) {
+ public RadialGradientPaint(float x, float y, float radius,
+ int[] colors, float[] positions, TileMode mode) {
super(colors, positions, mode);
mX = x;
mY = y;
@@ -130,14 +132,36 @@ public class RadialGradient_Delegate extends Gradient_Delegate {
java.awt.geom.AffineTransform xform,
java.awt.RenderingHints hints) {
precomputeGradientColors();
- return new RadialGradientPaintContext(colorModel);
+
+ AffineTransform canvasMatrix;
+ try {
+ canvasMatrix = xform.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ Bridge.getLog().error(null, "Unable to inverse matrix in RadialGradient", e);
+ canvasMatrix = new AffineTransform();
+ }
+
+ AffineTransform localMatrix = getLocalMatrix();
+ try {
+ localMatrix = localMatrix.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ Bridge.getLog().error(null, "Unable to inverse matrix in RadialGradient", e);
+ localMatrix = new AffineTransform();
+ }
+
+ return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel);
}
private class RadialGradientPaintContext implements java.awt.PaintContext {
+ private final AffineTransform mCanvasMatrix;
+ private final AffineTransform mLocalMatrix;
private final java.awt.image.ColorModel mColorModel;
- public RadialGradientPaintContext(java.awt.image.ColorModel colorModel) {
+ public RadialGradientPaintContext(AffineTransform canvasMatrix,
+ AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+ mCanvasMatrix = canvasMatrix;
+ mLocalMatrix = localMatrix;
mColorModel = colorModel;
}
@@ -157,10 +181,22 @@ public class RadialGradient_Delegate extends Gradient_Delegate {
// compute distance from each point to the center, and figure out the distance from
// it.
int index = 0;
+ float[] pt1 = new float[2];
+ float[] pt2 = new float[2];
for (int iy = 0 ; iy < h ; iy++) {
for (int ix = 0 ; ix < w ; ix++) {
- float _x = x + ix - mX;
- float _y = y + iy - mY;
+ // handle the canvas transform
+ pt1[0] = x + ix;
+ pt1[1] = y + iy;
+ mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
+
+ // handle the local matrix
+ pt1[0] = pt2[0] - mX;
+ pt1[1] = pt2[1] - mY;
+ mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
+
+ float _x = pt2[0];
+ float _y = pt2[1];
float distance = (float) Math.sqrt(_x * _x + _y * _y);
data[index++] = getGradientColor(distance / mRadius);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 646ac8044be6..7bf144314e10 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -18,6 +18,8 @@ package android.graphics;
import com.android.layoutlib.bridge.impl.DelegateManager;
+import java.awt.geom.AffineTransform;
+
/**
* Delegate implementing the native methods of android.graphics.Shader
*
@@ -109,4 +111,19 @@ public abstract class Shader_Delegate {
// ---- Private delegate/helper methods ----
+ protected AffineTransform getLocalMatrix() {
+ Matrix_Delegate localMatrixDelegate = null;
+ if (mLocalMatrix > 0) {
+ localMatrixDelegate = Matrix_Delegate.getDelegate(mLocalMatrix);
+ if (localMatrixDelegate == null) {
+ assert false;
+ return new AffineTransform();
+ }
+
+ return localMatrixDelegate.getAffineTransform();
+ }
+
+ return new AffineTransform();
+ }
+
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 358c3c7b53b8..97c3cfd24855 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -16,9 +16,12 @@
package android.graphics;
+import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import java.awt.Paint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
/**
* Delegate implementing the native methods of android.graphics.SweepGradient
@@ -90,16 +93,16 @@ public class SweepGradient_Delegate extends Gradient_Delegate {
private SweepGradient_Delegate(float cx, float cy,
int colors[], float positions[]) {
super(colors, positions);
-
mJavaPaint = new SweepGradientPaint(cx, cy, mColors, mPositions);
}
- private static class SweepGradientPaint extends GradientPaint {
+ private class SweepGradientPaint extends GradientPaint {
private final float mCx;
private final float mCy;
- public SweepGradientPaint(float cx, float cy, int[] colors, float[] positions) {
+ public SweepGradientPaint(float cx, float cy, int[] colors,
+ float[] positions) {
super(colors, positions, null /*tileMode*/);
mCx = cx;
mCy = cy;
@@ -112,14 +115,36 @@ public class SweepGradient_Delegate extends Gradient_Delegate {
java.awt.geom.AffineTransform xform,
java.awt.RenderingHints hints) {
precomputeGradientColors();
- return new SweepGradientPaintContext(colorModel);
+
+ AffineTransform canvasMatrix;
+ try {
+ canvasMatrix = xform.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ Bridge.getLog().error(null, "Unable to inverse matrix in SweepGradient", e);
+ canvasMatrix = new AffineTransform();
+ }
+
+ AffineTransform localMatrix = getLocalMatrix();
+ try {
+ localMatrix = localMatrix.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ Bridge.getLog().error(null, "Unable to inverse matrix in SweepGradient", e);
+ localMatrix = new AffineTransform();
+ }
+
+ return new SweepGradientPaintContext(canvasMatrix, localMatrix, colorModel);
}
private class SweepGradientPaintContext implements java.awt.PaintContext {
+ private final AffineTransform mCanvasMatrix;
+ private final AffineTransform mLocalMatrix;
private final java.awt.image.ColorModel mColorModel;
- public SweepGradientPaintContext(java.awt.image.ColorModel colorModel) {
+ public SweepGradientPaintContext(AffineTransform canvasMatrix,
+ AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+ mCanvasMatrix = canvasMatrix;
+ mLocalMatrix = localMatrix;
mColorModel = colorModel;
}
@@ -139,10 +164,23 @@ public class SweepGradient_Delegate extends Gradient_Delegate {
// compute angle from each point to the center, and figure out the distance from
// it.
int index = 0;
+ float[] pt1 = new float[2];
+ float[] pt2 = new float[2];
for (int iy = 0 ; iy < h ; iy++) {
for (int ix = 0 ; ix < w ; ix++) {
- float dx = x + ix - mCx;
- float dy = y + iy - mCy;
+ // handle the canvas transform
+ pt1[0] = x + ix;
+ pt1[1] = y + iy;
+ mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
+
+ // handle the local matrix
+ pt1[0] = pt2[0] - mCx;
+ pt1[1] = pt2[1] - mCy;
+ mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
+
+ float dx = pt2[0];
+ float dy = pt2[1];
+
float angle;
if (dx == 0) {
angle = (float) (dy < 0 ? 3 * Math.PI / 2 : Math.PI / 2);