Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 689b741a authored by Irfan Sheriff's avatar Irfan Sheriff Committed by Android (Google) Code Review
Browse files

Merge "Add initial framework for DNS service discovery"

parents 271cb5c0 7d024d37
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ LOCAL_SRC_FILES += \
	core/java/android/net/INetworkPolicyListener.aidl \
	core/java/android/net/INetworkPolicyManager.aidl \
	core/java/android/net/INetworkStatsService.aidl \
	core/java/android/net/nsd/INsdManager.aidl \
	core/java/android/nfc/INdefPushCallback.aidl \
	core/java/android/nfc/INfcAdapter.aidl \
	core/java/android/nfc/INfcAdapterExtras.aidl \
+10 −0
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ import android.net.NetworkPolicyManager;
import android.net.ThrottleManager;
import android.net.IThrottleManager;
import android.net.Uri;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.IWifiP2pManager;
@@ -372,6 +374,14 @@ class ContextImpl extends Context {
                        ctx.mMainThread.getHandler());
                }});

        registerService(NSD_SERVICE, new ServiceFetcher() {
                @Override
                public Object createService(ContextImpl ctx) {
                    IBinder b = ServiceManager.getService(NSD_SERVICE);
                    INsdManager service = INsdManager.Stub.asInterface(b);
                    return new NsdManager(service);
                }});

        // Note: this was previously cached in a static variable, but
        // constructed using mMainThread.getHandler(), so converting
        // it to be a regular Context-cached service...
