Loading packages/SystemUI/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -508,4 +508,7 @@ <!-- Allow dragging the PIP to a location to close it --> <bool name="config_pipEnableDismissDragToEdge">true</bool> <!-- SystemUI Plugins that can be loaded on user builds. --> <string-array name="config_pluginWhitelist" translatable="false" /> </resources> packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java +10 −4 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.UserHandle; import android.util.ArraySet; import android.util.Log; import android.view.LayoutInflater; Loading @@ -41,7 +42,9 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.plugins.VersionInfo.InvalidVersionException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.android.systemui.R; public class PluginInstanceManager<T extends Plugin> { Loading @@ -63,17 +66,19 @@ public class PluginInstanceManager<T extends Plugin> { private final boolean isDebuggable; private final PackageManager mPm; private final PluginManagerImpl mManager; private final ArraySet<String> mWhitelistedPlugins = new ArraySet<>(); PluginInstanceManager(Context context, String action, PluginListener<T> listener, boolean allowMultiple, Looper looper, VersionInfo version, PluginManagerImpl manager) { this(context, context.getPackageManager(), action, listener, allowMultiple, looper, version, manager, Build.IS_DEBUGGABLE); manager, Build.IS_DEBUGGABLE, context.getResources().getStringArray(R.array.config_pluginWhitelist)); } @VisibleForTesting PluginInstanceManager(Context context, PackageManager pm, String action, PluginListener<T> listener, boolean allowMultiple, Looper looper, VersionInfo version, PluginManagerImpl manager, boolean debuggable) { PluginManagerImpl manager, boolean debuggable, String[] pluginWhitelist) { mMainHandler = new MainHandler(Looper.getMainLooper()); mPluginHandler = new PluginHandler(looper); mManager = manager; Loading @@ -83,6 +88,7 @@ public class PluginInstanceManager<T extends Plugin> { mListener = listener; mAllowMultiple = allowMultiple; mVersion = version; mWhitelistedPlugins.addAll(Arrays.asList(pluginWhitelist)); isDebuggable = debuggable; } Loading Loading @@ -294,9 +300,9 @@ public class PluginInstanceManager<T extends Plugin> { protected PluginInfo<T> handleLoadPlugin(ComponentName component) { // This was already checked, but do it again here to make extra extra sure, we don't // use these on production builds. if (!isDebuggable) { if (!isDebuggable && !mWhitelistedPlugins.contains(component.getPackageName())) { // Never ever ever allow these on production builds, they are only for prototyping. Log.d(TAG, "Somehow hit second debuggable check"); Log.w(TAG, "Plugin cannot be loaded on production build: " + component); return null; } String pkg = component.getPackageName(); Loading packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java +20 −26 Original line number Diff line number Diff line Loading @@ -37,13 +37,12 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Log.TerribleFailure; import android.util.Log.TerribleFailureHandler; import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.PluginInstanceManager.PluginContextWrapper; import com.android.systemui.plugins.PluginInstanceManager.PluginInfo; import com.android.systemui.plugins.annotations.ProvidesInterface; Loading @@ -53,13 +52,14 @@ import dalvik.system.PathClassLoader; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.Thread.UncaughtExceptionHandler; import java.util.Arrays; import java.util.Map; /** * @see Plugin */ public class PluginManagerImpl extends BroadcastReceiver implements PluginManager { private static final String TAG = PluginManagerImpl.class.getSimpleName(); static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN"; private static PluginManager sInstance; Loading @@ -68,6 +68,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage = new ArrayMap<>(); private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>(); private final ArraySet<String> mOneShotPackages = new ArraySet<>(); private final ArraySet<String> mWhitelistedPlugins = new ArraySet<>(); private final Context mContext; private final PluginInstanceManagerFactory mFactory; private final boolean isDebuggable; Loading @@ -79,23 +80,24 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage private boolean mWtfsSet; public PluginManagerImpl(Context context) { this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE, Thread.getUncaughtExceptionPreHandler()); this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE, context.getResources().getStringArray(R.array.config_pluginWhitelist), Thread.getUncaughtExceptionPreHandler()); } @VisibleForTesting PluginManagerImpl(Context context, PluginInstanceManagerFactory factory, boolean debuggable, UncaughtExceptionHandler defaultHandler) { String[] whitelistedPlugins, UncaughtExceptionHandler defaultHandler) { mContext = context; mFactory = factory; mLooper = Dependency.get(Dependency.BG_LOOPER); isDebuggable = debuggable; mWhitelistedPlugins.addAll(Arrays.asList(whitelistedPlugins)); mPluginPrefs = new PluginPrefs(mContext); PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler( defaultHandler); Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler); if (isDebuggable) { new Handler(mLooper).post(() -> { // Plugin dependencies that don't have another good home can go here, but // dependencies that have better places to init can happen elsewhere. Loading @@ -103,7 +105,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage .allowPluginDependency(ActivityStarter.class); }); } } public <T extends Plugin> T getOneShotPlugin(Class<T> cls) { ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class); Loading @@ -117,10 +118,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public <T extends Plugin> T getOneShotPlugin(String action, Class<?> cls) { if (!isDebuggable) { // Never ever ever allow these on production builds, they are only for prototyping. return null; } if (Looper.myLooper() != Looper.getMainLooper()) { throw new RuntimeException("Must be called from UI thread"); } Loading Loading @@ -153,10 +150,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener, Class cls, boolean allowMultiple) { if (!isDebuggable) { // Never ever ever allow these on production builds, they are only for prototyping. return; } mPluginPrefs.addAction(action); PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener, allowMultiple, mLooper, cls, this); Loading @@ -166,10 +159,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public void removePluginListener(PluginListener<?> listener) { if (!isDebuggable) { // Never ever ever allow these on production builds, they are only for prototyping. return; } if (!mPluginMap.containsKey(listener)) return; mPluginMap.remove(listener).destroy(); if (mPluginMap.size() == 0) { Loading Loading @@ -261,6 +250,11 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public ClassLoader getClassLoader(String sourceDir, String pkg) { if (!isDebuggable && !mWhitelistedPlugins.contains(pkg)) { Log.w(TAG, "Cannot get class loader for non-whitelisted plugin. Src:" + sourceDir + ", pkg: " + pkg); return null; } if (mClassLoaders.containsKey(pkg)) { return mClassLoaders.get(pkg); } Loading packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java +22 −2 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class PluginInstanceManagerTest extends SysuiTestCase { private static final String WHITELISTED_PACKAGE = "com.android.systemui"; // Static since the plugin needs to be generated by the PluginInstanceManager using newInstance. private static Plugin sMockPlugin; Loading @@ -88,7 +89,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { mMockVersionInfo = mock(VersionInfo.class); mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), mMockVersionInfo, mMockManager, true); mMockManager, true, new String[0]); sMockPlugin = mock(Plugin.class); when(sMockPlugin.getVersion()).thenReturn(1); } Loading Loading @@ -186,7 +187,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { // Create a version that thinks the build is not debuggable. mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), mMockVersionInfo, mMockManager, false); mMockManager, false, new String[0]); setupFakePmQuery(); mPluginInstanceManager.loadAll(); Loading @@ -198,6 +199,25 @@ public class PluginInstanceManagerTest extends SysuiTestCase { verify(mMockListener, Mockito.never()).onPluginConnected(any(), any()); } @Test public void testNonDebuggable_whitelist() throws Exception { // Create a version that thinks the build is not debuggable. mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), mMockVersionInfo, mMockManager, false, new String[] {WHITELISTED_PACKAGE}); setupFakePmQuery(); mPluginInstanceManager.loadAll(); waitForIdleSync(mPluginInstanceManager.mPluginHandler); waitForIdleSync(mPluginInstanceManager.mMainHandler); // Verify startup lifecycle verify(sMockPlugin).onCreate(ArgumentCaptor.forClass(Context.class).capture(), ArgumentCaptor.forClass(Context.class).capture()); verify(mMockListener).onPluginConnected(any(), any()); } @Test public void testCheckAndDisable() throws Exception { createPlugin(); // Get into valid created state. Loading packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java +23 −12 Original line number Diff line number Diff line Loading @@ -13,8 +13,9 @@ */ package com.android.systemui.plugins; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertSame; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; Loading @@ -26,8 +27,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.support.test.annotation.UiThreadTest; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; Loading @@ -36,11 +35,10 @@ import android.testing.TestableLooper.RunWithLooper; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.annotations.ProvidesInterface; import com.android.systemui.plugins.PluginInstanceManager.PluginInfo; import com.android.systemui.plugins.PluginManagerImpl.PluginInstanceManagerFactory; import com.android.systemui.plugins.annotations.ProvidesInterface; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -54,6 +52,8 @@ import java.lang.Thread.UncaughtExceptionHandler; @RunWithLooper public class PluginManagerTest extends SysuiTestCase { private static final String WHITELISTED_PACKAGE = "com.android.systemui"; private PluginInstanceManagerFactory mMockFactory; private PluginInstanceManager mMockPluginInstance; private PluginManagerImpl mPluginManager; Loading @@ -74,7 +74,7 @@ public class PluginManagerTest extends SysuiTestCase { when(mMockFactory.createPluginInstanceManager(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(mMockPluginInstance); mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, true, mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, true, new String[0], mMockExceptionHandler); resetExceptionHandler(); mMockListener = mock(PluginListener.class); Loading @@ -87,7 +87,7 @@ public class PluginManagerTest extends SysuiTestCase { when(mMockPluginInstance.getPlugin()).thenReturn(new PluginInfo(null, null, mockPlugin, null, null)); Plugin result = mPluginManager.getOneShotPlugin("myAction", TestPlugin.class); assertTrue(result == mockPlugin); assertSame(mockPlugin, result); } @Test Loading @@ -106,16 +106,27 @@ public class PluginManagerTest extends SysuiTestCase { } @Test public void testNonDebuggable() { @RunWithLooper(setAsMainLooper = true) public void testNonDebuggable_noWhitelist() { mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, false, mMockExceptionHandler); new String[0], mMockExceptionHandler); resetExceptionHandler(); mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class); verify(mMockPluginInstance, Mockito.never()).loadAll(); assertNull(mPluginManager.getOneShotPlugin("myPlugin", TestPlugin.class)); verify(mMockPluginInstance, Mockito.never()).getPlugin(); assertNull(mPluginManager.getClassLoader("myPlugin", WHITELISTED_PACKAGE)); } @Test @RunWithLooper(setAsMainLooper = true) public void testNonDebuggable_whitelistedPkg() { mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, false, new String[] {WHITELISTED_PACKAGE}, mMockExceptionHandler); resetExceptionHandler(); mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class); assertNotNull(mPluginManager.getClassLoader("myPlugin", WHITELISTED_PACKAGE)); assertNull(mPluginManager.getClassLoader("myPlugin", "com.android.invalidpackage")); } @Test Loading Loading
packages/SystemUI/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -508,4 +508,7 @@ <!-- Allow dragging the PIP to a location to close it --> <bool name="config_pipEnableDismissDragToEdge">true</bool> <!-- SystemUI Plugins that can be loaded on user builds. --> <string-array name="config_pluginWhitelist" translatable="false" /> </resources>
packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java +10 −4 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.UserHandle; import android.util.ArraySet; import android.util.Log; import android.view.LayoutInflater; Loading @@ -41,7 +42,9 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.plugins.VersionInfo.InvalidVersionException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.android.systemui.R; public class PluginInstanceManager<T extends Plugin> { Loading @@ -63,17 +66,19 @@ public class PluginInstanceManager<T extends Plugin> { private final boolean isDebuggable; private final PackageManager mPm; private final PluginManagerImpl mManager; private final ArraySet<String> mWhitelistedPlugins = new ArraySet<>(); PluginInstanceManager(Context context, String action, PluginListener<T> listener, boolean allowMultiple, Looper looper, VersionInfo version, PluginManagerImpl manager) { this(context, context.getPackageManager(), action, listener, allowMultiple, looper, version, manager, Build.IS_DEBUGGABLE); manager, Build.IS_DEBUGGABLE, context.getResources().getStringArray(R.array.config_pluginWhitelist)); } @VisibleForTesting PluginInstanceManager(Context context, PackageManager pm, String action, PluginListener<T> listener, boolean allowMultiple, Looper looper, VersionInfo version, PluginManagerImpl manager, boolean debuggable) { PluginManagerImpl manager, boolean debuggable, String[] pluginWhitelist) { mMainHandler = new MainHandler(Looper.getMainLooper()); mPluginHandler = new PluginHandler(looper); mManager = manager; Loading @@ -83,6 +88,7 @@ public class PluginInstanceManager<T extends Plugin> { mListener = listener; mAllowMultiple = allowMultiple; mVersion = version; mWhitelistedPlugins.addAll(Arrays.asList(pluginWhitelist)); isDebuggable = debuggable; } Loading Loading @@ -294,9 +300,9 @@ public class PluginInstanceManager<T extends Plugin> { protected PluginInfo<T> handleLoadPlugin(ComponentName component) { // This was already checked, but do it again here to make extra extra sure, we don't // use these on production builds. if (!isDebuggable) { if (!isDebuggable && !mWhitelistedPlugins.contains(component.getPackageName())) { // Never ever ever allow these on production builds, they are only for prototyping. Log.d(TAG, "Somehow hit second debuggable check"); Log.w(TAG, "Plugin cannot be loaded on production build: " + component); return null; } String pkg = component.getPackageName(); Loading
packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java +20 −26 Original line number Diff line number Diff line Loading @@ -37,13 +37,12 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Log.TerribleFailure; import android.util.Log.TerribleFailureHandler; import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.PluginInstanceManager.PluginContextWrapper; import com.android.systemui.plugins.PluginInstanceManager.PluginInfo; import com.android.systemui.plugins.annotations.ProvidesInterface; Loading @@ -53,13 +52,14 @@ import dalvik.system.PathClassLoader; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.Thread.UncaughtExceptionHandler; import java.util.Arrays; import java.util.Map; /** * @see Plugin */ public class PluginManagerImpl extends BroadcastReceiver implements PluginManager { private static final String TAG = PluginManagerImpl.class.getSimpleName(); static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN"; private static PluginManager sInstance; Loading @@ -68,6 +68,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage = new ArrayMap<>(); private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>(); private final ArraySet<String> mOneShotPackages = new ArraySet<>(); private final ArraySet<String> mWhitelistedPlugins = new ArraySet<>(); private final Context mContext; private final PluginInstanceManagerFactory mFactory; private final boolean isDebuggable; Loading @@ -79,23 +80,24 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage private boolean mWtfsSet; public PluginManagerImpl(Context context) { this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE, Thread.getUncaughtExceptionPreHandler()); this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE, context.getResources().getStringArray(R.array.config_pluginWhitelist), Thread.getUncaughtExceptionPreHandler()); } @VisibleForTesting PluginManagerImpl(Context context, PluginInstanceManagerFactory factory, boolean debuggable, UncaughtExceptionHandler defaultHandler) { String[] whitelistedPlugins, UncaughtExceptionHandler defaultHandler) { mContext = context; mFactory = factory; mLooper = Dependency.get(Dependency.BG_LOOPER); isDebuggable = debuggable; mWhitelistedPlugins.addAll(Arrays.asList(whitelistedPlugins)); mPluginPrefs = new PluginPrefs(mContext); PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler( defaultHandler); Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler); if (isDebuggable) { new Handler(mLooper).post(() -> { // Plugin dependencies that don't have another good home can go here, but // dependencies that have better places to init can happen elsewhere. Loading @@ -103,7 +105,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage .allowPluginDependency(ActivityStarter.class); }); } } public <T extends Plugin> T getOneShotPlugin(Class<T> cls) { ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class); Loading @@ -117,10 +118,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public <T extends Plugin> T getOneShotPlugin(String action, Class<?> cls) { if (!isDebuggable) { // Never ever ever allow these on production builds, they are only for prototyping. return null; } if (Looper.myLooper() != Looper.getMainLooper()) { throw new RuntimeException("Must be called from UI thread"); } Loading Loading @@ -153,10 +150,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener, Class cls, boolean allowMultiple) { if (!isDebuggable) { // Never ever ever allow these on production builds, they are only for prototyping. return; } mPluginPrefs.addAction(action); PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener, allowMultiple, mLooper, cls, this); Loading @@ -166,10 +159,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public void removePluginListener(PluginListener<?> listener) { if (!isDebuggable) { // Never ever ever allow these on production builds, they are only for prototyping. return; } if (!mPluginMap.containsKey(listener)) return; mPluginMap.remove(listener).destroy(); if (mPluginMap.size() == 0) { Loading Loading @@ -261,6 +250,11 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public ClassLoader getClassLoader(String sourceDir, String pkg) { if (!isDebuggable && !mWhitelistedPlugins.contains(pkg)) { Log.w(TAG, "Cannot get class loader for non-whitelisted plugin. Src:" + sourceDir + ", pkg: " + pkg); return null; } if (mClassLoaders.containsKey(pkg)) { return mClassLoaders.get(pkg); } Loading
packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java +22 −2 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class PluginInstanceManagerTest extends SysuiTestCase { private static final String WHITELISTED_PACKAGE = "com.android.systemui"; // Static since the plugin needs to be generated by the PluginInstanceManager using newInstance. private static Plugin sMockPlugin; Loading @@ -88,7 +89,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { mMockVersionInfo = mock(VersionInfo.class); mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), mMockVersionInfo, mMockManager, true); mMockManager, true, new String[0]); sMockPlugin = mock(Plugin.class); when(sMockPlugin.getVersion()).thenReturn(1); } Loading Loading @@ -186,7 +187,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { // Create a version that thinks the build is not debuggable. mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), mMockVersionInfo, mMockManager, false); mMockManager, false, new String[0]); setupFakePmQuery(); mPluginInstanceManager.loadAll(); Loading @@ -198,6 +199,25 @@ public class PluginInstanceManagerTest extends SysuiTestCase { verify(mMockListener, Mockito.never()).onPluginConnected(any(), any()); } @Test public void testNonDebuggable_whitelist() throws Exception { // Create a version that thinks the build is not debuggable. mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), mMockVersionInfo, mMockManager, false, new String[] {WHITELISTED_PACKAGE}); setupFakePmQuery(); mPluginInstanceManager.loadAll(); waitForIdleSync(mPluginInstanceManager.mPluginHandler); waitForIdleSync(mPluginInstanceManager.mMainHandler); // Verify startup lifecycle verify(sMockPlugin).onCreate(ArgumentCaptor.forClass(Context.class).capture(), ArgumentCaptor.forClass(Context.class).capture()); verify(mMockListener).onPluginConnected(any(), any()); } @Test public void testCheckAndDisable() throws Exception { createPlugin(); // Get into valid created state. Loading
packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java +23 −12 Original line number Diff line number Diff line Loading @@ -13,8 +13,9 @@ */ package com.android.systemui.plugins; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertSame; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; Loading @@ -26,8 +27,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.support.test.annotation.UiThreadTest; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; Loading @@ -36,11 +35,10 @@ import android.testing.TestableLooper.RunWithLooper; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.annotations.ProvidesInterface; import com.android.systemui.plugins.PluginInstanceManager.PluginInfo; import com.android.systemui.plugins.PluginManagerImpl.PluginInstanceManagerFactory; import com.android.systemui.plugins.annotations.ProvidesInterface; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -54,6 +52,8 @@ import java.lang.Thread.UncaughtExceptionHandler; @RunWithLooper public class PluginManagerTest extends SysuiTestCase { private static final String WHITELISTED_PACKAGE = "com.android.systemui"; private PluginInstanceManagerFactory mMockFactory; private PluginInstanceManager mMockPluginInstance; private PluginManagerImpl mPluginManager; Loading @@ -74,7 +74,7 @@ public class PluginManagerTest extends SysuiTestCase { when(mMockFactory.createPluginInstanceManager(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(mMockPluginInstance); mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, true, mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, true, new String[0], mMockExceptionHandler); resetExceptionHandler(); mMockListener = mock(PluginListener.class); Loading @@ -87,7 +87,7 @@ public class PluginManagerTest extends SysuiTestCase { when(mMockPluginInstance.getPlugin()).thenReturn(new PluginInfo(null, null, mockPlugin, null, null)); Plugin result = mPluginManager.getOneShotPlugin("myAction", TestPlugin.class); assertTrue(result == mockPlugin); assertSame(mockPlugin, result); } @Test Loading @@ -106,16 +106,27 @@ public class PluginManagerTest extends SysuiTestCase { } @Test public void testNonDebuggable() { @RunWithLooper(setAsMainLooper = true) public void testNonDebuggable_noWhitelist() { mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, false, mMockExceptionHandler); new String[0], mMockExceptionHandler); resetExceptionHandler(); mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class); verify(mMockPluginInstance, Mockito.never()).loadAll(); assertNull(mPluginManager.getOneShotPlugin("myPlugin", TestPlugin.class)); verify(mMockPluginInstance, Mockito.never()).getPlugin(); assertNull(mPluginManager.getClassLoader("myPlugin", WHITELISTED_PACKAGE)); } @Test @RunWithLooper(setAsMainLooper = true) public void testNonDebuggable_whitelistedPkg() { mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, false, new String[] {WHITELISTED_PACKAGE}, mMockExceptionHandler); resetExceptionHandler(); mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class); assertNotNull(mPluginManager.getClassLoader("myPlugin", WHITELISTED_PACKAGE)); assertNull(mPluginManager.getClassLoader("myPlugin", "com.android.invalidpackage")); } @Test Loading