diff options
20 files changed, 501 insertions, 101 deletions
diff --git a/api/current.xml b/api/current.xml index 7e2ac7e9a027..4989eba7d2f7 100644 --- a/api/current.xml +++ b/api/current.xml @@ -137540,6 +137540,34 @@ <parameter name="params" type="Params..."> </parameter> </method> +<method name="execute" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="runnable" type="java.lang.Runnable"> +</parameter> +</method> +<method name="executeOnExecutor" + return="android.os.AsyncTask<Params, Progress, Result>" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="exec" type="java.util.concurrent.Executor"> +</parameter> +<parameter name="params" type="Params..."> +</parameter> +</method> <method name="get" return="Result" abstract="false" @@ -137672,6 +137700,16 @@ <parameter name="values" type="Progress..."> </parameter> </method> +<field name="THREAD_POOL_EXECUTOR" + type="java.util.concurrent.ThreadPoolExecutor" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> </class> <class name="AsyncTask.Status" extends="java.lang.Enum" diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 9f7e31cd8edb..adc0a8b322b9 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -16,9 +16,11 @@ package android.os; +import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.LinkedBlockingQueue; @@ -151,8 +153,6 @@ public abstract class AsyncTask<Params, Progress, Result> { private static final int MAXIMUM_POOL_SIZE = 128; private static final int KEEP_ALIVE = 1; - private static final BlockingQueue<Runnable> sWorkQueue = - new LinkedBlockingQueue<Runnable>(10); private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); @@ -162,8 +162,17 @@ public abstract class AsyncTask<Params, Progress, Result> { } }; - private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory); + private static final BlockingQueue<Runnable> sPoolWorkQueue = + new LinkedBlockingQueue<Runnable>(10); + + /** + * A {@link ThreadPoolExecutor} that can be used to execute tasks in parallel. + */ + public static final ThreadPoolExecutor THREAD_POOL_EXECUTOR + = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, + TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); + + private static final SerialExecutor sSerialExecutor = new SerialExecutor(); private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; @@ -177,6 +186,32 @@ public abstract class AsyncTask<Params, Progress, Result> { private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); + private static class SerialExecutor implements Executor { + final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); + Runnable mActive; + + public synchronized void execute(final Runnable r) { + mTasks.offer(new Runnable() { + public void run() { + try { + r.run(); + } finally { + scheduleNext(); + } + } + }); + if (mActive == null) { + scheduleNext(); + } + } + + protected synchronized void scheduleNext() { + if ((mActive = mTasks.poll()) != null) { + THREAD_POOL_EXECUTOR.execute(mActive); + } + } + } + /** * Indicates the current status of the task. Each status will be set only once * during the lifetime of a task. @@ -433,7 +468,11 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * Executes the task with the specified parameters. The task returns - * itself (this) so that the caller can keep a reference to it. + * itself (this) so that the caller can keep a reference to it. The tasks + * started by all invocations of this method in a given process are run + * sequentially. Call the {@link #execute(Executor,Params...) execute(Executor,Params...)} + * with a custom {@link Executor} to have finer grained control over how the + * tasks are run. * * This method must be invoked on the UI thread. * @@ -445,6 +484,26 @@ public abstract class AsyncTask<Params, Progress, Result> { * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. */ public final AsyncTask<Params, Progress, Result> execute(Params... params) { + return executeOnExecutor(sSerialExecutor, params); + } + + /** + * Executes the task with the specified parameters. The task returns + * itself (this) so that the caller can keep a reference to it. + * + * This method must be invoked on the UI thread. + * + * @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a + * convenient process-wide thread pool for tasks that are loosely coupled. + * @param params The parameters of the task. + * + * @return This instance of AsyncTask. + * + * @throws IllegalStateException If {@link #getStatus()} returns either + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. + */ + public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, + Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: @@ -462,12 +521,20 @@ public abstract class AsyncTask<Params, Progress, Result> { onPreExecute(); mWorker.mParams = params; - sExecutor.execute(mFuture); + exec.execute(mFuture); return this; } /** + * Schedules the {@link Runnable} in serial with the other AsyncTasks that were started + * with {@link #execute}. + */ + public static void execute(Runnable runnable) { + sSerialExecutor.execute(runnable); + } + + /** * This method can be invoked from {@link #doInBackground} to * publish updates on the UI thread while the background computation is * still running. Each call to this method will trigger the execution of diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index ad9e68633958..e2285373c7e8 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1780,7 +1780,7 @@ public final class ViewRoot extends Handler implements ViewParent, } void dispatchDetachedFromWindow() { - if (mView != null) { + if (mView != null && mView.mAttachInfo != null) { mView.dispatchDetachedFromWindow(); } diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 7d54d3b3255d..bb2843790ed7 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -27,6 +27,7 @@ #include "Rect.h" #include "SkiaColorFilter.h" +#include "Vertex.h" namespace android { namespace uirenderer { @@ -41,6 +42,14 @@ namespace uirenderer { struct Layer { Layer(const uint32_t layerWidth, const uint32_t layerHeight): width(layerWidth), height(layerHeight) { + mesh = NULL; + meshIndices = NULL; + meshElementCount = 0; + } + + ~Layer() { + if (mesh) delete mesh; + if (meshIndices) delete meshIndices; } /** @@ -99,6 +108,13 @@ struct Layer { * Color filter used to draw this layer. Optional. */ SkiaColorFilter* colorFilter; + + /** + * If the layer can be rendered as a mesh, this is non-null. + */ + TextureVertex* mesh; + uint16_t* meshIndices; + GLsizei meshElementCount; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index a25c95ed6614..cd2554e14a4f 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -29,6 +29,10 @@ namespace uirenderer { void LayerRenderer::prepare(bool opaque) { LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo); +#if RENDER_LAYERS_AS_REGIONS + mLayer->region.clear(); +#endif + glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &mPreviousFbo); glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo); @@ -39,11 +43,97 @@ void LayerRenderer::finish() { OpenGLRenderer::finish(); glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFbo); + generateMesh(); + LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->mFbo); } /////////////////////////////////////////////////////////////////////////////// -// Static functions +// Dirty region tracking +/////////////////////////////////////////////////////////////////////////////// + +bool LayerRenderer::hasLayer() { + return true; +} + +Region* LayerRenderer::getRegion() { +#if RENDER_LAYERS_AS_REGIONS + if (getSnapshot()->flags & Snapshot::kFlagFboTarget) { + return OpenGLRenderer::getRegion(); + } + return &mLayer->region; +#else + return OpenGLRenderer::getRegion(); +#endif +} + +void LayerRenderer::generateMesh() { +#if RENDER_LAYERS_AS_REGIONS + if (mLayer->region.isRect() || mLayer->region.isEmpty()) { + if (mLayer->mesh) { + delete mLayer->mesh; + delete mLayer->meshIndices; + + mLayer->mesh = NULL; + mLayer->meshIndices = NULL; + mLayer->meshElementCount = 0; + } + return; + } + + size_t count; + const android::Rect* rects = mLayer->region.getArray(&count); + + GLsizei elementCount = count * 6; + + if (mLayer->mesh && mLayer->meshElementCount < elementCount) { + delete mLayer->mesh; + delete mLayer->meshIndices; + + mLayer->mesh = NULL; + mLayer->meshIndices = NULL; + } + + if (!mLayer->mesh) { + mLayer->mesh = new TextureVertex[count * 4]; + mLayer->meshIndices = new uint16_t[elementCount]; + mLayer->meshElementCount = elementCount; + } + + const float texX = 1.0f / float(mLayer->width); + const float texY = 1.0f / float(mLayer->height); + const float height = mLayer->layer.getHeight(); + + TextureVertex* mesh = mLayer->mesh; + uint16_t* indices = mLayer->meshIndices; + + for (size_t i = 0; i < count; i++) { + const android::Rect* r = &rects[i]; + + const float u1 = r->left * texX; + const float v1 = (height - r->top) * texY; + const float u2 = r->right * texX; + const float v2 = (height - r->bottom) * texY; + + TextureVertex::set(mesh++, r->left, r->top, u1, v1); + TextureVertex::set(mesh++, r->right, r->top, u2, v1); + TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); + TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); + + uint16_t quad = i * 4; + int index = i * 6; + indices[index ] = quad; // top-left + indices[index + 1] = quad + 1; // top-right + indices[index + 2] = quad + 2; // bottom-left + indices[index + 3] = quad + 2; // bottom-left + indices[index + 4] = quad + 1; // top-right + indices[index + 5] = quad + 3; // bottom-right + } +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// Layers management /////////////////////////////////////////////////////////////////////////////// Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) { diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index ed5d9609c001..f2fb898b21c7 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -49,12 +49,17 @@ public: void prepare(bool opaque); void finish(); + bool hasLayer(); + Region* getRegion(); + static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false); static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); static void destroyLayer(Layer* layer); static void destroyLayerDeferred(Layer* layer); private: + void generateMesh(); + Layer* mLayer; GLuint mPreviousFbo; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index b9332327df99..16a1de7adc32 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -615,6 +615,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { const float alpha = layer->alpha / 255.0f; const float texX = 1.0f / float(layer->width); const float texY = 1.0f / float(layer->height); + const float height = rect.getHeight(); TextureVertex* mesh = mCaches.getRegionMesh(); GLsizei numQuads = 0; @@ -636,9 +637,9 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { const android::Rect* r = &rects[i]; const float u1 = r->left * texX; - const float v1 = (rect.getHeight() - r->top) * texY; + const float v1 = (height - r->top) * texY; const float u2 = r->right * texX; - const float v2 = (rect.getHeight() - r->bottom) * texY; + const float v2 = (height - r->bottom) * texY; // TODO: Reject quads outside of the clip TextureVertex::set(mesh++, r->left, r->top, u1, v1); @@ -694,10 +695,10 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { void OpenGLRenderer::dirtyLayer(const float left, const float top, const float right, const float bottom, const mat4 transform) { #if RENDER_LAYERS_AS_REGIONS - if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) { + if (hasLayer()) { Rect bounds(left, top, right, bottom); transform.mapRect(bounds); - dirtyLayerUnchecked(bounds, mSnapshot->region); + dirtyLayerUnchecked(bounds, getRegion()); } #endif } @@ -705,9 +706,9 @@ void OpenGLRenderer::dirtyLayer(const float left, const float top, void OpenGLRenderer::dirtyLayer(const float left, const float top, const float right, const float bottom) { #if RENDER_LAYERS_AS_REGIONS - if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) { + if (hasLayer()) { Rect bounds(left, top, right, bottom); - dirtyLayerUnchecked(bounds, mSnapshot->region); + dirtyLayerUnchecked(bounds, getRegion()); } #endif } @@ -1419,24 +1420,20 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); #if RENDER_LAYERS_AS_REGIONS - bool hasLayer = (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region; + bool hasActiveLayer = hasLayer(); #else - bool hasLayer = false; + bool hasActiveLayer = false; #endif mCaches.unbindMeshBuffer(); if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y, - hasLayer ? &bounds : NULL)) { + hasActiveLayer ? &bounds : NULL)) { #if RENDER_LAYERS_AS_REGIONS - if (hasLayer) { + if (hasActiveLayer) { if (!pureTranslate) { mSnapshot->transform->mapRect(bounds); } - bounds.intersect(*mSnapshot->clipRect); - bounds.snapToPixelBoundaries(); - - android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom); - mSnapshot->region->orSelf(dirty); + dirtyLayerUnchecked(bounds, getRegion()); } #endif } @@ -1501,8 +1498,36 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { layer->alpha = alpha; layer->mode = mode; + +#if RENDER_LAYERS_AS_REGIONS + if (layer->region.isRect()) { + const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight()); + composeLayerRect(layer, r); + } else if (!layer->region.isEmpty() && layer->mesh) { + const Rect& rect = layer->layer; + + setupDraw(); + setupDrawWithTexture(); + setupDrawColor(alpha, alpha, alpha, alpha); + setupDrawColorFilter(); + setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false); + setupDrawProgram(); + setupDrawDirtyRegionsDisabled(); + setupDrawPureColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawTexture(layer->texture); + setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom); + setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]); + + glDrawElements(GL_TRIANGLES, layer->meshElementCount, + GL_UNSIGNED_SHORT, layer->meshIndices); + + finishDrawTexture(); + } +#else const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight()); composeLayerRect(layer, r); +#endif } /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 56be13458e10..7387b9268c39 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -133,19 +133,24 @@ protected: virtual void composeLayer(sp<Snapshot> current, sp<Snapshot> previous); /** - * Mark the layer as dirty at the specified coordinates. The coordinates - * are transformed with the supplied matrix. + * Marks the specified region as dirty at the specified bounds. */ - virtual void dirtyLayer(const float left, const float top, - const float right, const float bottom, const mat4 transform); + void dirtyLayerUnchecked(Rect& bounds, Region* region); /** - * Mark the layer as dirty at the specified coordinates. + * Returns the current snapshot. */ - virtual void dirtyLayer(const float left, const float top, - const float right, const float bottom); + sp<Snapshot> getSnapshot() { + return mSnapshot; + } - void dirtyLayerUnchecked(Rect& bounds, Region* region); + virtual Region* getRegion() { + return mSnapshot->region; + } + + virtual bool hasLayer() { + return (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region; + } private: /** @@ -225,6 +230,19 @@ private: void clearLayerRegions(); /** + * Mark the layer as dirty at the specified coordinates. The coordinates + * are transformed with the supplied matrix. + */ + void dirtyLayer(const float left, const float top, + const float right, const float bottom, const mat4 transform); + + /** + * Mark the layer as dirty at the specified coordinates. + */ + void dirtyLayer(const float left, const float top, + const float right, const float bottom); + + /** * Draws a colored rectangle with the specified color. The specified coordinates * are transformed by the current snapshot's transform matrix. * diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index 9898df491eba..595ad4e92e3b 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -268,7 +268,7 @@ public: Rect* clipRect; /** - * The ancestor layer's dirty region.. + * The ancestor layer's dirty region. */ Region* region; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java index da60f0d681c7..1b2fcadcbeb9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java @@ -21,6 +21,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.AsyncTask; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; @@ -78,15 +79,19 @@ public class AirplaneModeController extends BroadcastReceiver // TODO: Fix this racy API by adding something better to TelephonyManager or // ConnectivityService. - private void unsafe(boolean enabled) { - Settings.System.putInt( - mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, - enabled ? 1 : 0); - Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra("state", enabled); - mContext.sendBroadcast(intent); + private void unsafe(final boolean enabled) { + AsyncTask.execute(new Runnable() { + public void run() { + Settings.System.putInt( + mContext.getContentResolver(), + Settings.System.AIRPLANE_MODE_ON, + enabled ? 1 : 0); + Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + intent.putExtra("state", enabled); + mContext.sendBroadcast(intent); + } + }); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java index 866e5fcad7b4..b0a6d7aeca78 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.policy; import android.content.ContentResolver; import android.content.Context; +import android.os.AsyncTask; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; @@ -45,7 +46,6 @@ public class AutoRotateController implements CompoundButton.OnCheckedChangeListe } public void onCheckedChanged(CompoundButton view, boolean checked) { - Slog.d(TAG, "onCheckedChanged checked=" + checked + " mLockRotation=" + mLockRotation); if (checked != mLockRotation) { setLockRotation(checked); } @@ -56,18 +56,22 @@ public class AutoRotateController implements CompoundButton.OnCheckedChangeListe return 0 == Settings.System.getInt(cr, Settings.System.ACCELEROMETER_ROTATION, 0); } - private void setLockRotation(boolean locked) { + private void setLockRotation(final boolean locked) { mLockRotation = locked; - try { - IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService( - Context.WINDOW_SERVICE)); - ContentResolver cr = mContext.getContentResolver(); - if (locked) { - wm.freezeRotation(); - } else { - wm.thawRotation(); - } - } catch (RemoteException exc) { - } + AsyncTask.execute(new Runnable() { + public void run() { + try { + IWindowManager wm = IWindowManager.Stub.asInterface( + ServiceManager.getService(Context.WINDOW_SERVICE)); + ContentResolver cr = mContext.getContentResolver(); + if (locked) { + wm.freezeRotation(); + } else { + wm.thawRotation(); + } + } catch (RemoteException exc) { + } + } + }); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java index ca1d98fc8984..521467a5d76a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.policy; import android.content.ContentResolver; import android.content.Context; +import android.os.AsyncTask; import android.os.IPowerManager; import android.os.RemoteException; import android.os.ServiceManager; @@ -79,11 +80,15 @@ public class BrightnessController implements ToggleSlider.Listener { setMode(automatic ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); if (!automatic) { - value = value + value + MINIMUM_BACKLIGHT; - setBrightness(value); + final int val = value + value + MINIMUM_BACKLIGHT; + setBrightness(val); if (!tracking) { - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.SCREEN_BRIGHTNESS, value); + AsyncTask.execute(new Runnable() { + public void run() { + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS, val); + } + }); } } } diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 1b590ba2190b..cf072392cbe1 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -37,6 +37,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WpsConfiguration; +import android.net.wifi.WpsResult; import android.net.ConnectivityManager; import android.net.InterfaceConfiguration; import android.net.DhcpInfo; @@ -841,13 +842,13 @@ public class WifiService extends IWifiManager.Stub { mWifiStateMachine.forgetNetwork(netId); } - public String startWps(WpsConfiguration config) { + public WpsResult startWps(WpsConfiguration config) { enforceChangePermission(); if (mChannel != null) { return mWifiStateMachine.startWps(mChannel, config); } else { Slog.e(TAG, "mChannel is not initialized"); - return ""; + return new WpsResult(WpsResult.Status.FAILURE); } } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 9dbba202689c..847577fea4ff 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -19,6 +19,7 @@ package android.net.wifi; import android.net.wifi.WifiInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WpsConfiguration; +import android.net.wifi.WpsResult; import android.net.wifi.ScanResult; import android.net.DhcpInfo; @@ -109,6 +110,6 @@ interface IWifiManager void forgetNetwork(int networkId); - String startWps(in WpsConfiguration config); + WpsResult startWps(in WpsConfiguration config); } diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java index 56bc5d773851..73c24cf02397 100644 --- a/wifi/java/android/net/wifi/WifiConfigStore.java +++ b/wifi/java/android/net/wifi/WifiConfigStore.java @@ -370,44 +370,52 @@ class WifiConfigStore { * Start WPS pin method configuration with pin obtained * from the access point */ - static boolean startWpsWithPinFromAccessPoint(WpsConfiguration config) { + static WpsResult startWpsWithPinFromAccessPoint(WpsConfiguration config) { + WpsResult result = new WpsResult(); if (WifiNative.startWpsWithPinFromAccessPointCommand(config.BSSID, config.pin)) { /* WPS leaves all networks disabled */ markAllNetworksDisabled(); - return true; + result.status = WpsResult.Status.SUCCESS; + } else { + Log.e(TAG, "Failed to start WPS pin method configuration"); + result.status = WpsResult.Status.FAILURE; } - Log.e(TAG, "Failed to start WPS pin method configuration"); - return false; + return result; } /** * Start WPS pin method configuration with pin obtained * from the device - * @return empty string on failure. null is never returned. + * @return WpsResult indicating status and pin */ - static String startWpsWithPinFromDevice(WpsConfiguration config) { - String pin = WifiNative.startWpsWithPinFromDeviceCommand(config.BSSID); + static WpsResult startWpsWithPinFromDevice(WpsConfiguration config) { + WpsResult result = new WpsResult(); + result.pin = WifiNative.startWpsWithPinFromDeviceCommand(config.BSSID); /* WPS leaves all networks disabled */ - if (!TextUtils.isEmpty(pin)) { + if (!TextUtils.isEmpty(result.pin)) { markAllNetworksDisabled(); + result.status = WpsResult.Status.SUCCESS; } else { Log.e(TAG, "Failed to start WPS pin method configuration"); - pin = ""; + result.status = WpsResult.Status.FAILURE; } - return pin; + return result; } /** * Start WPS push button configuration */ - static boolean startWpsPbc(WpsConfiguration config) { + static WpsResult startWpsPbc(WpsConfiguration config) { + WpsResult result = new WpsResult(); if (WifiNative.startWpsPbcCommand(config.BSSID)) { /* WPS leaves all networks disabled */ markAllNetworksDisabled(); - return true; + result.status = WpsResult.Status.SUCCESS; + } else { + Log.e(TAG, "Failed to start WPS push button configuration"); + result.status = WpsResult.Status.FAILURE; } - Log.e(TAG, "Failed to start WPS push button configuration"); - return false; + return result; } /** diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 46237214861b..54887d7be1a2 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1074,15 +1074,15 @@ public class WifiManager { * Start Wi-fi Protected Setup * * @param config WPS configuration - * @return pin generated by device, if any + * @return WpsResult containing pin and status * @hide * TODO: with use of AsyncChannel, return value should go away */ - public String startWps(WpsConfiguration config) { + public WpsResult startWps(WpsConfiguration config) { try { return mService.startWps(config); } catch (RemoteException e) { - return null; + return new WpsResult(WpsResult.Status.FAILURE); } } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 871811730679..d7d86f0b8fad 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -47,6 +47,7 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo.DetailedState; import android.net.LinkProperties; import android.net.wifi.NetworkUpdateResult; +import android.net.wifi.WpsResult.Status; import android.os.Binder; import android.os.Message; import android.os.IBinder; @@ -302,10 +303,11 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* Reset the supplicant state tracker */ static final int CMD_RESET_SUPPLICANT_STATE = 111; - /* Commands/events reported by WpsStateMachine */ /* Indicates the completion of WPS activity */ static final int WPS_COMPLETED_EVENT = 121; + /* Reset the WPS state machine */ + static final int CMD_RESET_WPS_STATE = 122; private static final int CONNECT_MODE = 1; private static final int SCAN_ONLY_MODE = 2; @@ -793,18 +795,19 @@ public class WifiStateMachine extends HierarchicalStateMachine { sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0)); } - public String startWps(AsyncChannel channel, WpsConfiguration config) { - String result = null; + public WpsResult startWps(AsyncChannel channel, WpsConfiguration config) { + WpsResult result; switch (config.setup) { case PIN_FROM_DEVICE: + case PBC: + case PIN_FROM_ACCESS_POINT: //TODO: will go away with AsyncChannel use from settings Message resultMsg = channel.sendMessageSynchronously(CMD_START_WPS, config); - result = (String) resultMsg.obj; + result = (WpsResult) resultMsg.obj; resultMsg.recycle(); break; - case PBC: - case PIN_FROM_ACCESS_POINT: - sendMessage(obtainMessage(CMD_START_WPS, config)); + default: + result = new WpsResult(Status.FAILURE); break; } return result; @@ -1511,13 +1514,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_ENABLE_ALL_NETWORKS: break; case CMD_START_WPS: - WpsConfiguration config = (WpsConfiguration) message.obj; - switch (config.setup) { - case PIN_FROM_DEVICE: - String pin = ""; - mReplyChannel.replyToMessage(message, message.what, pin); - break; - } + /* Return failure when the state machine cannot handle WPS initiation*/ + mReplyChannel.replyToMessage(message, message.what, + new WpsResult(Status.FAILURE)); break; default: Log.e(TAG, "Error! unhandled message" + message); @@ -1803,6 +1802,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* Reset the supplicant state to indicate the supplicant * state is not known at this time */ mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); + mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); /* Initialize data structures */ mLastBssid = null; mLastNetworkId = -1; @@ -1884,6 +1884,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { setWifiState(WIFI_STATE_DISABLING); sendSupplicantConnectionChangedBroadcast(false); mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); + mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); transitionTo(mSupplicantStoppingState); break; case SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ @@ -1894,6 +1895,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { handleNetworkDisconnect(); sendSupplicantConnectionChangedBroadcast(false); mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); + mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); transitionTo(mDriverLoadedState); sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); break; diff --git a/wifi/java/android/net/wifi/WpsResult.aidl b/wifi/java/android/net/wifi/WpsResult.aidl new file mode 100644 index 000000000000..eb4c4f5539ba --- /dev/null +++ b/wifi/java/android/net/wifi/WpsResult.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2010, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +parcelable WpsResult; diff --git a/wifi/java/android/net/wifi/WpsResult.java b/wifi/java/android/net/wifi/WpsResult.java new file mode 100644 index 000000000000..d4fd3e23d08f --- /dev/null +++ b/wifi/java/android/net/wifi/WpsResult.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A class representing the result of a WPS request + * @hide + */ +public class WpsResult implements Parcelable { + + public enum Status { + SUCCESS, + FAILURE, + IN_PROGRESS, + } + + public Status status; + + public String pin; + + public WpsResult() { + status = Status.FAILURE; + pin = null; + } + + public WpsResult(Status s) { + status = s; + pin = null; + } + + public String toString() { + StringBuffer sbuf = new StringBuffer(); + sbuf.append(" status: ").append(status.toString()); + sbuf.append('\n'); + sbuf.append(" pin: ").append(pin); + sbuf.append("\n"); + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** copy constructor {@hide} */ + public WpsResult(WpsResult source) { + if (source != null) { + status = source.status; + pin = source.pin; + } + } + + /** Implement the Parcelable interface {@hide} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(status.name()); + dest.writeString(pin); + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WpsResult> CREATOR = + new Creator<WpsResult>() { + public WpsResult createFromParcel(Parcel in) { + WpsResult result = new WpsResult(); + result.status = Status.valueOf(in.readString()); + result.pin = in.readString(); + return result; + } + + public WpsResult[] newArray(int size) { + return new WpsResult[size]; + } + }; +} diff --git a/wifi/java/android/net/wifi/WpsStateMachine.java b/wifi/java/android/net/wifi/WpsStateMachine.java index 381444c9b53f..92f9f57f5448 100644 --- a/wifi/java/android/net/wifi/WpsStateMachine.java +++ b/wifi/java/android/net/wifi/WpsStateMachine.java @@ -23,6 +23,7 @@ import com.android.internal.util.HierarchicalStateMachine; import android.content.Context; import android.content.Intent; import android.net.wifi.WifiStateMachine.StateChangeResult; +import android.net.wifi.WpsResult.Status; import android.os.Handler; import android.os.Message; import android.os.Parcelable; @@ -93,29 +94,32 @@ class WpsStateMachine extends HierarchicalStateMachine { switch (message.what) { case WifiStateMachine.CMD_START_WPS: mWpsConfig = (WpsConfiguration) message.obj; - boolean success = false; + WpsResult result; switch (mWpsConfig.setup) { case PBC: - success = WifiConfigStore.startWpsPbc(mWpsConfig); + result = WifiConfigStore.startWpsPbc(mWpsConfig); break; case PIN_FROM_ACCESS_POINT: - success = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig); + result = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig); break; case PIN_FROM_DEVICE: - String pin = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig); - success = (pin != null); - mReplyChannel.replyToMessage(message, message.what, pin); + result = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig); break; default: + result = new WpsResult(Status.FAILURE); Log.e(TAG, "Invalid setup for WPS"); break; } - if (success) { + mReplyChannel.replyToMessage(message, message.what, result); + if (result.status == Status.SUCCESS) { transitionTo(mActiveState); } else { Log.e(TAG, "Failed to start WPS with config " + mWpsConfig.toString()); } break; + case WifiStateMachine.CMD_RESET_WPS_STATE: + transitionTo(mInactiveState); + break; default: Log.e(TAG, "Failed to handle " + message); break; @@ -167,7 +171,9 @@ class WpsStateMachine extends HierarchicalStateMachine { } break; case WifiStateMachine.CMD_START_WPS: - deferMessage(message); + /* Ignore request and send an in progress message */ + mReplyChannel.replyToMessage(message, message.what, + new WpsResult(Status.IN_PROGRESS)); break; default: retValue = NOT_HANDLED; @@ -197,4 +203,4 @@ class WpsStateMachine extends HierarchicalStateMachine { } } -}
\ No newline at end of file +} |