+12 −0
Original line number Diff line number Diff line
@@ -1768,6 +1768,18 @@ public abstract class Context {
     */
    public static final String WIFI_P2P_SERVICE = "wifip2p";

    /**
     * Use with {@link #getSystemService} to retrieve a {@link
     * android.net.NsdManager} for handling management of network service
     * discovery
     *
     * @hide
     * @see #getSystemService
     * @see android.net.NsdManager
     */
    public static final String NSD_SERVICE = "servicediscovery";


    /**
     * Use with {@link #getSystemService} to retrieve a
     * {@link android.media.AudioManager} for handling management of volume,
+285 −269
Original line number Diff line number Diff line
@@ -19,130 +19,114 @@
 - fix set() to replace existing values
 */

package android.net.nsd;

package	com.apple.dnssd;

import android.os.Parcelable;
import android.os.Parcel;

/**
	Object used to construct and parse DNS-SD format TXT records.
	For more info see <a href="http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt">DNS-Based Service Discovery</a>, section 6. 
*/

public class	TXTRecord
{
	/* 
	DNS-SD specifies that a TXT record corresponding to an SRV record consist of
	a packed array of bytes, each preceded by a length byte. Each string
	is an attribute-value pair. 
	
	The TXTRecord object stores the entire TXT data as a single byte array, traversing it
	as need be to implement its various methods.
 * This class handles TXT record data for DNS based service discovery as specified at
 * http://tools.ietf.org/html/draft-cheshire-dnsext-dns-sd-11
 *
 * DNS-SD specifies that a TXT record corresponding to an SRV record consist of
 * a packed array of bytes, each preceded by a length byte. Each string
 * is an attribute-value pair.
 *
 * The DnsSdTxtRecord object stores the entire TXT data as a single byte array, traversing it
 * as need be to implement its various methods.
 *
 * @hide
 */
public class DnsSdTxtRecord implements Parcelable {
    private static final byte mSeperator = '=';

	static final protected byte		kAttrSep = '=';

	protected byte[]		fBytes;
    private byte[] mData;

    /** Constructs a new, empty TXT record. */
	public		TXTRecord() 
	{ fBytes = new byte[0]; }
    public DnsSdTxtRecord()  {
        mData = new byte[0];
    }

    /** Constructs a new TXT record from a byte array in the standard format. */
	public		TXTRecord( byte[] initBytes) 
	{ fBytes = (byte[]) initBytes.clone(); }

	/** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
		@param	key
					The key name. Must be ASCII, with no '=' characters.
		<P>
		@param	value
					Value to be encoded into bytes using the default platform character set.
	*/
	public void	set( String key, String value)
	{
		byte[]	valBytes = (value != null) ? value.getBytes() : null;
		this.set( key, valBytes);
	}

	/** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
		@param	key
					The key name. Must be ASCII, with no '=' characters.
		<P>
		@param	value
					Binary representation of the value.
    public DnsSdTxtRecord(byte[] data) {
        mData = (byte[]) data.clone();
    }

    /** Copy constructor */
    public DnsSdTxtRecord(DnsSdTxtRecord src) {
        if (src != null && src.mData != null) {
            mData = (byte[]) src.mData.clone();
        }
    }

    /**
     * Set a key/value pair. Setting an existing key will replace its value.
     * @param key Must be ascii with no '='
     * @param value matching value to key
     */
	public void	set( String key, byte[] value)
	{
    public void set(String key, String value) {
        byte[] keyBytes;
		int		valLen = (value != null) ? value.length : 0;
        byte[] valBytes;
        int valLen;

        if (value != null) {
            valBytes = value.getBytes();
            valLen = valBytes.length;
        } else {
            valBytes = null;
            valLen = 0;
        }

        try {
            keyBytes = key.getBytes("US-ASCII");
        }
		catch ( java.io.UnsupportedEncodingException uee) {
			throw new IllegalArgumentException();
        catch (java.io.UnsupportedEncodingException e) {
            throw new IllegalArgumentException("key should be US-ASCII");
        }

		for ( int i=0; i < keyBytes.length; i++)
			if ( keyBytes[i] == '=')
				throw new IllegalArgumentException();

		if ( keyBytes.length + valLen >= 255)
			throw new ArrayIndexOutOfBoundsException();

		int		prevLoc = this.remove( key);
		if ( prevLoc == -1)
			prevLoc = this.size();

		this.insert( keyBytes, value, prevLoc);
        for (int i = 0; i < keyBytes.length; i++) {
            if (keyBytes[i] == '=') {
                throw new IllegalArgumentException("= is not a valid character in key");
            }
        }

	protected void	insert( byte[] keyBytes, byte[] value, int index)
	// Insert a key-value pair at index
	{
		byte[]	oldBytes = fBytes;
		int		valLen = (value != null) ? value.length : 0;
		int		insertion = 0;
		int		newLen, avLen;
	
		// locate the insertion point
		for ( int i=0; i < index && insertion < fBytes.length; i++)
			insertion += (0xFF & (fBytes[ insertion] + 1));
        if (keyBytes.length + valLen >= 255) {
            throw new IllegalArgumentException("Key and Value length cannot exceed 255 bytes");
        }

		avLen = keyBytes.length + valLen + (value != null ? 1 : 0);
		newLen = avLen + oldBytes.length + 1;
        int currentLoc = remove(key);
        if (currentLoc == -1)
            currentLoc = keyCount();

		fBytes = new byte[ newLen];
		System.arraycopy( oldBytes, 0, fBytes, 0, insertion);
		int secondHalfLen = oldBytes.length - insertion;
		System.arraycopy( oldBytes, insertion, fBytes, newLen - secondHalfLen, secondHalfLen);
		fBytes[ insertion] = ( byte) avLen;
		System.arraycopy( keyBytes, 0, fBytes, insertion + 1, keyBytes.length);
		if ( value != null)
		{
			fBytes[ insertion + 1 + keyBytes.length] = kAttrSep;
			System.arraycopy( value, 0, fBytes, insertion + keyBytes.length + 2, valLen);
        insert(keyBytes, valBytes, currentLoc);
    }

    /**
     * Get a value for a key
     *
     * @param key
     * @return The value associated with the key
     */
    public String get(String key) {
        byte[] val = this.getValue(key);
        return val != null ? new String(val) : null;
    }

	/** Remove a key/value pair from the TXT record. Returns index it was at, or -1 if not found. */
	public int	remove( String key)
	{
    /** Remove a key/value pair. If found, returns the index or -1 if not found */
    public int remove(String key) {
        int avStart = 0;

		for ( int i=0; avStart < fBytes.length; i++)
		{
			int		avLen = fBytes[ avStart];
        for (int i=0; avStart < mData.length; i++) {
            int avLen = mData[avStart];
            if (key.length() <= avLen &&
				 ( key.length() == avLen || fBytes[ avStart + key.length() + 1] == kAttrSep))
			{
				String	s = new String( fBytes, avStart + 1, key.length());
				if ( 0 == key.compareToIgnoreCase( s))
				{
					byte[]	oldBytes = fBytes;
					fBytes = new byte[ oldBytes.length - avLen - 1];
					System.arraycopy( oldBytes, 0, fBytes, 0, avStart);
					System.arraycopy( oldBytes, avStart + avLen + 1, fBytes, avStart, oldBytes.length - avStart - avLen - 1);
                    (key.length() == avLen || mData[avStart + key.length() + 1] == mSeperator)) {
                String s = new String(mData, avStart + 1, key.length());
                if (0 == key.compareToIgnoreCase(s)) {
                    byte[] oldBytes = mData;
                    mData = new byte[oldBytes.length - avLen - 1];
                    System.arraycopy(oldBytes, 0, mData, 0, avStart);
                    System.arraycopy(oldBytes, avStart + avLen + 1, mData, avStart,
                            oldBytes.length - avStart - avLen - 1);
                    return i;
                }
            }
@@ -151,72 +135,100 @@ public class TXTRecord
        return -1;
    }

	/**	Return the number of keys in the TXT record. */
	public int	size()
	{
		int		i, avStart;

		for ( i=0, avStart=0; avStart < fBytes.length; i++)
			avStart += (0xFF & (fBytes[ avStart] + 1));
		return i;
    /** Return the count of keys */
    public int keyCount() {
        int count = 0, nextKey;
        for (nextKey = 0; nextKey < mData.length; count++) {
            nextKey += (0xFF & (mData[nextKey] + 1));
        }
        return count;
    }

	/** Return true if key is present in the TXT record, false if not. */
	public boolean	contains( String key)
	{		
    /** Return true if key is present, false if not. */
    public boolean contains(String key) {
        String s = null;

		for ( int i=0; null != ( s = this.getKey( i)); i++)
			if ( 0 == key.compareToIgnoreCase( s))
				return true;
        for (int i = 0; null != (s = this.getKey(i)); i++) {
            if (0 == key.compareToIgnoreCase(s)) return true;
        }
        return false;
    }

    /* Gets the size in bytes */
    public int size() {
        return mData.length;
    }

    /* Gets the raw data in bytes */
    public byte[] getRawData() {
        return mData;
    }

    private void insert(byte[] keyBytes, byte[] value, int index) {
        byte[] oldBytes = mData;
        int valLen = (value != null) ? value.length : 0;
        int insertion = 0;
        int newLen, avLen;

        for (int i = 0; i < index && insertion < mData.length; i++) {
            insertion += (0xFF & (mData[insertion] + 1));
        }

        avLen = keyBytes.length + valLen + (value != null ? 1 : 0);
        newLen = avLen + oldBytes.length + 1;

        mData = new byte[newLen];
        System.arraycopy(oldBytes, 0, mData, 0, insertion);
        int secondHalfLen = oldBytes.length - insertion;
        System.arraycopy(oldBytes, insertion, mData, newLen - secondHalfLen, secondHalfLen);
        mData[insertion] = (byte) avLen;
        System.arraycopy(keyBytes, 0, mData, insertion + 1, keyBytes.length);
        if (value != null) {
            mData[insertion + 1 + keyBytes.length] = mSeperator;
            System.arraycopy(value, 0, mData, insertion + keyBytes.length + 2, valLen);
        }
    }

    /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */
	public String	getKey( int index)
	{
    private String getKey(int index) {
        int avStart = 0;

		for ( int i=0; i < index && avStart < fBytes.length; i++)
			avStart += fBytes[ avStart] + 1;
        for (int i=0; i < index && avStart < mData.length; i++) {
            avStart += mData[avStart] + 1;
        }

		if ( avStart < fBytes.length)
		{
			int	avLen = fBytes[ avStart];
        if (avStart < mData.length) {
            int avLen = mData[avStart];
            int aLen = 0;

			for ( aLen=0; aLen < avLen; aLen++)
				if ( fBytes[ avStart + aLen + 1] == kAttrSep)
					break;
			return new String( fBytes, avStart + 1, aLen);
            for (aLen=0; aLen < avLen; aLen++) {
                if (mData[avStart + aLen + 1] == mSeperator) break;
            }
            return new String(mData, avStart + 1, aLen);
        }
        return null;
    }

    /**
		Look up a key in the TXT record by zero-based index and return its value. <P>
		Returns null if index exceeds the total number of keys. 
		Returns null if the key is present with no value.
     * Look up a key in the TXT record by zero-based index and return its value.
     * Returns null if index exceeds the total number of keys.
     * Returns null if the key is present with no value.
     */
	public byte[]	getValue( int index)
	{
    private byte[] getValue(int index) {
        int avStart = 0;
        byte[] value = null;

		for ( int i=0; i < index && avStart < fBytes.length; i++)
			avStart += fBytes[ avStart] + 1;
        for (int i=0; i < index && avStart < mData.length; i++) {
            avStart += mData[avStart] + 1;
        }

		if ( avStart < fBytes.length)
		{
			int	avLen = fBytes[ avStart];
        if (avStart < mData.length) {
            int avLen = mData[avStart];
            int aLen = 0;

			for ( aLen=0; aLen < avLen; aLen++)
			{
				if ( fBytes[ avStart + aLen + 1] == kAttrSep)
				{
            for (aLen=0; aLen < avLen; aLen++) {
                if (mData[avStart + aLen + 1] == mSeperator) {
                    value = new byte[avLen - aLen - 1];
					System.arraycopy( fBytes, avStart + aLen + 2, value, 0, avLen - aLen - 1);
                    System.arraycopy(mData, avStart + aLen + 2, value, 0, avLen - aLen - 1);
                    break;
                }
            }
@@ -224,56 +236,36 @@ public class TXTRecord
        return value;
    }

	/** Converts the result of getValue() to a string in the platform default character set. */
	public String	getValueAsString( int index)
	{
    private String getValueAsString(int index) {
        byte[] value = this.getValue(index);
        return value != null ? new String(value) : null;
    }

	/**	Get the value associated with a key. Will be null if the key is not defined.
		Array will have length 0 if the key is defined with an = but no value.<P> 

		@param	forKey
					The left-hand side of the key-value pair.
		<P>
		@return		The binary representation of the value.
	*/
	public byte[]	getValue( String forKey)
	{
    private byte[] getValue(String forKey) {
        String s = null;
        int i;

		for ( i=0; null != ( s = this.getKey( i)); i++)
			if ( 0 == forKey.compareToIgnoreCase( s))
        for (i = 0; null != (s = this.getKey(i)); i++) {
            if (0 == forKey.compareToIgnoreCase(s)) {
                return this.getValue(i);
		return null;
            }

	/**	Converts the result of getValue() to a string in the platform default character set.<P> 

		@param	forKey
					The left-hand side of the key-value pair.
		<P>
		@return		The value represented in the default platform character set.
	*/
	public String	getValueAsString( String forKey)
	{
		byte[]	val = this.getValue( forKey);
		return val != null ? new String( val) : null;
        }

	/** Return the contents of the TXT record as raw bytes. */
	public byte[]	getRawBytes() { return (byte[]) fBytes.clone(); }
        return null;
    }

	/** Return a string representation of the object. */
	public String	toString()
	{
    /**
     * Return a string representation.
     * Example : {key1=value1},{key2=value2}..
     *
     * For a key say like "key3" with null value
     * {key1=value1},{key2=value2}{key3}
     */
    public String toString() {
        String a, result = null;

		for ( int i=0; null != ( a = this.getKey( i)); i++)
		{
			String av = String.valueOf( i) + "={" + a;
        for (int i = 0; null != (a = this.getKey(i)); i++) {
            String av =  "{" + a;
            String val = this.getValueAsString(i);
            if (val != null)
                av += "=" + val + "}";
@@ -286,4 +278,28 @@ public class TXTRecord
        }
        return result != null ? result : "";
    }

    /** Implement the Parcelable interface */
    public int describeContents() {
        return 0;
    }

    /** Implement the Parcelable interface */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeByteArray(mData);
    }

    /** Implement the Parcelable interface */
    public static final Creator<DnsSdTxtRecord> CREATOR =
        new Creator<DnsSdTxtRecord>() {
            public DnsSdTxtRecord createFromParcel(Parcel in) {
                DnsSdTxtRecord info = new DnsSdTxtRecord();
                in.readByteArray(info.mData);
                return info;
            }

            public DnsSdTxtRecord[] newArray(int size) {
                return new DnsSdTxtRecord[size];
            }
        };
}
+29 −0
Original line number Diff line number Diff line
/**
 * Copyright (c) 2012, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.nsd;

import android.os.Messenger;

/**
 * Interface that NsdService implements
 *
 * {@hide}
 */
interface INsdManager
{
    Messenger getMessenger();
}
Loading