15914aa7da50a90a4c705b5be02a215499d0ad232George Mount/* 25914aa7da50a90a4c705b5be02a215499d0ad232George Mount * Copyright (C) 2015 The Android Open Source Project 35914aa7da50a90a4c705b5be02a215499d0ad232George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 45914aa7da50a90a4c705b5be02a215499d0ad232George Mount * you may not use this file except in compliance with the License. 55914aa7da50a90a4c705b5be02a215499d0ad232George Mount * You may obtain a copy of the License at 65914aa7da50a90a4c705b5be02a215499d0ad232George Mount * http://www.apache.org/licenses/LICENSE-2.0 75914aa7da50a90a4c705b5be02a215499d0ad232George Mount * Unless required by applicable law or agreed to in writing, software 85914aa7da50a90a4c705b5be02a215499d0ad232George Mount * distributed under the License is distributed on an "AS IS" BASIS, 95914aa7da50a90a4c705b5be02a215499d0ad232George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 105914aa7da50a90a4c705b5be02a215499d0ad232George Mount * See the License for the specific language governing permissions and 115914aa7da50a90a4c705b5be02a215499d0ad232George Mount * limitations under the License. 125914aa7da50a90a4c705b5be02a215499d0ad232George Mount */ 135914aa7da50a90a4c705b5be02a215499d0ad232George Mount 145914aa7da50a90a4c705b5be02a215499d0ad232George Mountpackage android.databinding.testapp; 155914aa7da50a90a4c705b5be02a215499d0ad232George Mount 162e2043d30f95585de2069e1cbb23e022ab0e71c4George Mountimport android.databinding.testapp.databinding.LeakTestBinding; 175914aa7da50a90a4c705b5be02a215499d0ad232George Mountimport android.test.ActivityInstrumentationTestCase2; 185914aa7da50a90a4c705b5be02a215499d0ad232George Mountimport android.util.Log; 195914aa7da50a90a4c705b5be02a215499d0ad232George Mountimport android.widget.FrameLayout; 205914aa7da50a90a4c705b5be02a215499d0ad232George Mount 215914aa7da50a90a4c705b5be02a215499d0ad232George Mountimport java.lang.ref.WeakReference; 22b7eeedbfadec03792551014e9dfa2bd384fc21a3George Mountimport java.util.ArrayList; 235914aa7da50a90a4c705b5be02a215499d0ad232George Mount 245914aa7da50a90a4c705b5be02a215499d0ad232George Mountpublic class LeakTest extends ActivityInstrumentationTestCase2<TestActivity> { 255914aa7da50a90a4c705b5be02a215499d0ad232George Mount WeakReference<LeakTestBinding> mWeakReference = new WeakReference<LeakTestBinding>(null); 265914aa7da50a90a4c705b5be02a215499d0ad232George Mount 275914aa7da50a90a4c705b5be02a215499d0ad232George Mount public LeakTest() { 285914aa7da50a90a4c705b5be02a215499d0ad232George Mount super(TestActivity.class); 295914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 305914aa7da50a90a4c705b5be02a215499d0ad232George Mount 315914aa7da50a90a4c705b5be02a215499d0ad232George Mount @Override 325914aa7da50a90a4c705b5be02a215499d0ad232George Mount protected void setUp() throws Exception { 335914aa7da50a90a4c705b5be02a215499d0ad232George Mount super.setUp(); 345914aa7da50a90a4c705b5be02a215499d0ad232George Mount 355914aa7da50a90a4c705b5be02a215499d0ad232George Mount try { 365914aa7da50a90a4c705b5be02a215499d0ad232George Mount getActivity().runOnUiThread(new Runnable() { 375914aa7da50a90a4c705b5be02a215499d0ad232George Mount @Override 385914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void run() { 395914aa7da50a90a4c705b5be02a215499d0ad232George Mount try { 409bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount LeakTestBinding binding = LeakTestBinding.inflate( 419bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount getActivity().getLayoutInflater()); 425914aa7da50a90a4c705b5be02a215499d0ad232George Mount getActivity().setContentView(binding.getRoot()); 435914aa7da50a90a4c705b5be02a215499d0ad232George Mount mWeakReference = new WeakReference<LeakTestBinding>(binding); 445914aa7da50a90a4c705b5be02a215499d0ad232George Mount binding.setName("hello world"); 455914aa7da50a90a4c705b5be02a215499d0ad232George Mount binding.executePendingBindings(); 465914aa7da50a90a4c705b5be02a215499d0ad232George Mount } catch (Exception e) { 475914aa7da50a90a4c705b5be02a215499d0ad232George Mount e.printStackTrace(); 485914aa7da50a90a4c705b5be02a215499d0ad232George Mount throw e; 495914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 505914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 515914aa7da50a90a4c705b5be02a215499d0ad232George Mount }); 525914aa7da50a90a4c705b5be02a215499d0ad232George Mount getInstrumentation().waitForIdleSync(); 535914aa7da50a90a4c705b5be02a215499d0ad232George Mount } catch (Throwable t) { 545914aa7da50a90a4c705b5be02a215499d0ad232George Mount throw new Exception(t); 555914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 565914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 575914aa7da50a90a4c705b5be02a215499d0ad232George Mount 585914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void testBindingLeak() throws Throwable { 595914aa7da50a90a4c705b5be02a215499d0ad232George Mount assertNotNull(mWeakReference.get()); 605914aa7da50a90a4c705b5be02a215499d0ad232George Mount runTestOnUiThread(new Runnable() { 615914aa7da50a90a4c705b5be02a215499d0ad232George Mount @Override 625914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void run() { 635914aa7da50a90a4c705b5be02a215499d0ad232George Mount getActivity().setContentView(new FrameLayout(getActivity())); 645914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 655914aa7da50a90a4c705b5be02a215499d0ad232George Mount }); 66d653884235a14c932c4d6d2c579e248477fb9744George Mount WeakReference<Object> canary = new WeakReference<Object>(new Object()); 67b7eeedbfadec03792551014e9dfa2bd384fc21a3George Mount ArrayList<WeakReference<byte[]>> leak = new ArrayList<>(); 68d653884235a14c932c4d6d2c579e248477fb9744George Mount while (canary.get() != null) { 69b7eeedbfadec03792551014e9dfa2bd384fc21a3George Mount leak.add(new WeakReference<byte[]>(new byte[100])); 70d653884235a14c932c4d6d2c579e248477fb9744George Mount System.gc(); 71d653884235a14c932c4d6d2c579e248477fb9744George Mount } 725914aa7da50a90a4c705b5be02a215499d0ad232George Mount assertNull(mWeakReference.get()); 735914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 745914aa7da50a90a4c705b5be02a215499d0ad232George Mount 755914aa7da50a90a4c705b5be02a215499d0ad232George Mount // Test to ensure that when the View is detached that it doesn't rebind 765914aa7da50a90a4c705b5be02a215499d0ad232George Mount // the dirty Views. The rebind should happen only after the root view is 775914aa7da50a90a4c705b5be02a215499d0ad232George Mount // reattached. 785914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void testNoChangeWhenDetached() throws Throwable { 795914aa7da50a90a4c705b5be02a215499d0ad232George Mount final LeakTestBinding binding = mWeakReference.get(); 805914aa7da50a90a4c705b5be02a215499d0ad232George Mount final AnimationWatcher watcher = new AnimationWatcher(); 815914aa7da50a90a4c705b5be02a215499d0ad232George Mount 825914aa7da50a90a4c705b5be02a215499d0ad232George Mount runTestOnUiThread(new Runnable() { 835914aa7da50a90a4c705b5be02a215499d0ad232George Mount @Override 845914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void run() { 855914aa7da50a90a4c705b5be02a215499d0ad232George Mount getActivity().setContentView(new FrameLayout(getActivity())); 865914aa7da50a90a4c705b5be02a215499d0ad232George Mount binding.setName("goodbye world"); 879ece2cad2c24dd6620239a8447d4a6e6714f7487George Mount getActivity().getWindow().getDecorView().postOnAnimation(watcher); 885914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 895914aa7da50a90a4c705b5be02a215499d0ad232George Mount }); 905914aa7da50a90a4c705b5be02a215499d0ad232George Mount 915914aa7da50a90a4c705b5be02a215499d0ad232George Mount watcher.waitForAnimationThread(); 925914aa7da50a90a4c705b5be02a215499d0ad232George Mount 935914aa7da50a90a4c705b5be02a215499d0ad232George Mount runTestOnUiThread(new Runnable() { 945914aa7da50a90a4c705b5be02a215499d0ad232George Mount @Override 955914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void run() { 9634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount assertEquals("hello world", binding.textView.getText().toString()); 975914aa7da50a90a4c705b5be02a215499d0ad232George Mount getActivity().setContentView(binding.getRoot()); 989ece2cad2c24dd6620239a8447d4a6e6714f7487George Mount getActivity().getWindow().getDecorView().postOnAnimation(watcher); 995914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1005914aa7da50a90a4c705b5be02a215499d0ad232George Mount }); 1015914aa7da50a90a4c705b5be02a215499d0ad232George Mount 1025914aa7da50a90a4c705b5be02a215499d0ad232George Mount watcher.waitForAnimationThread(); 1035914aa7da50a90a4c705b5be02a215499d0ad232George Mount 1045914aa7da50a90a4c705b5be02a215499d0ad232George Mount runTestOnUiThread(new Runnable() { 1055914aa7da50a90a4c705b5be02a215499d0ad232George Mount @Override 1065914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void run() { 10734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount assertEquals("goodbye world", binding.textView.getText().toString()); 1085914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1095914aa7da50a90a4c705b5be02a215499d0ad232George Mount }); 1105914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1115914aa7da50a90a4c705b5be02a215499d0ad232George Mount 1125914aa7da50a90a4c705b5be02a215499d0ad232George Mount private static class AnimationWatcher implements Runnable { 1135914aa7da50a90a4c705b5be02a215499d0ad232George Mount private boolean mWaiting = true; 1145914aa7da50a90a4c705b5be02a215499d0ad232George Mount 1155914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void waitForAnimationThread() throws InterruptedException { 1165914aa7da50a90a4c705b5be02a215499d0ad232George Mount synchronized (this) { 1175914aa7da50a90a4c705b5be02a215499d0ad232George Mount while (mWaiting) { 1185914aa7da50a90a4c705b5be02a215499d0ad232George Mount this.wait(); 1195914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1205914aa7da50a90a4c705b5be02a215499d0ad232George Mount mWaiting = true; 1215914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1225914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1235914aa7da50a90a4c705b5be02a215499d0ad232George Mount 1245914aa7da50a90a4c705b5be02a215499d0ad232George Mount 1255914aa7da50a90a4c705b5be02a215499d0ad232George Mount @Override 1265914aa7da50a90a4c705b5be02a215499d0ad232George Mount public void run() { 1275914aa7da50a90a4c705b5be02a215499d0ad232George Mount synchronized (this) { 1285914aa7da50a90a4c705b5be02a215499d0ad232George Mount mWaiting = false; 1295914aa7da50a90a4c705b5be02a215499d0ad232George Mount this.notifyAll(); 1305914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1315914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1325914aa7da50a90a4c705b5be02a215499d0ad232George Mount } 1335914aa7da50a90a4c705b5be02a215499d0ad232George Mount} 134