Merge "Add support for linking to a skia bitmap rather than always copying the data from the bitmap."
diff --git a/common/java/com/android/common/AndroidHttpClient.java b/common/java/com/android/common/AndroidHttpClient.java
deleted file mode 100644
index 4c65eb0..0000000
--- a/common/java/com/android/common/AndroidHttpClient.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponse;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.protocol.ClientContext;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.params.HttpClientParams;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.RequestWrapper;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.protocol.BasicHttpProcessor;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.BasicHttpContext;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-import java.net.URI;
-import java.security.KeyManagementException;
-
-import android.content.Context;
-import android.content.ContentResolver;
-import android.net.SSLCertificateSocketFactory;
-import android.net.SSLSessionCache;
-import android.os.Looper;
-import android.util.Log;
-
-/**
- * Subclass of the Apache {@link DefaultHttpClient} that is configured with
- * reasonable default settings and registered schemes for Android, and
- * also lets the user add {@link HttpRequestInterceptor} classes.
- * Don't create this directly, use the {@link #newInstance} factory method.
- *
- * <p>This client processes cookies but does not retain them by default.
- * To retain cookies, simply add a cookie store to the HttpContext:</p>
- *
- * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
- */
-public final class AndroidHttpClient implements HttpClient {
-
-    // Gzip of data shorter than this probably won't be worthwhile
-    public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256;
-
-    private static final String TAG = "AndroidHttpClient";
-
-
-    /** Interceptor throws an exception if the executing thread is blocked */
-    private static final HttpRequestInterceptor sThreadCheckInterceptor =
-            new HttpRequestInterceptor() {
-        public void process(HttpRequest request, HttpContext context) {
-            // Prevent the HttpRequest from being sent on the main thread
-            if (Looper.myLooper() != null && Looper.myLooper() == Looper.getMainLooper() ) {
-                throw new RuntimeException("This thread forbids HTTP requests");
-            }
-        }
-    };
-
-    /**
-     * Create a new HttpClient with reasonable defaults (which you can update).
-     *
-     * @param userAgent to report in your HTTP requests
-     * @param context to use for caching SSL sessions (may be null for no caching)
-     * @return AndroidHttpClient for you to use for all your requests.
-     */
-    public static AndroidHttpClient newInstance(String userAgent, Context context) {
-        HttpParams params = new BasicHttpParams();
-
-        // Turn off stale checking.  Our connections break all the time anyway,
-        // and it's not worth it to pay the penalty of checking every time.
-        HttpConnectionParams.setStaleCheckingEnabled(params, false);
-
-        // Default connection and socket timeout of 20 seconds.  Tweak to taste.
-        HttpConnectionParams.setConnectionTimeout(params, 20 * 1000);
-        HttpConnectionParams.setSoTimeout(params, 20 * 1000);
-        HttpConnectionParams.setSocketBufferSize(params, 8192);
-
-        // Don't handle redirects -- return them to the caller.  Our code
-        // often wants to re-POST after a redirect, which we must do ourselves.
-        HttpClientParams.setRedirecting(params, false);
-
-        // Use a session cache for SSL sockets
-        SSLSessionCache sessionCache = context == null ? null : new SSLSessionCache(context);
-
-        // Set the specified user agent and register standard protocols.
-        HttpProtocolParams.setUserAgent(params, userAgent);
-        SchemeRegistry schemeRegistry = new SchemeRegistry();
-        schemeRegistry.register(new Scheme("http",
-                PlainSocketFactory.getSocketFactory(), 80));
-        schemeRegistry.register(new Scheme("https",
-                SSLCertificateSocketFactory.getHttpSocketFactory(30 * 1000, sessionCache), 443));
-
-        ClientConnectionManager manager =
-                new ThreadSafeClientConnManager(params, schemeRegistry);
-
-        // We use a factory method to modify superclass initialization
-        // parameters without the funny call-a-static-method dance.
-        return new AndroidHttpClient(manager, params);
-    }
-
-    /**
-     * Create a new HttpClient with reasonable defaults (which you can update).
-     * @param userAgent to report in your HTTP requests.
-     * @return AndroidHttpClient for you to use for all your requests.
-     */
-    public static AndroidHttpClient newInstance(String userAgent) {
-        return newInstance(userAgent, null /* session cache */);
-    }
-
-    private final HttpClient delegate;
-
-    private RuntimeException mLeakedException = new IllegalStateException(
-            "AndroidHttpClient created and never closed");
-
-    private AndroidHttpClient(ClientConnectionManager ccm, HttpParams params) {
-        this.delegate = new DefaultHttpClient(ccm, params) {
-            @Override
-            protected BasicHttpProcessor createHttpProcessor() {
-                // Add interceptor to prevent making requests from main thread.
-                BasicHttpProcessor processor = super.createHttpProcessor();
-                processor.addRequestInterceptor(sThreadCheckInterceptor);
-                processor.addRequestInterceptor(new CurlLogger());
-
-                return processor;
-            }
-
-            @Override
-            protected HttpContext createHttpContext() {
-                // Same as DefaultHttpClient.createHttpContext() minus the
-                // cookie store.
-                HttpContext context = new BasicHttpContext();
-                context.setAttribute(
-                        ClientContext.AUTHSCHEME_REGISTRY,
-                        getAuthSchemes());
-                context.setAttribute(
-                        ClientContext.COOKIESPEC_REGISTRY,
-                        getCookieSpecs());
-                context.setAttribute(
-                        ClientContext.CREDS_PROVIDER,
-                        getCredentialsProvider());
-                return context;
-            }
-        };
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        super.finalize();
-        if (mLeakedException != null) {
-            Log.e(TAG, "Leak found", mLeakedException);
-            mLeakedException = null;
-        }
-    }
-
-    /**
-     * Modifies a request to indicate to the server that we would like a
-     * gzipped response.  (Uses the "Accept-Encoding" HTTP header.)
-     * @param request the request to modify
-     * @see #getUngzippedContent
-     */
-    public static void modifyRequestToAcceptGzipResponse(HttpRequest request) {
-        request.addHeader("Accept-Encoding", "gzip");
-    }
-
-    /**
-     * Gets the input stream from a response entity.  If the entity is gzipped
-     * then this will get a stream over the uncompressed data.
-     *
-     * @param entity the entity whose content should be read
-     * @return the input stream to read from
-     * @throws IOException
-     */
-    public static InputStream getUngzippedContent(HttpEntity entity)
-            throws IOException {
-        InputStream responseStream = entity.getContent();
-        if (responseStream == null) return responseStream;
-        Header header = entity.getContentEncoding();
-        if (header == null) return responseStream;
-        String contentEncoding = header.getValue();
-        if (contentEncoding == null) return responseStream;
-        if (contentEncoding.contains("gzip")) responseStream
-                = new GZIPInputStream(responseStream);
-        return responseStream;
-    }
-
-    /**
-     * Release resources associated with this client.  You must call this,
-     * or significant resources (sockets and memory) may be leaked.
-     */
-    public void close() {
-        if (mLeakedException != null) {
-            getConnectionManager().shutdown();
-            mLeakedException = null;
-        }
-    }
-
-    public HttpParams getParams() {
-        return delegate.getParams();
-    }
-
-    public ClientConnectionManager getConnectionManager() {
-        return delegate.getConnectionManager();
-    }
-
-    public HttpResponse execute(HttpUriRequest request) throws IOException {
-        return delegate.execute(request);
-    }
-
-    public HttpResponse execute(HttpUriRequest request, HttpContext context)
-            throws IOException {
-        return delegate.execute(request, context);
-    }
-
-    public HttpResponse execute(HttpHost target, HttpRequest request)
-            throws IOException {
-        return delegate.execute(target, request);
-    }
-
-    public HttpResponse execute(HttpHost target, HttpRequest request,
-            HttpContext context) throws IOException {
-        return delegate.execute(target, request, context);
-    }
-
-    public <T> T execute(HttpUriRequest request, 
-            ResponseHandler<? extends T> responseHandler)
-            throws IOException, ClientProtocolException {
-        return delegate.execute(request, responseHandler);
-    }
-
-    public <T> T execute(HttpUriRequest request,
-            ResponseHandler<? extends T> responseHandler, HttpContext context)
-            throws IOException, ClientProtocolException {
-        return delegate.execute(request, responseHandler, context);
-    }
-
-    public <T> T execute(HttpHost target, HttpRequest request,
-            ResponseHandler<? extends T> responseHandler) throws IOException,
-            ClientProtocolException {
-        return delegate.execute(target, request, responseHandler);
-    }
-
-    public <T> T execute(HttpHost target, HttpRequest request,
-            ResponseHandler<? extends T> responseHandler, HttpContext context)
-            throws IOException, ClientProtocolException {
-        return delegate.execute(target, request, responseHandler, context);
-    }
-
-    /**
-     * Compress data to send to server.
-     * Creates a Http Entity holding the gzipped data.
-     * The data will not be compressed if it is too short.
-     * @param data The bytes to compress
-     * @return Entity holding the data
-     */
-    public static AbstractHttpEntity getCompressedEntity(byte data[], ContentResolver resolver)
-            throws IOException {
-        AbstractHttpEntity entity;
-        if (data.length < getMinGzipSize(resolver)) {
-            entity = new ByteArrayEntity(data);
-        } else {
-            ByteArrayOutputStream arr = new ByteArrayOutputStream();
-            OutputStream zipper = new GZIPOutputStream(arr);
-            zipper.write(data);
-            zipper.close();
-            entity = new ByteArrayEntity(arr.toByteArray());
-            entity.setContentEncoding("gzip");
-        }
-        return entity;
-    }
-
-    /**
-     * Retrieves the minimum size for compressing data.
-     * Shorter data will not be compressed.
-     */
-    public static long getMinGzipSize(ContentResolver resolver) {
-        return DEFAULT_SYNC_MIN_GZIP_BYTES;  // For now, this is just a constant.
-    }
-
-    /* cURL logging support. */
-
-    /**
-     * Logging tag and level.
-     */
-    private static class LoggingConfiguration {
-
-        private final String tag;
-        private final int level;
-
-        private LoggingConfiguration(String tag, int level) {
-            this.tag = tag;
-            this.level = level;
-        }
-
-        /**
-         * Returns true if logging is turned on for this configuration.
-         */
-        private boolean isLoggable() {
-            return Log.isLoggable(tag, level);
-        }
-
-        /**
-         * Prints a message using this configuration.
-         */
-        private void println(String message) {
-            Log.println(level, tag, message);
-        }
-    }
-
-    /** cURL logging configuration. */
-    private volatile LoggingConfiguration curlConfiguration;
-
-    /**
-     * Enables cURL request logging for this client.
-     *
-     * @param name to log messages with
-     * @param level at which to log messages (see {@link android.util.Log})
-     */
-    public void enableCurlLogging(String name, int level) {
-        if (name == null) {
-            throw new NullPointerException("name");
-        }
-        if (level < Log.VERBOSE || level > Log.ASSERT) {
-            throw new IllegalArgumentException("Level is out of range ["
-                + Log.VERBOSE + ".." + Log.ASSERT + "]");    
-        }
-
-        curlConfiguration = new LoggingConfiguration(name, level);
-    }
-
-    /**
-     * Disables cURL logging for this client.
-     */
-    public void disableCurlLogging() {
-        curlConfiguration = null;
-    }
-
-    /**
-     * Logs cURL commands equivalent to requests.
-     */
-    private class CurlLogger implements HttpRequestInterceptor {
-        public void process(HttpRequest request, HttpContext context)
-                throws HttpException, IOException {
-            LoggingConfiguration configuration = curlConfiguration;
-            if (configuration != null
-                    && configuration.isLoggable()
-                    && request instanceof HttpUriRequest) {
-                // Never print auth token -- we used to check ro.secure=0 to
-                // enable that, but can't do that in unbundled code.
-                configuration.println(toCurl((HttpUriRequest) request, false));
-            }
-        }
-    }
-
-    /**
-     * Generates a cURL command equivalent to the given request.
-     */
-    private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException {
-        StringBuilder builder = new StringBuilder();
-
-        builder.append("curl ");
-
-        for (Header header: request.getAllHeaders()) {
-            if (!logAuthToken
-                    && (header.getName().equals("Authorization") ||
-                        header.getName().equals("Cookie"))) {
-                continue;
-            }
-            builder.append("--header \"");
-            builder.append(header.toString().trim());
-            builder.append("\" ");
-        }
-
-        URI uri = request.getURI();
-
-        // If this is a wrapped request, use the URI from the original
-        // request instead. getURI() on the wrapper seems to return a
-        // relative URI. We want an absolute URI.
-        if (request instanceof RequestWrapper) {
-            HttpRequest original = ((RequestWrapper) request).getOriginal();
-            if (original instanceof HttpUriRequest) {
-                uri = ((HttpUriRequest) original).getURI();
-            }
-        }
-
-        builder.append("\"");
-        builder.append(uri);
-        builder.append("\"");
-
-        if (request instanceof HttpEntityEnclosingRequest) {
-            HttpEntityEnclosingRequest entityRequest =
-                    (HttpEntityEnclosingRequest) request;
-            HttpEntity entity = entityRequest.getEntity();
-            if (entity != null && entity.isRepeatable()) {
-                if (entity.getContentLength() < 1024) {
-                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
-                    entity.writeTo(stream);
-                    String entityString = stream.toString();
-
-                    // TODO: Check the content type, too.
-                    builder.append(" --data-ascii \"")
-                            .append(entityString)
-                            .append("\"");
-                } else {
-                    builder.append(" [TOO MUCH DATA TO INCLUDE]");
-                }
-            }
-        }
-
-        return builder.toString();
-    }
-}
diff --git a/common/java/com/android/common/DNParser.java b/common/java/com/android/common/DNParser.java
deleted file mode 100644
index 32d57c0..0000000
--- a/common/java/com/android/common/DNParser.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.common;
-
-import android.util.Log;
-
-import java.io.IOException;
-
-import javax.security.auth.x500.X500Principal;
-
-/**
- * A simple distinguished name(DN) parser.
- *
- * <p>This class is based on org.apache.harmony.security.x509.DNParser.  It's customized to remove
- * external references which are unnecessary for our requirements.
- *
- * <p>This class is only meant for extracting a string value from a DN.  e.g. it doesn't support
- * values in the hex-string style.
- *
- * <p>This class is used by {@link DomainNameValidator} only.  However, in order to make this
- * class visible from unit tests, it's made public.
- */
-public final class DNParser {
-    private static final String TAG = "DNParser";
-
-    /** DN to be parsed. */
-    private final String dn;
-
-    // length of distinguished name string
-    private final int length;
-
-    private int pos, beg, end;
-
-    // tmp vars to store positions of the currently parsed item
-    private int cur;
-
-    // distinguished name chars
-    private char[] chars;
-
-    /**
-     * Exception message thrown when we failed to parse DN, which shouldn't happen because we
-     * only handle DNs that {@link X500Principal#getName} returns, which shouldn't be malformed.
-     */
-    private static final String ERROR_PARSE_ERROR = "Failed to parse DN";
-
-    /**
-     * Constructor.
-     *
-     * @param principal - {@link X500Principal} to be parsed
-     */
-    public DNParser(X500Principal principal) {
-        this.dn = principal.getName(X500Principal.RFC2253);
-        this.length = dn.length();
-    }
-
-    // gets next attribute type: (ALPHA 1*keychar) / oid
-    private String nextAT() throws IOException {
-
-        // skip preceding space chars, they can present after
-        // comma or semicolon (compatibility with RFC 1779)
-        for (; pos < length && chars[pos] == ' '; pos++) {
-        }
-        if (pos == length) {
-            return null; // reached the end of DN
-        }
-
-        // mark the beginning of attribute type
-        beg = pos;
-
-        // attribute type chars
-        pos++;
-        for (; pos < length && chars[pos] != '=' && chars[pos] != ' '; pos++) {
-            // we don't follow exact BNF syntax here:
-            // accept any char except space and '='
-        }
-        if (pos >= length) {
-            // unexpected end of DN
-            throw new IOException(ERROR_PARSE_ERROR);
-        }
-
-        // mark the end of attribute type
-        end = pos;
-
-        // skip trailing space chars between attribute type and '='
-        // (compatibility with RFC 1779)
-        if (chars[pos] == ' ') {
-            for (; pos < length && chars[pos] != '=' && chars[pos] == ' '; pos++) {
-            }
-
-            if (chars[pos] != '=' || pos == length) {
-                // unexpected end of DN
-                throw new IOException(ERROR_PARSE_ERROR);
-            }
-        }
-
-        pos++; //skip '=' char
-
-        // skip space chars between '=' and attribute value
-        // (compatibility with RFC 1779)
-        for (; pos < length && chars[pos] == ' '; pos++) {
-        }
-
-        // in case of oid attribute type skip its prefix: "oid." or "OID."
-        // (compatibility with RFC 1779)
-        if ((end - beg > 4) && (chars[beg + 3] == '.')
-                && (chars[beg] == 'O' || chars[beg] == 'o')
-                && (chars[beg + 1] == 'I' || chars[beg + 1] == 'i')
-                && (chars[beg + 2] == 'D' || chars[beg + 2] == 'd')) {
-            beg += 4;
-        }
-
-        return new String(chars, beg, end - beg);
-    }
-
-    // gets quoted attribute value: QUOTATION *( quotechar / pair ) QUOTATION
-    private String quotedAV() throws IOException {
-
-        pos++;
-        beg = pos;
-        end = beg;
-        while (true) {
-
-            if (pos == length) {
-                // unexpected end of DN
-                throw new IOException(ERROR_PARSE_ERROR);
-            }
-
-            if (chars[pos] == '"') {
-                // enclosing quotation was found
-                pos++;
-                break;
-            } else if (chars[pos] == '\\') {
-                chars[end] = getEscaped();
-            } else {
-                // shift char: required for string with escaped chars
-                chars[end] = chars[pos];
-            }
-            pos++;
-            end++;
-        }
-
-        // skip trailing space chars before comma or semicolon.
-        // (compatibility with RFC 1779)
-        for (; pos < length && chars[pos] == ' '; pos++) {
-        }
-
-        return new String(chars, beg, end - beg);
-    }
-
-    // gets hex string attribute value: "#" hexstring
-    private String hexAV() throws IOException {
-
-        if (pos + 4 >= length) {
-            // encoded byte array  must be not less then 4 c
-            throw new IOException(ERROR_PARSE_ERROR);
-        }
-
-        beg = pos; // store '#' position
-        pos++;
-        while (true) {
-
-            // check for end of attribute value
-            // looks for space and component separators
-            if (pos == length || chars[pos] == '+' || chars[pos] == ','
-                    || chars[pos] == ';') {
-                end = pos;
-                break;
-            }
-
-            if (chars[pos] == ' ') {
-                end = pos;
-                pos++;
-                // skip trailing space chars before comma or semicolon.
-                // (compatibility with RFC 1779)
-                for (; pos < length && chars[pos] == ' '; pos++) {
-                }
-                break;
-            } else if (chars[pos] >= 'A' && chars[pos] <= 'F') {
-                chars[pos] += 32; //to low case
-            }
-
-            pos++;
-        }
-
-        // verify length of hex string
-        // encoded byte array  must be not less then 4 and must be even number
-        int hexLen = end - beg; // skip first '#' char
-        if (hexLen < 5 || (hexLen & 1) == 0) {
-            throw new IOException(ERROR_PARSE_ERROR);
-        }
-
-        // get byte encoding from string representation
-        byte[] encoded = new byte[hexLen / 2];
-        for (int i = 0, p = beg + 1; i < encoded.length; p += 2, i++) {
-            encoded[i] = (byte) getByte(p);
-        }
-
-        return new String(chars, beg, hexLen);
-    }
-
-    // gets string attribute value: *( stringchar / pair )
-    private String escapedAV() throws IOException {
-
-        beg = pos;
-        end = pos;
-        while (true) {
-
-            if (pos >= length) {
-                // the end of DN has been found
-                return new String(chars, beg, end - beg);
-            }
-
-            switch (chars[pos]) {
-            case '+':
-            case ',':
-            case ';':
-                // separator char has beed found
-                return new String(chars, beg, end - beg);
-            case '\\':
-                // escaped char
-                chars[end++] = getEscaped();
-                pos++;
-                break;
-            case ' ':
-                // need to figure out whether space defines
-                // the end of attribute value or not
-                cur = end;
-
-                pos++;
-                chars[end++] = ' ';
-
-                for (; pos < length && chars[pos] == ' '; pos++) {
-                    chars[end++] = ' ';
-                }
-                if (pos == length || chars[pos] == ',' || chars[pos] == '+'
-                        || chars[pos] == ';') {
-                    // separator char or the end of DN has beed found
-                    return new String(chars, beg, cur - beg);
-                }
-                break;
-            default:
-                chars[end++] = chars[pos];
-                pos++;
-            }
-        }
-    }
-
-    // returns escaped char
-    private char getEscaped() throws IOException {
-
-        pos++;
-        if (pos == length) {
-            throw new IOException(ERROR_PARSE_ERROR);
-        }
-
-        switch (chars[pos]) {
-        case '"':
-        case '\\':
-        case ',':
-        case '=':
-        case '+':
-        case '<':
-        case '>':
-        case '#':
-        case ';':
-        case ' ':
-        case '*':
-        case '%':
-        case '_':
-            //FIXME: escaping is allowed only for leading or trailing space char
-            return chars[pos];
-        default:
-            // RFC doesn't explicitly say that escaped hex pair is
-            // interpreted as UTF-8 char. It only contains an example of such DN.
-            return getUTF8();
-        }
-    }
-
-    // decodes UTF-8 char
-    // see http://www.unicode.org for UTF-8 bit distribution table
-    private char getUTF8() throws IOException {
-
-        int res = getByte(pos);
-        pos++; //FIXME tmp
-
-        if (res < 128) { // one byte: 0-7F
-            return (char) res;
-        } else if (res >= 192 && res <= 247) {
-
-            int count;
-            if (res <= 223) { // two bytes: C0-DF
-                count = 1;
-                res = res & 0x1F;
-            } else if (res <= 239) { // three bytes: E0-EF
-                count = 2;
-                res = res & 0x0F;
-            } else { // four bytes: F0-F7
-                count = 3;
-                res = res & 0x07;
-            }
-
-            int b;
-            for (int i = 0; i < count; i++) {
-                pos++;
-                if (pos == length || chars[pos] != '\\') {
-                    return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
-                }
-                pos++;
-
-                b = getByte(pos);
-                pos++; //FIXME tmp
-                if ((b & 0xC0) != 0x80) {
-                    return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
-                }
-
-                res = (res << 6) + (b & 0x3F);
-            }
-            return (char) res;
-        } else {
-            return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
-        }
-    }
-
-    // Returns byte representation of a char pair
-    // The char pair is composed of DN char in
-    // specified 'position' and the next char
-    // According to BNF syntax:
-    // hexchar    = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
-    //                    / "a" / "b" / "c" / "d" / "e" / "f"
-    private int getByte(int position) throws IOException {
-
-        if ((position + 1) >= length) {
-            // to avoid ArrayIndexOutOfBoundsException
-            throw new IOException(ERROR_PARSE_ERROR);
-        }
-
-        int b1, b2;
-
-        b1 = chars[position];
-        if (b1 >= '0' && b1 <= '9') {
-            b1 = b1 - '0';
-        } else if (b1 >= 'a' && b1 <= 'f') {
-            b1 = b1 - 87; // 87 = 'a' - 10
-        } else if (b1 >= 'A' && b1 <= 'F') {
-            b1 = b1 - 55; // 55 = 'A' - 10
-        } else {
-            throw new IOException(ERROR_PARSE_ERROR);
-        }
-
-        b2 = chars[position + 1];
-        if (b2 >= '0' && b2 <= '9') {
-            b2 = b2 - '0';
-        } else if (b2 >= 'a' && b2 <= 'f') {
-            b2 = b2 - 87; // 87 = 'a' - 10
-        } else if (b2 >= 'A' && b2 <= 'F') {
-            b2 = b2 - 55; // 55 = 'A' - 10
-        } else {
-            throw new IOException(ERROR_PARSE_ERROR);
-        }
-
-        return (b1 << 4) + b2;
-    }
-
-    /**
-     * Parses the DN and returns the attribute value for an attribute type.
-     *
-     * @param attributeType attribute type to look for (e.g. "ca")
-     * @return value of the attribute that first found, or null if none found
-     */
-    public String find(String attributeType) {
-        try {
-            // Initialize internal state.
-            pos = 0;
-            beg = 0;
-            end = 0;
-            cur = 0;
-            chars = dn.toCharArray();
-
-            String attType = nextAT();
-            if (attType == null) {
-                return null;
-            }
-            while (true) {
-                String attValue = "";
-
-                if (pos == length) {
-                    return null;
-                }
-
-                switch (chars[pos]) {
-                case '"':
-                    attValue = quotedAV();
-                    break;
-                case '#':
-                    attValue = hexAV();
-                    break;
-                case '+':
-                case ',':
-                case ';': // compatibility with RFC 1779: semicolon can separate RDNs
-                    //empty attribute value
-                    break;
-                default:
-                    attValue = escapedAV();
-                }
-
-                if (attributeType.equalsIgnoreCase(attType)) {
-                    return attValue;
-                }
-
-                if (pos >= length) {
-                    return null;
-                }
-
-                if (chars[pos] == ',' || chars[pos] == ';') {
-                } else if (chars[pos] != '+') {
-                    throw new IOException(ERROR_PARSE_ERROR);
-                }
-
-                pos++;
-                attType = nextAT();
-                if (attType == null) {
-                    throw new IOException(ERROR_PARSE_ERROR);
-                }
-            }
-        } catch (IOException e) {
-            // Parse error shouldn't happen, because we only handle DNs that
-            // X500Principal.getName() returns, which shouldn't be malformed.
-            Log.e(TAG, "Failed to parse DN: " + dn);
-            return null;
-        }
-    }
-}
diff --git a/common/java/com/android/common/DomainNameValidator.java b/common/java/com/android/common/DomainNameValidator.java
deleted file mode 100644
index 25dc007..0000000
--- a/common/java/com/android/common/DomainNameValidator.java
+++ /dev/null
@@ -1,275 +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.
- */
-package com.android.common;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import javax.security.auth.x500.X500Principal;
-
-public class DomainNameValidator {
-    private final static String TAG = "DomainNameValidator";
-
-    private static final boolean DEBUG = false;
-    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
-
-    private static Pattern QUICK_IP_PATTERN;
-    static {
-        try {
-            QUICK_IP_PATTERN = Pattern.compile("^[a-f0-9\\.:]+$");
-        } catch (PatternSyntaxException e) {}
-    }
-
-    private static final int ALT_DNS_NAME = 2;
-    private static final int ALT_IPA_NAME = 7;
-
-    /**
-     * Checks the site certificate against the domain name of the site being visited
-     * @param certificate The certificate to check
-     * @param thisDomain The domain name of the site being visited
-     * @return True iff if there is a domain match as specified by RFC2818
-     */
-    public static boolean match(X509Certificate certificate, String thisDomain) {
-        if (certificate == null || thisDomain == null || thisDomain.length() == 0) {
-            return false;
-        }
-
-        thisDomain = thisDomain.toLowerCase();
-        if (!isIpAddress(thisDomain)) {
-            return matchDns(certificate, thisDomain);
-        } else {
-            return matchIpAddress(certificate, thisDomain);
-        }
-    }
-
-    /**
-     * @return True iff the domain name is specified as an IP address
-     */
-    private static boolean isIpAddress(String domain) {
-        boolean rval = (domain != null && domain.length() != 0);
-        if (rval) {
-            try {
-                // do a quick-dirty IP match first to avoid DNS lookup
-                rval = QUICK_IP_PATTERN.matcher(domain).matches();
-                if (rval) {
-                    rval = domain.equals(
-                        InetAddress.getByName(domain).getHostAddress());
-                }
-            } catch (UnknownHostException e) {
-                String errorMessage = e.getMessage();
-                if (errorMessage == null) {
-                  errorMessage = "unknown host exception";
-                }
-
-                if (LOG_ENABLED) {
-                    Log.v(TAG, "DomainNameValidator.isIpAddress(): " + errorMessage);
-                }
-
-                rval = false;
-            }
-        }
-
-        return rval;
-    }
-
-    /**
-     * Checks the site certificate against the IP domain name of the site being visited
-     * @param certificate The certificate to check
-     * @param thisDomain The DNS domain name of the site being visited
-     * @return True iff if there is a domain match as specified by RFC2818
-     */
-    private static boolean matchIpAddress(X509Certificate certificate, String thisDomain) {
-        if (LOG_ENABLED) {
-            Log.v(TAG, "DomainNameValidator.matchIpAddress(): this domain: " + thisDomain);
-        }
-
-        try {
-            Collection subjectAltNames = certificate.getSubjectAlternativeNames();
-            if (subjectAltNames != null) {
-                Iterator i = subjectAltNames.iterator();
-                while (i.hasNext()) {
-                    List altNameEntry = (List)(i.next());
-                    if (altNameEntry != null && 2 <= altNameEntry.size()) {
-                        Integer altNameType = (Integer)(altNameEntry.get(0));
-                        if (altNameType != null) {
-                            if (altNameType.intValue() == ALT_IPA_NAME) {
-                                String altName = (String)(altNameEntry.get(1));
-                                if (altName != null) {
-                                    if (LOG_ENABLED) {
-                                        Log.v(TAG, "alternative IP: " + altName);
-                                    }
-                                    if (thisDomain.equalsIgnoreCase(altName)) {
-                                        return true;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        } catch (CertificateParsingException e) {}
-
-        return false;
-    }
-
-    /**
-     * Checks the site certificate against the DNS domain name of the site being visited
-     * @param certificate The certificate to check
-     * @param thisDomain The DNS domain name of the site being visited
-     * @return True iff if there is a domain match as specified by RFC2818
-     */
-    private static boolean matchDns(X509Certificate certificate, String thisDomain) {
-        boolean hasDns = false;
-        try {
-            Collection subjectAltNames = certificate.getSubjectAlternativeNames();
-            if (subjectAltNames != null) {
-                Iterator i = subjectAltNames.iterator();
-                while (i.hasNext()) {
-                    List altNameEntry = (List)(i.next());
-                    if (altNameEntry != null && 2 <= altNameEntry.size()) {
-                        Integer altNameType = (Integer)(altNameEntry.get(0));
-                        if (altNameType != null) {
-                            if (altNameType.intValue() == ALT_DNS_NAME) {
-                                hasDns = true;
-                                String altName = (String)(altNameEntry.get(1));
-                                if (altName != null) {
-                                    if (matchDns(thisDomain, altName)) {
-                                        return true;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        } catch (CertificateParsingException e) {
-            String errorMessage = e.getMessage();
-            if (errorMessage == null) {
-                errorMessage = "failed to parse certificate";
-            }
-
-            Log.w(TAG, "DomainNameValidator.matchDns(): " + errorMessage);
-            return false;
-        }
-
-        if (!hasDns) {
-            final String cn = new DNParser(certificate.getSubjectX500Principal())
-                    .find("cn");
-            if (LOG_ENABLED) {
-                Log.v(TAG, "Validating subject: DN:"
-                        + certificate.getSubjectX500Principal().getName(X500Principal.CANONICAL)
-                        + "  CN:" + cn);
-            }
-            if (cn != null) {
-                return matchDns(thisDomain, cn);
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * @param thisDomain The domain name of the site being visited
-     * @param thatDomain The domain name from the certificate
-     * @return True iff thisDomain matches thatDomain as specified by RFC2818
-     */
-    // not private for testing
-    public static boolean matchDns(String thisDomain, String thatDomain) {
-        if (LOG_ENABLED) {
-            Log.v(TAG, "DomainNameValidator.matchDns():" +
-                      " this domain: " + thisDomain +
-                      " that domain: " + thatDomain);
-        }
-
-        if (thisDomain == null || thisDomain.length() == 0 ||
-            thatDomain == null || thatDomain.length() == 0) {
-            return false;
-        }
-
-        thatDomain = thatDomain.toLowerCase();
-
-        // (a) domain name strings are equal, ignoring case: X matches X
-        boolean rval = thisDomain.equals(thatDomain);
-        if (!rval) {
-            String[] thisDomainTokens = thisDomain.split("\\.");
-            String[] thatDomainTokens = thatDomain.split("\\.");
-
-            int thisDomainTokensNum = thisDomainTokens.length;
-            int thatDomainTokensNum = thatDomainTokens.length;
-
-            // (b) OR thatHost is a '.'-suffix of thisHost: Z.Y.X matches X
-            if (thisDomainTokensNum >= thatDomainTokensNum) {
-                for (int i = thatDomainTokensNum - 1; i >= 0; --i) {
-                    rval = thisDomainTokens[i].equals(thatDomainTokens[i]);
-                    if (!rval) {
-                        // (c) OR we have a special *-match:
-                        // *.Y.X matches Z.Y.X but *.X doesn't match Z.Y.X
-                        rval = (i == 0 && thisDomainTokensNum == thatDomainTokensNum);
-                        if (rval) {
-                            rval = thatDomainTokens[0].equals("*");
-                            if (!rval) {
-                                // (d) OR we have a *-component match:
-                                // f*.com matches foo.com but not bar.com
-                                rval = domainTokenMatch(
-                                    thisDomainTokens[0], thatDomainTokens[0]);
-                            }
-                        }
-                        break;
-                    }
-                }
-            } else {
-              // (e) OR thatHost has a '*.'-prefix of thisHost:
-              // *.Y.X matches Y.X
-              rval = thatDomain.equals("*." + thisDomain);
-            }
-        }
-
-        return rval;
-    }
-
-    /**
-     * @param thisDomainToken The domain token from the current domain name
-     * @param thatDomainToken The domain token from the certificate
-     * @return True iff thisDomainToken matches thatDomainToken, using the
-     * wildcard match as specified by RFC2818-3.1. For example, f*.com must
-     * match foo.com but not bar.com
-     */
-    private static boolean domainTokenMatch(String thisDomainToken, String thatDomainToken) {
-        if (thisDomainToken != null && thatDomainToken != null) {
-            int starIndex = thatDomainToken.indexOf('*');
-            if (starIndex >= 0) {
-                if (thatDomainToken.length() - 1 <= thisDomainToken.length()) {
-                    String prefix = thatDomainToken.substring(0,  starIndex);
-                    String suffix = thatDomainToken.substring(starIndex + 1);
-
-                    return thisDomainToken.startsWith(prefix) && thisDomainToken.endsWith(suffix);
-                }
-            }
-        }
-
-        return false;
-    }
-}
diff --git a/common/java/com/android/common/FastXmlSerializer.java b/common/java/com/android/common/FastXmlSerializer.java
deleted file mode 100644
index 0d33941..0000000
--- a/common/java/com/android/common/FastXmlSerializer.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-
-/**
- * This is a quick and dirty implementation of XmlSerializer that isn't horribly
- * painfully slow like the normal one.  It only does what is needed for the
- * specific XML files being written with it.
- */
-public class FastXmlSerializer implements XmlSerializer {
-    private static final String ESCAPE_TABLE[] = new String[] {
-        null,     null,     null,     null,     null,     null,     null,     null,  // 0-7
-        null,     null,     null,     null,     null,     null,     null,     null,  // 8-15
-        null,     null,     null,     null,     null,     null,     null,     null,  // 16-23
-        null,     null,     null,     null,     null,     null,     null,     null,  // 24-31
-        null,     null,     "&quot;", null,     null,     null,     "&amp;",  null,  // 32-39
-        null,     null,     null,     null,     null,     null,     null,     null,  // 40-47
-        null,     null,     null,     null,     null,     null,     null,     null,  // 48-55
-        null,     null,     null,     null,     "&lt;",   null,     "&gt;",   null,  // 56-63
-    };
-
-    private static final int BUFFER_LEN = 8192;
-
-    private final char[] mText = new char[BUFFER_LEN];
-    private int mPos;
-
-    private Writer mWriter;
-
-    private OutputStream mOutputStream;
-    private CharsetEncoder mCharset;
-    private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
-
-    private boolean mInTag;
-
-    private void append(char c) throws IOException {
-        int pos = mPos;
-        if (pos >= (BUFFER_LEN-1)) {
-            flush();
-            pos = mPos;
-        }
-        mText[pos] = c;
-        mPos = pos+1;
-    }
-
-    private void append(String str, int i, final int length) throws IOException {
-        if (length > BUFFER_LEN) {
-            final int end = i + length;
-            while (i < end) {
-                int next = i + BUFFER_LEN;
-                append(str, i, next<end ? BUFFER_LEN : (end-i));
-                i = next;
-            }
-            return;
-        }
-        int pos = mPos;
-        if ((pos+length) > BUFFER_LEN) {
-            flush();
-            pos = mPos;
-        }
-        str.getChars(i, i+length, mText, pos);
-        mPos = pos + length;
-    }
-
-    private void append(char[] buf, int i, final int length) throws IOException {
-        if (length > BUFFER_LEN) {
-            final int end = i + length;
-            while (i < end) {
-                int next = i + BUFFER_LEN;
-                append(buf, i, next<end ? BUFFER_LEN : (end-i));
-                i = next;
-            }
-            return;
-        }
-        int pos = mPos;
-        if ((pos+length) > BUFFER_LEN) {
-            flush();
-            pos = mPos;
-        }
-        System.arraycopy(buf, i, mText, pos, length);
-        mPos = pos + length;
-    }
-
-    private void append(String str) throws IOException {
-        append(str, 0, str.length());
-    }
-
-    private void escapeAndAppendString(final String string) throws IOException {
-        final int N = string.length();
-        final char NE = (char)ESCAPE_TABLE.length;
-        final String[] escapes = ESCAPE_TABLE;
-        int lastPos = 0;
-        int pos;
-        for (pos=0; pos<N; pos++) {
-            char c = string.charAt(pos);
-            if (c >= NE) continue;
-            String escape = escapes[c];
-            if (escape == null) continue;
-            if (lastPos < pos) append(string, lastPos, pos-lastPos);
-            lastPos = pos + 1;
-            append(escape);
-        }
-        if (lastPos < pos) append(string, lastPos, pos-lastPos);
-    }
-
-    private void escapeAndAppendString(char[] buf, int start, int len) throws IOException {
-        final char NE = (char)ESCAPE_TABLE.length;
-        final String[] escapes = ESCAPE_TABLE;
-        int end = start+len;
-        int lastPos = start;
-        int pos;
-        for (pos=start; pos<end; pos++) {
-            char c = buf[pos];
-            if (c >= NE) continue;
-            String escape = escapes[c];
-            if (escape == null) continue;
-            if (lastPos < pos) append(buf, lastPos, pos-lastPos);
-            lastPos = pos + 1;
-            append(escape);
-        }
-        if (lastPos < pos) append(buf, lastPos, pos-lastPos);
-    }
-
-    public XmlSerializer attribute(String namespace, String name, String value) throws IOException,
-            IllegalArgumentException, IllegalStateException {
-        append(' ');
-        if (namespace != null) {
-            append(namespace);
-            append(':');
-        }
-        append(name);
-        append("=\"");
-
-        escapeAndAppendString(value);
-        append('"');
-        return this;
-    }
-
-    public void cdsect(String text) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void comment(String text) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void docdecl(String text) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void endDocument() throws IOException, IllegalArgumentException, IllegalStateException {
-        flush();
-    }
-
-    public XmlSerializer endTag(String namespace, String name) throws IOException,
-            IllegalArgumentException, IllegalStateException {
-        if (mInTag) {
-            append(" />\n");
-        } else {
-            append("</");
-            if (namespace != null) {
-                append(namespace);
-                append(':');
-            }
-            append(name);
-            append(">\n");
-        }
-        mInTag = false;
-        return this;
-    }
-
-    public void entityRef(String text) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    private void flushBytes() throws IOException {
-        int position;
-        if ((position = mBytes.position()) > 0) {
-            mBytes.flip();
-            mOutputStream.write(mBytes.array(), 0, position);
-            mBytes.clear();
-        }
-    }
-
-    public void flush() throws IOException {
-        //Log.i("PackageManager", "flush mPos=" + mPos);
-        if (mPos > 0) {
-            if (mOutputStream != null) {
-                CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos);
-                CoderResult result = mCharset.encode(charBuffer, mBytes, true);
-                while (true) {
-                    if (result.isError()) {
-                        throw new IOException(result.toString());
-                    } else if (result.isOverflow()) {
-                        flushBytes();
-                        result = mCharset.encode(charBuffer, mBytes, true);
-                        continue;
-                    }
-                    break;
-                }
-                flushBytes();
-                mOutputStream.flush();
-            } else {
-                mWriter.write(mText, 0, mPos);
-                mWriter.flush();
-            }
-            mPos = 0;
-        }
-    }
-
-    public int getDepth() {
-        throw new UnsupportedOperationException();
-    }
-
-    public boolean getFeature(String name) {
-        throw new UnsupportedOperationException();
-    }
-
-    public String getName() {
-        throw new UnsupportedOperationException();
-    }
-
-    public String getNamespace() {
-        throw new UnsupportedOperationException();
-    }
-
-    public String getPrefix(String namespace, boolean generatePrefix)
-            throws IllegalArgumentException {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object getProperty(String name) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void ignorableWhitespace(String text) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void processingInstruction(String text) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void setFeature(String name, boolean state) throws IllegalArgumentException,
-            IllegalStateException {
-        if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) {
-            return;
-        }
-        throw new UnsupportedOperationException();
-    }
-
-    public void setOutput(OutputStream os, String encoding) throws IOException,
-            IllegalArgumentException, IllegalStateException {
-        if (os == null)
-            throw new IllegalArgumentException();
-        if (true) {
-            try {
-                mCharset = Charset.forName(encoding).newEncoder();
-            } catch (IllegalCharsetNameException e) {
-                throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
-                        encoding).initCause(e));
-            } catch (UnsupportedCharsetException e) {
-                throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
-                        encoding).initCause(e));
-            }
-            mOutputStream = os;
-        } else {
-            setOutput(
-                encoding == null
-                    ? new OutputStreamWriter(os)
-                    : new OutputStreamWriter(os, encoding));
-        }
-    }
-
-    public void setOutput(Writer writer) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        mWriter = writer;
-    }
-
-    public void setPrefix(String prefix, String namespace) throws IOException,
-            IllegalArgumentException, IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void setProperty(String name, Object value) throws IllegalArgumentException,
-            IllegalStateException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void startDocument(String encoding, Boolean standalone) throws IOException,
-            IllegalArgumentException, IllegalStateException {
-        append("<?xml version='1.0' encoding='utf-8' standalone='"
-                + (standalone ? "yes" : "no") + "' ?>\n");
-    }
-
-    public XmlSerializer startTag(String namespace, String name) throws IOException,
-            IllegalArgumentException, IllegalStateException {
-        if (mInTag) {
-            append(">\n");
-        }
-        append('<');
-        if (namespace != null) {
-            append(namespace);
-            append(':');
-        }
-        append(name);
-        mInTag = true;
-        return this;
-    }
-
-    public XmlSerializer text(char[] buf, int start, int len) throws IOException,
-            IllegalArgumentException, IllegalStateException {
-        if (mInTag) {
-            append(">");
-            mInTag = false;
-        }
-        escapeAndAppendString(buf, start, len);
-        return this;
-    }
-
-    public XmlSerializer text(String text) throws IOException, IllegalArgumentException,
-            IllegalStateException {
-        if (mInTag) {
-            append(">");
-            mInTag = false;
-        }
-        escapeAndAppendString(text);
-        return this;
-    }
-
-}
diff --git a/common/java/com/android/common/HttpDateTime.java b/common/java/com/android/common/HttpDateTime.java
deleted file mode 100644
index f4052cc..0000000
--- a/common/java/com/android/common/HttpDateTime.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-import android.text.format.Time;
-
-import java.util.Calendar;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-/** {@hide} */
-public final class HttpDateTime {
-
-    /*
-     * Regular expression for parsing HTTP-date.
-     *
-     * Wdy, DD Mon YYYY HH:MM:SS GMT
-     * RFC 822, updated by RFC 1123
-     *
-     * Weekday, DD-Mon-YY HH:MM:SS GMT
-     * RFC 850, obsoleted by RFC 1036
-     *
-     * Wdy Mon DD HH:MM:SS YYYY
-     * ANSI C's asctime() format
-     *
-     * with following variations
-     *
-     * Wdy, DD-Mon-YYYY HH:MM:SS GMT
-     * Wdy, (SP)D Mon YYYY HH:MM:SS GMT
-     * Wdy,DD Mon YYYY HH:MM:SS GMT
-     * Wdy, DD-Mon-YY HH:MM:SS GMT
-     * Wdy, DD Mon YYYY HH:MM:SS -HHMM
-     * Wdy, DD Mon YYYY HH:MM:SS
-     * Wdy Mon (SP)D HH:MM:SS YYYY
-     * Wdy Mon DD HH:MM:SS YYYY GMT
-     * 
-     * HH can be H if the first digit is zero.
-     * 
-     * Mon can be the full name of the month.
-     */
-    private static final String HTTP_DATE_RFC_REGEXP =
-            "([0-9]{1,2})[- ]([A-Za-z]{3,9})[- ]([0-9]{2,4})[ ]"
-            + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])";
-
-    private static final String HTTP_DATE_ANSIC_REGEXP =
-            "[ ]([A-Za-z]{3,9})[ ]+([0-9]{1,2})[ ]"
-            + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])[ ]([0-9]{2,4})";
-
-    /**
-     * The compiled version of the HTTP-date regular expressions.
-     */
-    private static final Pattern HTTP_DATE_RFC_PATTERN =
-            Pattern.compile(HTTP_DATE_RFC_REGEXP);
-    private static final Pattern HTTP_DATE_ANSIC_PATTERN =
-            Pattern.compile(HTTP_DATE_ANSIC_REGEXP);
-
-    private static class TimeOfDay {
-        TimeOfDay(int h, int m, int s) {
-            this.hour = h;
-            this.minute = m;
-            this.second = s;
-        }
-        
-        int hour;
-        int minute;
-        int second;
-    }
-
-    public static Long parse(String timeString)
-            throws IllegalArgumentException {
-
-        int date = 1;
-        int month = Calendar.JANUARY;
-        int year = 1970;
-        TimeOfDay timeOfDay;
-
-        Matcher rfcMatcher = HTTP_DATE_RFC_PATTERN.matcher(timeString);
-        if (rfcMatcher.find()) {
-            date = getDate(rfcMatcher.group(1));
-            month = getMonth(rfcMatcher.group(2));
-            year = getYear(rfcMatcher.group(3));
-            timeOfDay = getTime(rfcMatcher.group(4));
-        } else {
-            Matcher ansicMatcher = HTTP_DATE_ANSIC_PATTERN.matcher(timeString);
-            if (ansicMatcher.find()) {
-                month = getMonth(ansicMatcher.group(1));
-                date = getDate(ansicMatcher.group(2));
-                timeOfDay = getTime(ansicMatcher.group(3));
-                year = getYear(ansicMatcher.group(4));
-            } else {
-                throw new IllegalArgumentException();
-            }
-        }
-
-        // FIXME: Y2038 BUG!
-        if (year >= 2038) {
-            year = 2038;
-            month = Calendar.JANUARY;
-            date = 1;
-        }
-
-        Time time = new Time(Time.TIMEZONE_UTC);
-        time.set(timeOfDay.second, timeOfDay.minute, timeOfDay.hour, date,
-                month, year);
-        return time.toMillis(false /* use isDst */);
-    }
-
-    private static int getDate(String dateString) {
-        if (dateString.length() == 2) {
-            return (dateString.charAt(0) - '0') * 10
-                    + (dateString.charAt(1) - '0');
-        } else {
-            return (dateString.charAt(0) - '0');
-        }
-    }
-
-    /*
-     * jan = 9 + 0 + 13 = 22
-     * feb = 5 + 4 + 1 = 10
-     * mar = 12 + 0 + 17 = 29
-     * apr = 0 + 15 + 17 = 32
-     * may = 12 + 0 + 24 = 36
-     * jun = 9 + 20 + 13 = 42
-     * jul = 9 + 20 + 11 = 40
-     * aug = 0 + 20 + 6 = 26
-     * sep = 18 + 4 + 15 = 37
-     * oct = 14 + 2 + 19 = 35
-     * nov = 13 + 14 + 21 = 48
-     * dec = 3 + 4 + 2 = 9
-     */
-    private static int getMonth(String monthString) {
-        int hash = Character.toLowerCase(monthString.charAt(0)) +
-                Character.toLowerCase(monthString.charAt(1)) +
-                Character.toLowerCase(monthString.charAt(2)) - 3 * 'a';
-        switch (hash) {
-            case 22:
-                return Calendar.JANUARY;
-            case 10:
-                return Calendar.FEBRUARY;
-            case 29:
-                return Calendar.MARCH;
-            case 32:
-                return Calendar.APRIL;
-            case 36:
-                return Calendar.MAY;
-            case 42:
-                return Calendar.JUNE;
-            case 40:
-                return Calendar.JULY;
-            case 26:
-                return Calendar.AUGUST;
-            case 37:
-                return Calendar.SEPTEMBER;
-            case 35:
-                return Calendar.OCTOBER;
-            case 48:
-                return Calendar.NOVEMBER;
-            case 9:
-                return Calendar.DECEMBER;
-            default:
-                throw new IllegalArgumentException();
-        }
-    }
-
-    private static int getYear(String yearString) {
-        if (yearString.length() == 2) {
-            int year = (yearString.charAt(0) - '0') * 10
-                    + (yearString.charAt(1) - '0');
-            if (year >= 70) {
-                return year + 1900;
-            } else {
-                return year + 2000;
-            }
-        } else if (yearString.length() == 3) {
-            // According to RFC 2822, three digit years should be added to 1900.
-            int year = (yearString.charAt(0) - '0') * 100
-                    + (yearString.charAt(1) - '0') * 10
-                    + (yearString.charAt(2) - '0');
-            return year + 1900;
-        } else if (yearString.length() == 4) {
-             return (yearString.charAt(0) - '0') * 1000
-                    + (yearString.charAt(1) - '0') * 100
-                    + (yearString.charAt(2) - '0') * 10
-                    + (yearString.charAt(3) - '0');
-        } else {
-             return 1970;
-        }
-    }
-
-    private static TimeOfDay getTime(String timeString) {
-        // HH might be H
-        int i = 0;
-        int hour = timeString.charAt(i++) - '0';
-        if (timeString.charAt(i) != ':')
-            hour = hour * 10 + (timeString.charAt(i++) - '0');
-        // Skip ':'
-        i++;
-        
-        int minute = (timeString.charAt(i++) - '0') * 10
-                    + (timeString.charAt(i++) - '0');
-        // Skip ':'
-        i++;
-        
-        int second = (timeString.charAt(i++) - '0') * 10
-                  + (timeString.charAt(i++) - '0');
-
-        return new TimeOfDay(hour, minute, second);        
-    }
-}
diff --git a/common/java/com/android/common/OperationScheduler.java b/common/java/com/android/common/OperationScheduler.java
index 0c7ca83..0a48fe7 100644
--- a/common/java/com/android/common/OperationScheduler.java
+++ b/common/java/com/android/common/OperationScheduler.java
@@ -17,6 +17,7 @@
 package com.android.common;
 
 import android.content.SharedPreferences;
+import android.net.http.HttpDateTime;
 import android.text.format.Time;
 
 import java.util.Map;
diff --git a/common/java/com/android/common/Patterns.java b/common/java/com/android/common/Patterns.java
deleted file mode 100644
index 3b3b038..0000000
--- a/common/java/com/android/common/Patterns.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Commonly used regular expression patterns.
- */
-public class Patterns {
-    /**
-     *  Regular expression to match all IANA top-level domains.
-     *  List accurate as of 2010/02/05.  List taken from:
-     *  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
-     *  This pattern is auto-generated by frameworks/base/common/tools/make-iana-tld-pattern.py
-     */
-    public static final String TOP_LEVEL_DOMAIN_STR =
-        "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
-        + "|(biz|b[abdefghijmnorstvwyz])"
-        + "|(cat|com|coop|c[acdfghiklmnoruvxyz])"
-        + "|d[ejkmoz]"
-        + "|(edu|e[cegrstu])"
-        + "|f[ijkmor]"
-        + "|(gov|g[abdefghilmnpqrstuwy])"
-        + "|h[kmnrtu]"
-        + "|(info|int|i[delmnoqrst])"
-        + "|(jobs|j[emop])"
-        + "|k[eghimnprwyz]"
-        + "|l[abcikrstuvy]"
-        + "|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])"
-        + "|(name|net|n[acefgilopruz])"
-        + "|(org|om)"
-        + "|(pro|p[aefghklmnrstwy])"
-        + "|qa"
-        + "|r[eosuw]"
-        + "|s[abcdeghijklmnortuvyz]"
-        + "|(tel|travel|t[cdfghjklmnoprtvwz])"
-        + "|u[agksyz]"
-        + "|v[aceginu]"
-        + "|w[fs]"
-        + "|(xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-zckzah)"
-        + "|y[etu]"
-        + "|z[amw])";
-
-    /**
-     *  Regular expression pattern to match all IANA top-level domains.
-     */
-    public static final Pattern TOP_LEVEL_DOMAIN =
-        Pattern.compile(TOP_LEVEL_DOMAIN_STR);
-
-    /**
-     *  Regular expression to match all IANA top-level domains for WEB_URL.
-     *  List accurate as of 2010/02/05.  List taken from:
-     *  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
-     *  This pattern is auto-generated by frameworks/base/common/tools/make-iana-tld-pattern.py
-     */
-    public static final String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL =
-        "(?:"
-        + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
-        + "|(?:biz|b[abdefghijmnorstvwyz])"
-        + "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
-        + "|d[ejkmoz]"
-        + "|(?:edu|e[cegrstu])"
-        + "|f[ijkmor]"
-        + "|(?:gov|g[abdefghilmnpqrstuwy])"
-        + "|h[kmnrtu]"
-        + "|(?:info|int|i[delmnoqrst])"
-        + "|(?:jobs|j[emop])"
-        + "|k[eghimnprwyz]"
-        + "|l[abcikrstuvy]"
-        + "|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])"
-        + "|(?:name|net|n[acefgilopruz])"
-        + "|(?:org|om)"
-        + "|(?:pro|p[aefghklmnrstwy])"
-        + "|qa"
-        + "|r[eosuw]"
-        + "|s[abcdeghijklmnortuvyz]"
-        + "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
-        + "|u[agksyz]"
-        + "|v[aceginu]"
-        + "|w[fs]"
-        + "|(?:xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-zckzah)"
-        + "|y[etu]"
-        + "|z[amw]))";
-
-    /**
-     * Good characters for Internationalized Resource Identifiers (IRI).
-     * This comprises most common used Unicode characters allowed in IRI
-     * as detailed in RFC 3987.
-     * Specifically, those two byte Unicode characters are not included.
-     */
-    public static final String GOOD_IRI_CHAR =
-        "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
-
-    /**
-     *  Regular expression pattern to match most part of RFC 3987
-     *  Internationalized URLs, aka IRIs.  Commonly used Unicode characters are
-     *  added.
-     */
-    public static final Pattern WEB_URL = Pattern.compile(
-        "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
-        + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
-        + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
-        + "((?:(?:[" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]{0,64}\\.)+"   // named host
-        + TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL
-        + "|(?:(?:25[0-5]|2[0-4]" // or ip address
-        + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
-        + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
-        + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
-        + "|[1-9][0-9]|[0-9])))"
-        + "(?:\\:\\d{1,5})?)" // plus option port number
-        + "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~"  // plus option query params
-        + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
-        + "(?:\\b|$)"); // and finally, a word boundary or end of
-                        // input.  This is to stop foo.sure from
-                        // matching as foo.su
-
-    public static final Pattern IP_ADDRESS
-        = Pattern.compile(
-            "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
-            + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
-            + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
-            + "|[1-9][0-9]|[0-9]))");
-
-    public static final Pattern DOMAIN_NAME
-        = Pattern.compile(
-            "(((([" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]*)*[" + GOOD_IRI_CHAR + "]\\.)+"
-            + TOP_LEVEL_DOMAIN + ")|"
-            + IP_ADDRESS + ")");
-
-    public static final Pattern EMAIL_ADDRESS
-        = Pattern.compile(
-            "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
-            "\\@" +
-            "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
-            "(" +
-                "\\." +
-                "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
-            ")+"
-        );
-
-    /**
-     * This pattern is intended for searching for things that look like they
-     * might be phone numbers in arbitrary text, not for validating whether
-     * something is in fact a phone number.  It will miss many things that
-     * are legitimate phone numbers.
-     * 
-     * <p> The pattern matches the following:
-     * <ul>
-     * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
-     * may follow.
-     * <li>Optionally, sets of digits in parentheses, separated by spaces, dots, or dashes.
-     * <li>A string starting and ending with a digit, containing digits, spaces, dots, and/or dashes.
-     * </ul>
-     */
-    public static final Pattern PHONE
-        = Pattern.compile(                                  // sdd = space, dot, or dash
-                "(\\+[0-9]+[\\- \\.]*)?"                    // +<digits><sdd>*
-                + "(\\([0-9]+\\)[\\- \\.]*)?"               // (<digits>)<sdd>*
-                + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit> 
-
-    /**
-     *  Convenience method to take all of the non-null matching groups in a
-     *  regex Matcher and return them as a concatenated string.
-     *
-     *  @param matcher      The Matcher object from which grouped text will
-     *                      be extracted
-     *
-     *  @return             A String comprising all of the non-null matched
-     *                      groups concatenated together
-     */
-    public static final String concatGroups(Matcher matcher) {
-        StringBuilder b = new StringBuilder();
-        final int numGroups = matcher.groupCount();
-
-        for (int i = 1; i <= numGroups; i++) {
-            String s = matcher.group(i);
-
-            System.err.println("Group(" + i + ") : " + s);
-
-            if (s != null) {
-                b.append(s);
-            }
-        }
-
-        return b.toString();
-    }
-
-    /**
-     * Convenience method to return only the digits and plus signs
-     * in the matching string.
-     *
-     * @param matcher      The Matcher object from which digits and plus will
-     *                     be extracted
-     *
-     * @return             A String comprising all of the digits and plus in
-     *                     the match
-     */
-    public static final String digitsAndPlusOnly(Matcher matcher) {
-        StringBuilder buffer = new StringBuilder();
-        String matchingRegion = matcher.group();
-
-        for (int i = 0, size = matchingRegion.length(); i < size; i++) {
-            char character = matchingRegion.charAt(i);
-
-            if (character == '+' || Character.isDigit(character)) {
-                buffer.append(character);
-            }
-        }
-        return buffer.toString();
-    }
-
-    /**
-     * Do not create this static utility class.
-     */
-    private Patterns() {}
-}
diff --git a/common/java/com/android/common/XmlUtils.java b/common/java/com/android/common/XmlUtils.java
deleted file mode 100644
index dd57e49..0000000
--- a/common/java/com/android/common/XmlUtils.java
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import android.util.Xml;
-
-/** {@hide} */
-public class XmlUtils
-{
-
-    public static void skipCurrentTag(XmlPullParser parser)
-            throws XmlPullParserException, IOException {
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-               && (type != XmlPullParser.END_TAG
-                       || parser.getDepth() > outerDepth)) {
-        }
-    }
-
-    public static final int
-    convertValueToList(CharSequence value, String[] options, int defaultValue)
-    {
-        if (null != value) {
-            for (int i = 0; i < options.length; i++) {
-                if (value.equals(options[i]))
-                    return i;
-            }
-        }
-
-        return defaultValue;
-    }
-
-    public static final boolean
-    convertValueToBoolean(CharSequence value, boolean defaultValue)
-    {
-        boolean result = false;
-
-        if (null == value)
-            return defaultValue;
-
-        if (value.equals("1")
-        ||  value.equals("true")
-        ||  value.equals("TRUE"))
-            result = true;
-
-        return result;
-    }
-
-    public static final int
-    convertValueToInt(CharSequence charSeq, int defaultValue)
-    {
-        if (null == charSeq)
-            return defaultValue;
-
-        String nm = charSeq.toString();
-
-        // XXX This code is copied from Integer.decode() so we don't
-        // have to instantiate an Integer!
-
-        int value;
-        int sign = 1;
-        int index = 0;
-        int len = nm.length();
-        int base = 10;
-
-        if ('-' == nm.charAt(0)) {
-            sign = -1;
-            index++;
-        }
-
-        if ('0' == nm.charAt(index)) {
-            //  Quick check for a zero by itself
-            if (index == (len - 1))
-                return 0;
-
-            char    c = nm.charAt(index + 1);
-
-            if ('x' == c || 'X' == c) {
-                index += 2;
-                base = 16;
-            } else {
-                index++;
-                base = 8;
-            }
-        }
-        else if ('#' == nm.charAt(index))
-        {
-            index++;
-            base = 16;
-        }
-
-        return Integer.parseInt(nm.substring(index), base) * sign;
-    }
-
-    public static final int
-    convertValueToUnsignedInt(String value, int defaultValue)
-    {
-        if (null == value)
-            return defaultValue;
-
-        return parseUnsignedIntAttribute(value);
-    }
-
-    public static final int
-    parseUnsignedIntAttribute(CharSequence charSeq)
-    {
-        String  value = charSeq.toString();
-
-        long    bits;
-        int     index = 0;
-        int     len = value.length();
-        int     base = 10;
-
-        if ('0' == value.charAt(index)) {
-            //  Quick check for zero by itself
-            if (index == (len - 1))
-                return 0;
-
-            char    c = value.charAt(index + 1);
-
-            if ('x' == c || 'X' == c) {     //  check for hex
-                index += 2;
-                base = 16;
-            } else {                        //  check for octal
-                index++;
-                base = 8;
-            }
-        } else if ('#' == value.charAt(index)) {
-            index++;
-            base = 16;
-        }
-
-        return (int) Long.parseLong(value.substring(index), base);
-    }
-
-    /**
-     * Flatten a Map into an output stream as XML.  The map can later be
-     * read back with readMapXml().
-     *
-     * @param val The map to be flattened.
-     * @param out Where to write the XML data.
-     *
-     * @see #writeMapXml(Map, String, XmlSerializer)
-     * @see #writeListXml
-     * @see #writeValueXml
-     * @see #readMapXml
-     */
-    public static final void writeMapXml(Map val, OutputStream out)
-            throws XmlPullParserException, java.io.IOException {
-        XmlSerializer serializer = new FastXmlSerializer();
-        serializer.setOutput(out, "utf-8");
-        serializer.startDocument(null, true);
-        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-        writeMapXml(val, null, serializer);
-        serializer.endDocument();
-    }
-
-    /**
-     * Flatten a List into an output stream as XML.  The list can later be
-     * read back with readListXml().
-     *
-     * @param val The list to be flattened.
-     * @param out Where to write the XML data.
-     *
-     * @see #writeListXml(List, String, XmlSerializer)
-     * @see #writeMapXml
-     * @see #writeValueXml
-     * @see #readListXml
-     */
-    public static final void writeListXml(List val, OutputStream out)
-    throws XmlPullParserException, java.io.IOException
-    {
-        XmlSerializer serializer = Xml.newSerializer();
-        serializer.setOutput(out, "utf-8");
-        serializer.startDocument(null, true);
-        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-        writeListXml(val, null, serializer);
-        serializer.endDocument();
-    }
-
-    /**
-     * Flatten a Map into an XmlSerializer.  The map can later be read back
-     * with readThisMapXml().
-     *
-     * @param val The map to be flattened.
-     * @param name Name attribute to include with this list's tag, or null for
-     *             none.
-     * @param out XmlSerializer to write the map into.
-     *
-     * @see #writeMapXml(Map, OutputStream)
-     * @see #writeListXml
-     * @see #writeValueXml
-     * @see #readMapXml
-     */
-    public static final void writeMapXml(Map val, String name, XmlSerializer out)
-    throws XmlPullParserException, java.io.IOException
-    {
-        if (val == null) {
-            out.startTag(null, "null");
-            out.endTag(null, "null");
-            return;
-        }
-
-        Set s = val.entrySet();
-        Iterator i = s.iterator();
-
-        out.startTag(null, "map");
-        if (name != null) {
-            out.attribute(null, "name", name);
-        }
-
-        while (i.hasNext()) {
-            Map.Entry e = (Map.Entry)i.next();
-            writeValueXml(e.getValue(), (String)e.getKey(), out);
-        }
-
-        out.endTag(null, "map");
-    }
-
-    /**
-     * Flatten a List into an XmlSerializer.  The list can later be read back
-     * with readThisListXml().
-     *
-     * @param val The list to be flattened.
-     * @param name Name attribute to include with this list's tag, or null for
-     *             none.
-     * @param out XmlSerializer to write the list into.
-     *
-     * @see #writeListXml(List, OutputStream)
-     * @see #writeMapXml
-     * @see #writeValueXml
-     * @see #readListXml
-     */
-    public static final void writeListXml(List val, String name, XmlSerializer out)
-    throws XmlPullParserException, java.io.IOException
-    {
-        if (val == null) {
-            out.startTag(null, "null");
-            out.endTag(null, "null");
-            return;
-        }
-
-        out.startTag(null, "list");
-        if (name != null) {
-            out.attribute(null, "name", name);
-        }
-
-        int N = val.size();
-        int i=0;
-        while (i < N) {
-            writeValueXml(val.get(i), null, out);
-            i++;
-        }
-
-        out.endTag(null, "list");
-    }
-
-    /**
-     * Flatten a byte[] into an XmlSerializer.  The list can later be read back
-     * with readThisByteArrayXml().
-     *
-     * @param val The byte array to be flattened.
-     * @param name Name attribute to include with this array's tag, or null for
-     *             none.
-     * @param out XmlSerializer to write the array into.
-     *
-     * @see #writeMapXml
-     * @see #writeValueXml
-     */
-    public static final void writeByteArrayXml(byte[] val, String name,
-            XmlSerializer out)
-            throws XmlPullParserException, java.io.IOException {
-
-        if (val == null) {
-            out.startTag(null, "null");
-            out.endTag(null, "null");
-            return;
-        }
-
-        out.startTag(null, "byte-array");
-        if (name != null) {
-            out.attribute(null, "name", name);
-        }
-
-        final int N = val.length;
-        out.attribute(null, "num", Integer.toString(N));
-
-        StringBuilder sb = new StringBuilder(val.length*2);
-        for (int i=0; i<N; i++) {
-            int b = val[i];
-            int h = b>>4;
-            sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
-            h = b&0xff;
-            sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
-        }
-
-        out.text(sb.toString());
-
-        out.endTag(null, "byte-array");
-    }
-
-    /**
-     * Flatten an int[] into an XmlSerializer.  The list can later be read back
-     * with readThisIntArrayXml().
-     *
-     * @param val The int array to be flattened.
-     * @param name Name attribute to include with this array's tag, or null for
-     *             none.
-     * @param out XmlSerializer to write the array into.
-     *
-     * @see #writeMapXml
-     * @see #writeValueXml
-     * @see #readThisIntArrayXml
-     */
-    public static final void writeIntArrayXml(int[] val, String name,
-            XmlSerializer out)
-            throws XmlPullParserException, java.io.IOException {
-
-        if (val == null) {
-            out.startTag(null, "null");
-            out.endTag(null, "null");
-            return;
-        }
-
-        out.startTag(null, "int-array");
-        if (name != null) {
-            out.attribute(null, "name", name);
-        }
-
-        final int N = val.length;
-        out.attribute(null, "num", Integer.toString(N));
-
-        for (int i=0; i<N; i++) {
-            out.startTag(null, "item");
-            out.attribute(null, "value", Integer.toString(val[i]));
-            out.endTag(null, "item");
-        }
-
-        out.endTag(null, "int-array");
-    }
-
-    /**
-     * Flatten an object's value into an XmlSerializer.  The value can later
-     * be read back with readThisValueXml().
-     *
-     * Currently supported value types are: null, String, Integer, Long,
-     * Float, Double Boolean, Map, List.
-     *
-     * @param v The object to be flattened.
-     * @param name Name attribute to include with this value's tag, or null
-     *             for none.
-     * @param out XmlSerializer to write the object into.
-     *
-     * @see #writeMapXml
-     * @see #writeListXml
-     * @see #readValueXml
-     */
-    public static final void writeValueXml(Object v, String name, XmlSerializer out)
-    throws XmlPullParserException, java.io.IOException
-    {
-        String typeStr;
-        if (v == null) {
-            out.startTag(null, "null");
-            if (name != null) {
-                out.attribute(null, "name", name);
-            }
-            out.endTag(null, "null");
-            return;
-        } else if (v instanceof String) {
-            out.startTag(null, "string");
-            if (name != null) {
-                out.attribute(null, "name", name);
-            }
-            out.text(v.toString());
-            out.endTag(null, "string");
-            return;
-        } else if (v instanceof Integer) {
-            typeStr = "int";
-        } else if (v instanceof Long) {
-            typeStr = "long";
-        } else if (v instanceof Float) {
-            typeStr = "float";
-        } else if (v instanceof Double) {
-            typeStr = "double";
-        } else if (v instanceof Boolean) {
-            typeStr = "boolean";
-        } else if (v instanceof byte[]) {
-            writeByteArrayXml((byte[])v, name, out);
-            return;
-        } else if (v instanceof int[]) {
-            writeIntArrayXml((int[])v, name, out);
-            return;
-        } else if (v instanceof Map) {
-            writeMapXml((Map)v, name, out);
-            return;
-        } else if (v instanceof List) {
-            writeListXml((List)v, name, out);
-            return;
-        } else if (v instanceof CharSequence) {
-            // XXX This is to allow us to at least write something if
-            // we encounter styled text...  but it means we will drop all
-            // of the styling information. :(
-            out.startTag(null, "string");
-            if (name != null) {
-                out.attribute(null, "name", name);
-            }
-            out.text(v.toString());
-            out.endTag(null, "string");
-            return;
-        } else {
-            throw new RuntimeException("writeValueXml: unable to write value " + v);
-        }
-
-        out.startTag(null, typeStr);
-        if (name != null) {
-            out.attribute(null, "name", name);
-        }
-        out.attribute(null, "value", v.toString());
-        out.endTag(null, typeStr);
-    }
-
-    /**
-     * Read a HashMap from an InputStream containing XML.  The stream can
-     * previously have been written by writeMapXml().
-     *
-     * @param in The InputStream from which to read.
-     *
-     * @return HashMap The resulting map.
-     *
-     * @see #readListXml
-     * @see #readValueXml
-     * @see #readThisMapXml
-     * #see #writeMapXml
-     */
-    public static final HashMap readMapXml(InputStream in)
-    throws XmlPullParserException, java.io.IOException
-    {
-        XmlPullParser   parser = Xml.newPullParser();
-        parser.setInput(in, null);
-        return (HashMap)readValueXml(parser, new String[1]);
-    }
-
-    /**
-     * Read an ArrayList from an InputStream containing XML.  The stream can
-     * previously have been written by writeListXml().
-     *
-     * @param in The InputStream from which to read.
-     *
-     * @return HashMap The resulting list.
-     *
-     * @see #readMapXml
-     * @see #readValueXml
-     * @see #readThisListXml
-     * @see #writeListXml
-     */
-    public static final ArrayList readListXml(InputStream in)
-    throws XmlPullParserException, java.io.IOException
-    {
-        XmlPullParser   parser = Xml.newPullParser();
-        parser.setInput(in, null);
-        return (ArrayList)readValueXml(parser, new String[1]);
-    }
-
-    /**
-     * Read a HashMap object from an XmlPullParser.  The XML data could
-     * previously have been generated by writeMapXml().  The XmlPullParser
-     * must be positioned <em>after</em> the tag that begins the map.
-     *
-     * @param parser The XmlPullParser from which to read the map data.
-     * @param endTag Name of the tag that will end the map, usually "map".
-     * @param name An array of one string, used to return the name attribute
-     *             of the map's tag.
-     *
-     * @return HashMap The newly generated map.
-     *
-     * @see #readMapXml
-     */
-    public static final HashMap readThisMapXml(XmlPullParser parser, String endTag, String[] name)
-    throws XmlPullParserException, java.io.IOException
-    {
-        HashMap map = new HashMap();
-
-        int eventType = parser.getEventType();
-        do {
-            if (eventType == parser.START_TAG) {
-                Object val = readThisValueXml(parser, name);
-                if (name[0] != null) {
-                    //System.out.println("Adding to map: " + name + " -> " + val);
-                    map.put(name[0], val);
-                } else {
-                    throw new XmlPullParserException(
-                        "Map value without name attribute: " + parser.getName());
-                }
-            } else if (eventType == parser.END_TAG) {
-                if (parser.getName().equals(endTag)) {
-                    return map;
-                }
-                throw new XmlPullParserException(
-                    "Expected " + endTag + " end tag at: " + parser.getName());
-            }
-            eventType = parser.next();
-        } while (eventType != parser.END_DOCUMENT);
-
-        throw new XmlPullParserException(
-            "Document ended before " + endTag + " end tag");
-    }
-
-    /**
-     * Read an ArrayList object from an XmlPullParser.  The XML data could
-     * previously have been generated by writeListXml().  The XmlPullParser
-     * must be positioned <em>after</em> the tag that begins the list.
-     *
-     * @param parser The XmlPullParser from which to read the list data.
-     * @param endTag Name of the tag that will end the list, usually "list".
-     * @param name An array of one string, used to return the name attribute
-     *             of the list's tag.
-     *
-     * @return HashMap The newly generated list.
-     *
-     * @see #readListXml
-     */
-    public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, String[] name)
-    throws XmlPullParserException, java.io.IOException
-    {
-        ArrayList list = new ArrayList();
-
-        int eventType = parser.getEventType();
-        do {
-            if (eventType == parser.START_TAG) {
-                Object val = readThisValueXml(parser, name);
-                list.add(val);
-                //System.out.println("Adding to list: " + val);
-            } else if (eventType == parser.END_TAG) {
-                if (parser.getName().equals(endTag)) {
-                    return list;
-                }
-                throw new XmlPullParserException(
-                    "Expected " + endTag + " end tag at: " + parser.getName());
-            }
-            eventType = parser.next();
-        } while (eventType != parser.END_DOCUMENT);
-
-        throw new XmlPullParserException(
-            "Document ended before " + endTag + " end tag");
-    }
-
-    /**
-     * Read an int[] object from an XmlPullParser.  The XML data could
-     * previously have been generated by writeIntArrayXml().  The XmlPullParser
-     * must be positioned <em>after</em> the tag that begins the list.
-     *
-     * @param parser The XmlPullParser from which to read the list data.
-     * @param endTag Name of the tag that will end the list, usually "list".
-     * @param name An array of one string, used to return the name attribute
-     *             of the list's tag.
-     *
-     * @return Returns a newly generated int[].
-     *
-     * @see #readListXml
-     */
-    public static final int[] readThisIntArrayXml(XmlPullParser parser,
-            String endTag, String[] name)
-            throws XmlPullParserException, java.io.IOException {
-
-        int num;
-        try {
-            num = Integer.parseInt(parser.getAttributeValue(null, "num"));
-        } catch (NullPointerException e) {
-            throw new XmlPullParserException(
-                    "Need num attribute in byte-array");
-        } catch (NumberFormatException e) {
-            throw new XmlPullParserException(
-                    "Not a number in num attribute in byte-array");
-        }
-
-        int[] array = new int[num];
-        int i = 0;
-
-        int eventType = parser.getEventType();
-        do {
-            if (eventType == parser.START_TAG) {
-                if (parser.getName().equals("item")) {
-                    try {
-                        array[i] = Integer.parseInt(
-                                parser.getAttributeValue(null, "value"));
-                    } catch (NullPointerException e) {
-                        throw new XmlPullParserException(
-                                "Need value attribute in item");
-                    } catch (NumberFormatException e) {
-                        throw new XmlPullParserException(
-                                "Not a number in value attribute in item");
-                    }
-                } else {
-                    throw new XmlPullParserException(
-                            "Expected item tag at: " + parser.getName());
-                }
-            } else if (eventType == parser.END_TAG) {
-                if (parser.getName().equals(endTag)) {
-                    return array;
-                } else if (parser.getName().equals("item")) {
-                    i++;
-                } else {
-                    throw new XmlPullParserException(
-                        "Expected " + endTag + " end tag at: "
-                        + parser.getName());
-                }
-            }
-            eventType = parser.next();
-        } while (eventType != parser.END_DOCUMENT);
-
-        throw new XmlPullParserException(
-            "Document ended before " + endTag + " end tag");
-    }
-
-    /**
-     * Read a flattened object from an XmlPullParser.  The XML data could
-     * previously have been written with writeMapXml(), writeListXml(), or
-     * writeValueXml().  The XmlPullParser must be positioned <em>at</em> the
-     * tag that defines the value.
-     *
-     * @param parser The XmlPullParser from which to read the object.
-     * @param name An array of one string, used to return the name attribute
-     *             of the value's tag.
-     *
-     * @return Object The newly generated value object.
-     *
-     * @see #readMapXml
-     * @see #readListXml
-     * @see #writeValueXml
-     */
-    public static final Object readValueXml(XmlPullParser parser, String[] name)
-    throws XmlPullParserException, java.io.IOException
-    {
-        int eventType = parser.getEventType();
-        do {
-            if (eventType == parser.START_TAG) {
-                return readThisValueXml(parser, name);
-            } else if (eventType == parser.END_TAG) {
-                throw new XmlPullParserException(
-                    "Unexpected end tag at: " + parser.getName());
-            } else if (eventType == parser.TEXT) {
-                throw new XmlPullParserException(
-                    "Unexpected text: " + parser.getText());
-            }
-            eventType = parser.next();
-        } while (eventType != parser.END_DOCUMENT);
-
-        throw new XmlPullParserException(
-            "Unexpected end of document");
-    }
-
-    private static final Object readThisValueXml(XmlPullParser parser, String[] name)
-    throws XmlPullParserException, java.io.IOException
-    {
-        final String valueName = parser.getAttributeValue(null, "name");
-        final String tagName = parser.getName();
-
-        //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName);
-
-        Object res;
-
-        if (tagName.equals("null")) {
-            res = null;
-        } else if (tagName.equals("string")) {
-            String value = "";
-            int eventType;
-            while ((eventType = parser.next()) != parser.END_DOCUMENT) {
-                if (eventType == parser.END_TAG) {
-                    if (parser.getName().equals("string")) {
-                        name[0] = valueName;
-                        //System.out.println("Returning value for " + valueName + ": " + value);
-                        return value;
-                    }
-                    throw new XmlPullParserException(
-                        "Unexpected end tag in <string>: " + parser.getName());
-                } else if (eventType == parser.TEXT) {
-                    value += parser.getText();
-                } else if (eventType == parser.START_TAG) {
-                    throw new XmlPullParserException(
-                        "Unexpected start tag in <string>: " + parser.getName());
-                }
-            }
-            throw new XmlPullParserException(
-                "Unexpected end of document in <string>");
-        } else if (tagName.equals("int")) {
-            res = Integer.parseInt(parser.getAttributeValue(null, "value"));
-        } else if (tagName.equals("long")) {
-            res = Long.valueOf(parser.getAttributeValue(null, "value"));
-        } else if (tagName.equals("float")) {
-            res = new Float(parser.getAttributeValue(null, "value"));
-        } else if (tagName.equals("double")) {
-            res = new Double(parser.getAttributeValue(null, "value"));
-        } else if (tagName.equals("boolean")) {
-            res = Boolean.valueOf(parser.getAttributeValue(null, "value"));
-        } else if (tagName.equals("int-array")) {
-            parser.next();
-            res = readThisIntArrayXml(parser, "int-array", name);
-            name[0] = valueName;
-            //System.out.println("Returning value for " + valueName + ": " + res);
-            return res;
-        } else if (tagName.equals("map")) {
-            parser.next();
-            res = readThisMapXml(parser, "map", name);
-            name[0] = valueName;
-            //System.out.println("Returning value for " + valueName + ": " + res);
-            return res;
-        } else if (tagName.equals("list")) {
-            parser.next();
-            res = readThisListXml(parser, "list", name);
-            name[0] = valueName;
-            //System.out.println("Returning value for " + valueName + ": " + res);
-            return res;
-        } else {
-            throw new XmlPullParserException(
-                "Unknown tag: " + tagName);
-        }
-
-        // Skip through to end tag.
-        int eventType;
-        while ((eventType = parser.next()) != parser.END_DOCUMENT) {
-            if (eventType == parser.END_TAG) {
-                if (parser.getName().equals(tagName)) {
-                    name[0] = valueName;
-                    //System.out.println("Returning value for " + valueName + ": " + res);
-                    return res;
-                }
-                throw new XmlPullParserException(
-                    "Unexpected end tag in <" + tagName + ">: " + parser.getName());
-            } else if (eventType == parser.TEXT) {
-                throw new XmlPullParserException(
-                "Unexpected text in <" + tagName + ">: " + parser.getName());
-            } else if (eventType == parser.START_TAG) {
-                throw new XmlPullParserException(
-                    "Unexpected start tag in <" + tagName + ">: " + parser.getName());
-            }
-        }
-        throw new XmlPullParserException(
-            "Unexpected end of document in <" + tagName + ">");
-    }
-
-    public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
-    {
-        int type;
-        while ((type=parser.next()) != parser.START_TAG
-                   && type != parser.END_DOCUMENT) {
-            ;
-        }
-
-        if (type != parser.START_TAG) {
-            throw new XmlPullParserException("No start tag found");
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
-                    ", expected " + firstElementName);
-        }
-    }
-
-    public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
-    {
-        int type;
-        while ((type=parser.next()) != parser.START_TAG
-                   && type != parser.END_DOCUMENT) {
-            ;
-        }
-    }
-}
diff --git a/common/java/com/android/common/speech/Recognition.java b/common/java/com/android/common/speech/Recognition.java
index 6f164a9..a79a19b 100644
--- a/common/java/com/android/common/speech/Recognition.java
+++ b/common/java/com/android/common/speech/Recognition.java
@@ -19,18 +19,42 @@
 /**
  * Utilities for voice recognition implementations.
  *
- * @see android.app.RecognitionService
+ * @see android.speech.RecognitionService
+ * @see android.speech.RecognizerIntent
  */
 public class Recognition {
-
+    
     /**
-     * The extra key used in an intent to the speech recognizer for voice search. Not
-     * generally to be used by developers. The system search dialog uses this, for example,
-     * to set a calling package for identification by a voice search API. If this extra
-     * is set by anyone but the system process, it should be overridden by the voice search
-     * implementation.
+     * The key to the extra in the Bundle returned by
+     * android.speech.RecognizerIntent#ACTION_GET_LANGUAGE_DETAILS
+     * which is an ArrayList of CharSequences which are hints that can be shown to
+     * the user for voice actions currently supported by voice search for the user's current
+     * language preference for voice search (i.e., the one defined in the extra
+     * android.speech.RecognizerIntent#EXTRA_LANGUAGE_PREFERENCE).
+     *
+     * If this is paired with EXTRA_HINT_CONTEXT, should return a set of hints that are
+     * appropriate for the provided context.
+     *
+     * The CharSequences are SpannedStrings and will contain segments wrapped in
+     * <annotation action="true"></annotation>. This is to indicate the section of the text
+     * which represents the voice action, to be highlighted in the UI if so desired.
      */
-    public final static String EXTRA_CALLING_PACKAGE = "calling_package";
+    public static final String EXTRA_HINT_STRINGS = "android.speech.extra.HINT_STRINGS";
+    
+    /**
+     * The key to an extra to be included in the request intent for
+     * android.speech.RecognizerIntent#ACTION_GET_LANGUAGE_DETAILS.
+     * Should be an int of one of the values defined below. If an
+     * unknown int value is provided, it should be ignored.
+     */
+    public static final String EXTRA_HINT_CONTEXT = "android.speech.extra.HINT_CONTEXT";
+    
+    /**
+     * A set of values for EXTRA_HINT_CONTEXT.
+     */
+    public static final int HINT_CONTEXT_UNKNOWN = 0;
+    public static final int HINT_CONTEXT_VOICE_SEARCH_HELP = 1;
+    public static final int HINT_CONTEXT_CAR_HOME = 2;
 
     private Recognition() { }   // don't instantiate
 }
