summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Wallgren <martin.wallgren@sonyericsson.com>2011-04-13 15:03:35 +0200
committerJohan Redestig <johan.redestig@sonyericsson.com>2011-04-13 15:03:35 +0200
commit505bd0d60d26811ac1e61d2c39a2d5a995d2254d (patch)
tree2a2e227fa038ed1ef3fbe90cc84fad16d6a660d9
parent08d9d9a46250c4fad66e9b637e8898a3524c4286 (diff)
downloadframeworks_base-505bd0d60d26811ac1e61d2c39a2d5a995d2254d.zip
frameworks_base-505bd0d60d26811ac1e61d2c39a2d5a995d2254d.tar.gz
frameworks_base-505bd0d60d26811ac1e61d2c39a2d5a995d2254d.tar.bz2
onDetachedFromWindow is called before onAttachedToWindow
Multiple threads are adding messages about the current state of the views to the main looper. This can cause onDetachedFromWindow to be posted on the looper before onAttachedToWindow. This change will make sure to only dispatch onDetachedFromWindow if we have previously dispatched onAttachToWindow. Change-Id: Ibc7cbcafb098bc000d2ef5480d2110d3fff4d55a
-rw-r--r--core/java/android/view/ViewRoot.java9
-rw-r--r--core/tests/coretests/AndroidManifest.xml6
-rw-r--r--core/tests/coretests/res/layout/attach_view_test.xml12
-rw-r--r--core/tests/coretests/src/android/view/ViewAttachTest.java54
-rw-r--r--core/tests/coretests/src/android/view/ViewAttachTestActivity.java31
-rw-r--r--core/tests/coretests/src/android/view/ViewAttachView.java80
6 files changed, 190 insertions, 2 deletions
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ccaef40..afec1c3 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -176,6 +176,7 @@ public final class ViewRoot extends Handler implements ViewParent,
private final Surface mSurface = new Surface();
boolean mAdded;
+ private boolean mAttached;
boolean mAddedTouchMode;
/*package*/ int mAddNesting;
@@ -762,7 +763,10 @@ public final class ViewRoot extends Handler implements ViewParent,
attachInfo.mKeepScreenOn = false;
viewVisibilityChanged = false;
mLastConfiguration.setTo(host.getResources().getConfiguration());
- host.dispatchAttachedToWindow(attachInfo, 0);
+ if (!mAttached) {
+ host.dispatchAttachedToWindow(attachInfo, 0);
+ mAttached = true;
+ }
//Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
} else {
@@ -1743,8 +1747,9 @@ public final class ViewRoot extends Handler implements ViewParent,
void dispatchDetachedFromWindow() {
if (Config.LOGV) Log.v(TAG, "Detaching in " + this + " of " + mSurface);
- if (mView != null) {
+ if (mView != null && mAttached) {
mView.dispatchDetachedFromWindow();
+ mAttached = false;
}
mView = null;
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 487a00d..18a6d7b 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -96,6 +96,12 @@
<application android:theme="@style/Theme">
<uses-library android:name="android.test.runner" />
+ <activity android:name="android.view.ViewAttachTestActivity" android:label="View Attach Test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
<activity android:name="StubTestBrowserActivity" android:label="Stubbed Test Browser">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
diff --git a/core/tests/coretests/res/layout/attach_view_test.xml b/core/tests/coretests/res/layout/attach_view_test.xml
new file mode 100644
index 0000000..42841cb
--- /dev/null
+++ b/core/tests/coretests/res/layout/attach_view_test.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <android.view.ViewAttachView
+ android:id="@+id/view_attach_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:keepScreenOn="true"/>
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/view/ViewAttachTest.java b/core/tests/coretests/src/android/view/ViewAttachTest.java
new file mode 100644
index 0000000..cff66e4
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 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.view;
+
+import android.content.pm.ActivityInfo;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class ViewAttachTest extends
+ ActivityInstrumentationTestCase2<ViewAttachTestActivity> {
+
+ public ViewAttachTest() {
+ super(ViewAttachTestActivity.class);
+ }
+
+ /**
+ * Make sure that onAttachedToWindow and onDetachedToWindow is called in the
+ * correct order The ViewAttachTestActivity contains a view that will throw
+ * an RuntimeException if onDetachedToWindow and onAttachedToWindow is
+ * called in the wrong order.
+ *
+ * 1. Initiate the activity 2. Perform a series of orientation changes to
+ * the activity (this will force the View hierarchy to be rebuild,
+ * generating onAttachedToWindow and onDetachedToWindow)
+ *
+ * Expected result: No RuntimeException is thrown from the TestView in
+ * ViewFlipperTestActivity.
+ *
+ * @throws Throwable
+ */
+ public void testAttached() throws Throwable {
+ final ViewAttachTestActivity activity = getActivity();
+ for (int i = 0; i < 20; i++) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ SystemClock.sleep(250);
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ SystemClock.sleep(250);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ViewAttachTestActivity.java b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
new file mode 100644
index 0000000..59e25ae
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 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.view;
+
+import com.android.frameworks.coretests.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ViewAttachTestActivity extends Activity {
+ public static final String TAG = "OnAttachedTest";
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.attach_view_test);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ViewAttachView.java b/core/tests/coretests/src/android/view/ViewAttachView.java
new file mode 100644
index 0000000..5af2d8f
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachView.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 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.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+/**
+ * A View that will throw a RuntimeException if onAttachedToWindow and
+ * onDetachedFromWindow is called in the wrong order for ViewAttachTest
+ */
+public class ViewAttachView extends View {
+ public static final String TAG = "OnAttachedTest";
+ private boolean attached;
+
+ public ViewAttachView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(attrs, defStyle);
+ }
+
+ public ViewAttachView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs, 0);
+ }
+
+ public ViewAttachView(Context context) {
+ super(context);
+ init(null, 0);
+ }
+
+ private void init(AttributeSet attrs, int defStyle) {
+ SystemClock.sleep(2000);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ Log.d(TAG, "onAttachedToWindow");
+ super.onAttachedToWindow();
+ if (attached) {
+ throw new RuntimeException("OnAttachedToWindow called more than once in a row");
+ }
+ attached = true;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ Log.d(TAG, "onDetachedFromWindow");
+ super.onDetachedFromWindow();
+ if (!attached) {
+ throw new RuntimeException(
+ "onDetachedFromWindowcalled without prior call to OnAttachedToWindow");
+ }
+ attached = false;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawColor(Color.BLUE);
+ }
+}