diff options
| -rw-r--r-- | core/java/android/nfc/NfcAdapter.java | 55 | ||||
| -rw-r--r-- | core/java/android/os/AsyncTask.java | 88 | ||||
| -rw-r--r-- | core/java/android/os/StrictMode.java | 7 | ||||
| -rw-r--r-- | data/keyboards/keyboards.mk | 3 | ||||
| -rw-r--r-- | libs/hwui/LayerRenderer.cpp | 15 | ||||
| -rw-r--r-- | media/java/android/media/RemoteControlClient.java | 17 | ||||
| -rw-r--r-- | policy/src/com/android/internal/policy/impl/GlobalActions.java | 7 | ||||
| -rw-r--r-- | services/java/com/android/server/NetworkManagementService.java | 5 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java | 18 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java | 57 |
10 files changed, 164 insertions, 108 deletions
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index fe0106dc52c4..33310dfd0ad8 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -768,61 +768,6 @@ public final class NfcAdapter { } /** - * TODO: Remove this once pre-built apk's (Maps, Youtube etc) are updated - * @deprecated use {@link CreateNdefMessageCallback} or {@link OnNdefPushCompleteCallback} - * @hide - */ - @Deprecated - public interface NdefPushCallback { - /** - * @deprecated use {@link CreateNdefMessageCallback} instead - */ - @Deprecated - NdefMessage createMessage(); - /** - * @deprecated use{@link OnNdefPushCompleteCallback} instead - */ - @Deprecated - void onMessagePushed(); - } - - /** - * TODO: Remove this - * Converts new callbacks to old callbacks. - */ - static final class LegacyCallbackWrapper implements CreateNdefMessageCallback, - OnNdefPushCompleteCallback { - final NdefPushCallback mLegacyCallback; - LegacyCallbackWrapper(NdefPushCallback legacyCallback) { - mLegacyCallback = legacyCallback; - } - @Override - public void onNdefPushComplete(NfcEvent event) { - mLegacyCallback.onMessagePushed(); - } - @Override - public NdefMessage createNdefMessage(NfcEvent event) { - return mLegacyCallback.createMessage(); - } - } - - /** - * TODO: Remove this once pre-built apk's (Maps, Youtube etc) are updated - * @deprecated use {@link #setNdefPushMessageCallback} instead - * @hide - */ - @Deprecated - public void enableForegroundNdefPush(Activity activity, final NdefPushCallback callback) { - if (activity == null || callback == null) { - throw new NullPointerException(); - } - enforceResumed(activity); - LegacyCallbackWrapper callbackWrapper = new LegacyCallbackWrapper(callback); - mNfcActivityManager.setNdefPushMessageCallback(activity, callbackWrapper); - mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callbackWrapper); - } - - /** * Enable NDEF Push feature. * <p>This API is for the Settings application. * @hide diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 9dea4c43b699..70ec0af4064c 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -32,12 +32,13 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** - * <p>AsyncTask enables proper and easy use of the UI thread. This class allows to - * perform background operations and publish results on the UI thread without - * having to manipulate threads and/or handlers.</p> + * <p>AsyncTask enables proper and easy use of the UI thread (also called main thread) or + * any other looper thread. AsyncTask is most commonly used to interact with the UI thread. + * This class allows to perform background operations and publish results on a looper + * thread without having to manipulate threads and/or handlers.</p> * * <p>An asynchronous task is defined by a computation that runs on a background thread and - * whose result is published on the UI thread. An asynchronous task is defined by 3 generic + * whose result is published on a looper thread. An asynchronous task is defined by 3 generic * types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>, * and 4 steps, called <code>onPreExecute</code>, <code>doInBackground</code>, * <code>onProgressUpdate</code> and <code>onPostExecute</code>.</p> @@ -101,7 +102,7 @@ import java.util.concurrent.atomic.AtomicInteger; * <h2>The 4 steps</h2> * <p>When an asynchronous task is executed, the task goes through 4 steps:</p> * <ol> - * <li>{@link #onPreExecute()}, invoked on the UI thread immediately after the task + * <li>{@link #onPreExecute()}, invoked on the looper thread immediately after the task * is executed. This step is normally used to setup the task, for instance by * showing a progress bar in the user interface.</li> * <li>{@link #doInBackground}, invoked on the background thread @@ -110,14 +111,14 @@ import java.util.concurrent.atomic.AtomicInteger; * of the asynchronous task are passed to this step. The result of the computation must * be returned by this step and will be passed back to the last step. This step * can also use {@link #publishProgress} to publish one or more units - * of progress. These values are published on the UI thread, in the + * of progress. These values are published on the looper thread, in the * {@link #onProgressUpdate} step.</li> - * <li>{@link #onProgressUpdate}, invoked on the UI thread after a + * <li>{@link #onProgressUpdate}, invoked on the looper thread after a * call to {@link #publishProgress}. The timing of the execution is * undefined. This method is used to display any form of progress in the user * interface while the background computation is still executing. For instance, * it can be used to animate a progress bar or show logs in a text field.</li> - * <li>{@link #onPostExecute}, invoked on the UI thread after the background + * <li>{@link #onPostExecute}, invoked on the looper thread after the background * computation finishes. The result of the background computation is passed to * this step as a parameter.</li> * </ol> @@ -135,8 +136,8 @@ import java.util.concurrent.atomic.AtomicInteger; * <p>There are a few threading rules that must be followed for this class to * work properly:</p> * <ul> - * <li>The task instance must be created on the UI thread.</li> - * <li>{@link #execute} must be invoked on the UI thread.</li> + * <li>The task instance must be created on the looper thread.</li> + * <li>{@link #execute} must be invoked on the looper thread.</li> * <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute}, * {@link #doInBackground}, {@link #onProgressUpdate} manually.</li> * <li>The task can be executed only once (an exception will be thrown if @@ -152,6 +153,9 @@ import java.util.concurrent.atomic.AtomicInteger; * <li>Set member fields in {@link #doInBackground}, and refer to them in * {@link #onProgressUpdate} and {@link #onPostExecute}. * </ul> + * + * @see Looper + * @see Handler */ public abstract class AsyncTask<Params, Progress, Result> { private static final String LOG_TAG = "AsyncTask"; @@ -187,7 +191,13 @@ public abstract class AsyncTask<Params, Progress, Result> { private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; - private static final InternalHandler sHandler = new InternalHandler(); + private static final ThreadLocal<InternalHandler> sHandler = + new ThreadLocal<InternalHandler>() { + @Override + protected InternalHandler initialValue() { + return new InternalHandler(); + } + }; private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; private final WorkerRunnable<Params, Result> mWorker; @@ -196,6 +206,7 @@ public abstract class AsyncTask<Params, Progress, Result> { private volatile Status mStatus = Status.PENDING; private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); + private final InternalHandler mHandler; private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); @@ -242,9 +253,8 @@ public abstract class AsyncTask<Params, Progress, Result> { FINISHED, } - /** @hide Used to force static handler to be created. */ + /** @hide */ public static void init() { - sHandler.getLooper(); } /** @hide */ @@ -253,14 +263,26 @@ public abstract class AsyncTask<Params, Progress, Result> { } /** - * Creates a new asynchronous task. This constructor must be invoked on the UI thread. + * Creates a new asynchronous task. This constructor must be invoked on the looper thread. + * + * @throws IllegalStateException if this constructor is invoked on a non-looper thread + * + * @see Looper */ public AsyncTask() { + if (Looper.myLooper() == null) { + throw new IllegalStateException("AsyncTask can be only instanciated on a " + + "looper thread. The current thread is " + Thread.currentThread()); + } + + mHandler = sHandler.get(); + mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + //noinspection unchecked return postResult(doInBackground(mParams)); } }; @@ -295,7 +317,8 @@ public abstract class AsyncTask<Params, Progress, Result> { } private Result postResult(Result result) { - Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, + @SuppressWarnings({"unchecked"}) + Message message = mHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; @@ -316,7 +339,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * by the caller of this task. * * This method can call {@link #publishProgress} to publish updates - * on the UI thread. + * on the looper thread. * * @param params The parameters of the task. * @@ -329,7 +352,7 @@ public abstract class AsyncTask<Params, Progress, Result> { protected abstract Result doInBackground(Params... params); /** - * Runs on the UI thread before {@link #doInBackground}. + * Runs on the looper thread before {@link #doInBackground}. * * @see #onPostExecute * @see #doInBackground @@ -338,7 +361,7 @@ public abstract class AsyncTask<Params, Progress, Result> { } /** - * <p>Runs on the UI thread after {@link #doInBackground}. The + * <p>Runs on the looper thread after {@link #doInBackground}. The * specified result is the value returned by {@link #doInBackground}.</p> * * <p>This method won't be invoked if the task was cancelled.</p> @@ -354,7 +377,7 @@ public abstract class AsyncTask<Params, Progress, Result> { } /** - * Runs on the UI thread after {@link #publishProgress} is invoked. + * Runs on the looper thread after {@link #publishProgress} is invoked. * The specified values are the values passed to {@link #publishProgress}. * * @param values The values indicating progress. @@ -367,7 +390,7 @@ public abstract class AsyncTask<Params, Progress, Result> { } /** - * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and + * <p>Runs on the looper thread after {@link #cancel(boolean)} is invoked and * {@link #doInBackground(Object[])} has finished.</p> * * <p>The default implementation simply invokes {@link #onCancelled()} and @@ -390,7 +413,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * This method is invoked by the default implementation of * {@link #onCancelled(Object)}.</p> * - * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and + * <p>Runs on the looper thread after {@link #cancel(boolean)} is invoked and * {@link #doInBackground(Object[])} has finished.</p> * * @see #onCancelled(Object) @@ -425,7 +448,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * an attempt to stop the task.</p> * * <p>Calling this method will result in {@link #onCancelled(Object)} being - * invoked on the UI thread after {@link #doInBackground(Object[])} + * invoked on the looper thread after {@link #doInBackground(Object[])} * returns. Calling this method guarantees that {@link #onPostExecute(Object)} * is never invoked. After invoking this method, you should check the * value returned by {@link #isCancelled()} periodically from @@ -498,14 +521,15 @@ public abstract class AsyncTask<Params, Progress, Result> { * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings on * its use. * - * <p>This method must be invoked on the UI thread. + * <p>This method must be invoked on the looper thread. * * @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}. + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED} or + * the current thread is not a looper thread. */ public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); @@ -531,7 +555,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * executed in serial; to guarantee such work is serialized regardless of * platform version you can use this function with {@link #SERIAL_EXECUTOR}. * - * <p>This method must be invoked on the UI thread. + * <p>This method must be invoked on the looper 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. @@ -540,10 +564,16 @@ public abstract class AsyncTask<Params, Progress, Result> { * @return This instance of AsyncTask. * * @throws IllegalStateException If {@link #getStatus()} returns either - * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED} or + * the current thread is not a looper thread. */ public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { + if (Looper.myLooper() == null) { + throw new IllegalStateException("AsyncTask can be only instanciated on a " + + "looper thread. The current thread is " + Thread.currentThread()); + } + if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: @@ -576,9 +606,9 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * This method can be invoked from {@link #doInBackground} to - * publish updates on the UI thread while the background computation is + * publish updates on the looper thread while the background computation is * still running. Each call to this method will trigger the execution of - * {@link #onProgressUpdate} on the UI thread. + * {@link #onProgressUpdate} on the looper thread. * * {@link #onProgressUpdate} will note be called if the task has been * canceled. @@ -590,7 +620,7 @@ public abstract class AsyncTask<Params, Progress, Result> { */ protected final void publishProgress(Progress... values) { if (!isCancelled()) { - sHandler.obtainMessage(MESSAGE_POST_PROGRESS, + mHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } } diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 4d7a9bbf8938..cc2fa8532d3d 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -35,7 +35,6 @@ import dalvik.system.VMDebug; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -902,15 +901,13 @@ public final class StrictMode { return false; } + // Thread policy controls BlockGuard. int threadPolicyMask = StrictMode.DETECT_DISK_WRITE | StrictMode.DETECT_DISK_READ | StrictMode.DETECT_NETWORK; if (!IS_USER_BUILD) { threadPolicyMask |= StrictMode.PENALTY_DROPBOX; - if (IS_ENG_BUILD) { - threadPolicyMask |= StrictMode.PENALTY_LOG; - } } if (doFlashes) { threadPolicyMask |= StrictMode.PENALTY_FLASH; @@ -918,6 +915,8 @@ public final class StrictMode { StrictMode.setThreadPolicyMask(threadPolicyMask); + // VM Policy controls CloseGuard, detection of Activity leaks, + // and instance counting. if (IS_USER_BUILD) { setCloseGuardEnabled(false); } else { diff --git a/data/keyboards/keyboards.mk b/data/keyboards/keyboards.mk index 564f41cb4cf6..c96496195849 100644 --- a/data/keyboards/keyboards.mk +++ b/data/keyboards/keyboards.mk @@ -24,6 +24,3 @@ PRODUCT_COPY_FILES += $(foreach file,$(keycharmaps),\ PRODUCT_COPY_FILES += $(foreach file,$(keyconfigs),\ frameworks/base/data/keyboards/$(file):system/usr/idc/$(file)) - -PRODUCT_PACKAGES := $(keylayouts) $(keycharmaps) $(keyconfigs) - diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 349b9e32268d..079950852150 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -264,7 +264,7 @@ Layer* LayerRenderer::createTextureLayer(bool isOpaque) { layer->setFbo(0); layer->setAlpha(255, SkXfermode::kSrcOver_Mode); layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f); - layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f); + layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f); layer->region.clear(); layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer() @@ -400,6 +400,18 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { renderer.setViewport(bitmap->width(), bitmap->height()); renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f, bitmap->width(), bitmap->height(), !layer->isBlend()); + + glDisable(GL_SCISSOR_TEST); + renderer.translate(0.0f, bitmap->height()); + renderer.scale(1.0f, -1.0f); + + mat4 texTransform(layer->getTexTransform()); + + mat4 invert; + invert.translate(0.0f, 1.0f, 0.0f); + invert.scale(1.0f, -1.0f, 1.0f); + layer->getTexTransform().multiply(invert); + if ((error = glGetError()) != GL_NO_ERROR) goto error; { @@ -413,6 +425,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { if ((error = glGetError()) != GL_NO_ERROR) goto error; } + layer->getTexTransform().load(texTransform); status = true; } diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java index 198ae4c8f7f7..77acfe6beae8 100644 --- a/media/java/android/media/RemoteControlClient.java +++ b/media/java/android/media/RemoteControlClient.java @@ -35,14 +35,27 @@ import android.util.Log; import java.lang.IllegalArgumentException; /** - * TODO javadoc update for ComponentName - PendingIntent change * RemoteControlClient enables exposing information meant to be consumed by remote controls * capable of displaying metadata, artwork and media transport control buttons. - * A remote control client object is associated with a media button event receiver. This + * + * <p>A remote control client object is associated with a media button event receiver. This * event receiver must have been previously registered with * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} before the * RemoteControlClient can be registered through * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. + * + * <p>Here is an example of creating a RemoteControlClient instance after registering a media + * button event receiver: + * <pre>ComponentName myEventReceiver = new ComponentName(getPackageName(), MyRemoteControlEventReceiver.class.getName()); + * AudioManager myAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + * myAudioManager.registerMediaButtonEventReceiver(myEventReceiver); + * // build the PendingIntent for the remote control client + * Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); + * mediaButtonIntent.setComponent(myEventReceiver); + * PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0); + * // create and register the remote control client + * RemoteControlClient myRemoteControlClient = new RemoteControlClient(mediaPendingIntent); + * myAudioManager.registerRemoteControlClient(myRemoteControlClient);</pre> */ public class RemoteControlClient { diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index 856914359517..11b6c15185d3 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -18,7 +18,6 @@ package com.android.internal.policy.impl; import android.app.Activity; import android.app.AlertDialog; -import android.app.StatusBarManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; @@ -57,8 +56,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private static final String TAG = "GlobalActions"; - private StatusBarManager mStatusBar; - private final Context mContext; private final AudioManager mAudioManager; @@ -103,13 +100,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; if (mDialog == null) { - mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE); mDialog = createDialog(); } prepareDialog(); - mStatusBar.disable(StatusBarManager.DISABLE_EXPAND); mDialog.show(); + mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND); } /** @@ -249,7 +245,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac /** {@inheritDoc} */ public void onDismiss(DialogInterface dialog) { - mStatusBar.disable(StatusBarManager.DISABLE_NONE); } /** {@inheritDoc} */ diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index b05705eb1224..bcb1aa24930d 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -238,6 +238,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub * Notify our observers of an interface removal. */ private void notifyInterfaceRemoved(String iface) { + // netd already clears out quota and alerts for removed ifaces; update + // our sanity-checking state. + mActiveAlertIfaces.remove(iface); + mActiveQuotaIfaces.remove(iface); + for (INetworkManagementEventObserver obs : mObservers) { try { obs.interfaceRemoved(iface); diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java index 3232eedcf51e..414ae0dd34bc 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java @@ -22,9 +22,11 @@ import android.app.Activity; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Matrix; import android.graphics.SurfaceTexture; import android.opengl.GLUtils; import android.os.Bundle; +import android.os.Environment; import android.util.Log; import android.view.Gravity; import android.view.TextureView; @@ -39,6 +41,7 @@ import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL; import java.io.BufferedOutputStream; +import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -65,7 +68,8 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa Bitmap b = mTextureView.getBitmap(800, 800); BufferedOutputStream out = null; try { - out = new BufferedOutputStream(new FileOutputStream("/sdcard/out.png")); + File dump = new File(Environment.getExternalStorageDirectory(), "out.png"); + out = new BufferedOutputStream(new FileOutputStream(dump)); b.compress(Bitmap.CompressFormat.PNG, 100, out); } catch (FileNotFoundException e) { e.printStackTrace(); @@ -168,10 +172,10 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; private final float[] mTriangleVerticesData = { // X, Y, Z, U, V - -1.0f, -1.0f, 0, 0.f, 0.f, - 1.0f, -1.0f, 0, 1.f, 0.f, - -1.0f, 1.0f, 0, 0.f, 1.f, - 1.0f, 1.0f, 0, 1.f, 1.f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; @Override @@ -212,8 +216,6 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa while (!mFinished) { checkCurrent(); - Log.d(LOG_TAG, "Rendering frame"); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); checkGlError(); @@ -237,7 +239,7 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa checkEglError(); try { - Thread.sleep(20); + Thread.sleep(2000); } catch (InterruptedException e) { // Ignore } diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java index fcb57d96b3f1..0f4c66817a05 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java @@ -17,16 +17,23 @@ package com.android.test.hwui; import android.app.Activity; +import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.os.Bundle; +import android.os.Environment; import android.view.Gravity; +import android.view.Surface; import android.view.TextureView; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; @SuppressWarnings({"UnusedDeclaration"}) @@ -44,6 +51,26 @@ public class TextureViewActivity extends Activity implements TextureView.Surface mTextureView = new TextureView(this); mTextureView.setSurfaceTextureListener(this); + mTextureView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Bitmap b = mTextureView.getBitmap(800, 800); + BufferedOutputStream out = null; + try { + File dump = new File(Environment.getExternalStorageDirectory(), "out.png"); + out = new BufferedOutputStream(new FileOutputStream(dump)); + b.compress(Bitmap.CompressFormat.PNG, 100, out); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + if (out != null) try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }); Button button = new Button(this); button.setText("Remove/Add"); @@ -73,6 +100,8 @@ public class TextureViewActivity extends Activity implements TextureView.Surface @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mCamera = Camera.open(); + mCamera.setDisplayOrientation(getCameraOrientation()); + Camera.Size previewSize = mCamera.getParameters().getPreviewSize(); mTextureView.setLayoutParams(new FrameLayout.LayoutParams( previewSize.width, previewSize.height, Gravity.CENTER)); @@ -86,6 +115,34 @@ public class TextureViewActivity extends Activity implements TextureView.Surface mCamera.startPreview(); } + private int getCameraOrientation() { + Camera.CameraInfo info = new Camera.CameraInfo(); + for (int i = 0; i < Camera.getNumberOfCameras(); i++) { + Camera.getCameraInfo(i, info); + if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) break; + } + + int rotation = getWindowManager().getDefaultDisplay().getRotation(); + int degrees = 0; + + switch (rotation) { + case Surface.ROTATION_0: + degrees = 0; + break; + case Surface.ROTATION_90: + degrees = 90; + break; + case Surface.ROTATION_180: + degrees = 180; + break; + case Surface.ROTATION_270: + degrees = 270; + break; + } + + return (info.orientation - degrees + 360) % 360; + } + @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { // Ignored, the Camera does all the work for us |