diff --git a/common/tests/res/raw/alt_ip_only.crt b/common/tests/res/raw/alt_ip_only.crt
deleted file mode 100644
index 3ac9f5a..0000000
--- a/common/tests/res/raw/alt_ip_only.crt
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICsjCCAZqgAwIBAgIJALrC37YAXFIeMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV
-BAYTAkpQMCAXDTEwMDExMjIxMzk0NloYDzIwNjQxMDE1MjEzOTQ2WjANMQswCQYD
-VQQGEwJKUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALr8s/4Abpby
-IYks5YCJE2nbWH7kj6XbwnRzsVP9RVC33bPoQ1M+2ZY24HqkigjQS/HEXR0s0bYh
-dewNUnTj1uGyGs6cYzsbu7x114vmVYqjxUo3hKjwfYiPeF6f3IE1vpLI7I2G32gq
-Zwm9c1/vXNHIdWQxCpFcuPA8P3YGfoApFX4pQPFplBUNAQqnjdmA68cbxxMC+1F3
-mX42D7iIEVwyVpah5HjyxjIZQlf3X7QBj0bCmkL+ibIHTALrkNNwNM6i4xzYLz/5
-14GkN9ncHY87eSOk6r53ptER6mQMhCe9qPRjSHnpWTTyj6IXTaYe+dDQw657B80w
-cSHL7Ed25zUCAwEAAaMTMBEwDwYDVR0RBAgwBocEwKgKATANBgkqhkiG9w0BAQUF
-AAOCAQEAgrwrtOWZT3fbi1AafpGaAiOBWSJqYqRhtQy0AfiZBxv1U0XaYqmZmpnq
-DVAqr0NkljowD28NBrxIFO5gBNum2ZOPDl2/5vjFn+IirUCJ9u9wS7zYkTCW2lQR
-xE7Ic3mfWv7wUbKDfjlWqP1IDHUxwkrBTAl+HnwOPiaKKk1ttwcrgS8AHlqASe03
-mlwnvJ+Stk54IneRaegL0L93sNAy63RZqnPCTxGz7eHcFwX8Jdr4sbxTxQqV6pIc
-WPjHQcWfpkFzAF5wyOq0kveVfx0g5xPhOVDd+U+q7WastbXICpCoHp9FxISmZVik
-sAyifp8agkYdzaSh55fFmKXlFnRsQw==
------END CERTIFICATE-----
diff --git a/common/tests/res/raw/subject_alt_only.crt b/common/tests/res/raw/subject_alt_only.crt
deleted file mode 100644
index d5808fb..0000000
--- a/common/tests/res/raw/subject_alt_only.crt
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICvTCCAaWgAwIBAgIJALbA0TZk2YmNMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV
-BAYTAkpQMCAXDTEwMDExMjIwNTg1NFoYDzIwNjQxMDE1MjA1ODU0WjANMQswCQYD
-VQQGEwJKUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMEg6acVC9V4
-xNGoLNVLPbqBc8IvMvcsc88dF6MW3d9VagX3aeWU8c79tI/KOV/1AOakH7WYxw/w
-yD8aOX7+9BK1Hu0qKKKbSM+ycqaMthXd6xytrNDsIx5WiGUz8zTko0Gk3orIR7p7
-rPcNzB/zwtESkscqPv85aEn7S/yClNkzLfEzm3CtaYOc0tfhBMyzi/ipXzGMxUmx
-PvOLr3v/Oz5pZEQw7Kxlm4+tAtn7bJlHziQ1UW4WPIy+T3hySBEpODFiqZi7Ok3X
-Zjxdii62fgo5B2Ee7q5Amo0mUIwcQTDjJ2CLAqzYnSh3tpiPJGjEIjmRyCoMQ1bx
-7D+y7nSPIq8CAwEAAaMeMBwwGgYDVR0RBBMwEYIPd3d3LmV4YW1wbGUuY29tMA0G
-CSqGSIb3DQEBBQUAA4IBAQBsGEh+nHc0l9FJTzWqvG3qs7i6XoJZdtThCDx4HjKJ
-8GMrJtreNN4JvIxn7KC+alVbnILjzCRO+c3rsnpxKBi5cp2imjuw5Kf/x2Seimb9
-UvZbaJvBVOzy4Q1IGef9bLy3wZzy2/WfBFyvPTAkgkRaX7LN2jnYOYVhNoNFrwqe
-EWxkA6fzrpyseUEFeGFFjGxRSRCDcQ25Eq6d9rkC1x21zNtt4QwZBO0wHrTy155M
-JPRynf9244Pn0Sr/wsnmdsTRFIFYynrc51hQ7DkwbUxpcaewkZzilru/SwZ3+pPT
-9JSqm5hJ1pg5WDlPkW7c/1VA0/141N52Q8MIU+2ZpuOj
------END CERTIFICATE-----
diff --git a/common/tests/res/raw/subject_only.crt b/common/tests/res/raw/subject_only.crt
deleted file mode 100644
index 11b34e7..0000000
--- a/common/tests/res/raw/subject_only.crt
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC0TCCAbmgAwIBAgIJANCQbJPPw31SMA0GCSqGSIb3DQEBBQUAMCcxCzAJBgNV
-BAYTAkpQMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wIBcNMTAwMTEyMjA1ODE4
-WhgPMjA2NDEwMTUyMDU4MThaMCcxCzAJBgNVBAYTAkpQMRgwFgYDVQQDEw93d3cu
-ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDsdUJk
-4KxADA3vlDHxNbyC27Ozw4yiSVzPTHUct471YmdDRW3orO2P5a5hRnUGV70gjH9X
-MU4oeOdWYAgXB9pxfLyr6621k1+uNrmaZtzp0ECH9twcwxNJJFDZsN7o9vt7V6Ej
-NN9weeqDr/aeQXo07a12vyVfR6jWO8jHB0e4aemwZNoYjNvM69fivQTse2ZoRVfj
-eSHhjRTX6I8ry4a31Hwt+fT1QiWWNN6o7+WOtpJAhX3eg4smhSD1svi2kOT8tdUe
-NS4hWlmXmumU9G4tI8PBurcLNTm7PB2lUlbn/IV18WavqKE/Uy/1WgAx+a1EJNdp
-i07AG1PsqaONKkf1AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAJrNsuL7fZZNC8gL
-BdePJ7DYW2e7mXANU3bCBe2BZqmXKQxKwibZnEsqA+yMLqcSd8uxISlyHY2tw9wT
-4wB9KPIttfNLbwn/rk+MbOTHpvyF60d9WhJJVUkPBl8D4VuPSl+VnlA54kU9dtZN
-+ZYdxYbNtSsI/Flz9SCoOV79W9GhN+uYJhv6RwyIMIHeMpZpyX1xSUVx5dZlmerQ
-WAUvghDH3fFRt2ZdnA4OXoKkTAaM3Pv7PUMsnah8bux6MQi0AuLMWFWOI1H34koH
-rs2oQLwOLnuifH52ey9+tJguabo+brlYYigAuWWFEzJfBzikDkIwnE/L7wlrypIk
-taXDWI4=
------END CERTIFICATE-----
diff --git a/common/tests/res/raw/subject_with_alt_names.crt b/common/tests/res/raw/subject_with_alt_names.crt
deleted file mode 100644
index 6963c7e..0000000
--- a/common/tests/res/raw/subject_with_alt_names.crt
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDBDCCAeygAwIBAgIJALv14qjcuhw9MA0GCSqGSIb3DQEBBQUAMCcxCzAJBgNV
-BAYTAkpQMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wIBcNMTAwMTEyMjA1OTM4
-WhgPMjA2NDEwMTUyMDU5MzhaMCcxCzAJBgNVBAYTAkpQMRgwFgYDVQQDEw93d3cu
-ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCiTVgU
-kBO9KNYZZLmiPR0eBrk8u61CLnm35BGKW8EFpDaINLbbIFIQvqOMekURON/N+xFY
-D8roo7aFZVuHWAUqFcOJ4e6NmviK5qocLihtzAexsw4f4AzZxM3A8kcLlWLyAt7e
-EVLxhcMHogY7GaF6q+33Z8p+zp6x3tj07mwyPrriCLse2PeRsRunZl/fp/VvRlr6
-YbC7CbRrhnIv5nqohs8BsbBiiFpxQftsMQmiXhY2LUzqY2RXUIOw24fHjoQkHTL2
-4z5nUM3b6ueQe+CBnobUS6fzK/36Nct4dRpev9i/ORdRLuIDKJ+QR16G1V/BJYBR
-dAK+3iXvg6z8vP1XAgMBAAGjMTAvMC0GA1UdEQQmMCSCEHd3dzIuZXhhbXBsZS5j
-b22CEHd3dzMuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEBAJQNf38uXm3h
-0vsF+Yd6/HqM48Su7tWnTDAfTXnQZZkzjzITq3JXzquMXICktAVN2cLnT9zPfRAE
-8V8A3BNO5zXiR5W3o/mJP5HQ3/WxpzBGM2N+YmDCJyBoQrIVaAZaXAZUaBBvn5A+
-kEVfGWquwIFuvA67xegbJOCRLD4eUzRdNsn5+NFiakWO1tkFqEzqyQ0PNPviRjgu
-z9NxdPvd1JQOhydkucsPKJzlEBbGyL5QL/Jkot3Qy+FOeuNzgQUfAGtQgzRrsZDK
-hrTVypLSoRXuTB2aWilu4p6aNh84xTdyqo2avtNr2MiQMZIcdamBq8LdBIAShFXI
-h5G2eVGXH/Y=
------END CERTIFICATE-----
diff --git a/common/tests/res/raw/subject_with_wild_alt_name.crt b/common/tests/res/raw/subject_with_wild_alt_name.crt
deleted file mode 100644
index 19b1174..0000000
--- a/common/tests/res/raw/subject_with_wild_alt_name.crt
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC8DCCAdigAwIBAgIJAL/oWJ64VAdXMA0GCSqGSIb3DQEBBQUAMCcxCzAJBgNV
-BAYTAkpQMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wIBcNMTAwMTEyMjEwMDAx
-WhgPMjA2NDEwMTUyMTAwMDFaMCcxCzAJBgNVBAYTAkpQMRgwFgYDVQQDEw93d3cu
-ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbx1QB
-92iea7VybLYICA4MX4LWipYrRsgXUXQrcIQ3YLTQ9rH0VwScrHL4O4JDxgXCQnR+
-4VOzD42q1KXHJAqzqGUYCNPyvZEzkGCnQ4FBIUEmxZd5SNEefJVH3Z6GizYJomTh
-p78yDcoqymD9umxRC2cWFu8GscfFGMVyhsqLlOofu7UWOs22mkXPo43jDx+VOAoV
-n48YP3P57a2Eo0gcd4zVL00y62VegqBO/1LW38aTS7teiCBFc1TkNYa5I40yN9lP
-rB9ICHYQWyzf/7OxU9iauEK2w6DmSsQoLs9JzEhgeNZddkcc77ciSUCo2Hx0VpOJ
-BFyf2rbryJeAk+FDAgMBAAGjHTAbMBkGA1UdEQQSMBCCDiouZXhhbXBsZTIuY29t
-MA0GCSqGSIb3DQEBBQUAA4IBAQA2a14pRL+4laJ8sscQlucaDB/oSdb0cwhk4IkE
-kKl/ZKr6rKwPZ81sJRgzvI4imLbUAKt4AJHdpI9cIQUq1gw9bzil7LKwmFtFSPmC
-MYb1iadaYrvp7RE4yXrWCcSbU0hup9JQLHTrHLlqLtRuU48NHMvWYThBcS9Q/hQp
-nJ/JxYy3am99MHALWLAfuRxQXhE4C5utDmBwI2KD6A8SA30s+CnuegmkYScuSqBu
-Y3R0HZvKzNIU3pwAm69HCJoG+/9MZEIDJb0WJc5UygxDT45XE9zQMQe4dBOTaNXT
-+ntgaB62kE10HzrzpqXAgoAWxWK4RzFcUpBWw9qYq9xOCewJ
------END CERTIFICATE-----
diff --git a/common/tests/res/raw/wild_alt_name_only.crt b/common/tests/res/raw/wild_alt_name_only.crt
deleted file mode 100644
index fafdebf..0000000
--- a/common/tests/res/raw/wild_alt_name_only.crt
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICuzCCAaOgAwIBAgIJAP82tgcvmAGxMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV
-BAYTAkpQMCAXDTEwMDExMjIxMDAyN1oYDzIwNjQxMDE1MjEwMDI3WjANMQswCQYD
-VQQGEwJKUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALs528EQbcB1
-x4BwxthQBZrgDJzoO7KPV3dhGYoeP8EnRjapZm+T/sj9P/O4HvfxjnB+fsjYSdmE
-WWUtnFrP7wtG9DUC748Ea2PMV8WFhOG58dqBNIko5XzkHB7SxkNZD5S/0KQYMGLr
-rchDsDlmsEf2Qb6qiqpNEU70aSkExZJcH+B9nWdeBpsVFu7wtezwSWEc2NUa2bhW
-gcXQ/aafwHZ4o2PyGwy0sgS/UifqO9tEllC2tPleSNJOmYsVudv5Bz4Q0GG38BSz
-Pc0IcOoln0ZWpXbGr03V2vlXWCwzaFAl3I1T3O7YVqDiaSWoP+d0tHZzmw8aJLXd
-B+KaUUGxRPsCAwEAAaMcMBowGAYDVR0RBBEwD4INKi5leGFtcGxlLmNvbTANBgkq
-hkiG9w0BAQUFAAOCAQEAJbVan4QgJ0cvpJnK9UWIVJNC+UbP87RC5go2fQiTnmGv
-prOrIuMqz1+vGcpIheLTLctJRHPoadXq0+UbQEIaU3pQbY6C4nNdfl+hcvmJeqrt
-kOCcvmIamO68iNvTSeszuHuu4O38PefrW2Xd0nn7bjFZrzBzHFhTudmnqNliP3ue
-KKQpqkUt5lCytnH8V/u/UCWdvVx5LnUa2XFGVLi3ongBIojW5fvF+yxn9ADqxdrI
-va++ow5r1VxQXFJc0ZPzsDo+6TlktoDHaRQJGMqQomqHWT4i7F5UZgf6BHGfEUPU
-qep+GsF3QRHSBtpObWkVDZNFvky3a1iZ2q25+hFIqQ==
------END CERTIFICATE-----
diff --git a/common/tests/src/com/android/common/DNParserTest.java b/common/tests/src/com/android/common/DNParserTest.java
deleted file mode 100644
index 34b140a..0000000
--- a/common/tests/src/com/android/common/DNParserTest.java
+++ /dev/null
@@ -1,49 +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.
- */
-package com.android.common;
-
-import javax.security.auth.x500.X500Principal;
-
-import junit.framework.TestCase;
-
-public class DNParserTest extends TestCase {
-    public void testFind() {
-        checkFind("", "cn", null);
-        checkFind("ou=xxx", "cn", null);
-        checkFind("ou=xxx,cn=xxx", "cn", "xxx");
-        checkFind("ou=xxx+cn=yyy,cn=zzz+cn=abc", "cn", "yyy");
-        checkFind("2.5.4.3=a,ou=xxx", "cn", "a"); // OID
-        checkFind("cn=a,cn=b", "cn", "a");
-        checkFind("ou=Cc,ou=Bb,ou=Aa", "ou", "Cc");
-        checkFind("cn=imap.gmail.com", "cn", "imap.gmail.com");
-
-        // Quoted string (see http://www.ietf.org/rfc/rfc2253.txt)
-        checkFind("o=\"\\\" a ,=<>#;\"", "o", "\" a ,=<>#;");
-        checkFind("o=abc\\,def", "o", "abc,def");
-
-        // UTF-8 (example in rfc 2253)
-        checkFind("cn=Lu\\C4\\8Di\\C4\\87", "cn", "\u004c\u0075\u010d\u0069\u0107");
-
-        // whitespaces
-        checkFind("ou=a, o=  a  b  ,cn=x", "o", "a  b");
-        checkFind("o=\"  a  b  \" ,cn=x", "o", "  a  b  ");
-    }
-
-    private void checkFind(String dn, String attrType, String expected) {
-        String actual = new DNParser(new X500Principal(dn)).find(attrType);
-        assertEquals("dn:" + dn + "  attr:" + attrType, expected, actual);
-    }
-}
diff --git a/common/tests/src/com/android/common/DomainNameValidatorTest.java b/common/tests/src/com/android/common/DomainNameValidatorTest.java
deleted file mode 100644
index b825be4..0000000
--- a/common/tests/src/com/android/common/DomainNameValidatorTest.java
+++ /dev/null
@@ -1,399 +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.
- */
-package com.android.common;
-
-import com.android.common.tests.R;
-
-import android.test.AndroidTestCase;
-
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Principal;
-import java.security.PublicKey;
-import java.security.SignatureException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import javax.security.auth.x500.X500Principal;
-
-public class DomainNameValidatorTest extends AndroidTestCase {
-    private static final int ALT_UNKNOWN = 0;
-    private static final int ALT_DNS_NAME = 2;
-    private static final int ALT_IPA_NAME = 7;
-
-    /**
-     * Tests {@link DomainNameValidator#match}, using a simple {@link X509Certificate}
-     * implementation.
-     */
-    public void testMatch() {
-        checkMatch("11", new StubX509Certificate("cn=imap.g.com"), "imap.g.com", true);
-        checkMatch("12", new StubX509Certificate("cn=imap2.g.com"), "imap.g.com", false);
-        checkMatch("13", new StubX509Certificate("cn=sub.imap.g.com"), "imap.g.com", false);
-
-        // If a subjectAltName extension of type dNSName is present, that MUST
-        // be used as the identity
-        checkMatch("21", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "a.y.com")
-                , "imap.g.com", false);
-        checkMatch("22", new StubX509Certificate("cn=imap.g.com") // This cn should be ignored
-                .addSubjectAlternativeName(ALT_DNS_NAME, "a.y.com")
-                , "imap.g.com", false);
-        checkMatch("23", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
-                , "imap.g.com", true);
-
-        // With wildcards
-        checkMatch("24", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "*.g.com")
-                , "imap.g.com", true);
-
-        // host name is ip address
-        checkMatch("31", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4")
-                , "1.2.3.4", true);
-        checkMatch("32", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4")
-                , "1.2.3.5", false);
-        checkMatch("32", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "192.168.100.1")
-                , "192.168.100.1", true);
-
-        // Has unknown subject alternative names
-        checkMatch("41", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
-                .addSubjectAlternativeName(ALT_UNKNOWN,  "random string 2")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
-                , "imap.g.com", true);
-
-        checkMatch("42", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
-                , "2.33.44.55", true);
-
-        checkMatch("43", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
-                , "g.com", false);
-
-        checkMatch("44", new StubX509Certificate("")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
-                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
-                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
-                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
-                , "2.33.44.1", false);
-    }
-
-    private void checkMatch(String message, X509Certificate certificate, String thisDomain,
-            boolean expected) {
-        Boolean actual = DomainNameValidator.match(certificate, thisDomain);
-        assertEquals(message, (Object) expected, (Object) actual);
-    }
-
-    /**
-     * Tests {@link DomainNameValidator#matchDns}
-     */
-    public void testMatchDns() {
-        checkMatchDns("11", "a.b.c.d", "a.b.c.d", true);
-        checkMatchDns("12", "a.b.c.d", "*.b.c.d", true);
-        checkMatchDns("13", "b.c.d", "*.b.c.d", true);
-        checkMatchDns("14", "b.c.d", "b*.c.d", true);
-
-        checkMatchDns("15", "a.b.c.d", "*.*.c.d", false);
-        checkMatchDns("16", "a.b.c.d", "*.c.d", false);
-
-        checkMatchDns("21", "imap.google.com", "imap.google.com", true);
-        checkMatchDns("22", "imap2.google.com", "imap.google.com", false);
-        checkMatchDns("23", "imap.google.com", "*.google.com", true);
-        checkMatchDns("24", "imap2.google.com", "*.google.com", true);
-        checkMatchDns("25", "imap.google.com", "*.googl.com", false);
-        checkMatchDns("26", "imap2.google2.com", "*.google3.com", false);
-        checkMatchDns("27", "imap.google.com", "ima*.google.com", true);
-        checkMatchDns("28", "imap.google.com", "imap*.google.com", true);
-        checkMatchDns("29", "imap.google.com", "*.imap.google.com", true);
-
-        checkMatchDns("41", "imap.google.com", "a*.google.com", false);
-        checkMatchDns("42", "imap.google.com", "ix*.google.com", false);
-
-        checkMatchDns("51", "imap.google.com", "iMap.Google.Com", true);
-    }
-
-    private void checkMatchDns(String message, String thisDomain, String thatDomain,
-            boolean expected) {
-        boolean actual = DomainNameValidator.matchDns(thisDomain, thatDomain);
-        assertEquals(message, expected, actual);
-    }
-
-    /**
-     * Test {@link DomainNameValidator#match} with actual certificates.
-     */
-    public void testWithActualCert() throws Exception {
-        // subject_only
-        //
-        // subject: C=JP, CN=www.example.com
-        // subject alt names: n/a
-        checkWithActualCert("11", R.raw.subject_only, "www.example.com", true);
-        checkWithActualCert("12", R.raw.subject_only, "www2.example.com", false);
-
-        // subject_alt_only
-        //
-        // subject: C=JP (no CN)
-        // subject alt names: DNS:www.example.com
-        checkWithActualCert("21", R.raw.subject_alt_only, "www.example.com", true);
-        checkWithActualCert("22", R.raw.subject_alt_only, "www2.example.com", false);
-
-        // subject_with_alt_names
-        //
-        // subject: C=JP, CN=www.example.com
-        // subject alt names: DNS:www2.example.com, DNS:www3.example.com
-        // * Subject should be ignored, because it has subject alt names.
-        checkWithActualCert("31", R.raw.subject_with_alt_names, "www.example.com", false);
-        checkWithActualCert("32", R.raw.subject_with_alt_names, "www2.example.com", true);
-        checkWithActualCert("33", R.raw.subject_with_alt_names, "www3.example.com", true);
-        checkWithActualCert("34", R.raw.subject_with_alt_names, "www4.example.com", false);
-
-        // subject_with_wild_alt_name
-        //
-        // subject: C=JP, CN=www.example.com
-        // subject alt names: DNS:*.example2.com
-        // * Subject should be ignored, because it has subject alt names.
-        checkWithActualCert("41", R.raw.subject_with_wild_alt_name, "www.example.com", false);
-        checkWithActualCert("42", R.raw.subject_with_wild_alt_name, "www2.example.com", false);
-        checkWithActualCert("43", R.raw.subject_with_wild_alt_name, "www.example2.com", true);
-        checkWithActualCert("44", R.raw.subject_with_wild_alt_name, "abc.example2.com", true);
-        checkWithActualCert("45", R.raw.subject_with_wild_alt_name, "www.example3.com", false);
-
-        // wild_alt_name_only
-        //
-        // subject: C=JP
-        // subject alt names: DNS:*.example.com
-        checkWithActualCert("51", R.raw.wild_alt_name_only, "www.example.com", true);
-        checkWithActualCert("52", R.raw.wild_alt_name_only, "www2.example.com", true);
-        checkWithActualCert("53", R.raw.wild_alt_name_only, "www.example2.com", false);
-
-        // wild_alt_name_only
-        //
-        // subject: C=JP
-        // subject alt names: IP Address:192.168.10.1
-        checkWithActualCert("61", R.raw.alt_ip_only, "192.168.10.1", true);
-        checkWithActualCert("61", R.raw.alt_ip_only, "192.168.10.2", false);
-    }
-
-    private void checkWithActualCert(String message, int resId, String domain,
-            boolean expected) throws Exception {
-        CertificateFactory factory = CertificateFactory.getInstance("X509");
-        InputStream certStream = getContext().getResources().openRawResource(resId);
-        X509Certificate certificate = (X509Certificate) factory.generateCertificate(certStream);
-
-        checkMatch(message, certificate, domain, expected);
-    }
-
-    /**
-     * Minimal {@link X509Certificate} implementation for {@link DomainNameValidator}.
-     */
-    private static class StubX509Certificate extends X509Certificate {
-        private final X500Principal subjectX500Principal;
-        private Collection<List<?>> subjectAlternativeNames;
-
-        public StubX509Certificate(String subjectDn) {
-            subjectX500Principal = new X500Principal(subjectDn);
-            subjectAlternativeNames = null;
-        }
-
-        public StubX509Certificate addSubjectAlternativeName(int type, String name) {
-            if (subjectAlternativeNames == null) {
-                subjectAlternativeNames = new ArrayList<List<?>>();
-            }
-            LinkedList<Object> entry = new LinkedList<Object>();
-            entry.add(type);
-            entry.add(name);
-            subjectAlternativeNames.add(entry);
-            return this;
-        }
-
-        @Override
-        public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException {
-            return subjectAlternativeNames;
-        }
-
-        @Override
-        public X500Principal getSubjectX500Principal() {
-            return subjectX500Principal;
-        }
-
-        @Override
-        public void checkValidity() throws CertificateExpiredException,
-                CertificateNotYetValidException {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public void checkValidity(Date date) throws CertificateExpiredException,
-                CertificateNotYetValidException {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public int getBasicConstraints() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public Principal getIssuerDN() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public boolean[] getIssuerUniqueID() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public boolean[] getKeyUsage() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public Date getNotAfter() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public Date getNotBefore() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public BigInteger getSerialNumber() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public String getSigAlgName() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public String getSigAlgOID() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public byte[] getSigAlgParams() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public byte[] getSignature() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public Principal getSubjectDN() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public boolean[] getSubjectUniqueID() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public byte[] getTBSCertificate() throws CertificateEncodingException {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public int getVersion() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public byte[] getEncoded() throws CertificateEncodingException {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public PublicKey getPublicKey() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public String toString() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException,
-                InvalidKeyException, NoSuchProviderException, SignatureException {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        @Override
-        public void verify(PublicKey key, String sigProvider) throws CertificateException,
-                NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException,
-                SignatureException {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        public Set<String> getCriticalExtensionOIDs() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        public byte[] getExtensionValue(String oid) {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        public Set<String> getNonCriticalExtensionOIDs() {
-            throw new RuntimeException("Method not implemented");
-        }
-
-        public boolean hasUnsupportedCriticalExtension() {
-            throw new RuntimeException("Method not implemented");
-        }
-    }
-}
diff --git a/common/tests/src/com/android/common/PatternsTest.java b/common/tests/src/com/android/common/PatternsTest.java
deleted file mode 100644
index 9e2ad58..0000000
--- a/common/tests/src/com/android/common/PatternsTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import junit.framework.TestCase;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class PatternsTest extends TestCase {
-
-    @SmallTest
-    public void testTldPattern() throws Exception {
-        boolean t;
-
-        t = Patterns.TOP_LEVEL_DOMAIN.matcher("com").matches();
-        assertTrue("Missed valid TLD", t);
-
-        // One of the new top level domain.
-        t = Patterns.TOP_LEVEL_DOMAIN.matcher("me").matches();
-        assertTrue("Missed valid TLD", t);
-
-        // One of the new top level test domain.
-        t = Patterns.TOP_LEVEL_DOMAIN.matcher("xn--0zwm56d").matches();
-        assertTrue("Missed valid TLD", t);
-
-        t = Patterns.TOP_LEVEL_DOMAIN.matcher("mem").matches();
-        assertFalse("Matched invalid TLD!", t);
-
-        t = Patterns.TOP_LEVEL_DOMAIN.matcher("xn").matches();
-        assertFalse("Matched invalid TLD!", t);
-
-        t = Patterns.TOP_LEVEL_DOMAIN.matcher("xer").matches();
-        assertFalse("Matched invalid TLD!", t);
-    }
-
-    @SmallTest
-    public void testUrlPattern() throws Exception {
-        boolean t;
-
-        t = Patterns.WEB_URL.matcher("http://www.google.com").matches();
-        assertTrue("Valid URL", t);
-
-        // Google in one of the new top level domain.
-        t = Patterns.WEB_URL.matcher("http://www.google.me").matches();
-        assertTrue("Valid URL", t);
-        t = Patterns.WEB_URL.matcher("google.me").matches();
-        assertTrue("Valid URL", t);
-
-        // Test url in Chinese: http://xn--fsqu00a.xn--0zwm56d
-        t = Patterns.WEB_URL.matcher("http://xn--fsqu00a.xn--0zwm56d").matches();
-        assertTrue("Valid URL", t);
-        t = Patterns.WEB_URL.matcher("xn--fsqu00a.xn--0zwm56d").matches();
-        assertTrue("Valid URL", t);
-
-        // Internationalized URL.
-        t = Patterns.WEB_URL.matcher("http://\uD604\uAE08\uC601\uC218\uC99D.kr").matches();
-        assertTrue("Valid URL", t);
-        t = Patterns.WEB_URL.matcher("\uD604\uAE08\uC601\uC218\uC99D.kr").matches();
-        assertTrue("Valid URL", t);
-
-        t = Patterns.WEB_URL.matcher("ftp://www.example.com").matches();
-        assertFalse("Matched invalid protocol", t);
-
-        t = Patterns.WEB_URL.matcher("http://www.example.com:8080").matches();
-        assertTrue("Didn't match valid URL with port", t);
-
-        t = Patterns.WEB_URL.matcher("http://www.example.com:8080/?foo=bar").matches();
-        assertTrue("Didn't match valid URL with port and query args", t);
-
-        t = Patterns.WEB_URL.matcher("http://www.example.com:8080/~user/?foo=bar").matches();
-        assertTrue("Didn't match valid URL with ~", t);
-    }
-
-    @SmallTest
-    public void testIpPattern() throws Exception {
-        boolean t;
-
-        t = Patterns.IP_ADDRESS.matcher("172.29.86.3").matches();
-        assertTrue("Valid IP", t);
-
-        t = Patterns.IP_ADDRESS.matcher("1234.4321.9.9").matches();
-        assertFalse("Invalid IP", t);
-    }
-
-    @SmallTest
-    public void testDomainPattern() throws Exception {
-        boolean t;
-
-        t = Patterns.DOMAIN_NAME.matcher("mail.example.com").matches();
-        assertTrue("Valid domain", t);
-
-        t = Patterns.WEB_URL.matcher("google.me").matches();
-        assertTrue("Valid domain", t);
-
-        // Internationalized domains.
-        t = Patterns.DOMAIN_NAME.matcher("\uD604\uAE08\uC601\uC218\uC99D.kr").matches();
-        assertTrue("Valid domain", t);
-
-        t = Patterns.DOMAIN_NAME.matcher("__+&42.xer").matches();
-        assertFalse("Invalid domain", t);
-    }
-
-    @SmallTest
-    public void testPhonePattern() throws Exception {
-        boolean t;
-
-        t = Patterns.PHONE.matcher("(919) 555-1212").matches();
-        assertTrue("Valid phone", t);
-
-        t = Patterns.PHONE.matcher("2334 9323/54321").matches();
-        assertFalse("Invalid phone", t);
-
-        String[] tests = {
-                "Me: 16505551212 this\n",
-                "Me: 6505551212 this\n",
-                "Me: 5551212 this\n",
-
-                "Me: 1-650-555-1212 this\n",
-                "Me: (650) 555-1212 this\n",
-                "Me: +1 (650) 555-1212 this\n",
-                "Me: +1-650-555-1212 this\n",
-                "Me: 650-555-1212 this\n",
-                "Me: 555-1212 this\n",
-
-                "Me: 1.650.555.1212 this\n",
-                "Me: (650) 555.1212 this\n",
-                "Me: +1 (650) 555.1212 this\n",
-                "Me: +1.650.555.1212 this\n",
-                "Me: 650.555.1212 this\n",
-                "Me: 555.1212 this\n",
-
-                "Me: 1 650 555 1212 this\n",
-                "Me: (650) 555 1212 this\n",
-                "Me: +1 (650) 555 1212 this\n",
-                "Me: +1 650 555 1212 this\n",
-                "Me: 650 555 1212 this\n",
-                "Me: 555 1212 this\n",
-        };
-
-        for (String test : tests) {
-            Matcher m = Patterns.PHONE.matcher(test);
-
-            assertTrue("Valid phone " + test, m.find());
-        }
-    }
-}
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 13ea27e..cd657e8 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -447,6 +447,8 @@
     }
     const char16_t* stringAt(size_t idx, size_t* outLen) const;
 
+    const char* string8At(size_t idx, size_t* outLen) const;
+
     const ResStringPool_span* styleAt(const ResStringPool_ref& ref) const;
     const ResStringPool_span* styleAt(size_t idx) const;
 
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index 096aa73..7b866c7 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -82,8 +82,8 @@
                     // keep track of SCO device address
                     mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
 #ifdef WITH_A2DP
-                    if ((mA2dpDeviceAddress == mScoDeviceAddress) &&
-                        (mPhoneState != AudioSystem::MODE_NORMAL)) {
+                    if (mA2dpOutput != 0 &&
+                        mPhoneState != AudioSystem::MODE_NORMAL) {
                         mpClientInterface->suspendOutput(mA2dpOutput);
                     }
 #endif
@@ -116,8 +116,8 @@
                 if (AudioSystem::isBluetoothScoDevice(device)) {
                     mScoDeviceAddress = "";
 #ifdef WITH_A2DP
-                    if ((mA2dpDeviceAddress == mScoDeviceAddress) &&
-                        (mPhoneState != AudioSystem::MODE_NORMAL)) {
+                    if (mA2dpOutput != 0 &&
+                        mPhoneState != AudioSystem::MODE_NORMAL) {
                         mpClientInterface->restoreOutput(mA2dpOutput);
                     }
 #endif
@@ -275,10 +275,8 @@
     newDevice = getNewDevice(mHardwareOutput, false);
 #ifdef WITH_A2DP
     checkOutputForAllStrategies(newDevice);
-    // suspend A2DP output if SCO device address is the same as A2DP device address.
-    // no need to check that a SCO device is actually connected as mScoDeviceAddress == ""
-    // if none is connected and the test below will fail.
-    if (mA2dpDeviceAddress == mScoDeviceAddress) {
+    // suspend A2DP output if a SCO device is present.
+    if (mA2dpOutput != 0 && mScoDeviceAddress != "") {
         if (oldState == AudioSystem::MODE_NORMAL) {
             mpClientInterface->suspendOutput(mA2dpOutput);
         } else if (state == AudioSystem::MODE_NORMAL) {
@@ -295,13 +293,31 @@
     if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
         newDevice = hwOutputDesc->device();
     }
+
+    // when changing from ring tone to in call mode, mute the ringing tone
+    // immediately and delay the route change to avoid sending the ring tone
+    // tail into the earpiece or headset.
+    int delayMs = 0;
+    if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
+        // delay the device change command by twice the output latency to have some margin
+        // and be sure that audio buffers not yet affected by the mute are out when
+        // we actually apply the route change
+        delayMs = hwOutputDesc->mLatency*2;
+        setStreamMute(AudioSystem::RING, true, mHardwareOutput);
+    }
+
     // change routing is necessary
-    setOutputDevice(mHardwareOutput, newDevice, force);
+    setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
 
     // if entering in call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
     if (state == AudioSystem::MODE_IN_CALL) {
         LOGV("setPhoneState() in call state management: new state is %d", state);
+        // unmute the ringing tone after a sufficient delay if it was muted before
+        // setting output device above
+        if (oldState == AudioSystem::MODE_RINGTONE) {
+            setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
+        }
         for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
             handleIncallSonification(stream, true, true);
         }
@@ -1173,7 +1189,7 @@
     }
     AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
 
-    if (mA2dpDeviceAddress == mScoDeviceAddress) {
+    if (mScoDeviceAddress != "") {
         // It is normal to suspend twice if we are both in call,
         // and have the hardware audio output routed to BT SCO
         if (mPhoneState != AudioSystem::MODE_NORMAL) {
@@ -1207,10 +1223,10 @@
         return INVALID_OPERATION;
     }
 
-    // mute media during 2 seconds to avoid outputing sound on hardware output while music stream
+    // mute media strategy to avoid outputting sound on hardware output while music stream
     // is switched from A2DP output and before music is paused by music application
     setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
-    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, 2000);
+    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
 
     if (!a2dpUsedForSonification()) {
         // unmute music on A2DP output if a notification or ringtone is playing
@@ -1538,9 +1554,9 @@
         usleep(outputDesc->mLatency*2*1000);
     }
 #ifdef WITH_A2DP
-    // suspend A2D output if SCO device is selected
+    // suspend A2DP output if SCO device is selected
     if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) {
-         if (mA2dpOutput && mScoDeviceAddress == mA2dpDeviceAddress) {
+         if (mA2dpOutput != 0) {
              mpClientInterface->suspendOutput(mA2dpOutput);
          }
     }
@@ -1555,7 +1571,7 @@
 #ifdef WITH_A2DP
     // if disconnecting SCO device, restore A2DP output
     if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)prevDevice)) {
-         if (mA2dpOutput && mScoDeviceAddress == mA2dpDeviceAddress) {
+         if (mA2dpOutput != 0) {
              LOGV("restore A2DP output");
              mpClientInterface->restoreOutput(mA2dpOutput);
          }
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 395a937..86eb78d 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -35,7 +35,6 @@
 	libpixelflinger \
 	libhardware \
 	libutils \
-	libskia \
 	libEGL \
 	libGLESv1_CM \
 	libbinder \
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 1310ecc..743afb4 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -78,6 +78,8 @@
     inline const sp<FreezeLock>&  getFreezeLock() const { return mFreezeLock; }
     // only for debugging
     inline PixelFormat pixelFormat() const { return mFormat; }
+    // only for debugging
+    inline int getFrontBufferIndex() const { return mFrontBufferIndex; }
 
 private:
     inline sp<GraphicBuffer> getFrontBufferLocked() {
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index d1bbd04..6aacd82 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -22,6 +22,7 @@
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
+#include <GLES/gl.h>
 
 #include <utils/RefBase.h>
 
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 2d6152e..4555b3c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1496,8 +1496,8 @@
                     layer->needsBlending(), layer->needsDithering(),
                     layer->contentDirty,
                     s.alpha, s.flags,
-                    s.transform[0], s.transform[1],
-                    s.transform[2], s.transform[3]);
+                    s.transform[0][0], s.transform[0][1],
+                    s.transform[1][0], s.transform[1][1]);
             result.append(buffer);
             buffer[0] = 0;
             /*** LayerBaseClient ***/
@@ -1519,6 +1519,10 @@
             if (l != 0) {
                 SharedBufferStack::Statistics stats = l->lcblk->getStats();
                 result.append( l->lcblk->dump("      ") );
+                snprintf(buffer, SIZE,
+                        "      front-index=%u\n", l->getFrontBufferIndex());
+                result.append(buffer);
+
                 sp<const GraphicBuffer> buf0(l->getBuffer(0));
                 sp<const GraphicBuffer> buf1(l->getBuffer(1));
                 uint32_t w0=0, h0=0, s0=0;
@@ -1833,27 +1837,25 @@
 
 status_t GraphicPlane::orientationToTransfrom(
         int orientation, int w, int h, Transform* tr)
-{    
-    float a, b, c, d, x, y;
+{
+    uint32_t flags = 0;
     switch (orientation) {
     case ISurfaceComposer::eOrientationDefault:
-        // make sure the default orientation is optimal
-        tr->reset();
-        return NO_ERROR;
+        flags = Transform::ROT_0;
+        break;
     case ISurfaceComposer::eOrientation90:
-        a=0; b=-1; c=1; d=0; x=w; y=0;
+        flags = Transform::ROT_90;
         break;
     case ISurfaceComposer::eOrientation180:
-        a=-1; b=0; c=0; d=-1; x=w; y=h;
+        flags = Transform::ROT_180;
         break;
     case ISurfaceComposer::eOrientation270:
-        a=0; b=1; c=-1; d=0; x=0; y=h;
+        flags = Transform::ROT_270;
         break;
     default:
         return BAD_VALUE;
     }
-    tr->set(a, b, c, d);
-    tr->set(x, y);
+    tr->set(flags, w, h);
     return NO_ERROR;
 }
 
@@ -1869,24 +1871,13 @@
     mHeight = int(h);
 
     Transform orientationTransform;
-    if (UNLIKELY(orientation == 42)) {
-        float a, b, c, d, x, y;
-        const float r = (3.14159265f / 180.0f) * 42.0f;
-        const float si = sinf(r);
-        const float co = cosf(r);
-        a=co; b=-si; c=si; d=co;
-        x = si*(h*0.5f) + (1-co)*(w*0.5f);
-        y =-si*(w*0.5f) + (1-co)*(h*0.5f);
-        orientationTransform.set(a, b, c, d);
-        orientationTransform.set(x, y);
-    } else {
-        GraphicPlane::orientationToTransfrom(orientation, w, h,
-                &orientationTransform);
-        if (orientation & ISurfaceComposer::eOrientationSwapMask) {
-            mWidth = int(h);
-            mHeight = int(w);
-        }
+    GraphicPlane::orientationToTransfrom(orientation, w, h,
+            &orientationTransform);
+    if (orientation & ISurfaceComposer::eOrientationSwapMask) {
+        mWidth = int(h);
+        mHeight = int(w);
     }
+
     mOrientation = orientation;
     mGlobalTransform = mDisplayTransform * orientationTransform;
     return NO_ERROR;
diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp
index ab6f7ba..b2d5856 100644
--- a/libs/surfaceflinger/Transform.cpp
+++ b/libs/surfaceflinger/Transform.cpp
@@ -14,180 +14,257 @@
  * limitations under the License.
  */
 
+#include <math.h>
+
+#include <cutils/compiler.h>
+#include <utils/String8.h>
 #include <ui/Region.h>
 
-#include <private/pixelflinger/ggl_fixed.h>
-
 #include "Transform.h"
 
 // ---------------------------------------------------------------------------
 
-#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
-#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
-
-// ---------------------------------------------------------------------------
-
 namespace android {
 
 // ---------------------------------------------------------------------------
 
-Transform::Transform()
-    : mType(0)
-{
-    mTransform.reset();
+template <typename T> inline T min(T a, T b) {
+    return a<b ? a : b;
+}
+template <typename T> inline T min(T a, T b, T c) {
+    return min(a, min(b, c));
+}
+template <typename T> inline T min(T a, T b, T c, T d) {
+    return min(a, b, min(c, d));
+}
+
+template <typename T> inline T max(T a, T b) {
+    return a>b ? a : b;
+}
+template <typename T> inline T max(T a, T b, T c) {
+    return max(a, max(b, c));
+}
+template <typename T> inline T max(T a, T b, T c, T d) {
+    return max(a, b, max(c, d));
+}
+
+// ---------------------------------------------------------------------------
+
+Transform::Transform() {
+    reset();
 }
 
 Transform::Transform(const Transform&  other)
-    : mTransform(other.mTransform), mType(other.mType)
-{
+    : mMatrix(other.mMatrix), mType(other.mType) {
 }
 
-Transform::Transform(int32_t flags) {
-    mTransform.reset();
-    int sx = (flags & FLIP_H) ? -1 : 1;
-    int sy = (flags & FLIP_V) ? -1 : 1;
-    if (flags & ROT_90) {
-        this->set(0, -sy, sx, 0);
-    } else {
-        this->set(sx, 0, 0, sy);
-    }
+Transform::Transform(uint32_t orientation) {
+    set(orientation, 0, 0);
 }
 
 Transform::~Transform() {
 }
 
+
+bool Transform::absIsOne(float f) {
+    return fabs(f) == 1.0f;
+}
+
+bool Transform::isZero(float f) {
+    return fabs(f) == 0.0f;
+}
+
+bool Transform::absEqual(float a, float b) {
+    return fabs(a) == fabs(b);
+}
+
 Transform Transform::operator * (const Transform& rhs) const
 {
-    if (LIKELY(mType == 0))
+    if (CC_LIKELY(mType == IDENTITY))
         return rhs;
 
     Transform r(*this);
-    r.mTransform.preConcat(rhs.mTransform);
+    if (rhs.mType == IDENTITY)
+        return r;
+
+    // TODO: we could use mType to optimize the matrix multiply
+    const mat33& A(mMatrix);
+    const mat33& B(rhs.mMatrix);
+          mat33& D(r.mMatrix);
+    for (int i=0 ; i<3 ; i++) {
+        const float v0 = A[0][i];
+        const float v1 = A[1][i];
+        const float v2 = A[2][i];
+        D[0][i] = v0*B[0][0] + v1*B[0][1] + v2*B[0][2];
+        D[1][i] = v0*B[1][0] + v1*B[1][1] + v2*B[1][2];
+        D[2][i] = v0*B[2][0] + v1*B[2][1] + v2*B[2][2];
+    }
     r.mType |= rhs.mType;
+
+    // TODO: we could recompute this value from r and rhs
+    r.mType &= 0xFF;
+    r.mType |= UNKNOWN_TYPE;
     return r;
 }
 
-float Transform::operator [] (int i) const
-{
-    float r = 0;
-    switch(i) {
-        case 0: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleX] );  break;
-        case 1: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewX] );   break;
-        case 2: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewY] );   break;
-        case 3: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleY] );  break;
-    }
-    return r;
-}
-
-uint8_t Transform::type() const
-{
-    if (UNLIKELY(mType & 0x80000000)) {
-        mType = mTransform.getType();
-    }
-    return uint8_t(mType & 0xFF);
+float const* Transform::operator [] (int i) const {
+    return mMatrix[i].v;
 }
 
 bool Transform::transformed() const {
-    return type() > SkMatrix::kTranslate_Mask;
+    return type() > TRANSLATE;
 }
 
 int Transform::tx() const {
-    return SkScalarRound( mTransform[SkMatrix::kMTransX] );
+    return floorf(mMatrix[2][0] + 0.5f);
 }
 
 int Transform::ty() const {
-    return SkScalarRound( mTransform[SkMatrix::kMTransY] );
+    return floorf(mMatrix[2][1] + 0.5f);
 }
 
 void Transform::reset() {
-    mTransform.reset();
-    mType = 0;
-}
-
-void Transform::set( float xx, float xy,
-                     float yx, float yy)
-{
-    mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(xx));
-    mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(xy));
-    mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(yx));
-    mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(yy));
-    mType |= 0x80000000;
-}
-
-void Transform::set(float radian, float x, float y)
-{
-    float r00 = cosf(radian);    float r01 = -sinf(radian);
-    float r10 = sinf(radian);    float r11 =  cosf(radian);
-    mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(r00));
-    mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(r01));
-    mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(r10));
-    mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(r11));
-    mTransform.set(SkMatrix::kMTransX, SkIntToScalar(x - r00*x - r01*y));
-    mTransform.set(SkMatrix::kMTransY, SkIntToScalar(y - r10*x - r11*y));
-    mType |= 0x80000000 | SkMatrix::kTranslate_Mask;
-}
-
-void Transform::scale(float s, float x, float y)
-{
-    mTransform.postScale(s, s, x, y); 
-    mType |= 0x80000000;
-}
-
-void Transform::set(int tx, int ty)
-{
-    if (tx | ty) {
-        mTransform.set(SkMatrix::kMTransX, SkIntToScalar(tx));
-        mTransform.set(SkMatrix::kMTransY, SkIntToScalar(ty));
-        mType |= SkMatrix::kTranslate_Mask;
-    } else {
-        mTransform.set(SkMatrix::kMTransX, 0);
-        mTransform.set(SkMatrix::kMTransY, 0);
-        mType &= ~SkMatrix::kTranslate_Mask;
+    mType = IDENTITY;
+    for(int i=0 ; i<3 ; i++) {
+        vec3& v(mMatrix[i]);
+        for (int j=0 ; j<3 ; j++)
+            v[j] = ((i==j) ? 1.0f : 0.0f);
     }
 }
 
-void Transform::transform(GLfixed* point, int x, int y) const
+void Transform::set(float tx, float ty)
 {
-    SkPoint s;
-    mTransform.mapXY(SkIntToScalar(x), SkIntToScalar(y), &s);
-    point[0] = SkScalarToFixed(s.fX);
-    point[1] = SkScalarToFixed(s.fY);
+    mMatrix[2][0] = tx;
+    mMatrix[2][1] = ty;
+    mMatrix[2][2] = 1.0f;
+
+    if (isZero(tx) && isZero(ty)) {
+        mType &= ~TRANSLATE;
+    } else {
+        mType |= TRANSLATE;
+    }
+}
+
+void Transform::set(float a, float b, float c, float d)
+{
+    mat33& M(mMatrix);
+    M[0][0] = a;    M[1][0] = b;
+    M[0][1] = c;    M[1][1] = d;
+    M[0][2] = 0;    M[1][2] = 0;
+    mType = UNKNOWN_TYPE;
+}
+
+void Transform::set(uint32_t flags, float w, float h)
+{
+    mType = flags << 8;
+    float sx = (flags & FLIP_H) ? -1 : 1;
+    float sy = (flags & FLIP_V) ? -1 : 1;
+    float a=0, b=0, c=0, d=0, x=0, y=0;
+    int xmask = 0;
+
+    // computation of x,y
+    // x y
+    // 0 0  0
+    // w 0  ROT90
+    // w h  FLIPH|FLIPV
+    // 0 h  FLIPH|FLIPV|ROT90
+
+    if (flags & ROT_90) {
+        mType |= ROTATE;
+        b = -sy;
+        c = sx;
+        xmask = 1;
+    } else {
+        a = sx;
+        d = sy;
+    }
+
+    if (flags & FLIP_H) {
+        mType ^= SCALE;
+        xmask ^= 1;
+    }
+
+    if (flags & FLIP_V) {
+        mType ^= SCALE;
+        y = h;
+    }
+
+    if ((flags & ROT_180) == ROT_180) {
+        mType |= ROTATE;
+    }
+
+    if (xmask) {
+        x = w;
+    }
+
+    if (!isZero(x) || !isZero(y)) {
+        mType |= TRANSLATE;
+    }
+
+    mat33& M(mMatrix);
+    M[0][0] = a;    M[1][0] = b;    M[2][0] = x;
+    M[0][1] = c;    M[1][1] = d;    M[2][1] = y;
+    M[0][2] = 0;    M[1][2] = 0;    M[2][2] = 1;
+}
+
+Transform::vec2 Transform::transform(const vec2& v) const {
+    vec2 r;
+    const mat33& M(mMatrix);
+    r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0];
+    r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1];
+    return r;
+}
+
+Transform::vec3 Transform::transform(const vec3& v) const {
+    vec3 r;
+    const mat33& M(mMatrix);
+    r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]*v[2];
+    r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]*v[2];
+    r[2] = M[0][2]*v[0] + M[1][2]*v[1] + M[2][2]*v[2];
+    return r;
+}
+
+void Transform::transform(fixed1616* point, int x, int y) const
+{
+    const float toFixed = 65536.0f;
+    const mat33& M(mMatrix);
+    vec2 v(x, y);
+    v = transform(v);
+    point[0] = v[0] * toFixed;
+    point[1] = v[1] * toFixed;
 }
 
 Rect Transform::makeBounds(int w, int h) const
 {
-    Rect r;
-    SkRect d, s;
-    s.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
-    mTransform.mapRect(&d, s);
-    r.left   = SkScalarRound( d.fLeft );
-    r.top    = SkScalarRound( d.fTop );
-    r.right  = SkScalarRound( d.fRight );
-    r.bottom = SkScalarRound( d.fBottom );
-    return r;
+    return transform( Rect(w, h) );
 }
 
 Rect Transform::transform(const Rect& bounds) const
 {
     Rect r;
-    SkRect d, s;
-    s.set(  SkIntToScalar( bounds.left ),
-            SkIntToScalar( bounds.top ),
-            SkIntToScalar( bounds.right ),
-            SkIntToScalar( bounds.bottom ));
-    mTransform.mapRect(&d, s);
-    r.left   = SkScalarRound( d.fLeft );
-    r.top    = SkScalarRound( d.fTop );
-    r.right  = SkScalarRound( d.fRight );
-    r.bottom = SkScalarRound( d.fBottom );
+    vec2 lt( bounds.left,  bounds.top    );
+    vec2 rt( bounds.right, bounds.top    );
+    vec2 lb( bounds.left,  bounds.bottom );
+    vec2 rb( bounds.right, bounds.bottom );
+
+    lt = transform(lt);
+    rt = transform(rt);
+    lb = transform(lb);
+    rb = transform(rb);
+
+    r.left   = floorf(min(lt[0], rt[0], lb[0], rb[0]) + 0.5f);
+    r.top    = floorf(min(lt[1], rt[1], lb[1], rb[1]) + 0.5f);
+    r.right  = floorf(max(lt[0], rt[0], lb[0], rb[0]) + 0.5f);
+    r.bottom = floorf(max(lt[1], rt[1], lb[1], rb[1]) + 0.5f);
+
     return r;
 }
 
 Region Transform::transform(const Region& reg) const
 {
     Region out;
-    if (UNLIKELY(transformed())) {
-        if (LIKELY(preserveRects())) {
+    if (CC_UNLIKELY(transformed())) {
+        if (CC_LIKELY(preserveRects())) {
             Region::const_iterator it = reg.begin();
             Region::const_iterator const end = reg.end();
             while (it != end) {
@@ -202,31 +279,108 @@
     return out;
 }
 
-int32_t Transform::getOrientation() const
+uint32_t Transform::type() const
 {
-    uint32_t flags = 0;
-    if (UNLIKELY(transformed())) {
-        SkScalar a = mTransform[SkMatrix::kMScaleX];
-        SkScalar b = mTransform[SkMatrix::kMSkewX];
-        SkScalar c = mTransform[SkMatrix::kMSkewY];
-        SkScalar d = mTransform[SkMatrix::kMScaleY];
-        if (b==0 && c==0 && a && d) {
-            if (a<0)    flags |= FLIP_H;
-            if (d<0)    flags |= FLIP_V;
-        } else if (b && c && a==0 && d==0) {
-            flags |= ROT_90;
-            if (b>0)    flags |= FLIP_H;
-            if (c<0)    flags |= FLIP_V;
+    if (mType & UNKNOWN_TYPE) {
+        // recompute what this transform is
+
+        const mat33& M(mMatrix);
+        const float a = M[0][0];
+        const float b = M[1][0];
+        const float c = M[0][1];
+        const float d = M[1][1];
+        const float x = M[2][0];
+        const float y = M[2][1];
+
+        bool scale = false;
+        uint32_t flags = ROT_0;
+        if (isZero(b) && isZero(c)) {
+            if (absEqual(a, d)) {
+                if (a<0)    flags |= FLIP_H;
+                if (d<0)    flags |= FLIP_V;
+                if (!absIsOne(a) || !absIsOne(d)) {
+                    scale = true;
+                }
+            } else {
+                flags = ROT_INVALID;
+            }
+        } else if (isZero(a) && isZero(d)) {
+            if (absEqual(b, c)) {
+                flags |= ROT_90;
+                if (b>0)    flags |= FLIP_H;
+                if (c<0)    flags |= FLIP_V;
+                if (!absIsOne(b) || !absIsOne(c)) {
+                    scale = true;
+                }
+            } else {
+                flags = ROT_INVALID;
+            }
         } else {
-            flags = 0x80000000;
+            flags = ROT_INVALID;
         }
+
+        mType = flags << 8;
+        if (flags & ROT_INVALID) {
+            mType |= UNKNOWN;
+        } else {
+            if ((flags & ROT_90) || ((flags & ROT_180) == ROT_180))
+                mType |= ROTATE;
+            if (flags & FLIP_H)
+                mType ^= SCALE;
+            if (flags & FLIP_V)
+                mType ^= SCALE;
+            if (scale)
+                mType |= SCALE;
+        }
+
+        if (!isZero(x) || !isZero(y))
+            mType |= TRANSLATE;
     }
-    return flags;
+    return mType;
+}
+
+uint32_t Transform::getType() const {
+    return type() & 0xFF;
+}
+
+uint32_t Transform::getOrientation() const
+{
+    return (type() >> 8) & 0xFF;
 }
 
 bool Transform::preserveRects() const
 {
-    return mTransform.rectStaysRect();
+    return (type() & ROT_INVALID) ? false : true;
+}
+
+void Transform::dump(const char* name) const
+{
+    type(); // updates the type
+
+    String8 flags, type;
+    const mat33& m(mMatrix);
+    uint32_t orient = mType >> 8;
+
+    if (orient&ROT_INVALID)
+        flags.append("ROT_INVALID ");
+    if (orient&ROT_90)
+        flags.append("ROT_90 ");
+    if (orient&FLIP_V)
+        flags.append("FLIP_V ");
+    if (orient&FLIP_H)
+        flags.append("FLIP_H ");
+
+    if (mType&SCALE)
+        type.append("SCALE ");
+    if (mType&ROTATE)
+        type.append("ROTATE ");
+    if (mType&TRANSLATE)
+        type.append("TRANSLATE ");
+
+    LOGD("%s (%s, %s)", name, flags.string(), type.string());
+    LOGD("%.2f  %.2f  %.2f", m[0][0], m[1][0], m[2][0]);
+    LOGD("%.2f  %.2f  %.2f", m[0][1], m[1][1], m[2][1]);
+    LOGD("%.2f  %.2f  %.2f", m[0][2], m[1][2], m[2][2]);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h
index ddab404..51d3e3f 100644
--- a/libs/surfaceflinger/Transform.h
+++ b/libs/surfaceflinger/Transform.h
@@ -23,10 +23,6 @@
 #include <ui/Point.h>
 #include <ui/Rect.h>
 
-#include <GLES/gl.h>
-
-#include <core/SkMatrix.h>
-
 namespace android {
 
 class Region;
@@ -38,9 +34,12 @@
 public:
                     Transform();
                     Transform(const Transform&  other);
-                    Transform(int32_t flags);
+           explicit Transform(uint32_t orientation);
                     ~Transform();
 
+            typedef int32_t fixed1616;
+
+            // FIXME: must match OVERLAY_TRANSFORM_*, pull from hardware.h
             enum orientation_flags {
                 ROT_0   = 0x00000000,
                 FLIP_H  = 0x00000001,
@@ -48,48 +47,79 @@
                 ROT_90  = 0x00000004,
                 ROT_180 = FLIP_H|FLIP_V,
                 ROT_270 = ROT_180|ROT_90,
-                ROT_INVALID = 0x80000000
+                ROT_INVALID = 0x80
             };
 
             enum type_mask {
                 IDENTITY            = 0,
                 TRANSLATE           = 0x1,
-                SCALE               = 0x2,
-                AFFINE              = 0x4,
-                PERSPECTIVE         = 0x8
+                ROTATE              = 0x2,
+                SCALE               = 0x4,
+                UNKNOWN             = 0x8
             };
 
-            bool    transformed() const;
-            int32_t getOrientation() const;
-            bool    preserveRects() const;
-            
+            // query the transform
+            bool        transformed() const;
+            bool        preserveRects() const;
+            uint32_t    getType() const;
+            uint32_t    getOrientation() const;
+
+            float const* operator [] (int i) const;  // returns column i
             int     tx() const;
             int     ty() const;
-        
+
+            // modify the transform
             void    reset();
-            void    set(float xx, float xy, float yx, float yy);
-            void    set(int tx, int ty);
-            void    set(float radian, float x, float y);
-            void    scale(float s, float x, float y);
-            
+            void    set(float tx, float ty);
+            void    set(float a, float b, float c, float d);
+            void    set(uint32_t flags, float w, float h);
+
+            // transform data
             Rect    makeBounds(int w, int h) const;
-            void    transform(GLfixed* point, int x, int y) const;
+            void    transform(fixed1616* point, int x, int y) const;
             Region  transform(const Region& reg) const;
-            Rect    transform(const Rect& bounds) const;
-
             Transform operator * (const Transform& rhs) const;
-            float operator [] (int i) const;
-
-    inline uint32_t getType() const { return type(); }
-            
-    inline Transform(bool) : mType(0xFF) { };
 
 private:
-    uint8_t     type() const;
+    struct vec3 {
+        float v[3];
+        inline vec3() { }
+        inline vec3(float a, float b, float c) {
+            v[0] = a; v[1] = b; v[2] = c;
+        }
+        inline float operator [] (int i) const { return v[i]; }
+        inline float& operator [] (int i) { return v[i]; }
+    };
+    struct vec2 {
+        float v[2];
+        inline vec2() { }
+        inline vec2(float a, float b) {
+            v[0] = a; v[1] = b;
+        }
+        inline float operator [] (int i) const { return v[i]; }
+        inline float& operator [] (int i) { return v[i]; }
+    };
+    struct mat33 {
+        vec3 v[3];
+        inline const vec3& operator [] (int i) const { return v[i]; }
+        inline vec3& operator [] (int i) { return v[i]; }
+    };
 
-private:
-            SkMatrix    mTransform;
-    mutable uint32_t    mType;      
+    enum { UNKNOWN_TYPE = 0x80000000 };
+
+    // assumes the last row is < 0 , 0 , 1 >
+    vec2 transform(const vec2& v) const;
+    vec3 transform(const vec3& v) const;
+    Rect transform(const Rect& bounds) const;
+    uint32_t type() const;
+    static bool absIsOne(float f);
+    static bool absEqual(float a, float b);
+    static bool isZero(float f);
+
+    void dump(const char* name) const;
+
+    mat33               mMatrix;
+    mutable uint32_t    mType;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index e8bd5cf..38600b9 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -497,6 +497,34 @@
     return NULL;
 }
 
+const char* ResStringPool::string8At(size_t idx, size_t* outLen) const
+{
+    if (mError == NO_ERROR && idx < mHeader->stringCount) {
+        const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
+        const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
+        if (off < (mStringPoolSize-1)) {
+            if (isUTF8) {
+                const uint8_t* strings = (uint8_t*)mStrings;
+                const uint8_t* str = strings+off;
+                DECODE_LENGTH(str, sizeof(uint8_t), *outLen)
+                size_t encLen;
+                DECODE_LENGTH(str, sizeof(uint8_t), encLen)
+                if ((uint32_t)(str+encLen-strings) < mStringPoolSize) {
+                    return (const char*)str;
+                } else {
+                    LOGW("Bad string block: string #%d extends to %d, past end at %d\n",
+                            (int)idx, (int)(str+encLen-strings), (int)mStringPoolSize);
+                }
+            }
+        } else {
+            LOGW("Bad string block: string #%d entry is at %d, past end at %d\n",
+                    (int)idx, (int)(off*sizeof(uint16_t)),
+                    (int)(mStringPoolSize*sizeof(uint16_t)));
+        }
+    }
+    return NULL;
+}
+
 const ResStringPool_span* ResStringPool::styleAt(const ResStringPool_ref& ref) const
 {
     return styleAt(ref.index);
@@ -4018,14 +4046,19 @@
         printf("(attribute) 0x%08x\n", value.data);
     } else if (value.dataType == Res_value::TYPE_STRING) {
         size_t len;
-        const char16_t* str = pkg->header->values.stringAt(
+        const char* str8 = pkg->header->values.string8At(
                 value.data, &len);
-        if (str == NULL) {
-            printf("(string) null\n");
+        if (str8 != NULL) {
+            printf("(string8) \"%s\"\n", str8);
         } else {
-            printf("(string%d) \"%s\"\n",
-                    pkg->header->values.isUTF8()?8:16,
-                    String8(str, len).string());
+            const char16_t* str16 = pkg->header->values.stringAt(
+                    value.data, &len);
+            if (str16 != NULL) {
+                printf("(string16) \"%s\"\n",
+                    String8(str16, len).string());
+            } else {
+                printf("(string) null\n");
+            }
         } 
     } else if (value.dataType == Res_value::TYPE_FLOAT) {
         printf("(float) %g\n", *(const float*)&value.data);
diff --git a/mms-common/Android.mk b/mms-common/Android.mk
index de994c0..57f1ccc 100644
--- a/mms-common/Android.mk
+++ b/mms-common/Android.mk
@@ -20,6 +20,7 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := mms-common
 LOCAL_SRC_FILES := $(call all-java-files-under, java)
+LOCAL_STATIC_JAVA_LIBRARIES += android-common
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Include this library in the build server's output directory
diff --git a/mms-common/java/com/android/mmscommon/mms/pdu/PduPersister.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduPersister.java
index 46f28c7f..d92f0e1 100644
--- a/mms-common/java/com/android/mmscommon/mms/pdu/PduPersister.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduPersister.java
@@ -1145,6 +1145,10 @@
             }
         }
 
+        // mark "read" and "seen"
+        values.put(Mms.READ, 0);
+        values.put(Mms.SEEN, 0);
+
         Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
         if (res == null) {
             throw new MmsException("persist() failed: return null.");
diff --git a/mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java b/mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java
index 0237bc2..cfc9231 100644
--- a/mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java
+++ b/mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java
@@ -32,8 +32,8 @@
 import android.text.TextUtils;
 import android.util.Config;
 import android.util.Log;
+import android.util.Patterns;
 
-import com.android.common.Patterns;
 import android.database.sqlite.SqliteWrapper;
 
 /**
@@ -51,37 +51,6 @@
     private static final boolean DEBUG = true;
     private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
 
-//    public static final Pattern EMAIL_ADDRESS
-//        = Pattern.compile(
-//            "[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}" +
-//            "\\@" +
-//            "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
-//            "(" +
-//                "\\." +
-//                "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
-//            ")+"
-//        );
-//
-//    /**
-//     * This pattern is intended for searching for things that look like they
-//     * might be phone numbers in arbitrary text, not for validating whether
-//     * something is in fact a phone number.  It will miss many things that
-//     * are legitimate phone numbers.
-//     *
-//     * <p> The pattern matches the following:
-//     * <ul>
-//     * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
-//     * may follow.
-//     * <li>Optionally, sets of digits in parentheses, separated by spaces, dots, or dashes.
-//     * <li>A string starting and ending with a digit, containing digits, spaces, dots, and/or dashes.
-//     * </ul>
-//     */
-//    public static final Pattern PHONE
-//        = Pattern.compile(                                  // sdd = space, dot, or dash
-//                "(\\+[0-9]+[\\- \\.]*)?"                    // +<digits><sdd>*
-//                + "(\\([0-9]+\\)[\\- \\.]*)?"               // (<digits>)<sdd>*
-//                + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit>
-
     // Constructor
     public TelephonyProvider() {
     }
@@ -136,6 +105,12 @@
         public static final String READ = "read";
 
         /**
+         * Indicates whether this message has been seen by the user. The "seen" flag will be
+         * used to figure out whether we need to throw up a statusbar notification or not.
+         */
+        public static final String SEEN = "seen";
+
+        /**
          * The TP-Status value for the message, or -1 if no status has
          * been received
          */
@@ -706,6 +681,12 @@
         public static final String READ = "read";
 
         /**
+         * Indicates whether this message has been seen by the user. The "seen" flag will be
+         * used to figure out whether we need to throw up a statusbar notification or not.
+         */
+        public static final String SEEN = "seen";
+
+        /**
          * The Message-ID of the message.
          * <P>Type: TEXT</P>
          */
@@ -1157,6 +1138,7 @@
          * <P>Type: INTEGER</P>
          */
         public static final String READ = "read";
+
         /**
          * The snippet of the latest message in the thread.
          * <P>Type: TEXT</P>
@@ -1697,6 +1679,13 @@
              */
             public static final String LAST_TRY = "last_try";
         }
+
+        public static final class WordsTable {
+            public static final String ID = "_id";
+            public static final String SOURCE_ROW_ID = "source_id";
+            public static final String TABLE_ID = "table_to_use";
+            public static final String INDEXED_TEXT = "index_text";
+        }
     }
 
     public static final class Carriers implements BaseColumns {