SysuiTestCase.java revision 1d9632df97bdd4879cff0328a46a8fab6fde441a
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; 26 27import com.android.systemui.Dependency.DependencyKey; 28import com.android.systemui.utils.TestableContext; 29import com.android.systemui.utils.leaks.Tracker; 30 31import org.junit.After; 32import org.junit.Before; 33 34/** 35 * Base class that does System UI specific setup. 36 */ 37public abstract class SysuiTestCase { 38 39 private Throwable mException; 40 private Handler mHandler; 41 protected TestableContext mContext; 42 protected TestDependency mDependency; 43 44 @Before 45 public void SysuiSetup() throws Exception { 46 mException = null; 47 System.setProperty("dexmaker.share_classloader", "true"); 48 mContext = new TestableContext(InstrumentationRegistry.getTargetContext(), this); 49 SystemUIFactory.createFromConfig(mContext); 50 mDependency = new TestDependency(); 51 mDependency.mContext = mContext; 52 mDependency.start(); 53 } 54 55 @After 56 public void cleanup() throws Exception { 57 mContext.getSettingsProvider().clearOverrides(this); 58 } 59 60 protected Context getContext() { 61 return mContext; 62 } 63 64 protected void waitForIdleSync() { 65 if (mHandler == null) { 66 mHandler = new Handler(Looper.getMainLooper()); 67 } 68 waitForIdleSync(mHandler); 69 } 70 71 public static void waitForIdleSync(Handler h) { 72 validateThread(h.getLooper()); 73 Idler idler = new Idler(null); 74 h.getLooper().getQueue().addIdleHandler(idler); 75 // Ensure we are non-idle, so the idle handler can run. 76 h.post(new EmptyRunnable()); 77 idler.waitForIdle(); 78 } 79 80 private static final void validateThread(Looper l) { 81 if (Looper.myLooper() == l) { 82 throw new RuntimeException( 83 "This method can not be called from the looper being synced"); 84 } 85 } 86 87 // Used for leak tracking, returns null to indicate no leak tracking by default. 88 public Tracker getTracker(String tag) { 89 return null; 90 } 91 92 public <T> T injectMockDependency(Class<T> cls) { 93 final T mock = mock(cls); 94 mDependency.injectTestDependency(cls, mock); 95 return mock; 96 } 97 98 public <T> void injectTestDependency(Class<T> cls, T obj) { 99 mDependency.injectTestDependency(cls, obj); 100 } 101 102 public <T> void injectTestDependency(DependencyKey<T> key, T 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<Object, Object> mObjs = new ArrayMap<>(); 113 114 private <T> void injectTestDependency(DependencyKey<T> key, T obj) { 115 mObjs.put(key, obj); 116 } 117 118 private <T> void injectTestDependency(Class<T> key, T obj) { 119 mObjs.put(key, obj); 120 } 121 122 @Override 123 protected <T> T createDependency(Object key) { 124 if (mObjs.containsKey(key)) return (T) mObjs.get(key); 125 return super.createDependency(key); 126 } 127 } 128 129 public static final class Idler implements MessageQueue.IdleHandler { 130 private final Runnable mCallback; 131 private boolean mIdle; 132 133 public Idler(Runnable callback) { 134 mCallback = callback; 135 mIdle = false; 136 } 137 138 @Override 139 public boolean queueIdle() { 140 if (mCallback != null) { 141 mCallback.run(); 142 } 143 synchronized (this) { 144 mIdle = true; 145 notifyAll(); 146 } 147 return false; 148 } 149 150 public void waitForIdle() { 151 synchronized (this) { 152 while (!mIdle) { 153 try { 154 wait(); 155 } catch (InterruptedException e) { 156 } 157 } 158 } 159 } 160 } 161} 162