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