SysuiTestCase.java revision aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6b
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.systemui; 17 18import static org.mockito.Mockito.mock; 19 20import android.content.Context; 21import android.os.Handler; 22import android.os.Looper; 23import android.os.MessageQueue; 24import android.support.test.InstrumentationRegistry; 25import android.util.ArrayMap; 26import android.util.Log; 27 28import com.android.systemui.utils.TestableContext; 29import com.android.systemui.utils.leaks.Tracker; 30 31import org.junit.After; 32import org.junit.Before; 33 34import java.lang.Thread.UncaughtExceptionHandler; 35 36/** 37 * Base class that does System UI specific setup. 38 */ 39public abstract class SysuiTestCase { 40 41 private Throwable mException; 42 private Handler mHandler; 43 protected TestableContext mContext; 44 protected TestDependency mDependency; 45 46 @Before 47 public void SysuiSetup() throws Exception { 48 mException = null; 49 System.setProperty("dexmaker.share_classloader", "true"); 50 mContext = new TestableContext(InstrumentationRegistry.getTargetContext(), this); 51 SystemUIFactory.createFromConfig(mContext); 52 mDependency = new TestDependency(); 53 mDependency.mContext = mContext; 54 mDependency.start(); 55 } 56 57 @After 58 public void cleanup() throws Exception { 59 mContext.getSettingsProvider().clearOverrides(this); 60 } 61 62 protected Context getContext() { 63 return mContext; 64 } 65 66 protected void waitForIdleSync() { 67 if (mHandler == null) { 68 mHandler = new Handler(Looper.getMainLooper()); 69 } 70 waitForIdleSync(mHandler); 71 } 72 73 public static void waitForIdleSync(Handler h) { 74 validateThread(h.getLooper()); 75 Idler idler = new Idler(null); 76 h.getLooper().getQueue().addIdleHandler(idler); 77 // Ensure we are non-idle, so the idle handler can run. 78 h.post(new EmptyRunnable()); 79 idler.waitForIdle(); 80 } 81 82 private static final void validateThread(Looper l) { 83 if (Looper.myLooper() == l) { 84 throw new RuntimeException( 85 "This method can not be called from the looper being synced"); 86 } 87 } 88 89 // Used for leak tracking, returns null to indicate no leak tracking by default. 90 public Tracker getTracker(String tag) { 91 return null; 92 } 93 94 public void injectMockDependency(Class<?> cls) { 95 mDependency.injectTestDependency(cls.getName(), mock(cls)); 96 } 97 98 public void injectTestDependency(Class<?> cls, Object obj) { 99 mDependency.injectTestDependency(cls.getName(), obj); 100 } 101 102 public void injectTestDependency(String key, Object obj) { 103 mDependency.injectTestDependency(key, obj); 104 } 105 106 public static final class EmptyRunnable implements Runnable { 107 public void run() { 108 } 109 } 110 111 public static class TestDependency extends Dependency { 112 private final ArrayMap<String, Object> mObjs = new ArrayMap<>(); 113 114 private void injectTestDependency(String key, Object obj) { 115 mObjs.put(key, obj); 116 } 117 118 @Override 119 protected <T> T createDependency(String cls) { 120 if (mObjs.containsKey(cls)) return (T) mObjs.get(cls); 121 return super.createDependency(cls); 122 } 123 } 124 125 public static final class Idler implements MessageQueue.IdleHandler { 126 private final Runnable mCallback; 127 private boolean mIdle; 128 129 public Idler(Runnable callback) { 130 mCallback = callback; 131 mIdle = false; 132 } 133 134 @Override 135 public boolean queueIdle() { 136 if (mCallback != null) { 137 mCallback.run(); 138 } 139 synchronized (this) { 140 mIdle = true; 141 notifyAll(); 142 } 143 return false; 144 } 145 146 public void waitForIdle() { 147 synchronized (this) { 148 while (!mIdle) { 149 try { 150 wait(); 151 } catch (InterruptedException e) { 152 } 153 } 154 } 155 } 156 } 157} 158