diff options
37 files changed, 1253 insertions, 828 deletions
diff --git a/api/current.txt b/api/current.txt index ec3d54a..a8bf949 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12708,21 +12708,6 @@ package android.net.http { package android.net.nsd { - public class DnsSdServiceInfo implements android.os.Parcelable { - ctor public DnsSdServiceInfo(); - method public int describeContents(); - method public java.net.InetAddress getHost(); - method public int getPort(); - method public java.lang.String getServiceName(); - method public java.lang.String getServiceType(); - method public void setHost(java.net.InetAddress); - method public void setPort(int); - method public void setServiceName(java.lang.String); - method public void setServiceType(java.lang.String); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - } - public class DnsSdTxtRecord implements android.os.Parcelable { ctor public DnsSdTxtRecord(); ctor public DnsSdTxtRecord(byte[]); @@ -12739,53 +12724,56 @@ package android.net.nsd { field public static final android.os.Parcelable.Creator CREATOR; } - public class NsdManager { - method public void deinitialize(android.net.nsd.NsdManager.Channel); - method public void discoverServices(android.net.nsd.NsdManager.Channel, java.lang.String, android.net.nsd.NsdManager.DnsSdDiscoveryListener); - method public void initialize(android.content.Context, android.os.Looper, android.net.nsd.NsdManager.ChannelListener); - method public void registerService(android.net.nsd.NsdManager.Channel, java.lang.String, java.lang.String, int, android.net.nsd.NsdManager.DnsSdRegisterListener); - method public void resolveService(android.net.nsd.NsdManager.Channel, java.lang.String, java.lang.String, android.net.nsd.NsdManager.DnsSdResolveListener); - method public void stopServiceDiscovery(android.net.nsd.NsdManager.Channel, android.net.nsd.NsdManager.ActionListener); - method public void unregisterService(android.net.nsd.NsdManager.Channel, int, android.net.nsd.NsdManager.ActionListener); + public final class NsdManager { + method public void discoverServices(java.lang.String, int, android.net.nsd.NsdManager.DiscoveryListener); + method public void registerService(android.net.nsd.NsdServiceInfo, int, android.net.nsd.NsdManager.RegistrationListener); + method public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener); + method public void stopServiceDiscovery(android.net.nsd.NsdManager.DiscoveryListener); + method public void unregisterService(android.net.nsd.NsdManager.RegistrationListener); field public static final java.lang.String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED"; - field public static final int ALREADY_ACTIVE = 3; // 0x3 - field public static final int BUSY = 2; // 0x2 - field public static final int ERROR = 0; // 0x0 field public static final java.lang.String EXTRA_NSD_STATE = "nsd_state"; - field public static final int MAX_REGS_REACHED = 4; // 0x4 + field public static final int FAILURE_ALREADY_ACTIVE = 3; // 0x3 + field public static final int FAILURE_INTERNAL_ERROR = 0; // 0x0 + field public static final int FAILURE_MAX_LIMIT = 4; // 0x4 field public static final int NSD_STATE_DISABLED = 1; // 0x1 field public static final int NSD_STATE_ENABLED = 2; // 0x2 - field public static final int UNSUPPORTED = 1; // 0x1 - } - - public static abstract interface NsdManager.ActionListener { - method public abstract void onFailure(int); - method public abstract void onSuccess(); - } - - public static class NsdManager.Channel { + field public static final int PROTOCOL_DNS_SD = 1; // 0x1 } - public static abstract interface NsdManager.ChannelListener { - method public abstract void onChannelConnected(android.net.nsd.NsdManager.Channel); - method public abstract void onChannelDisconnected(); + public static abstract interface NsdManager.DiscoveryListener { + method public abstract void onDiscoveryStarted(java.lang.String); + method public abstract void onDiscoveryStopped(java.lang.String); + method public abstract void onServiceFound(android.net.nsd.NsdServiceInfo); + method public abstract void onServiceLost(android.net.nsd.NsdServiceInfo); + method public abstract void onStartDiscoveryFailed(java.lang.String, int); + method public abstract void onStopDiscoveryFailed(java.lang.String, int); } - public static abstract interface NsdManager.DnsSdDiscoveryListener { - method public abstract void onFailure(int); - method public abstract void onServiceFound(android.net.nsd.DnsSdServiceInfo); - method public abstract void onServiceLost(android.net.nsd.DnsSdServiceInfo); - method public abstract void onStarted(java.lang.String); + public static abstract interface NsdManager.RegistrationListener { + method public abstract void onRegistrationFailed(android.net.nsd.NsdServiceInfo, int); + method public abstract void onServiceRegistered(android.net.nsd.NsdServiceInfo); + method public abstract void onServiceUnregistered(android.net.nsd.NsdServiceInfo); + method public abstract void onUnregistrationFailed(android.net.nsd.NsdServiceInfo, int); } - public static abstract interface NsdManager.DnsSdRegisterListener { - method public abstract void onFailure(int); - method public abstract void onServiceRegistered(int, android.net.nsd.DnsSdServiceInfo); + public static abstract interface NsdManager.ResolveListener { + method public abstract void onResolveFailed(android.net.nsd.NsdServiceInfo, int); + method public abstract void onServiceResolved(android.net.nsd.NsdServiceInfo); } - public static abstract interface NsdManager.DnsSdResolveListener { - method public abstract void onFailure(int); - method public abstract void onServiceResolved(android.net.nsd.DnsSdServiceInfo); + public final class NsdServiceInfo implements android.os.Parcelable { + ctor public NsdServiceInfo(); + method public int describeContents(); + method public java.net.InetAddress getHost(); + method public int getPort(); + method public java.lang.String getServiceName(); + method public java.lang.String getServiceType(); + method public void setHost(java.net.InetAddress); + method public void setPort(int); + method public void setServiceName(java.lang.String); + method public void setServiceType(java.lang.String); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; } } @@ -19085,12 +19073,12 @@ package android.renderscript { method public void transpose(); } - public class Mesh extends android.renderscript.BaseObj { - method public android.renderscript.Allocation getIndexSetAllocation(int); - method public android.renderscript.Mesh.Primitive getPrimitive(int); - method public int getPrimitiveCount(); - method public android.renderscript.Allocation getVertexAllocation(int); - method public int getVertexAllocationCount(); + public deprecated class Mesh extends android.renderscript.BaseObj { + method public deprecated android.renderscript.Allocation getIndexSetAllocation(int); + method public deprecated android.renderscript.Mesh.Primitive getPrimitive(int); + method public deprecated int getPrimitiveCount(); + method public deprecated android.renderscript.Allocation getVertexAllocation(int); + method public deprecated int getVertexAllocationCount(); } public static deprecated class Mesh.AllocationBuilder { @@ -19103,27 +19091,27 @@ package android.renderscript { method public deprecated int getCurrentVertexTypeIndex(); } - public static class Mesh.Builder { - ctor public Mesh.Builder(android.renderscript.RenderScript, int); - method public android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Type, android.renderscript.Mesh.Primitive); - method public android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Mesh.Primitive); - method public android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Element, int, android.renderscript.Mesh.Primitive); - method public android.renderscript.Mesh.Builder addVertexType(android.renderscript.Type) throws java.lang.IllegalStateException; - method public android.renderscript.Mesh.Builder addVertexType(android.renderscript.Element, int) throws java.lang.IllegalStateException; - method public android.renderscript.Mesh create(); - method public int getCurrentIndexSetIndex(); - method public int getCurrentVertexTypeIndex(); + public static deprecated class Mesh.Builder { + ctor public deprecated Mesh.Builder(android.renderscript.RenderScript, int); + method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Type, android.renderscript.Mesh.Primitive); + method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Mesh.Primitive); + method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Element, int, android.renderscript.Mesh.Primitive); + method public deprecated android.renderscript.Mesh.Builder addVertexType(android.renderscript.Type) throws java.lang.IllegalStateException; + method public deprecated android.renderscript.Mesh.Builder addVertexType(android.renderscript.Element, int) throws java.lang.IllegalStateException; + method public deprecated android.renderscript.Mesh create(); + method public deprecated int getCurrentIndexSetIndex(); + method public deprecated int getCurrentVertexTypeIndex(); } - public static final class Mesh.Primitive extends java.lang.Enum { + public static final deprecated class Mesh.Primitive extends java.lang.Enum { method public static android.renderscript.Mesh.Primitive valueOf(java.lang.String); method public static final android.renderscript.Mesh.Primitive[] values(); - enum_constant public static final android.renderscript.Mesh.Primitive LINE; - enum_constant public static final android.renderscript.Mesh.Primitive LINE_STRIP; - enum_constant public static final android.renderscript.Mesh.Primitive POINT; - enum_constant public static final android.renderscript.Mesh.Primitive TRIANGLE; - enum_constant public static final android.renderscript.Mesh.Primitive TRIANGLE_FAN; - enum_constant public static final android.renderscript.Mesh.Primitive TRIANGLE_STRIP; + enum_constant public static final deprecated android.renderscript.Mesh.Primitive LINE; + enum_constant public static final deprecated android.renderscript.Mesh.Primitive LINE_STRIP; + enum_constant public static final deprecated android.renderscript.Mesh.Primitive POINT; + enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE; + enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE_FAN; + enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE_STRIP; } public static deprecated class Mesh.TriangleMeshBuilder { @@ -19170,12 +19158,12 @@ package android.renderscript { enum_constant public static final android.renderscript.Program.TextureType TEXTURE_CUBE; } - public class ProgramFragment extends android.renderscript.Program { + public deprecated class ProgramFragment extends android.renderscript.Program { } - public static class ProgramFragment.Builder extends android.renderscript.Program.BaseProgramBuilder { - ctor public ProgramFragment.Builder(android.renderscript.RenderScript); - method public android.renderscript.ProgramFragment create(); + public static deprecated class ProgramFragment.Builder extends android.renderscript.Program.BaseProgramBuilder { + ctor public deprecated ProgramFragment.Builder(android.renderscript.RenderScript); + method public deprecated android.renderscript.ProgramFragment create(); } public deprecated class ProgramFragmentFixedFunction extends android.renderscript.ProgramFragment { @@ -19207,27 +19195,27 @@ package android.renderscript { enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format RGBA; } - public class ProgramRaster extends android.renderscript.BaseObj { - method public static android.renderscript.ProgramRaster CULL_BACK(android.renderscript.RenderScript); - method public static android.renderscript.ProgramRaster CULL_FRONT(android.renderscript.RenderScript); - method public static android.renderscript.ProgramRaster CULL_NONE(android.renderscript.RenderScript); - method public android.renderscript.ProgramRaster.CullMode getCullMode(); - method public boolean isPointSpriteEnabled(); + public deprecated class ProgramRaster extends android.renderscript.BaseObj { + method public static deprecated android.renderscript.ProgramRaster CULL_BACK(android.renderscript.RenderScript); + method public static deprecated android.renderscript.ProgramRaster CULL_FRONT(android.renderscript.RenderScript); + method public static deprecated android.renderscript.ProgramRaster CULL_NONE(android.renderscript.RenderScript); + method public deprecated android.renderscript.ProgramRaster.CullMode getCullMode(); + method public deprecated boolean isPointSpriteEnabled(); } - public static class ProgramRaster.Builder { - ctor public ProgramRaster.Builder(android.renderscript.RenderScript); - method public android.renderscript.ProgramRaster create(); - method public android.renderscript.ProgramRaster.Builder setCullMode(android.renderscript.ProgramRaster.CullMode); - method public android.renderscript.ProgramRaster.Builder setPointSpriteEnabled(boolean); + public static deprecated class ProgramRaster.Builder { + ctor public deprecated ProgramRaster.Builder(android.renderscript.RenderScript); + method public deprecated android.renderscript.ProgramRaster create(); + method public deprecated android.renderscript.ProgramRaster.Builder setCullMode(android.renderscript.ProgramRaster.CullMode); + method public deprecated android.renderscript.ProgramRaster.Builder setPointSpriteEnabled(boolean); } - public static final class ProgramRaster.CullMode extends java.lang.Enum { + public static final deprecated class ProgramRaster.CullMode extends java.lang.Enum { method public static android.renderscript.ProgramRaster.CullMode valueOf(java.lang.String); method public static final android.renderscript.ProgramRaster.CullMode[] values(); - enum_constant public static final android.renderscript.ProgramRaster.CullMode BACK; - enum_constant public static final android.renderscript.ProgramRaster.CullMode FRONT; - enum_constant public static final android.renderscript.ProgramRaster.CullMode NONE; + enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode BACK; + enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode FRONT; + enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode NONE; } public class ProgramStore extends android.renderscript.BaseObj { @@ -19295,15 +19283,15 @@ package android.renderscript { enum_constant public static final android.renderscript.ProgramStore.DepthFunc NOT_EQUAL; } - public class ProgramVertex extends android.renderscript.Program { - method public android.renderscript.Element getInput(int); - method public int getInputCount(); + public deprecated class ProgramVertex extends android.renderscript.Program { + method public deprecated android.renderscript.Element getInput(int); + method public deprecated int getInputCount(); } - public static class ProgramVertex.Builder extends android.renderscript.Program.BaseProgramBuilder { - ctor public ProgramVertex.Builder(android.renderscript.RenderScript); - method public android.renderscript.ProgramVertex.Builder addInput(android.renderscript.Element) throws java.lang.IllegalStateException; - method public android.renderscript.ProgramVertex create(); + public static deprecated class ProgramVertex.Builder extends android.renderscript.Program.BaseProgramBuilder { + ctor public deprecated ProgramVertex.Builder(android.renderscript.RenderScript); + method public deprecated android.renderscript.ProgramVertex.Builder addInput(android.renderscript.Element) throws java.lang.IllegalStateException; + method public deprecated android.renderscript.ProgramVertex create(); } public deprecated class ProgramVertexFixedFunction extends android.renderscript.ProgramVertex { @@ -19354,19 +19342,19 @@ package android.renderscript { method public deprecated void surfaceDestroyed(android.view.SurfaceHolder); } - public class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener { - ctor public RSTextureView(android.content.Context); - ctor public RSTextureView(android.content.Context, android.util.AttributeSet); - method public android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig); - method public void destroyRenderScriptGL(); - method public android.renderscript.RenderScriptGL getRenderScriptGL(); - method public void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int); - method public boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture); - method public void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int); - method public void onSurfaceTextureUpdated(android.graphics.SurfaceTexture); - method public void pause(); - method public void resume(); - method public void setRenderScriptGL(android.renderscript.RenderScriptGL); + public deprecated class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener { + ctor public deprecated RSTextureView(android.content.Context); + ctor public deprecated RSTextureView(android.content.Context, android.util.AttributeSet); + method public deprecated android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig); + method public deprecated void destroyRenderScriptGL(); + method public deprecated android.renderscript.RenderScriptGL getRenderScriptGL(); + method public deprecated void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int); + method public deprecated boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture); + method public deprecated void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int); + method public deprecated void onSurfaceTextureUpdated(android.graphics.SurfaceTexture); + method public deprecated void pause(); + method public deprecated void resume(); + method public deprecated void setRenderScriptGL(android.renderscript.RenderScriptGL); } public class RenderScript { @@ -19404,28 +19392,28 @@ package android.renderscript { field protected int mLength; } - public class RenderScriptGL extends android.renderscript.RenderScript { - ctor public RenderScriptGL(android.content.Context, android.renderscript.RenderScriptGL.SurfaceConfig); - method public void bindProgramFragment(android.renderscript.ProgramFragment); - method public void bindProgramRaster(android.renderscript.ProgramRaster); - method public void bindProgramStore(android.renderscript.ProgramStore); - method public void bindProgramVertex(android.renderscript.ProgramVertex); - method public void bindRootScript(android.renderscript.Script); - method public int getHeight(); - method public int getWidth(); - method public void pause(); - method public void resume(); - method public void setSurface(android.view.SurfaceHolder, int, int); + public deprecated class RenderScriptGL extends android.renderscript.RenderScript { + ctor public deprecated RenderScriptGL(android.content.Context, android.renderscript.RenderScriptGL.SurfaceConfig); + method public deprecated void bindProgramFragment(android.renderscript.ProgramFragment); + method public deprecated void bindProgramRaster(android.renderscript.ProgramRaster); + method public deprecated void bindProgramStore(android.renderscript.ProgramStore); + method public deprecated void bindProgramVertex(android.renderscript.ProgramVertex); + method public deprecated void bindRootScript(android.renderscript.Script); + method public deprecated int getHeight(); + method public deprecated int getWidth(); + method public deprecated void pause(); + method public deprecated void resume(); + method public deprecated void setSurface(android.view.SurfaceHolder, int, int); method public deprecated void setSurfaceTexture(android.graphics.SurfaceTexture, int, int); } - public static class RenderScriptGL.SurfaceConfig { - ctor public RenderScriptGL.SurfaceConfig(); - ctor public RenderScriptGL.SurfaceConfig(android.renderscript.RenderScriptGL.SurfaceConfig); - method public void setAlpha(int, int); - method public void setColor(int, int); - method public void setDepth(int, int); - method public void setSamples(int, int, float); + public static deprecated class RenderScriptGL.SurfaceConfig { + ctor public deprecated RenderScriptGL.SurfaceConfig(); + ctor public deprecated RenderScriptGL.SurfaceConfig(android.renderscript.RenderScriptGL.SurfaceConfig); + method public deprecated void setAlpha(int, int); + method public deprecated void setColor(int, int); + method public deprecated void setDepth(int, int); + method public deprecated void setSamples(int, int, float); } public class Sampler extends android.renderscript.BaseObj { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 64a05a8..4943c9a 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -387,7 +387,7 @@ class ContextImpl extends Context { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(NSD_SERVICE); INsdManager service = INsdManager.Stub.asInterface(b); - return new NsdManager(service); + return new NsdManager(ctx.getOuterContext(), service); }}); // Note: this was previously cached in a static variable, but diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 77e97e1..08ba728 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -22,12 +22,16 @@ import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.Handler; +import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.Messenger; import android.text.TextUtils; import android.util.Log; +import android.util.SparseArray; + +import java.util.concurrent.CountDownLatch; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; @@ -39,88 +43,73 @@ import com.android.internal.util.Protocol; * B. Another example use case is an application discovering printers on the network. * * <p> The API currently supports DNS based service discovery and discovery is currently - * limited to a local network over Multicast DNS. In future, it will be extended to - * support wide area discovery and other service discovery mechanisms. - * DNS service discovery is described at http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt + * limited to a local network over Multicast DNS. DNS service discovery is described at + * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt * * <p> The API is asynchronous and responses to requests from an application are on listener - * callbacks provided by the application. The application must invoke {@link #initialize} before - * doing any other operation. + * callbacks on a seperate thread. * * <p> There are three main operations the API supports - registration, discovery and resolution. * <pre> * Application start * | - * | <---------------------------------------------- - * initialize() | - * | | - * | Wait until channel connects | - * | before doing any operation | - * | | - * onChannelConnected() __________ | - * | | | - * | | | - * | onServiceRegistered() | | - * Register any local services / | | - * to be advertised with \ | | If application needs to - * registerService() onFailure() | | do any further operations - * | | | again, it needs to - * | | | initialize() connection - * discoverServices() | | to framework again - * | | | - * Maintain a list to track | | - * discovered services | | - * | | | - * |---------> |-> onChannelDisconnected() - * | | | - * | onServiceFound() | - * | | | - * | add service to list | - * | | | - * |<---------- | - * | | - * |---------> | - * | | | - * | onServiceLost() | - * | | | - * | remove service from list | - * | | | - * |<---------- | - * | | - * | | - * | Connect to a service | - * | from list ? | - * | | - * resolveService() | - * | | - * onServiceResolved() | - * | | - * Establish connection to service | - * with the host and port information | - * | | - * | ___________| - * deinitialize() - * when done with all operations - * or before quit + * | + * | onServiceRegistered() + * Register any local services / + * to be advertised with \ + * registerService() onRegistrationFailed() + * | + * | + * discoverServices() + * | + * Maintain a list to track + * discovered services + * | + * |---------> + * | | + * | onServiceFound() + * | | + * | add service to list + * | | + * |<---------- + * | + * |---------> + * | | + * | onServiceLost() + * | | + * | remove service from list + * | | + * |<---------- + * | + * | + * | Connect to a service + * | from list ? + * | + * resolveService() + * | + * onServiceResolved() + * | + * Establish connection to service + * with the host and port information * * </pre> * An application that needs to advertise itself over a network for other applications to * discover it can do so with a call to {@link #registerService}. If Example is a http based * application that can provide HTML data to peer services, it can register a name "Example" * with service type "_http._tcp". A successful registration is notified with a callback to - * {@link DnsSdRegisterListener#onServiceRegistered} and a failure to register is notified - * over {@link DnsSdRegisterListener#onFailure} + * {@link RegistrationListener#onServiceRegistered} and a failure to register is notified + * over {@link RegistrationListener#onRegistrationFailed} * * <p> A peer application looking for http services can initiate a discovery for "_http._tcp" * with a call to {@link #discoverServices}. A service found is notified with a callback - * to {@link DnsSdDiscoveryListener#onServiceFound} and a service lost is notified on - * {@link DnsSdDiscoveryListener#onServiceLost}. + * to {@link DiscoveryListener#onServiceFound} and a service lost is notified on + * {@link DiscoveryListener#onServiceLost}. * * <p> Once the peer application discovers the "Example" http srevice, and needs to receive data * from the "Example" application, it can initiate a resolve with {@link #resolveService} to * resolve the host and port details for the purpose of establishing a connection. A successful - * resolve is notified on {@link DnsSdResolveListener#onServiceResolved} and a failure is notified - * on {@link DnsSdResolveListener#onFailure}. + * resolve is notified on {@link ResolveListener#onServiceResolved} and a failure is notified + * on {@link ResolveListener#onResolveFailed}. * * Applications can reserve for a service type at * http://www.iana.org/form/ports-service. Existing services can be found at @@ -129,9 +118,9 @@ import com.android.internal.util.Protocol; * Get an instance of this class by calling {@link android.content.Context#getSystemService(String) * Context.getSystemService(Context.NSD_SERVICE)}. * - * {@see DnsSdServiceInfo} + * {@see NsdServiceInfo} */ -public class NsdManager { +public final class NsdManager { private static final String TAG = "NsdManager"; INsdManager mService; @@ -204,13 +193,6 @@ public class NsdManager { public static final int UNREGISTER_SERVICE_SUCCEEDED = BASE + 14; /** @hide */ - public static final int UPDATE_SERVICE = BASE + 15; - /** @hide */ - public static final int UPDATE_SERVICE_FAILED = BASE + 16; - /** @hide */ - public static final int UPDATE_SERVICE_SUCCEEDED = BASE + 17; - - /** @hide */ public static final int RESOLVE_SERVICE = BASE + 18; /** @hide */ public static final int RESOLVE_SERVICE_FAILED = BASE + 19; @@ -218,17 +200,27 @@ public class NsdManager { public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20; /** @hide */ - public static final int STOP_RESOLVE = BASE + 21; - /** @hide */ - public static final int STOP_RESOLVE_FAILED = BASE + 22; - /** @hide */ - public static final int STOP_RESOLVE_SUCCEEDED = BASE + 23; - - /** @hide */ public static final int ENABLE = BASE + 24; /** @hide */ public static final int DISABLE = BASE + 25; + /** @hide */ + public static final int NATIVE_DAEMON_EVENT = BASE + 26; + + /** Dns based service discovery protocol */ + public static final int PROTOCOL_DNS_SD = 0x0001; + + private Context mContext; + + private static final int INVALID_LISTENER_KEY = 0; + private int mListenerKey = 1; + private final SparseArray mListenerMap = new SparseArray(); + private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<NsdServiceInfo>(); + private final Object mMapLock = new Object(); + + private final AsyncChannel mAsyncChannel = new AsyncChannel(); + private ServiceHandler mHandler; + private final CountDownLatch mConnected = new CountDownLatch(1); /** * Create a new Nsd instance. Applications use @@ -238,271 +230,213 @@ public class NsdManager { * @hide - hide this because it takes in a parameter of type INsdManager, which * is a system private class. */ - public NsdManager(INsdManager service) { + public NsdManager(Context context, INsdManager service) { mService = service; + mContext = context; + init(); } /** - * Passed with onFailure() calls. + * Failures are passed with {@link RegistrationListener#onRegistrationFailed}, + * {@link RegistrationListener#onUnregistrationFailed}, + * {@link DiscoveryListener#onStartDiscoveryFailed}, + * {@link DiscoveryListener#onStopDiscoveryFailed} or {@link ResolveListener#onResolveFailed}. + * * Indicates that the operation failed due to an internal error. */ - public static final int ERROR = 0; + public static final int FAILURE_INTERNAL_ERROR = 0; /** - * Passed with onFailure() calls. - * Indicates that the operation failed because service discovery - * is unsupported on the device. - */ - public static final int UNSUPPORTED = 1; - - /** - * Passed with onFailure() calls. - * Indicates that the operation failed because the framework is - * busy and unable to service the request. - */ - public static final int BUSY = 2; - - /** - * Passed with onFailure() calls. * Indicates that the operation failed because it is already active. */ - public static final int ALREADY_ACTIVE = 3; + public static final int FAILURE_ALREADY_ACTIVE = 3; /** - * Passed with onFailure() calls. - * Indicates that the operation failed because maximum limit on - * service registrations has reached. + * Indicates that the operation failed because the maximum outstanding + * requests from the applications have reached. */ - public static final int MAX_REGS_REACHED = 4; - - /** Interface for callback invocation when framework channel is connected or lost */ - public interface ChannelListener { - /** - * The channel to the framework is connected. - * Application can initiate calls into the framework using the channel instance passed. - */ - public void onChannelConnected(Channel c); - /** - * The channel to the framework has been disconnected. - * Application could try re-initializing using {@link #initialize} - */ - public void onChannelDisconnected(); - } + public static final int FAILURE_MAX_LIMIT = 4; - /** Generic interface for callback invocation for a success or failure */ - public interface ActionListener { + /** Interface for callback invocation for service discovery */ + public interface DiscoveryListener { - public void onFailure(int errorCode); + public void onStartDiscoveryFailed(String serviceType, int errorCode); - public void onSuccess(); - } + public void onStopDiscoveryFailed(String serviceType, int errorCode); - /** Interface for callback invocation for service discovery */ - public interface DnsSdDiscoveryListener { + public void onDiscoveryStarted(String serviceType); - public void onFailure(int errorCode); + public void onDiscoveryStopped(String serviceType); - public void onStarted(String serviceType); + public void onServiceFound(NsdServiceInfo serviceInfo); - public void onServiceFound(DnsSdServiceInfo serviceInfo); - - public void onServiceLost(DnsSdServiceInfo serviceInfo); + public void onServiceLost(NsdServiceInfo serviceInfo); } /** Interface for callback invocation for service registration */ - public interface DnsSdRegisterListener { - - public void onFailure(int errorCode); + public interface RegistrationListener { - public void onServiceRegistered(int registeredId, DnsSdServiceInfo serviceInfo); - } + public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode); - /** @hide */ - public interface DnsSdUpdateRegistrationListener { + public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode); - public void onFailure(int errorCode); + public void onServiceRegistered(NsdServiceInfo serviceInfo); - public void onServiceUpdated(int registeredId, DnsSdTxtRecord txtRecord); + public void onServiceUnregistered(NsdServiceInfo serviceInfo); } /** Interface for callback invocation for service resolution */ - public interface DnsSdResolveListener { + public interface ResolveListener { - public void onFailure(int errorCode); + public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode); - public void onServiceResolved(DnsSdServiceInfo serviceInfo); + public void onServiceResolved(NsdServiceInfo serviceInfo); } - /** - * A channel that connects the application to the NetworkService framework. - * Most service operations require a Channel as an argument. An instance of Channel is obtained - * by doing a call on {@link #initialize} - */ - public static class Channel { - Channel(Looper looper, ChannelListener l) { - mAsyncChannel = new AsyncChannel(); - mHandler = new ServiceHandler(looper); - mChannelListener = l; + private class ServiceHandler extends Handler { + ServiceHandler(Looper looper) { + super(looper); } - private ChannelListener mChannelListener; - private DnsSdDiscoveryListener mDnsSdDiscoveryListener; - private ActionListener mDnsSdStopDiscoveryListener; - private DnsSdRegisterListener mDnsSdRegisterListener; - private ActionListener mDnsSdUnregisterListener; - private DnsSdUpdateRegistrationListener mDnsSdUpdateListener; - private DnsSdResolveListener mDnsSdResolveListener; - private ActionListener mDnsSdStopResolveListener; - - private AsyncChannel mAsyncChannel; - private ServiceHandler mHandler; - class ServiceHandler extends Handler { - ServiceHandler(Looper looper) { - super(looper); - } - @Override - public void handleMessage(Message message) { - switch (message.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); - break; - case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: - if (mChannelListener != null) { - mChannelListener.onChannelConnected(Channel.this); - } - break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - if (mChannelListener != null) { - mChannelListener.onChannelDisconnected(); - mChannelListener = null; - } - break; - case DISCOVER_SERVICES_STARTED: - if (mDnsSdDiscoveryListener != null) { - mDnsSdDiscoveryListener.onStarted((String) message.obj); - } - break; - case DISCOVER_SERVICES_FAILED: - if (mDnsSdDiscoveryListener != null) { - mDnsSdDiscoveryListener.onFailure(message.arg1); - } - break; - case SERVICE_FOUND: - if (mDnsSdDiscoveryListener != null) { - mDnsSdDiscoveryListener.onServiceFound( - (DnsSdServiceInfo) message.obj); - } - break; - case SERVICE_LOST: - if (mDnsSdDiscoveryListener != null) { - mDnsSdDiscoveryListener.onServiceLost( - (DnsSdServiceInfo) message.obj); - } - break; - case STOP_DISCOVERY_FAILED: - if (mDnsSdStopDiscoveryListener != null) { - mDnsSdStopDiscoveryListener.onFailure(message.arg1); - } - break; - case STOP_DISCOVERY_SUCCEEDED: - if (mDnsSdStopDiscoveryListener != null) { - mDnsSdStopDiscoveryListener.onSuccess(); - } - break; - case REGISTER_SERVICE_FAILED: - if (mDnsSdRegisterListener != null) { - mDnsSdRegisterListener.onFailure(message.arg1); - } - break; - case REGISTER_SERVICE_SUCCEEDED: - if (mDnsSdRegisterListener != null) { - mDnsSdRegisterListener.onServiceRegistered(message.arg1, - (DnsSdServiceInfo) message.obj); - } - break; - case UNREGISTER_SERVICE_FAILED: - if (mDnsSdUnregisterListener != null) { - mDnsSdUnregisterListener.onFailure(message.arg1); - } - break; - case UNREGISTER_SERVICE_SUCCEEDED: - if (mDnsSdUnregisterListener != null) { - mDnsSdUnregisterListener.onSuccess(); - } - break; - case UPDATE_SERVICE_FAILED: - if (mDnsSdUpdateListener != null) { - mDnsSdUpdateListener.onFailure(message.arg1); - } - break; - case UPDATE_SERVICE_SUCCEEDED: - if (mDnsSdUpdateListener != null) { - mDnsSdUpdateListener.onServiceUpdated(message.arg1, - (DnsSdTxtRecord) message.obj); - } - break; - case RESOLVE_SERVICE_FAILED: - if (mDnsSdResolveListener != null) { - mDnsSdResolveListener.onFailure(message.arg1); - } - break; - case RESOLVE_SERVICE_SUCCEEDED: - if (mDnsSdResolveListener != null) { - mDnsSdResolveListener.onServiceResolved( - (DnsSdServiceInfo) message.obj); - } - break; - case STOP_RESOLVE_FAILED: - if (mDnsSdStopResolveListener!= null) { - mDnsSdStopResolveListener.onFailure(message.arg1); - } - break; - case STOP_RESOLVE_SUCCEEDED: - if (mDnsSdStopResolveListener != null) { - mDnsSdStopResolveListener.onSuccess(); - } - break; - default: - Log.d(TAG, "Ignored " + message); - break; - } + @Override + public void handleMessage(Message message) { + Object listener = getListener(message.arg2); + boolean listenerRemove = true; + switch (message.what) { + case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: + mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); + mConnected.countDown(); + break; + case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: + // Ignore + break; + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: + Log.e(TAG, "Channel lost"); + break; + case DISCOVER_SERVICES_STARTED: + String s = ((NsdServiceInfo) message.obj).getServiceType(); + ((DiscoveryListener) listener).onDiscoveryStarted(s); + // Keep listener until stop discovery + listenerRemove = false; + break; + case DISCOVER_SERVICES_FAILED: + ((DiscoveryListener) listener).onStartDiscoveryFailed( + getNsdService(message.arg2).getServiceType(), message.arg1); + break; + case SERVICE_FOUND: + ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj); + // Keep listener until stop discovery + listenerRemove = false; + break; + case SERVICE_LOST: + ((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj); + // Keep listener until stop discovery + listenerRemove = false; + break; + case STOP_DISCOVERY_FAILED: + ((DiscoveryListener) listener).onStopDiscoveryFailed( + getNsdService(message.arg2).getServiceType(), message.arg1); + break; + case STOP_DISCOVERY_SUCCEEDED: + ((DiscoveryListener) listener).onDiscoveryStopped( + getNsdService(message.arg2).getServiceType()); + break; + case REGISTER_SERVICE_FAILED: + ((RegistrationListener) listener).onRegistrationFailed( + getNsdService(message.arg2), message.arg1); + break; + case REGISTER_SERVICE_SUCCEEDED: + ((RegistrationListener) listener).onServiceRegistered( + (NsdServiceInfo) message.obj); + // Keep listener until unregister + listenerRemove = false; + break; + case UNREGISTER_SERVICE_FAILED: + ((RegistrationListener) listener).onUnregistrationFailed( + getNsdService(message.arg2), message.arg1); + break; + case UNREGISTER_SERVICE_SUCCEEDED: + ((RegistrationListener) listener).onServiceUnregistered( + getNsdService(message.arg2)); + break; + case RESOLVE_SERVICE_FAILED: + ((ResolveListener) listener).onResolveFailed( + getNsdService(message.arg2), message.arg1); + break; + case RESOLVE_SERVICE_SUCCEEDED: + ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj); + break; + default: + Log.d(TAG, "Ignored " + message); + break; + } + if (listenerRemove) { + removeListener(message.arg2); } } - } + } - private static void checkChannel(Channel c) { - if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + private int putListener(Object listener, NsdServiceInfo s) { + if (listener == null) return INVALID_LISTENER_KEY; + int key; + synchronized (mMapLock) { + do { + key = mListenerKey++; + } while (key == INVALID_LISTENER_KEY); + mListenerMap.put(key, listener); + mServiceMap.put(key, s); + } + return key; } - /** - * Registers the application with the service discovery framework. This function - * must be the first to be called before any other operations are performed. No service - * discovery operations must be performed until the ChannelListener callback notifies - * that the channel is connected - * - * @param srcContext is the context of the source - * @param srcLooper is the Looper on which the callbacks are receivied - * @param listener for callback at loss of framework communication. Cannot be null. - */ - public void initialize(Context srcContext, Looper srcLooper, ChannelListener listener) { - Messenger messenger = getMessenger(); - if (messenger == null) throw new RuntimeException("Failed to initialize"); - if (listener == null) throw new IllegalArgumentException("ChannelListener cannot be null"); + private Object getListener(int key) { + if (key == INVALID_LISTENER_KEY) return null; + synchronized (mMapLock) { + return mListenerMap.get(key); + } + } + + private NsdServiceInfo getNsdService(int key) { + synchronized (mMapLock) { + return mServiceMap.get(key); + } + } + + private void removeListener(int key) { + if (key == INVALID_LISTENER_KEY) return; + synchronized (mMapLock) { + mListenerMap.remove(key); + mServiceMap.remove(key); + } + } - Channel c = new Channel(srcLooper, listener); - c.mAsyncChannel.connect(srcContext, c.mHandler, messenger); + private int getListenerKey(Object listener) { + synchronized (mMapLock) { + int valueIndex = mListenerMap.indexOfValue(listener); + if (valueIndex != -1) { + return mListenerMap.keyAt(valueIndex); + } + } + return INVALID_LISTENER_KEY; } + /** - * Disconnects application from service discovery framework. No further operations - * will succeed until a {@link #initialize} is called again. - * - * @param c channel initialized with {@link #initialize} + * Initialize AsyncChannel */ - public void deinitialize(Channel c) { - checkChannel(c); - c.mAsyncChannel.disconnect(); + private void init() { + final Messenger messenger = getMessenger(); + if (messenger == null) throw new RuntimeException("Failed to initialize"); + HandlerThread t = new HandlerThread("NsdManager"); + t.start(); + mHandler = new ServiceHandler(t.getLooper()); + mAsyncChannel.connect(mContext, mHandler, messenger); + try { + mConnected.await(); + } catch (InterruptedException e) { + Log.e(TAG, "interrupted wait at init"); + } } /** @@ -510,45 +444,51 @@ public class NsdManager { * * <p> The function call immediately returns after sending a request to register service * to the framework. The application is notified of a success to initiate - * discovery through the callback {@link DnsSdRegisterListener#onServiceRegistered} or a failure - * through {@link DnsSdRegisterListener#onFailure}. + * discovery through the callback {@link RegistrationListener#onServiceRegistered} or a failure + * through {@link RegistrationListener#onRegistrationFailed}. * - * @param c is the channel created at {@link #initialize} - * @param serviceType The service type being advertised. - * @param port on which the service is listenering for incoming connections - * @param listener for success or failure callback. Can be null. + * @param serviceInfo The service being registered + * @param protocolType The service discovery protocol + * @param listener The listener notifies of a successful registration and is used to + * unregister this service through a call on {@link #unregisterService}. Cannot be null. */ - public void registerService(Channel c, String serviceName, String serviceType, int port, - DnsSdRegisterListener listener) { - checkChannel(c); - if (TextUtils.isEmpty(serviceName) || TextUtils.isEmpty(serviceType)) { + public void registerService(NsdServiceInfo serviceInfo, int protocolType, + RegistrationListener listener) { + if (TextUtils.isEmpty(serviceInfo.getServiceName()) || + TextUtils.isEmpty(serviceInfo.getServiceType())) { throw new IllegalArgumentException("Service name or type cannot be empty"); } - if (port <= 0) { + if (serviceInfo.getPort() <= 0) { throw new IllegalArgumentException("Invalid port number"); } - DnsSdServiceInfo serviceInfo = new DnsSdServiceInfo(serviceName, serviceType, null); - serviceInfo.setPort(port); - c.mDnsSdRegisterListener = listener; - c.mAsyncChannel.sendMessage(REGISTER_SERVICE, serviceInfo); + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + if (protocolType != PROTOCOL_DNS_SD) { + throw new IllegalArgumentException("Unsupported protocol"); + } + mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, putListener(listener, serviceInfo), + serviceInfo); } /** - * Unregister a service registered through {@link #registerService} - * @param c is the channel created at {@link #initialize} - * @param registeredId is obtained at {@link DnsSdRegisterListener#onServiceRegistered} - * @param listener provides callbacks for success or failure. Can be null. + * Unregister a service registered through {@link #registerService}. A successful + * unregister is notified to the application with a call to + * {@link RegistrationListener#onServiceUnregistered}. + * + * @param listener This should be the listener object that was passed to + * {@link #registerService}. It identifies the service that should be unregistered + * and notifies of a successful unregistration. */ - public void unregisterService(Channel c, int registeredId, ActionListener listener) { - checkChannel(c); - c.mDnsSdUnregisterListener = listener; - c.mAsyncChannel.sendMessage(UNREGISTER_SERVICE, registeredId); - } - - /** @hide */ - public void updateService(Channel c, int registeredId, DnsSdTxtRecord txtRecord) { - checkChannel(c); - c.mAsyncChannel.sendMessage(UPDATE_SERVICE, registeredId, 0, txtRecord); + public void unregisterService(RegistrationListener listener) { + int id = getListenerKey(listener); + if (id == INVALID_LISTENER_KEY) { + throw new IllegalArgumentException("listener not registered"); + } + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id); } /** @@ -558,51 +498,61 @@ public class NsdManager { * * <p> The function call immediately returns after sending a request to start service * discovery to the framework. The application is notified of a success to initiate - * discovery through the callback {@link DnsSdDiscoveryListener#onStarted} or a failure - * through {@link DnsSdDiscoveryListener#onFailure}. + * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure + * through {@link DiscoveryListener#onStartDiscoveryFailed}. * * <p> Upon successful start, application is notified when a service is found with - * {@link DnsSdDiscoveryListener#onServiceFound} or when a service is lost with - * {@link DnsSdDiscoveryListener#onServiceLost}. + * {@link DiscoveryListener#onServiceFound} or when a service is lost with + * {@link DiscoveryListener#onServiceLost}. * * <p> Upon failure to start, service discovery is not active and application does * not need to invoke {@link #stopServiceDiscovery} * - * @param c is the channel created at {@link #initialize} * @param serviceType The service type being discovered. Examples include "_http._tcp" for * http services or "_ipp._tcp" for printers - * @param listener provides callbacks when service is found or lost. Cannot be null. + * @param protocolType The service discovery protocol + * @param listener The listener notifies of a successful discovery and is used + * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. + * Cannot be null. */ - public void discoverServices(Channel c, String serviceType, DnsSdDiscoveryListener listener) { - checkChannel(c); + public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { if (listener == null) { - throw new IllegalStateException("Discovery listener needs to be set first"); + throw new IllegalArgumentException("listener cannot be null"); } if (TextUtils.isEmpty(serviceType)) { - throw new IllegalStateException("Service type cannot be empty"); + throw new IllegalArgumentException("Service type cannot be empty"); } - DnsSdServiceInfo s = new DnsSdServiceInfo(); + + if (protocolType != PROTOCOL_DNS_SD) { + throw new IllegalArgumentException("Unsupported protocol"); + } + + NsdServiceInfo s = new NsdServiceInfo(); s.setServiceType(serviceType); - c.mDnsSdDiscoveryListener = listener; - c.mAsyncChannel.sendMessage(DISCOVER_SERVICES, s); + mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, putListener(listener, s), s); } /** * Stop service discovery initiated with {@link #discoverServices}. An active service - * discovery is notified to the application with {@link DnsSdDiscoveryListener#onStarted} - * and it stays active until the application invokes a stop service discovery. + * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted} + * and it stays active until the application invokes a stop service discovery. A successful + * stop is notified to with a call to {@link DiscoveryListener#onDiscoveryStopped}. * - * <p> Upon failure to start service discovery notified through - * {@link DnsSdDiscoveryListener#onFailure} service discovery is not active and - * application does not need to stop it. + * <p> Upon failure to stop service discovery, application is notified through + * {@link DiscoveryListener#onStopDiscoveryFailed}. * - * @param c is the channel created at {@link #initialize} - * @param listener notifies success or failure. Can be null. + * @param listener This should be the listener object that was passed to {@link #discoverServices}. + * It identifies the discovery that should be stopped and notifies of a successful stop. */ - public void stopServiceDiscovery(Channel c, ActionListener listener) { - checkChannel(c); - c.mDnsSdStopDiscoveryListener = listener; - c.mAsyncChannel.sendMessage(STOP_DISCOVERY); + public void stopServiceDiscovery(DiscoveryListener listener) { + int id = getListenerKey(listener); + if (id == INVALID_LISTENER_KEY) { + throw new IllegalArgumentException("service discovery not active on listener"); + } + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id); } /** @@ -610,30 +560,19 @@ public class NsdManager { * establishing a connection to fetch the IP and port details on which to setup * the connection. * - * @param c is the channel created at {@link #initialize} - * @param serviceName of the the service - * @param serviceType of the service + * @param serviceInfo service to be resolved * @param listener to receive callback upon success or failure. Cannot be null. */ - public void resolveService(Channel c, String serviceName, String serviceType, - DnsSdResolveListener listener) { - checkChannel(c); - if (TextUtils.isEmpty(serviceName) || TextUtils.isEmpty(serviceType)) { + public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { + if (TextUtils.isEmpty(serviceInfo.getServiceName()) || + TextUtils.isEmpty(serviceInfo.getServiceType())) { throw new IllegalArgumentException("Service name or type cannot be empty"); } - if (listener == null) throw new - IllegalStateException("Resolve listener cannot be null"); - c.mDnsSdResolveListener = listener; - DnsSdServiceInfo serviceInfo = new DnsSdServiceInfo(serviceName, serviceType, null); - c.mAsyncChannel.sendMessage(RESOLVE_SERVICE, serviceInfo); - } - - /** @hide */ - public void stopServiceResolve(Channel c) { - checkChannel(c); - if (c.mDnsSdResolveListener == null) throw new - IllegalStateException("Resolve listener needs to be set first"); - c.mAsyncChannel.sendMessage(STOP_RESOLVE); + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, putListener(listener, serviceInfo), + serviceInfo); } /** Internal use only @hide */ diff --git a/core/java/android/net/nsd/DnsSdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java index 66abd3a..205a21d 100644 --- a/core/java/android/net/nsd/DnsSdServiceInfo.java +++ b/core/java/android/net/nsd/NsdServiceInfo.java @@ -25,7 +25,7 @@ import java.net.InetAddress; * A class representing service information for network service discovery * {@see NsdManager} */ -public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { +public final class NsdServiceInfo implements Parcelable { private String mServiceName; @@ -37,36 +37,32 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { private int mPort; - public DnsSdServiceInfo() { + public NsdServiceInfo() { } /** @hide */ - public DnsSdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) { + public NsdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) { mServiceName = sn; mServiceType = rt; mTxtRecord = tr; } /** Get the service name */ - @Override public String getServiceName() { return mServiceName; } /** Set the service name */ - @Override public void setServiceName(String s) { mServiceName = s; } /** Get the service type */ - @Override public String getServiceType() { return mServiceType; } /** Set the service type */ - @Override public void setServiceType(String s) { mServiceType = s; } @@ -132,10 +128,10 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { } /** Implement the Parcelable interface */ - public static final Creator<DnsSdServiceInfo> CREATOR = - new Creator<DnsSdServiceInfo>() { - public DnsSdServiceInfo createFromParcel(Parcel in) { - DnsSdServiceInfo info = new DnsSdServiceInfo(); + public static final Creator<NsdServiceInfo> CREATOR = + new Creator<NsdServiceInfo>() { + public NsdServiceInfo createFromParcel(Parcel in) { + NsdServiceInfo info = new NsdServiceInfo(); info.mServiceName = in.readString(); info.mServiceType = in.readString(); info.mTxtRecord = in.readParcelable(null); @@ -150,8 +146,8 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { return info; } - public DnsSdServiceInfo[] newArray(int size) { - return new DnsSdServiceInfo[size]; + public NsdServiceInfo[] newArray(int size) { + return new NsdServiceInfo[size]; } }; } diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index 0586d9e..b7bc45f 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -140,6 +140,9 @@ public interface IBinder { */ int LIKE_TRANSACTION = ('_'<<24)|('L'<<16)|('I'<<8)|'K'; + /** @hide */ + int SYSPROPS_TRANSACTION = ('_'<<24)|('S'<<16)|('P'<<8)|'R'; + /** * Flag to {@link #transact}: this is a one-way call, meaning that the * caller returns immediately, without waiting for a result from the diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java index 43b5128..be24426 100644 --- a/core/java/android/os/ServiceManagerNative.java +++ b/core/java/android/os/ServiceManagerNative.java @@ -16,6 +16,8 @@ package android.os; +import java.util.ArrayList; + /** * Native implementation of the service manager. Most clients will only @@ -151,14 +153,32 @@ class ServiceManagerProxy implements IServiceManager { } public String[] listServices() throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - data.writeInterfaceToken(IServiceManager.descriptor); - mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0); - String[] list = reply.readStringArray(); - reply.recycle(); - data.recycle(); - return list; + ArrayList<String> services = new ArrayList<String>(); + int n = 0; + while (true) { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IServiceManager.descriptor); + data.writeInt(n); + n++; + try { + boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0); + if (!res) { + break; + } + } catch (RuntimeException e) { + // The result code that is returned by the C++ code can + // cause the call to throw an exception back instead of + // returning a nice result... so eat it here and go on. + break; + } + services.add(reply.readString()); + reply.recycle(); + data.recycle(); + } + String[] array = new String[services.size()]; + services.toArray(array); + return array; } public void setPermissionController(IPermissionController controller) diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index 619bf8d..156600e 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -16,6 +16,10 @@ package android.os; +import java.util.ArrayList; + +import android.util.Log; + /** * Gives access to the system properties store. The system properties @@ -28,12 +32,15 @@ public class SystemProperties public static final int PROP_NAME_MAX = 31; public static final int PROP_VALUE_MAX = 91; + private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>(); + private static native String native_get(String key); private static native String native_get(String key, String def); private static native int native_get_int(String key, int def); private static native long native_get_long(String key, long def); private static native boolean native_get_boolean(String key, boolean def); private static native void native_set(String key, String def); + private static native void native_add_change_callback(); /** * Get the value for the given key. @@ -124,4 +131,26 @@ public class SystemProperties } native_set(key, val); } + + public static void addChangeCallback(Runnable callback) { + synchronized (sChangeCallbacks) { + if (sChangeCallbacks.size() == 0) { + native_add_change_callback(); + } + sChangeCallbacks.add(callback); + } + } + + static void callChangeCallbacks() { + synchronized (sChangeCallbacks) { + //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!"); + if (sChangeCallbacks.size() == 0) { + return; + } + ArrayList<Runnable> callbacks = new ArrayList<Runnable>(sChangeCallbacks); + for (int i=0; i<callbacks.size(); i++) { + callbacks.get(i).run(); + } + } + } } diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index 7b6fd64..911183d 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -47,13 +47,21 @@ public final class Trace { public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags"; - private static final long sEnabledTags = nativeGetEnabledTags(); + private static long sEnabledTags = nativeGetEnabledTags(); private static native long nativeGetEnabledTags(); private static native void nativeTraceCounter(long tag, String name, int value); private static native void nativeTraceBegin(long tag, String name); private static native void nativeTraceEnd(long tag); + static { + SystemProperties.addChangeCallback(new Runnable() { + @Override public void run() { + sEnabledTags = nativeGetEnabledTags(); + } + }); + } + private Trace() { } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9fa67ac..aad6756 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -17250,7 +17250,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal /** * Show where the margins, bounds and layout bounds are for each view. */ - final boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); + boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); /** * Point used to compute visible regions. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 5f295cb..6e6fab2 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -408,6 +408,7 @@ public final class ViewRootImpl implements ViewParent, PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mAttachInfo.mScreenOn = powerManager.isScreenOn(); + loadSystemProperties(); } /** @@ -846,6 +847,16 @@ public final class ViewRootImpl implements ViewParent, scheduleTraversals(); } + void invalidateWorld(View view) { + view.invalidate(); + if (view instanceof ViewGroup) { + ViewGroup parent = (ViewGroup)view; + for (int i=0; i<parent.getChildCount(); i++) { + invalidateWorld(parent.getChildAt(i)); + } + } + } + public void invalidateChild(View child, Rect dirty) { invalidateChildInParent(null, dirty); } @@ -2730,6 +2741,7 @@ public final class ViewRootImpl implements ViewParent, private final static int MSG_INVALIDATE_DISPLAY_LIST = 21; private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22; private final static int MSG_DISPATCH_DONE_ANIMATING = 23; + private final static int MSG_INVALIDATE_WORLD = 24; final class ViewRootHandler extends Handler { @Override @@ -2997,6 +3009,9 @@ public final class ViewRootImpl implements ViewParent, case MSG_DISPATCH_DONE_ANIMATING: { handleDispatchDoneAnimating(); } break; + case MSG_INVALIDATE_WORLD: { + invalidateWorld(mView); + } break; } } } @@ -4016,6 +4031,17 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessage(msg); } + public void loadSystemProperties() { + boolean layout = SystemProperties.getBoolean( + View.DEBUG_LAYOUT_PROPERTY, false); + if (layout != mAttachInfo.mDebugLayout) { + mAttachInfo.mDebugLayout = layout; + if (!mHandler.hasMessages(MSG_INVALIDATE_WORLD)) { + mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_WORLD, 200); + } + } + } + private void destroyHardwareRenderer() { AttachInfo attachInfo = mAttachInfo; HardwareRenderer hardwareRenderer = attachInfo.mHardwareRenderer; diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index b5690e9..5d33cec 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -23,6 +23,7 @@ import android.content.res.Configuration; import android.graphics.PixelFormat; import android.opengl.ManagedEGLContext; import android.os.IBinder; +import android.os.SystemProperties; import android.util.AndroidRuntimeException; import android.util.Log; import android.view.inputmethod.InputMethodManager; @@ -112,6 +113,8 @@ public class WindowManagerImpl implements WindowManager { private WindowManager.LayoutParams[] mParams; private boolean mNeedsEglTerminate; + private Runnable mSystemPropertyUpdater = null; + private final static Object sLock = new Object(); private final static WindowManagerImpl sWindowManager = new WindowManagerImpl(); private final static HashMap<CompatibilityInfo, WindowManager> sCompatWindowManagers @@ -237,6 +240,22 @@ public class WindowManagerImpl implements WindowManager { View panelParentView = null; synchronized (this) { + // Start watching for system property changes. + if (mSystemPropertyUpdater == null) { + mSystemPropertyUpdater = new Runnable() { + @Override public void run() { + synchronized (this) { + synchronized (this) { + for (ViewRootImpl root : mRoots) { + root.loadSystemProperties(); + } + } + } + } + }; + SystemProperties.addChangeCallback(mSystemPropertyUpdater); + } + // Here's an odd/questionable case: if someone tries to add a // view multiple times, then we simply bump up a nesting count // and they need to remove the view the corresponding number of diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 6f33b1e..3aafba5 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -25,6 +25,7 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; +import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.Parcel; @@ -57,6 +58,7 @@ import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; @@ -648,6 +650,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te private int mGlowPaddingLeft; private int mGlowPaddingRight; + /** + * Used for interacting with list items from an accessibility service. + */ + private ListItemAccessibilityDelegate mAccessibilityDelegate; + private int mLastAccessibilityScrollEventFromIndex; private int mLastAccessibilityScrollEventToIndex; @@ -2121,9 +2128,77 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te child.setLayoutParams(lp); } + if (AccessibilityManager.getInstance(mContext).isEnabled()) { + if (mAccessibilityDelegate == null) { + mAccessibilityDelegate = new ListItemAccessibilityDelegate(); + } + child.setAccessibilityDelegate(mAccessibilityDelegate); + } + return child; } + class ListItemAccessibilityDelegate extends AccessibilityDelegate { + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + + final int position = getPositionForView(host); + + if (position == INVALID_POSITION) { + return; + } + + if (isClickable()) { + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + info.setClickable(true); + } + + if (isLongClickable()) { + info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); + info.setLongClickable(true); + } + + info.addAction(AccessibilityNodeInfo.ACTION_SELECT); + + if (position == getSelectedItemPosition()) { + info.setSelected(true); + } + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle arguments) { + final int position = getPositionForView(host); + + if (position == INVALID_POSITION) { + return false; + } + + final long id = getItemIdAtPosition(position); + + switch (action) { + case AccessibilityNodeInfo.ACTION_SELECT: + setSelection(position); + return true; + case AccessibilityNodeInfo.ACTION_CLICK: + if (!super.performAccessibilityAction(host, action, arguments)) { + return performItemClick(host, position, id); + } + return true; + case AccessibilityNodeInfo.ACTION_LONG_CLICK: + if (!super.performAccessibilityAction(host, action, arguments)) { + return performLongPress(host, position, id); + } + return true; + case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: + smoothScrollToPosition(position); + break; + } + + return super.performAccessibilityAction(host, action, arguments); + } + } + void positionSelector(int position, View sel) { if (position != INVALID_POSITION) { mSelectorPosition = position; @@ -5671,6 +5746,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // Don't reclaim header or footer views, or views that should be ignored if (lp != null && mRecycler.shouldRecycleViewType(lp.viewType)) { views.add(child); + child.setAccessibilityDelegate(null); if (listener != null) { // Pretend they went through the scrap heap listener.onMovedToScrapHeap(child); @@ -6226,6 +6302,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mScrapViews[viewType].add(scrap); } + scrap.setAccessibilityDelegate(null); if (mRecyclerListener != null) { mRecyclerListener.onMovedToScrapHeap(scrap); } @@ -6287,6 +6364,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te lp.scrappedFromPosition = mFirstActivePosition + i; scrapViews.add(victim); + victim.setAccessibilityDelegate(null); if (hasListener) { mRecyclerListener.onMovedToScrapHeap(victim); } diff --git a/core/java/com/android/internal/util/FileRotator.java b/core/java/com/android/internal/util/FileRotator.java index 6cfb97d..26235f1 100644 --- a/core/java/com/android/internal/util/FileRotator.java +++ b/core/java/com/android/internal/util/FileRotator.java @@ -19,8 +19,6 @@ package com.android.internal.util; import android.os.FileUtils; import android.util.Slog; -import com.android.internal.util.FileRotator.Rewriter; - import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; @@ -29,8 +27,11 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import libcore.io.IoUtils; +import libcore.io.Streams; /** * Utility that rotates files over time, similar to {@code logrotate}. There is @@ -137,10 +138,38 @@ public class FileRotator { public void deleteAll() { final FileInfo info = new FileInfo(mPrefix); for (String name : mBasePath.list()) { - if (!info.parse(name)) continue; + if (info.parse(name)) { + // delete each file that matches parser + new File(mBasePath, name).delete(); + } + } + } + + /** + * Dump all files managed by this rotator for debugging purposes. + */ + public void dumpAll(OutputStream os) throws IOException { + final ZipOutputStream zos = new ZipOutputStream(os); + try { + final FileInfo info = new FileInfo(mPrefix); + for (String name : mBasePath.list()) { + if (info.parse(name)) { + final ZipEntry entry = new ZipEntry(name); + zos.putNextEntry(entry); - // delete each file that matches parser - new File(mBasePath, name).delete(); + final File file = new File(mBasePath, name); + final FileInputStream is = new FileInputStream(file); + try { + Streams.copy(is, zos); + } finally { + IoUtils.closeQuietly(is); + } + + zos.closeEntry(); + } + } + } finally { + IoUtils.closeQuietly(zos); } } @@ -159,22 +188,22 @@ public class FileRotator { public void combineActive(final Reader reader, final Writer writer, long currentTimeMillis) throws IOException { rewriteActive(new Rewriter() { - /** {@inheritDoc} */ + @Override public void reset() { // ignored } - /** {@inheritDoc} */ + @Override public void read(InputStream in) throws IOException { reader.read(in); } - /** {@inheritDoc} */ + @Override public boolean shouldWrite() { return true; } - /** {@inheritDoc} */ + @Override public void write(OutputStream out) throws IOException { writer.write(out); } @@ -224,11 +253,11 @@ public class FileRotator { // write success, delete backup backupFile.delete(); - } catch (IOException e) { + } catch (Throwable t) { // write failed, delete file and restore backup file.delete(); backupFile.renameTo(file); - throw e; + throw rethrowAsIoException(t); } } else { @@ -241,11 +270,11 @@ public class FileRotator { // write success, delete empty backup backupFile.delete(); - } catch (IOException e) { + } catch (Throwable t) { // write failed, delete file and empty backup file.delete(); backupFile.delete(); - throw e; + throw rethrowAsIoException(t); } } } @@ -353,6 +382,14 @@ public class FileRotator { } } + private static IOException rethrowAsIoException(Throwable t) throws IOException { + if (t instanceof IOException) { + throw (IOException) t; + } else { + throw new IOException(t.getMessage(), t); + } + } + /** * Details for a rotated file, either parsed from an existing filename, or * ready to be built into a new filename. diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp index add616e..677396d1 100644 --- a/core/jni/android_os_SystemProperties.cpp +++ b/core/jni/android_os_SystemProperties.cpp @@ -15,7 +15,11 @@ ** limitations under the License. */ +#define LOG_TAG "SysPropJNI" + #include "cutils/properties.h" +#include "utils/misc.h" +#include <utils/Log.h> #include "jni.h" #include "android_runtime/AndroidRuntime.h" #include <nativehelper/JNIHelp.h> @@ -188,6 +192,34 @@ static void SystemProperties_set(JNIEnv *env, jobject clazz, } } +static JavaVM* sVM = NULL; +static jclass sClazz = NULL; +static jmethodID sCallChangeCallbacks; + +static void do_report_sysprop_change() { + //ALOGI("Java SystemProperties: VM=%p, Clazz=%p", sVM, sClazz); + if (sVM != NULL && sClazz != NULL) { + JNIEnv* env; + if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) { + //ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks); + env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks); + } + } +} + +static void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz) +{ + // This is called with the Java lock held. + if (sVM == NULL) { + env->GetJavaVM(&sVM); + } + if (sClazz == NULL) { + sClazz = (jclass) env->NewGlobalRef(clazz); + sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V"); + add_sysprop_change_callback(do_report_sysprop_change, -10000); + } +} + static JNINativeMethod method_table[] = { { "native_get", "(Ljava/lang/String;)Ljava/lang/String;", (void*) SystemProperties_getS }, @@ -201,6 +233,8 @@ static JNINativeMethod method_table[] = { (void*) SystemProperties_get_boolean }, { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) SystemProperties_set }, + { "native_add_change_callback", "()V", + (void*) SystemProperties_add_change_callback }, }; int register_android_os_SystemProperties(JNIEnv *env) diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 0f99fb2..04dc49f 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -308,6 +308,12 @@ protected: env->DeleteLocalRef(excep2); } + // Need to always call through the native implementation of + // SYSPROPS_TRANSACTION. + if (code == SYSPROPS_TRANSACTION) { + BBinder::onTransact(code, data, reply, flags); + } + //aout << "onTransact to Java code; result=" << res << endl // << "Transact from " << this << " to Java code returning " // << reply << ": " << *reply << endl; diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml index 61136e3..c5727ea 100644 --- a/core/res/res/values-sw600dp/dimens.xml +++ b/core/res/res/values-sw600dp/dimens.xml @@ -18,6 +18,10 @@ */ --> <resources> + <!-- The width that is used when creating thumbnails of applications. --> + <dimen name="thumbnail_width">200dp</dimen> + <!-- The height that is used when creating thumbnails of applications. --> + <dimen name="thumbnail_height">177dp</dimen> <!-- The maximum number of action buttons that should be permitted within an action bar/action mode. This will be used to determine how many showAsAction="ifRoom" items can fit. "always" items can override this. --> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index f812822..734151b 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -19,9 +19,9 @@ --> <resources> <!-- The width that is used when creating thumbnails of applications. --> - <dimen name="thumbnail_width">120dp</dimen> + <dimen name="thumbnail_width">164dp</dimen> <!-- The height that is used when creating thumbnails of applications. --> - <dimen name="thumbnail_height">120dp</dimen> + <dimen name="thumbnail_height">145dp</dimen> <!-- The standard size (both width and height) of an application icon that will be displayed in the app launcher and elsewhere. --> <dimen name="app_icon_size">48dip</dimen> diff --git a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java index 94d1cb6..95f0e67 100644 --- a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java +++ b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java @@ -187,12 +187,12 @@ public class FileRotatorTest extends AndroidTestCase { rotate.combineActive(reader, new Writer() { public void write(OutputStream out) throws IOException { new DataOutputStream(out).writeUTF("bar"); - throw new ProtocolException("yikes"); + throw new NullPointerException("yikes"); } }, currentTime); fail("woah, somehow able to write exception"); - } catch (ProtocolException e) { + } catch (IOException e) { // expected from above } diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java index f49a24e..7210513 100644 --- a/graphics/java/android/renderscript/Mesh.java +++ b/graphics/java/android/renderscript/Mesh.java @@ -21,6 +21,7 @@ import java.util.Vector; import android.util.Log; /** + * @deprecated in API 16 * <p>This class is a container for geometric data displayed with * Renderscript. Internally, a mesh is a collection of allocations that * represent vertex data (positions, normals, texture @@ -40,33 +41,40 @@ import android.util.Log; public class Mesh extends BaseObj { /** + * @deprecated in API 16 * Describes the way mesh vertex data is interpreted when rendering * **/ public enum Primitive { /** + * @deprecated in API 16 * Vertex data will be rendered as a series of points */ POINT (0), /** + * @deprecated in API 16 * Vertex pairs will be rendered as lines */ LINE (1), /** + * @deprecated in API 16 * Vertex data will be rendered as a connected line strip */ LINE_STRIP (2), /** + * @deprecated in API 16 * Vertices will be rendered as individual triangles */ TRIANGLE (3), /** + * @deprecated in API 16 * Vertices will be rendered as a connected triangle strip * defined by the first three vertices with each additional * triangle defined by a new vertex */ TRIANGLE_STRIP (4), /** + * @deprecated in API 16 * Vertices will be rendered as a sequence of triangles that all * share first vertex as the origin */ @@ -87,6 +95,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * @return number of allocations containing vertex data * **/ @@ -97,6 +106,7 @@ public class Mesh extends BaseObj { return mVertexBuffers.length; } /** + * @deprecated in API 16 * @param slot index in the list of allocations to return * @return vertex data allocation at the given index * @@ -106,6 +116,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * @return number of primitives or index sets in the mesh * **/ @@ -117,6 +128,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * @param slot locaton within the list of index set allocation * @return allocation containing primtive index data or null if * the index data is not specified explicitly @@ -126,6 +138,7 @@ public class Mesh extends BaseObj { return mIndexBuffers[slot]; } /** + * @deprecated in API 16 * @param slot locaiton within the list of index set primitives * @return index set primitive type * @@ -168,6 +181,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * Mesh builder object. It starts empty and requires you to * add the types necessary to create vertex and index * allocations. @@ -190,6 +204,7 @@ public class Mesh extends BaseObj { Vector mIndexTypes; /** + * @deprecated in API 16 * Creates builder object * @param rs Context to which the mesh will belong. * @param usage specifies how the mesh allocations are to be @@ -205,6 +220,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * @return internal index of the last vertex buffer type added to * builder **/ @@ -213,6 +229,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * @return internal index of the last index set added to the * builder **/ @@ -221,6 +238,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * Adds a vertex data type to the builder object * * @param t type of the vertex data allocation to be created @@ -240,6 +258,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * Adds a vertex data type to the builder object * * @param e element describing the vertex data layout @@ -261,6 +280,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * Adds an index set data type to the builder object * * @param t type of the index set data, could be null @@ -279,6 +299,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * Adds an index set primitive type to the builder object * * @param p primitive type @@ -296,6 +317,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * Adds an index set data type to the builder object * * @param e element describing the index set data layout @@ -321,6 +343,7 @@ public class Mesh extends BaseObj { } /** + * @deprecated in API 16 * Create a Mesh object from the current state of the builder * **/ diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java index fa6e2d4..69968ac 100644 --- a/graphics/java/android/renderscript/ProgramFragment.java +++ b/graphics/java/android/renderscript/ProgramFragment.java @@ -21,6 +21,7 @@ import android.util.Log; /** + * @deprecated in API 16 * <p>The Renderscript fragment program, also known as fragment shader is responsible * for manipulating pixel data in a user defined way. It's constructed from a GLSL * shader string containing the program body, textures inputs, and a Type object @@ -41,8 +42,12 @@ public class ProgramFragment extends Program { super(id, rs); } + /** + * @deprecated in API 16 + */ public static class Builder extends BaseProgramBuilder { /** + * @deprecated in API 16 * Create a builder object. * * @param rs Context to which the program will belong. @@ -52,6 +57,7 @@ public class ProgramFragment extends Program { } /** + * @deprecated in API 16 * Creates ProgramFragment from the current state of the builder * * @return ProgramFragment diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java index e40751f..c44521b 100644 --- a/graphics/java/android/renderscript/ProgramRaster.java +++ b/graphics/java/android/renderscript/ProgramRaster.java @@ -21,14 +21,27 @@ import android.util.Log; /** + * @deprecated in API 16 * Program raster is primarily used to specify whether point sprites are enabled and to control * the culling mode. By default, back faces are culled. **/ public class ProgramRaster extends BaseObj { + /** + * @deprecated in API 16 + **/ public enum CullMode { + /** + * @deprecated in API 16 + **/ BACK (0), + /** + * @deprecated in API 16 + **/ FRONT (1), + /** + * @deprecated in API 16 + **/ NONE (2); int mID; @@ -48,6 +61,7 @@ public class ProgramRaster extends BaseObj { } /** + * @deprecated in API 16 * Specifies whether vertices are rendered as screen aligned * elements of a specified size * @return whether point sprites are enabled @@ -57,6 +71,7 @@ public class ProgramRaster extends BaseObj { } /** + * @deprecated in API 16 * Specifies how triangles are culled based on their orientation * @return cull mode */ @@ -64,6 +79,9 @@ public class ProgramRaster extends BaseObj { return mCullMode; } + /** + * @deprecated in API 16 + */ public static ProgramRaster CULL_BACK(RenderScript rs) { if(rs.mProgramRaster_CULL_BACK == null) { ProgramRaster.Builder builder = new ProgramRaster.Builder(rs); @@ -73,6 +91,9 @@ public class ProgramRaster extends BaseObj { return rs.mProgramRaster_CULL_BACK; } + /** + * @deprecated in API 16 + */ public static ProgramRaster CULL_FRONT(RenderScript rs) { if(rs.mProgramRaster_CULL_FRONT == null) { ProgramRaster.Builder builder = new ProgramRaster.Builder(rs); @@ -82,6 +103,9 @@ public class ProgramRaster extends BaseObj { return rs.mProgramRaster_CULL_FRONT; } + /** + * @deprecated in API 16 + */ public static ProgramRaster CULL_NONE(RenderScript rs) { if(rs.mProgramRaster_CULL_NONE == null) { ProgramRaster.Builder builder = new ProgramRaster.Builder(rs); @@ -91,27 +115,42 @@ public class ProgramRaster extends BaseObj { return rs.mProgramRaster_CULL_NONE; } + /** + * @deprecated in API 16 + */ public static class Builder { RenderScript mRS; boolean mPointSprite; CullMode mCullMode; + /** + * @deprecated in API 16 + */ public Builder(RenderScript rs) { mRS = rs; mPointSprite = false; mCullMode = CullMode.BACK; } + /** + * @deprecated in API 16 + */ public Builder setPointSpriteEnabled(boolean enable) { mPointSprite = enable; return this; } + /** + * @deprecated in API 16 + */ public Builder setCullMode(CullMode m) { mCullMode = m; return this; } + /** + * @deprecated in API 16 + */ public ProgramRaster create() { mRS.validate(); int id = mRS.nProgramRasterCreate(mPointSprite, mCullMode.mID); diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java index 74d666b..2bd5124 100644 --- a/graphics/java/android/renderscript/ProgramVertex.java +++ b/graphics/java/android/renderscript/ProgramVertex.java @@ -43,6 +43,7 @@ import android.util.Log; /** + * @deprecated in API 16 * ProgramVertex, also know as a vertex shader, describes a * stage in the graphics pipeline responsible for manipulating * geometric data in a user-defined way. @@ -55,6 +56,7 @@ public class ProgramVertex extends Program { } /** + * @deprecated in API 16 * @return number of input attribute elements */ public int getInputCount() { @@ -62,6 +64,7 @@ public class ProgramVertex extends Program { } /** + * @deprecated in API 16 * @param slot location of the input to return * @return input attribute element */ @@ -73,6 +76,7 @@ public class ProgramVertex extends Program { } /** + * @deprecated in API 16 * Builder class for creating ProgramVertex objects. * The builder starts empty and the user must minimally provide * the GLSL shader code, and the varying inputs. Constant, or @@ -82,6 +86,7 @@ public class ProgramVertex extends Program { **/ public static class Builder extends BaseProgramBuilder { /** + * @deprecated in API 16 * Create a builder object. * * @param rs Context to which the program will belong. @@ -91,6 +96,7 @@ public class ProgramVertex extends Program { } /** + * @deprecated in API 16 * Add varying inputs to the program * * @param e element describing the layout of the varying input @@ -110,6 +116,7 @@ public class ProgramVertex extends Program { } /** + * @deprecated in API 16 * Creates ProgramVertex from the current state of the builder * * @return ProgramVertex diff --git a/graphics/java/android/renderscript/RSTextureView.java b/graphics/java/android/renderscript/RSTextureView.java index 30b2f99..ed04000 100644 --- a/graphics/java/android/renderscript/RSTextureView.java +++ b/graphics/java/android/renderscript/RSTextureView.java @@ -29,6 +29,7 @@ import android.util.Log; import android.view.TextureView; /** + * @deprecated in API 16 * The Texture View for a graphics renderscript (RenderScriptGL) * to draw on. * @@ -38,6 +39,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex private SurfaceTexture mSurfaceTexture; /** + * @deprecated in API 16 * Standard View constructor. In order to render something, you * must call {@link android.opengl.GLSurfaceView#setRenderer} to * register a renderer. @@ -49,6 +51,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } /** + * @deprecated in API 16 * Standard View constructor. In order to render something, you * must call {@link android.opengl.GLSurfaceView#setRenderer} to * register a renderer. @@ -64,6 +67,9 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex //android.util.Log.e("rs", "getSurfaceTextureListerner " + getSurfaceTextureListener()); } + /** + * @deprecated in API 16 + */ @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureAvailable"); @@ -74,6 +80,9 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } } + /** + * @deprecated in API 16 + */ @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureSizeChanged"); @@ -84,6 +93,9 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } } + /** + * @deprecated in API 16 + */ @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureDestroyed"); @@ -96,6 +108,9 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex return true; } + /** + * @deprecated in API 16 + */ @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureUpdated"); @@ -103,6 +118,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } /** + * @deprecated in API 16 * Inform the view that the activity is paused. The owner of this view must * call this method when the activity is paused. Calling this method will * pause the rendering thread. @@ -115,6 +131,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } /** + * @deprecated in API 16 * Inform the view that the activity is resumed. The owner of this view must * call this method when the activity is resumed. Calling this method will * recreate the OpenGL display and resume the rendering @@ -128,6 +145,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } /** + * @deprecated in API 16 * Create a new RenderScriptGL object and attach it to the * TextureView if present. * @@ -146,6 +164,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } /** + * @deprecated in API 16 * Destroy the RenderScriptGL object associated with this * TextureView. */ @@ -155,6 +174,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } /** + * @deprecated in API 16 * Set a new RenderScriptGL object. This also will attach the * new object to the TextureView if present. * @@ -168,6 +188,7 @@ public class RSTextureView extends TextureView implements TextureView.SurfaceTex } /** + * @deprecated in API 16 * Returns the previously set RenderScriptGL object. * * @return RenderScriptGL diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java index dbdbe3d..12c8102 100644 --- a/graphics/java/android/renderscript/RenderScriptGL.java +++ b/graphics/java/android/renderscript/RenderScriptGL.java @@ -29,6 +29,7 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; /** + * @deprecated in API 16 * The Graphics derivitive of Renderscript. Extends the basic context to add a * root script which is the display window for graphical output. When the * system needs to update the display the currently bound root script will be @@ -46,6 +47,7 @@ public class RenderScriptGL extends RenderScript { int mHeight; /** + * @deprecated in API 16 * Class which is used to describe a pixel format for a graphical buffer. * This is used to describe the intended format of the display surface. * @@ -66,9 +68,15 @@ public class RenderScriptGL extends RenderScript { int mSamplesPref = 1; float mSamplesQ = 1.f; + /** + * @deprecated in API 16 + */ public SurfaceConfig() { } + /** + * @deprecated in API 16 + */ public SurfaceConfig(SurfaceConfig sc) { mDepthMin = sc.mDepthMin; mDepthPref = sc.mDepthPref; @@ -93,6 +101,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Set the per-component bit depth for color (red, green, blue). This * configures the surface for an unsigned integer buffer type. * @@ -106,6 +115,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Set the bit depth for alpha. This configures the surface for * an unsigned integer buffer type. * @@ -119,6 +129,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Set the bit depth for the depth buffer. This configures the * surface for an unsigned integer buffer type. If a minimum of 0 * is specified then its possible no depth buffer will be @@ -134,6 +145,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Configure the multisample rendering. * * @param minimum The required number of samples, must be at least 1. @@ -157,6 +169,7 @@ public class RenderScriptGL extends RenderScript { SurfaceConfig mSurfaceConfig; /** + * @deprecated in API 16 * Construct a new RenderScriptGL context. * * @param ctx The context. @@ -187,6 +200,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Bind an os surface * * @@ -223,6 +237,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * return the height of the last set surface. * * @return int @@ -232,6 +247,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * return the width of the last set surface. * * @return int @@ -241,6 +257,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Temporarly halt calls to the root rendering script. * */ @@ -250,6 +267,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Resume calls to the root rendering script. * */ @@ -260,6 +278,7 @@ public class RenderScriptGL extends RenderScript { /** + * @deprecated in API 16 * Set the script to handle calls to render the primary surface. * * @param s Graphics script to process rendering requests. @@ -270,6 +289,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Set the default ProgramStore object seen as the parent state by the root * rendering script. * @@ -281,6 +301,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Set the default ProgramFragment object seen as the parent state by the * root rendering script. * @@ -292,6 +313,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Set the default ProgramRaster object seen as the parent state by the * root rendering script. * @@ -303,6 +325,7 @@ public class RenderScriptGL extends RenderScript { } /** + * @deprecated in API 16 * Set the default ProgramVertex object seen as the parent state by the * root rendering script. * diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml index fcdd56c..ec2abe0 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml @@ -45,7 +45,7 @@ android:fadingEdge="horizontal" android:scrollbars="none" android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length" - android:layout_gravity="bottom|left" + android:layout_gravity="bottom|right" android:orientation="horizontal" android:clipToPadding="false" android:clipChildren="false"> diff --git a/core/java/android/net/nsd/NetworkServiceInfo.java b/packages/SystemUI/res/values-sw600dp-land/values-land-sw600dp/dimens.xml index 34d83d1..e440de1 100644 --- a/core/java/android/net/nsd/NetworkServiceInfo.java +++ b/packages/SystemUI/res/values-sw600dp-land/values-land-sw600dp/dimens.xml @@ -1,32 +1,21 @@ -/* - * Copyright (C) 2012 The Android Open Source Project +<?xml version="1.0" encoding="utf-8"?> +<!-- + * 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 + * 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; - -/** - * Interface for a network service. - * - * {@hide} - */ -public interface NetworkServiceInfo { - - String getServiceName(); - void setServiceName(String s); - - String getServiceType(); - void setServiceType(String s); - -} +*/ +--> +<resources> + <!-- Recent Applications parameters --> + <dimen name="status_bar_recents_app_label_width">190dip</dimen> +</resources> diff --git a/packages/SystemUI/res/values-sw600dp-port/dimens.xml b/packages/SystemUI/res/values-sw600dp-port/dimens.xml new file mode 100644 index 0000000..7dc91d1 --- /dev/null +++ b/packages/SystemUI/res/values-sw600dp-port/dimens.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * 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. +*/ +--> +<resources> + <!-- Recent Applications parameters --> + <dimen name="status_bar_recents_app_label_width">140dip</dimen> +</resources> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index 2ff62a5..2cb99ff 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -39,4 +39,7 @@ <!-- Extra space above the clock in the panel; on this device, zero --> <dimen name="notification_panel_header_padding_top">0dp</dimen> + <!-- Size of application thumbnail --> + <dimen name="status_bar_recents_thumbnail_width">200dp</dimen> + <dimen name="status_bar_recents_thumbnail_height">177dp</dimen> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java index 185ca5b..57f15a8 100644 --- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java @@ -146,7 +146,7 @@ public class SearchPanelView extends FrameLayout implements } } - public void show(boolean show, boolean animate) { + public void show(final boolean show, boolean animate) { if (animate) { if (mShowing != show) { mShowing = show; @@ -156,21 +156,24 @@ public class SearchPanelView extends FrameLayout implements mShowing = show; onAnimationEnd(null); } - setVisibility(show ? View.VISIBLE : View.GONE); - if (show) { - setFocusable(true); - setFocusableInTouchMode(true); - requestFocus(); - } + postDelayed(new Runnable() { + public void run() { + setVisibility(show ? View.VISIBLE : View.INVISIBLE); + if (show) { + setFocusable(true); + setFocusableInTouchMode(true); + requestFocus(); + } + } + }, show ? 0 : 100); } public void hide(boolean animate) { - if (!animate) { - setVisibility(View.GONE); - } if (mBar != null) { // This will indirectly cause show(false, ...) to get called mBar.animateCollapse(); + } else { + setVisibility(View.INVISIBLE); } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index e865b9c..995ee43 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -91,6 +91,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener private int mThumbnailWidth; private boolean mFitThumbnailToXY; private int mRecentItemLayoutId; + private boolean mFirstScreenful = true; public static interface OnRecentsPanelVisibilityChangedListener { public void onRecentsPanelVisibilityChanged(boolean visible); @@ -206,6 +207,22 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } } + public RecentsPanelView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RecentsPanelView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mContext = context; + updateValuesFromResources(); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecentsPanelView, + defStyle, 0); + + mRecentItemLayoutId = a.getResourceId(R.styleable.RecentsPanelView_recentItemLayout, 0); + a.recycle(); + } + public int numItemsInOneScreenful() { if (mRecentsContainer instanceof RecentsScrollView){ RecentsScrollView scrollView @@ -297,6 +314,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener mRecentTasksDirty = true; mWaitingToShow = false; mReadyToShow = false; + mRecentsNoApps.setVisibility(View.INVISIBLE); } if (animate) { if (mShowing != show) { @@ -415,21 +433,6 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener super.setVisibility(visibility); } - public RecentsPanelView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public RecentsPanelView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mContext = context; - updateValuesFromResources(); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecentsPanelView, - defStyle, 0); - - mRecentItemLayoutId = a.getResourceId(R.styleable.RecentsPanelView_recentItemLayout, 0); - } - public void updateValuesFromResources() { final Resources res = mContext.getResources(); mThumbnailWidth = Math.round(res.getDimension(R.dimen.status_bar_recents_thumbnail_width)); @@ -572,7 +575,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener showIfReady(); } - // additional optimization when we have sofware system buttons - start loading the recent + // additional optimization when we have software system buttons - start loading the recent // tasks on touch down @Override public boolean onTouch(View v, MotionEvent ev) { @@ -631,7 +634,6 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } } - boolean mFirstScreenful; public void onTasksLoaded(ArrayList<TaskDescription> tasks) { if (!mFirstScreenful && tasks.size() == 0) { return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index f53a282..f5f2e28 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -467,6 +467,9 @@ public class PhoneStatusBar extends BaseStatusBar { // .03, the item disappears entirely (as if alpha = 0) and that discontinuity looks // a bit jarring mRecentsPanel.setMinSwipeAlpha(0.03f); + if (mNavigationBarView != null) { + mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel); + } } @Override @@ -482,7 +485,6 @@ public class PhoneStatusBar extends BaseStatusBar { WindowManager.LayoutParams lp = (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams(); lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; - lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY; WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp); } @@ -492,7 +494,6 @@ public class PhoneStatusBar extends BaseStatusBar { WindowManager.LayoutParams lp = (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams(); lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; - lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY; WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp); } @@ -573,8 +574,7 @@ public class PhoneStatusBar extends BaseStatusBar { | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH - | WindowManager.LayoutParams.FLAG_SLIPPERY, + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, PixelFormat.OPAQUE); // this will allow the navbar to run in an overlay on devices that support this if (ActivityManager.isHighEndGfx(mDisplay)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index a394596..b0830ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -704,7 +704,6 @@ public class TabletStatusBar extends BaseStatusBar implements WindowManager.LayoutParams lp = (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams(); lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; - lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY; WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp); } @@ -714,7 +713,6 @@ public class TabletStatusBar extends BaseStatusBar implements WindowManager.LayoutParams lp = (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams(); lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; - lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY; WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp); } diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java index f33bf8b..cc8e6a4 100644 --- a/services/java/com/android/server/NsdService.java +++ b/services/java/com/android/server/NsdService.java @@ -20,7 +20,7 @@ import android.content.Context; import android.content.ContentResolver; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.nsd.DnsSdServiceInfo; +import android.net.nsd.NsdServiceInfo; import android.net.nsd.DnsSdTxtRecord; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; @@ -32,6 +32,7 @@ import android.os.Messenger; import android.os.IBinder; import android.provider.Settings; import android.util.Slog; +import android.util.SparseArray; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -72,13 +73,16 @@ public class NsdService extends INsdManager.Stub { */ private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>(); + /* A map from unique id to client info */ + private SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<ClientInfo>(); + private AsyncChannel mReplyChannel = new AsyncChannel(); private int INVALID_ID = 0; private int mUniqueId = 1; private static final int BASE = Protocol.BASE_NSD_MANAGER; - private static final int CMD_TO_STRING_COUNT = NsdManager.STOP_RESOLVE - BASE + 1; + private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1; private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; static { @@ -87,7 +91,6 @@ public class NsdService extends INsdManager.Stub { sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER"; sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER"; sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE"; - sCmdToString[NsdManager.STOP_RESOLVE - BASE] = "STOP-RESOLVE"; } private static String cmdToString(int cmd) { @@ -101,9 +104,9 @@ public class NsdService extends INsdManager.Stub { private class NsdStateMachine extends StateMachine { - private DefaultState mDefaultState = new DefaultState(); - private DisabledState mDisabledState = new DisabledState(); - private EnabledState mEnabledState = new EnabledState(); + private final DefaultState mDefaultState = new DefaultState(); + private final DisabledState mDisabledState = new DisabledState(); + private final EnabledState mEnabledState = new EnabledState(); @Override protected String getMessageInfo(Message msg) { @@ -151,29 +154,26 @@ public class NsdService extends INsdManager.Stub { ac.connect(mContext, getHandler(), msg.replyTo); break; case NsdManager.DISCOVER_SERVICES: - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.BUSY); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.STOP_DISCOVERY: - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.REGISTER_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.UNREGISTER_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.RESOLVE_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NsdManager.STOP_RESOLVE: - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; + case NsdManager.NATIVE_DAEMON_EVENT: default: Slog.e(TAG, "Unhandled " + msg); return NOT_HANDLED; @@ -217,11 +217,30 @@ public class NsdService extends INsdManager.Stub { } } + private boolean requestLimitReached(ClientInfo clientInfo) { + if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) { + if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo); + return true; + } + return false; + } + + private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { + clientInfo.mClientIds.put(clientId, globalId); + mIdToClientInfoMap.put(globalId, clientInfo); + } + + private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { + clientInfo.mClientIds.remove(clientId); + mIdToClientInfoMap.remove(globalId); + } + @Override public boolean processMessage(Message msg) { ClientInfo clientInfo; - DnsSdServiceInfo servInfo; + NsdServiceInfo servInfo; boolean result = HANDLED; + int id; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: //First client @@ -244,111 +263,112 @@ public class NsdService extends INsdManager.Stub { break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); - servInfo = (DnsSdServiceInfo) msg.obj; + servInfo = (NsdServiceInfo) msg.obj; clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mDiscoveryId != INVALID_ID) { - //discovery already in progress - if (DBG) Slog.d(TAG, "discovery in progress"); - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ALREADY_ACTIVE); + + if (requestLimitReached(clientInfo)) { + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_MAX_LIMIT); break; } - clientInfo.mDiscoveryId = getUniqueId(); - if (discoverServices(clientInfo.mDiscoveryId, servInfo.getServiceType())) { - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED); + + id = getUniqueId(); + if (discoverServices(id, servInfo.getServiceType())) { + if (DBG) { + Slog.d(TAG, "Discover " + msg.arg2 + " " + id + + servInfo.getServiceType()); + } + storeRequestMap(msg.arg2, id, clientInfo); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo); } else { - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ERROR); - clientInfo.mDiscoveryId = INVALID_ID; + stopServiceDiscovery(id); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.STOP_DISCOVERY: if (DBG) Slog.d(TAG, "Stop service discovery"); clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mDiscoveryId == INVALID_ID) { - //already stopped - if (DBG) Slog.d(TAG, "discovery already stopped"); - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ALREADY_ACTIVE); + + try { + id = clientInfo.mClientIds.get(msg.arg2).intValue(); + } catch (NullPointerException e) { + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; } - if (stopServiceDiscovery(clientInfo.mDiscoveryId)) { - clientInfo.mDiscoveryId = INVALID_ID; - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); + removeRequestMap(msg.arg2, id, clientInfo); + if (stopServiceDiscovery(id)) { + replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); } else { - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.REGISTER_SERVICE: if (DBG) Slog.d(TAG, "Register service"); clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mRegisteredIds.size() >= ClientInfo.MAX_REG) { - if (DBG) Slog.d(TAG, "register service exceeds limit"); - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.MAX_REGS_REACHED); + if (requestLimitReached(clientInfo)) { + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_MAX_LIMIT); + break; } - int id = getUniqueId(); - if (registerService(id, (DnsSdServiceInfo) msg.obj)) { - clientInfo.mRegisteredIds.add(id); + id = getUniqueId(); + if (registerService(id, (NsdServiceInfo) msg.obj)) { + if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); + storeRequestMap(msg.arg2, id, clientInfo); + // Return success after mDns reports success } else { - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); + unregisterService(id); + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.UNREGISTER_SERVICE: if (DBG) Slog.d(TAG, "unregister service"); clientInfo = mClients.get(msg.replyTo); - int regId = msg.arg1; - if (clientInfo.mRegisteredIds.remove(new Integer(regId)) && - unregisterService(regId)) { - mReplyChannel.replyToMessage(msg, - NsdManager.UNREGISTER_SERVICE_SUCCEEDED); + try { + id = clientInfo.mClientIds.get(msg.arg2).intValue(); + } catch (NullPointerException e) { + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); + break; + } + removeRequestMap(msg.arg2, id, clientInfo); + if (unregisterService(id)) { + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); } else { - mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; - case NsdManager.UPDATE_SERVICE: - if (DBG) Slog.d(TAG, "Update service"); - //TODO: implement - mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED); - break; case NsdManager.RESOLVE_SERVICE: if (DBG) Slog.d(TAG, "Resolve service"); - servInfo = (DnsSdServiceInfo) msg.obj; + servInfo = (NsdServiceInfo) msg.obj; clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mResolveId != INVALID_ID) { - //first cancel existing resolve - stopResolveService(clientInfo.mResolveId); - } - clientInfo.mResolveId = getUniqueId(); - if (!resolveService(clientInfo.mResolveId, servInfo)) { - mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - clientInfo.mResolveId = INVALID_ID; - } - break; - case NsdManager.STOP_RESOLVE: - if (DBG) Slog.d(TAG, "Stop resolve"); - clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mResolveId == INVALID_ID) { - //already stopped - if (DBG) Slog.d(TAG, "resolve already stopped"); - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ALREADY_ACTIVE); + + if (clientInfo.mResolvedService != null) { + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_ALREADY_ACTIVE); break; } - if (stopResolveService(clientInfo.mResolveId)) { - clientInfo.mResolveId = INVALID_ID; - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_SUCCEEDED); + + id = getUniqueId(); + if (resolveService(id, servInfo)) { + clientInfo.mResolvedService = new NsdServiceInfo(); + storeRequestMap(msg.arg2, id, clientInfo); } else { - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; + case NsdManager.NATIVE_DAEMON_EVENT: + NativeEvent event = (NativeEvent) msg.obj; + handleNativeEvent(event.code, event.raw, + NativeDaemonEvent.unescapeArgs(event.raw)); + break; default: result = NOT_HANDLED; break; @@ -439,121 +459,144 @@ public class NsdService extends INsdManager.Stub { public static final int SERVICE_GET_ADDR_SUCCESS = 612; } + private class NativeEvent { + int code; + String raw; + + NativeEvent(int code, String raw) { + this.code = code; + this.raw = raw; + } + } + class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks { public void onDaemonConnected() { mNativeDaemonConnected.countDown(); } public boolean onEvent(int code, String raw, String[] cooked) { - ClientInfo clientInfo; - DnsSdServiceInfo servInfo; - int id = Integer.parseInt(cooked[1]); - switch (code) { - case NativeResponseCode.SERVICE_FOUND: - /* NNN uniqueId serviceName regType domain */ - if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, servInfo); - break; - case NativeResponseCode.SERVICE_LOST: - /* NNN uniqueId serviceName regType domain */ - if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, servInfo); - break; - case NativeResponseCode.SERVICE_DISCOVERY_FAILED: - /* NNN uniqueId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_REGISTERED: - /* NNN regId serviceName regType */ - if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); - clientInfo = getClientByRegistration(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], null, null); - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, - id, 0, servInfo); - break; - case NativeResponseCode.SERVICE_REGISTRATION_FAILED: - /* NNN regId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); - clientInfo = getClientByRegistration(id); - if (clientInfo == null) break; - - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_UPDATED: - /* NNN regId */ - break; - case NativeResponseCode.SERVICE_UPDATE_FAILED: - /* NNN regId errorCode */ - break; - case NativeResponseCode.SERVICE_RESOLVED: - /* NNN resolveId fullName hostName port txtlen txtdata */ - if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null) break; - - int index = cooked[2].indexOf("."); - if (index == -1) { - Slog.e(TAG, "Invalid service found " + raw); - break; - } - String name = cooked[2].substring(0, index); - String rest = cooked[2].substring(index); - String type = rest.replace(".local.", ""); + // TODO: NDC translates a message to a callback, we could enhance NDC to + // directly interact with a state machine through messages + NativeEvent event = new NativeEvent(code, raw); + mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event); + return true; + } + } - clientInfo.mResolvedService = new DnsSdServiceInfo(name, type, null); - clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); + private void handleNativeEvent(int code, String raw, String[] cooked) { + NsdServiceInfo servInfo; + int id = Integer.parseInt(cooked[1]); + ClientInfo clientInfo = mIdToClientInfoMap.get(id); + if (clientInfo == null) { + Slog.e(TAG, "Unique id with no client mapping: " + id); + return; + } - stopResolveService(id); - getAddrInfo(id, cooked[3]); + /* This goes in response as msg.arg2 */ + int clientId = -1; + int keyId = clientInfo.mClientIds.indexOfValue(id); + if (keyId != -1) { + clientId = clientInfo.mClientIds.keyAt(keyId); + } + switch (code) { + case NativeResponseCode.SERVICE_FOUND: + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0, + clientId, servInfo); + break; + case NativeResponseCode.SERVICE_LOST: + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0, + clientId, servInfo); + break; + case NativeResponseCode.SERVICE_DISCOVERY_FAILED: + /* NNN uniqueId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_REGISTERED: + /* NNN regId serviceName regType */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], null, null); + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, + id, clientId, servInfo); + break; + case NativeResponseCode.SERVICE_REGISTRATION_FAILED: + /* NNN regId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_UPDATED: + /* NNN regId */ + break; + case NativeResponseCode.SERVICE_UPDATE_FAILED: + /* NNN regId errorCode */ + break; + case NativeResponseCode.SERVICE_RESOLVED: + /* NNN resolveId fullName hostName port txtlen txtdata */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); + int index = cooked[2].indexOf("."); + if (index == -1) { + Slog.e(TAG, "Invalid service found " + raw); break; - case NativeResponseCode.SERVICE_RESOLUTION_FAILED: - case NativeResponseCode.SERVICE_GET_ADDR_FAILED: - /* NNN resolveId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null) break; + } + String name = cooked[2].substring(0, index); + String rest = cooked[2].substring(index); + String type = rest.replace(".local.", ""); + + clientInfo.mResolvedService.setServiceName(name); + clientInfo.mResolvedService.setServiceType(type); + clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); + stopResolveService(id); + if (!getAddrInfo(id, cooked[3])) { clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: - /* NNN resolveId hostname ttl addr */ - if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null || clientInfo.mResolvedService == null) break; - - try { - clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, - clientInfo.mResolvedService); - clientInfo.mResolvedService = null; - clientInfo.mResolveId = INVALID_ID; - } catch (java.net.UnknownHostException e) { - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - } - stopGetAddrInfo(id); - break; - default: - break; - } - return false; + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + } + break; + case NativeResponseCode.SERVICE_RESOLUTION_FAILED: + /* NNN resolveId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); + stopResolveService(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_GET_ADDR_FAILED: + /* NNN resolveId errorCode */ + stopGetAddrInfo(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: + /* NNN resolveId hostname ttl addr */ + if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); + try { + clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, + 0, clientId, clientInfo.mResolvedService); + } catch (java.net.UnknownHostException e) { + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + } + stopGetAddrInfo(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + break; + default: + break; } } @@ -579,7 +622,7 @@ public class NsdService extends INsdManager.Stub { return true; } - private boolean registerService(int regId, DnsSdServiceInfo service) { + private boolean registerService(int regId, NsdServiceInfo service) { if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service); try { //Add txtlen and txtdata @@ -637,7 +680,7 @@ public class NsdService extends INsdManager.Stub { return true; } - private boolean resolveService(int resolveId, DnsSdServiceInfo service) { + private boolean resolveService(int resolveId, NsdServiceInfo service) { if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service); try { mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(), @@ -700,49 +743,52 @@ public class NsdService extends INsdManager.Stub { mNsdStateMachine.dump(fd, pw, args); } - private ClientInfo getClientByDiscovery(int discoveryId) { - for (ClientInfo c: mClients.values()) { - if (c.mDiscoveryId == discoveryId) { - return c; - } - } - return null; + /* arg2 on the source message has an id that needs to be retained in replies + * see NsdManager for details */ + private Message obtainMessage(Message srcMsg) { + Message msg = Message.obtain(); + msg.arg2 = srcMsg.arg2; + return msg; } - private ClientInfo getClientByResolve(int resolveId) { - for (ClientInfo c: mClients.values()) { - if (c.mResolveId == resolveId) { - return c; - } - } - return null; + private void replyToMessage(Message msg, int what) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + mReplyChannel.replyToMessage(msg, dstMsg); } - private ClientInfo getClientByRegistration(int regId) { - for (ClientInfo c: mClients.values()) { - if (c.mRegisteredIds.contains(regId)) { - return c; - } - } - return null; + private void replyToMessage(Message msg, int what, int arg1) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + dstMsg.arg1 = arg1; + mReplyChannel.replyToMessage(msg, dstMsg); + } + + private void replyToMessage(Message msg, int what, Object obj) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + dstMsg.obj = obj; + mReplyChannel.replyToMessage(msg, dstMsg); } /* Information tracked per client */ private class ClientInfo { - private static final int MAX_REG = 5; + private static final int MAX_LIMIT = 10; private AsyncChannel mChannel; private Messenger mMessenger; - private int mDiscoveryId; - private int mResolveId; /* Remembers a resolved service until getaddrinfo completes */ - private DnsSdServiceInfo mResolvedService; - private ArrayList<Integer> mRegisteredIds = new ArrayList<Integer>(); + private NsdServiceInfo mResolvedService; + + /* A map from client id to unique id sent to mDns */ + private SparseArray<Integer> mClientIds = new SparseArray<Integer>(); private ClientInfo(AsyncChannel c, Messenger m) { mChannel = c; mMessenger = m; - mDiscoveryId = mResolveId = INVALID_ID; if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); } @@ -751,11 +797,10 @@ public class NsdService extends INsdManager.Stub { StringBuffer sb = new StringBuffer(); sb.append("mChannel ").append(mChannel).append("\n"); sb.append("mMessenger ").append(mMessenger).append("\n"); - sb.append("mDiscoveryId ").append(mDiscoveryId).append("\n"); - sb.append("mResolveId ").append(mResolveId).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); - for(int regId : mRegisteredIds) { - sb.append("regId ").append(regId).append("\n"); + for(int i = 0; i< mClientIds.size(); i++) { + sb.append("clientId ").append(mClientIds.keyAt(i)); + sb.append(" mDnsId ").append(mClientIds.valueAt(i)).append("\n"); } return sb.toString(); } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 40f64bf..aa7de82 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1567,6 +1567,31 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + if (code == SYSPROPS_TRANSACTION) { + // We need to tell all apps about the system property change. + ArrayList<IBinder> procs = new ArrayList<IBinder>(); + synchronized(this) { + for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) { + final int NA = apps.size(); + for (int ia=0; ia<NA; ia++) { + ProcessRecord app = apps.valueAt(ia); + if (app.thread != null) { + procs.add(app.thread.asBinder()); + } + } + } + } + + int N = procs.size(); + for (int i=0; i<N; i++) { + Parcel data2 = Parcel.obtain(); + try { + procs.get(i).transact(IBinder.SYSPROPS_TRANSACTION, data2, null, 0); + } catch (RemoteException e) { + } + data2.recycle(); + } + } try { return super.onTransact(code, data, reply, flags); } catch (RuntimeException e) { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 1e14f5b..c300411 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1794,10 +1794,6 @@ final class ActivityStack { mService.mWindowManager.prepareAppTransition( WindowManagerPolicy.TRANSIT_NONE, keepCurTransition); mNoAnimActivities.add(r); - } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { - mService.mWindowManager.prepareAppTransition( - WindowManagerPolicy.TRANSIT_TASK_OPEN, keepCurTransition); - mNoAnimActivities.remove(r); } else { mService.mWindowManager.prepareAppTransition(newTask ? WindowManagerPolicy.TRANSIT_TASK_OPEN diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java index 2ce7771..c3ecf54 100644 --- a/services/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/java/com/android/server/net/NetworkStatsRecorder.java @@ -26,6 +26,7 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.os.DropBoxManager; import android.util.Log; import android.util.MathUtils; import android.util.Slog; @@ -34,6 +35,7 @@ import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; import com.google.android.collect.Sets; +import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; @@ -43,6 +45,8 @@ import java.lang.ref.WeakReference; import java.util.HashSet; import java.util.Map; +import libcore.io.IoUtils; + /** * Logic to record deltas between periodic {@link NetworkStats} snapshots into * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}. @@ -56,8 +60,14 @@ public class NetworkStatsRecorder { private static final boolean LOGD = false; private static final boolean LOGV = false; + private static final String TAG_NETSTATS_DUMP = "netstats_dump"; + + /** Dump before deleting in {@link #recoverFromWtf()}. */ + private static final boolean DUMP_BEFORE_DELETE = true; + private final FileRotator mRotator; private final NonMonotonicObserver<String> mObserver; + private final DropBoxManager mDropBox; private final String mCookie; private final long mBucketDuration; @@ -74,9 +84,10 @@ public class NetworkStatsRecorder { private WeakReference<NetworkStatsCollection> mComplete; public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer, - String cookie, long bucketDuration, boolean onlyTags) { + DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) { mRotator = checkNotNull(rotator, "missing FileRotator"); mObserver = checkNotNull(observer, "missing NonMonotonicObserver"); + mDropBox = checkNotNull(dropBox, "missing DropBoxManager"); mCookie = cookie; mBucketDuration = bucketDuration; @@ -122,6 +133,7 @@ public class NetworkStatsRecorder { mComplete = new WeakReference<NetworkStatsCollection>(complete); } catch (IOException e) { Log.wtf(TAG, "problem completely reading network stats", e); + recoverFromWtf(); } } return complete; @@ -212,6 +224,7 @@ public class NetworkStatsRecorder { mPending.reset(); } catch (IOException e) { Log.wtf(TAG, "problem persisting pending stats", e); + recoverFromWtf(); } } } @@ -226,6 +239,7 @@ public class NetworkStatsRecorder { mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uid)); } catch (IOException e) { Log.wtf(TAG, "problem removing UID " + uid, e); + recoverFromWtf(); } // clear UID from current stats snapshot @@ -355,4 +369,25 @@ public class NetworkStatsRecorder { mSinceBoot.dump(pw); } } + + /** + * Recover from {@link FileRotator} failure by dumping state to + * {@link DropBoxManager} and deleting contents. + */ + private void recoverFromWtf() { + if (DUMP_BEFORE_DELETE) { + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + mRotator.dumpAll(os); + } catch (IOException e) { + // ignore partial contents + os.reset(); + } finally { + IoUtils.closeQuietly(os); + } + mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0); + } + + mRotator.deleteAll(); + } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 1a56b80..e710b33 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -338,9 +338,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStatsRecorder buildRecorder( String prefix, NetworkStatsSettings.Config config, boolean includeTags) { + final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService( + Context.DROPBOX_SERVICE); return new NetworkStatsRecorder(new FileRotator( mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis), - mNonMonotonicObserver, prefix, config.bucketDuration, includeTags); + mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags); } private void shutdownLocked() { |