1a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev/*
2a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * Copyright (C) 2015 The Android Open Source Project
3a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *
4a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * Licensed under the Apache License, Version 2.0 (the "License");
5a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * you may not use this file except in compliance with the License.
6a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * You may obtain a copy of the License at
7a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *
8a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *      http://www.apache.org/licenses/LICENSE-2.0
9a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *
10a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * Unless required by applicable law or agreed to in writing, software
11a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * distributed under the License is distributed on an "AS IS" BASIS,
12a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * See the License for the specific language governing permissions and
14a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * limitations under the License.
15a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev */
16a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
17a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevpackage android.support.v7.util;
18a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.Before;
200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.Test;
210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
22a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport static org.hamcrest.MatcherAssert.*;
23a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport static org.hamcrest.CoreMatchers.*;
24a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
25a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport android.os.Looper;
26de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheevimport android.support.annotation.UiThread;
27f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyarimport android.test.suitebuilder.annotation.MediumTest;
28a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
29a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport java.util.HashMap;
30a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport java.util.Map;
31a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport java.util.concurrent.Semaphore;
32a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport java.util.concurrent.TimeUnit;
33a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
34f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyar@MediumTest
35de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheevpublic class ThreadUtilTest extends BaseThreadedTest {
36a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    Map<String, LockedObject> results = new HashMap<>();
37a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
38a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    ThreadUtil.MainThreadCallback<Integer> mMainThreadProxy;
39a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    ThreadUtil.BackgroundCallback<Integer> mBackgroundProxy;
40a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
410a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Before
420a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void init() throws Exception {
430a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        super.setUp();
440a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    }
450a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
46de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheev    @Override
47de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheev    @UiThread
48de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheev    public void setUpUi() {
49a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        ThreadUtil<Integer> threadUtil = new MessageThreadUtil<>();
50a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
51a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mMainThreadProxy = threadUtil.getMainThreadProxy(
52a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                new ThreadUtil.MainThreadCallback<Integer>() {
53a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    @Override
54a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    public void updateItemCount(int generation, int itemCount) {
55a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        assertMainThread();
56a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        setResultData("updateItemCount", generation, itemCount);
57a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    }
58a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
59a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    @Override
60a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    public void addTile(int generation, TileList.Tile<Integer> data) {
61a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        assertMainThread();
62a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        setResultData("addTile", generation, data);
63a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    }
64a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
65a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    @Override
66a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    public void removeTile(int generation, int position) {
67a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        assertMainThread();
68a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        setResultData("removeTile", generation, position);
69a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    }
70a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                });
71a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
72a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mBackgroundProxy = threadUtil.getBackgroundProxy(
73a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                new ThreadUtil.BackgroundCallback<Integer>() {
74a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    @Override
75a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    public void refresh(int generation) {
76a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        assertBackgroundThread();
77a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        setResultData("refresh", generation);
78a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    }
79a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
80a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    @Override
81a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    public void updateRange(int rangeStart, int rangeEnd, int extRangeStart,
82a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                                            int extRangeEnd, int scrollHint) {
83a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        assertBackgroundThread();
84a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        setResultData("updateRange", rangeStart, rangeEnd,
85a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                                extRangeStart, extRangeEnd, scrollHint);
86a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    }
87a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
88a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    @Override
89a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    public void loadTile(int position, int scrollHint) {
90a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        assertBackgroundThread();
91a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        setResultData("loadTile", position, scrollHint);
92a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    }
93a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
94a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    @Override
95a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    public void recycleTile(TileList.Tile<Integer> data) {
96a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        assertBackgroundThread();
97a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                        setResultData("recycleTile", data);
98a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                    }
99a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                });
100a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
101a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
1020a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1030a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void updateItemCount() throws InterruptedException {
104a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        initWait("updateItemCount");
105de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheev        // In this test and below the calls to mMainThreadProxy are not really made from the UI
106de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheev        // thread. That's OK since the message queue inside mMainThreadProxy is synchronized.
107a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mMainThreadProxy.updateItemCount(7, 9);
108a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Object[] data = waitFor("updateItemCount");
109a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(data, is(new Object[]{7, 9}));
110a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
111a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
1120a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1130a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void addTile() throws InterruptedException {
114a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        initWait("addTile");
115a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        TileList.Tile<Integer> tile = new TileList.Tile<Integer>(Integer.class, 10);
116a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mMainThreadProxy.addTile(3, tile);
117a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Object[] data = waitFor("addTile");
118a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(data, is(new Object[]{3, tile}));
119a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
120a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
1210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void removeTile() throws InterruptedException {
123a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        initWait("removeTile");
124a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mMainThreadProxy.removeTile(1, 2);
125a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Object[] data = waitFor("removeTile");
126a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(data, is(new Object[]{1, 2}));
127a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
128a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
1290a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1300a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void refresh() throws InterruptedException {
131a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        initWait("refresh");
132de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheev        // In this test and below the calls to mBackgroundProxy are not really made from the worker
133de8e2baf9504defe12972fbf60935a1148f1098fVladislav Kaznacheev        // thread. That's OK since the message queue inside mBackgroundProxy is synchronized.
134a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mBackgroundProxy.refresh(2);
135a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Object[] data = waitFor("refresh");
136a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(data, is(new Object[]{2}));
137a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
138a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
1390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1400a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void rangeUpdate() throws InterruptedException {
141a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        initWait("updateRange");
142a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mBackgroundProxy.updateRange(10, 20, 5, 25, 1);
143a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Object[] data = waitFor("updateRange");
144a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(data, is(new Object[] {10, 20, 5, 25, 1}));
145a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
146a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
1470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void loadTile() throws InterruptedException {
149a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        initWait("loadTile");
150a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mBackgroundProxy.loadTile(2, 1);
151a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Object[] data = waitFor("loadTile");
152a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(data, is(new Object[]{2, 1}));
153a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
154a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
1550a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1560a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void recycleTile() throws InterruptedException {
157a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        initWait("recycleTile");
158a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        TileList.Tile<Integer> tile = new TileList.Tile<Integer>(Integer.class, 10);
159a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mBackgroundProxy.recycleTile(tile);
160a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Object[] data = waitFor("recycleTile");
161a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(data, is(new Object[]{tile}));
162a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
163a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
164a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    private void assertMainThread() {
165a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(Looper.myLooper(), notNullValue());
166a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(Looper.myLooper(), sameInstance(Looper.getMainLooper()));
167a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
168a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
169a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    private void assertBackgroundThread() {
170a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        assertThat(Looper.myLooper(), not(Looper.getMainLooper()));
171a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
172a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
173a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    private void initWait(String key) throws InterruptedException {
174a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        results.put(key, new LockedObject());
175a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
176a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
177a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    private Object[] waitFor(String key) throws InterruptedException {
178a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        return results.get(key).waitFor();
179a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
180a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
181a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    private void setResultData(String key, Object... args) {
182a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        if (results.containsKey(key)) {
183a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            results.get(key).set(args);
184a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
185a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
186a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
187a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    private class LockedObject {
188a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        private Semaphore mLock = new Semaphore(1);
189a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        private volatile Object[] mArgs;
190a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
191a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        public LockedObject() {
192a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mLock.drainPermits();
193a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
194a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
195a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        public void set(Object... args) {
196a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mArgs = args;
197a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mLock.release(1);
198a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
199a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
200a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        public Object[] waitFor() throws InterruptedException {
201a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mLock.tryAcquire(1, 2, TimeUnit.SECONDS);
202a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            return mArgs;
203a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
204a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
205a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev}
206