Loading packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java +49 −3 Original line number Diff line number Diff line Loading @@ -14,18 +14,27 @@ package com.android.systemui.plugins; import android.app.Notification; import android.app.Notification.Action; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.UserHandle; import android.util.Log; import android.view.LayoutInflater; Loading Loading @@ -260,10 +269,9 @@ public class PluginInstanceManager<T extends Plugin> { String pkg = component.getPackageName(); String cls = component.getClassName(); try { PackageManager pm = mPm; ApplicationInfo info = pm.getApplicationInfo(pkg, 0); ApplicationInfo info = mPm.getApplicationInfo(pkg, 0); // TODO: This probably isn't needed given that we don't have IGNORE_SECURITY on if (pm.checkPermission(PLUGIN_PERMISSION, pkg) if (mPm.checkPermission(PLUGIN_PERMISSION, pkg) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Plugin doesn't have permission: " + pkg); return null; Loading @@ -275,6 +283,44 @@ public class PluginInstanceManager<T extends Plugin> { Class<?> pluginClass = Class.forName(cls, true, classLoader); T plugin = (T) pluginClass.newInstance(); if (plugin.getVersion() != mVersion) { final int id = mContext.getResources().getIdentifier("notification_plugin", "id", mContext.getPackageName()); final int icon = mContext.getResources().getIdentifier("tuner", "drawable", mContext.getPackageName()); final int color = Resources.getSystem().getIdentifier( "system_notification_accent_color", "color", "android"); final Notification.Builder nb = new Notification.Builder(mContext) .setStyle(new Notification.BigTextStyle()) .setSmallIcon(icon) .setWhen(0) .setShowWhen(false) .setPriority(Notification.PRIORITY_MAX) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(mContext.getColor(color)); String label = cls; try { label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString(); } catch (NameNotFoundException e) { } if (plugin.getVersion() < mVersion) { // Localization not required as this will never ever appear in a user build. nb.setContentTitle("Plugin \"" + label + "\" is too old") .setContentText("Contact plugin developer to get an updated" + " version.\nPlugin version: " + plugin.getVersion() + "\nSystem version: " + mVersion); } else { // Localization not required as this will never ever appear in a user build. nb.setContentTitle("Plugin \"" + label + "\" is too new") .setContentText("Check to see if an OTA is available.\n" + "Plugin version: " + plugin.getVersion() + "\nSystem version: " + mVersion); } Intent i = new Intent(PluginManager.DISABLE_PLUGIN).setData( Uri.parse("package://" + component.flattenToString())); PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0); nb.addAction(new Action.Builder(null, "Disable plugin", pi).build()); mContext.getSystemService(NotificationManager.class) .notifyAsUser(cls, id, nb.build(), UserHandle.ALL); // TODO: Warn user. Log.w(TAG, "Plugin has invalid interface version " + plugin.getVersion() + ", expected " + mVersion); Loading packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java +17 −0 Original line number Diff line number Diff line Loading @@ -14,11 +14,14 @@ package com.android.systemui.plugins; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Build; Loading @@ -42,6 +45,8 @@ public class PluginManager extends BroadcastReceiver { public static final String PLUGIN_CHANGED = "com.android.systemui.action.PLUGIN_CHANGED"; static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN"; private static PluginManager sInstance; private final HandlerThread mBackgroundThread; Loading Loading @@ -112,6 +117,7 @@ public class PluginManager extends BroadcastReceiver { filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(PLUGIN_CHANGED); filter.addAction(DISABLE_PLUGIN); filter.addDataScheme("package"); mContext.registerReceiver(this, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); Loading @@ -128,6 +134,17 @@ public class PluginManager extends BroadcastReceiver { for (PluginInstanceManager manager : mPluginMap.values()) { manager.loadAll(); } } else if (DISABLE_PLUGIN.equals(intent.getAction())) { Uri uri = intent.getData(); ComponentName component = ComponentName.unflattenFromString( uri.toString().substring(10)); mContext.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); int id = mContext.getResources().getIdentifier("notification_plugin", "id", mContext.getPackageName()); mContext.getSystemService(NotificationManager.class).cancel(component.getClassName(), id); } else { Uri data = intent.getData(); String pkg = data.getEncodedSchemeSpecificPart(); Loading packages/SystemUI/res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ <item type="id" name="notification_hidden"/> <item type="id" name="notification_volumeui"/> <item type="id" name="notification_temperature"/> <item type="id" name="notification_plugin"/> <item type="id" name="transformation_start_x_tag"/> <item type="id" name="transformation_start_y_tag"/> <item type="id" name="transformation_start_scale_x_tag"/> Loading packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java +28 −22 Original line number Diff line number Diff line Loading @@ -17,11 +17,15 @@ package com.android.systemui.plugins; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Activity; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading @@ -34,6 +38,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.HandlerThread; import android.os.UserHandle; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; Loading Loading @@ -72,7 +77,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { mMockPm = mock(PackageManager.class); mMockListener = mock(PluginListener.class); mMockManager = mock(PluginManager.class); when(mMockManager.getClassLoader(Mockito.any(), Mockito.any())) when(mMockManager.getClassLoader(any(), any())) .thenReturn(getClass().getClassLoader()); mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, true); Loading @@ -87,8 +92,8 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testNoPlugins() { when(mMockPm.queryIntentServices(Mockito.any(), Mockito.anyInt())).thenReturn( public void testNoPlugins() throws Exception { when(mMockPm.queryIntentServices(any(), anyInt())).thenReturn( Collections.emptyList()); mPluginInstanceManager.loadAll(); Loading @@ -100,7 +105,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testPluginCreate() { public void testPluginCreate() throws Exception { createPlugin(); // Verify startup lifecycle Loading @@ -110,7 +115,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testPluginDestroy() { public void testPluginDestroy() throws Exception { createPlugin(); // Get into valid created state. mPluginInstanceManager.destroy(); Loading @@ -124,7 +129,9 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testIncorrectVersion() { public void testIncorrectVersion() throws Exception { NotificationManager nm = mock(NotificationManager.class); mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, nm); setupFakePmQuery(); when(sMockPlugin.getVersion()).thenReturn(2); Loading @@ -136,10 +143,12 @@ public class PluginInstanceManagerTest extends SysuiTestCase { // Plugin shouldn't be connected because it is the wrong version. verify(mMockListener, Mockito.never()).onPluginConnected( ArgumentCaptor.forClass(Plugin.class).capture()); verify(nm).notifyAsUser(eq(TestPlugin.class.getName()), eq(R.id.notification_plugin), any(), eq(UserHandle.ALL)); } @Test public void testReloadOnChange() { public void testReloadOnChange() throws Exception { createPlugin(); // Get into valid created state. mPluginInstanceManager.onPackageChange("com.android.systemui"); Loading @@ -159,7 +168,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testNonDebuggable() { public void testNonDebuggable() throws Exception { // Create a version that thinks the build is not debuggable. mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, false); Loading @@ -176,7 +185,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testCheckAndDisable() { public void testCheckAndDisable() throws Exception { createPlugin(); // Get into valid created state. // Start with an unrelated class. Loading @@ -197,7 +206,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testDisableAll() { public void testDisableAll() throws Exception { createPlugin(); // Get into valid created state. mPluginInstanceManager.disableAll(); Loading @@ -208,29 +217,26 @@ public class PluginInstanceManagerTest extends SysuiTestCase { ArgumentCaptor.forClass(int.class).capture()); } private void setupFakePmQuery() { private void setupFakePmQuery() throws Exception { List<ResolveInfo> list = new ArrayList<>(); ResolveInfo info = new ResolveInfo(); info.serviceInfo = new ServiceInfo(); info.serviceInfo = mock(ServiceInfo.class); info.serviceInfo.packageName = "com.android.systemui"; info.serviceInfo.name = TestPlugin.class.getName(); when(info.serviceInfo.loadLabel(any())).thenReturn("Test Plugin"); list.add(info); when(mMockPm.queryIntentServices(Mockito.any(), Mockito.anyInt())).thenReturn(list); when(mMockPm.queryIntentServices(any(), Mockito.anyInt())).thenReturn(list); when(mMockPm.getServiceInfo(any(), anyInt())).thenReturn(info.serviceInfo); when(mMockPm.checkPermission(Mockito.anyString(), Mockito.anyString())).thenReturn( PackageManager.PERMISSION_GRANTED); try { ApplicationInfo appInfo = getContext().getApplicationInfo(); when(mMockPm.getApplicationInfo(Mockito.anyString(), Mockito.anyInt())).thenReturn( appInfo); } catch (NameNotFoundException e) { // Shouldn't be possible, but if it is, we want to fail. throw new RuntimeException(e); } } private void createPlugin() { private void createPlugin() throws Exception { setupFakePmQuery(); mPluginInstanceManager.loadAll(); Loading packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java +25 −0 Original line number Diff line number Diff line Loading @@ -13,10 +13,17 @@ */ package com.android.systemui.plugins; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; Loading Loading @@ -113,6 +120,24 @@ public class PluginManagerTest extends SysuiTestCase { ArgumentCaptor.forClass(Throwable.class).capture()); } @Test public void testDisableIntent() { NotificationManager nm = mock(NotificationManager.class); PackageManager pm = mock(PackageManager.class); mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, nm); mContext.setMockPackageManager(pm); ComponentName testComponent = new ComponentName(getContext().getPackageName(), PluginManagerTest.class.getName()); Intent intent = new Intent(PluginManager.DISABLE_PLUGIN); intent.setData(Uri.parse("package://" + testComponent.flattenToString())); mPluginManager.onReceive(mContext, intent); verify(nm).cancel(eq(testComponent.getClassName()), eq(R.id.notification_plugin)); verify(pm).setComponentEnabledSetting(eq(testComponent), eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED), eq(PackageManager.DONT_KILL_APP)); } private void resetExceptionHandler() { mPluginExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); // Set back the real exception handler so the test can crash if it wants to. Loading Loading
packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java +49 −3 Original line number Diff line number Diff line Loading @@ -14,18 +14,27 @@ package com.android.systemui.plugins; import android.app.Notification; import android.app.Notification.Action; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.UserHandle; import android.util.Log; import android.view.LayoutInflater; Loading Loading @@ -260,10 +269,9 @@ public class PluginInstanceManager<T extends Plugin> { String pkg = component.getPackageName(); String cls = component.getClassName(); try { PackageManager pm = mPm; ApplicationInfo info = pm.getApplicationInfo(pkg, 0); ApplicationInfo info = mPm.getApplicationInfo(pkg, 0); // TODO: This probably isn't needed given that we don't have IGNORE_SECURITY on if (pm.checkPermission(PLUGIN_PERMISSION, pkg) if (mPm.checkPermission(PLUGIN_PERMISSION, pkg) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Plugin doesn't have permission: " + pkg); return null; Loading @@ -275,6 +283,44 @@ public class PluginInstanceManager<T extends Plugin> { Class<?> pluginClass = Class.forName(cls, true, classLoader); T plugin = (T) pluginClass.newInstance(); if (plugin.getVersion() != mVersion) { final int id = mContext.getResources().getIdentifier("notification_plugin", "id", mContext.getPackageName()); final int icon = mContext.getResources().getIdentifier("tuner", "drawable", mContext.getPackageName()); final int color = Resources.getSystem().getIdentifier( "system_notification_accent_color", "color", "android"); final Notification.Builder nb = new Notification.Builder(mContext) .setStyle(new Notification.BigTextStyle()) .setSmallIcon(icon) .setWhen(0) .setShowWhen(false) .setPriority(Notification.PRIORITY_MAX) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(mContext.getColor(color)); String label = cls; try { label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString(); } catch (NameNotFoundException e) { } if (plugin.getVersion() < mVersion) { // Localization not required as this will never ever appear in a user build. nb.setContentTitle("Plugin \"" + label + "\" is too old") .setContentText("Contact plugin developer to get an updated" + " version.\nPlugin version: " + plugin.getVersion() + "\nSystem version: " + mVersion); } else { // Localization not required as this will never ever appear in a user build. nb.setContentTitle("Plugin \"" + label + "\" is too new") .setContentText("Check to see if an OTA is available.\n" + "Plugin version: " + plugin.getVersion() + "\nSystem version: " + mVersion); } Intent i = new Intent(PluginManager.DISABLE_PLUGIN).setData( Uri.parse("package://" + component.flattenToString())); PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0); nb.addAction(new Action.Builder(null, "Disable plugin", pi).build()); mContext.getSystemService(NotificationManager.class) .notifyAsUser(cls, id, nb.build(), UserHandle.ALL); // TODO: Warn user. Log.w(TAG, "Plugin has invalid interface version " + plugin.getVersion() + ", expected " + mVersion); Loading
packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java +17 −0 Original line number Diff line number Diff line Loading @@ -14,11 +14,14 @@ package com.android.systemui.plugins; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Build; Loading @@ -42,6 +45,8 @@ public class PluginManager extends BroadcastReceiver { public static final String PLUGIN_CHANGED = "com.android.systemui.action.PLUGIN_CHANGED"; static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN"; private static PluginManager sInstance; private final HandlerThread mBackgroundThread; Loading Loading @@ -112,6 +117,7 @@ public class PluginManager extends BroadcastReceiver { filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(PLUGIN_CHANGED); filter.addAction(DISABLE_PLUGIN); filter.addDataScheme("package"); mContext.registerReceiver(this, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); Loading @@ -128,6 +134,17 @@ public class PluginManager extends BroadcastReceiver { for (PluginInstanceManager manager : mPluginMap.values()) { manager.loadAll(); } } else if (DISABLE_PLUGIN.equals(intent.getAction())) { Uri uri = intent.getData(); ComponentName component = ComponentName.unflattenFromString( uri.toString().substring(10)); mContext.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); int id = mContext.getResources().getIdentifier("notification_plugin", "id", mContext.getPackageName()); mContext.getSystemService(NotificationManager.class).cancel(component.getClassName(), id); } else { Uri data = intent.getData(); String pkg = data.getEncodedSchemeSpecificPart(); Loading
packages/SystemUI/res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ <item type="id" name="notification_hidden"/> <item type="id" name="notification_volumeui"/> <item type="id" name="notification_temperature"/> <item type="id" name="notification_plugin"/> <item type="id" name="transformation_start_x_tag"/> <item type="id" name="transformation_start_y_tag"/> <item type="id" name="transformation_start_scale_x_tag"/> Loading
packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java +28 −22 Original line number Diff line number Diff line Loading @@ -17,11 +17,15 @@ package com.android.systemui.plugins; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Activity; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading @@ -34,6 +38,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.HandlerThread; import android.os.UserHandle; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; Loading Loading @@ -72,7 +77,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { mMockPm = mock(PackageManager.class); mMockListener = mock(PluginListener.class); mMockManager = mock(PluginManager.class); when(mMockManager.getClassLoader(Mockito.any(), Mockito.any())) when(mMockManager.getClassLoader(any(), any())) .thenReturn(getClass().getClassLoader()); mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, true); Loading @@ -87,8 +92,8 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testNoPlugins() { when(mMockPm.queryIntentServices(Mockito.any(), Mockito.anyInt())).thenReturn( public void testNoPlugins() throws Exception { when(mMockPm.queryIntentServices(any(), anyInt())).thenReturn( Collections.emptyList()); mPluginInstanceManager.loadAll(); Loading @@ -100,7 +105,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testPluginCreate() { public void testPluginCreate() throws Exception { createPlugin(); // Verify startup lifecycle Loading @@ -110,7 +115,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testPluginDestroy() { public void testPluginDestroy() throws Exception { createPlugin(); // Get into valid created state. mPluginInstanceManager.destroy(); Loading @@ -124,7 +129,9 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testIncorrectVersion() { public void testIncorrectVersion() throws Exception { NotificationManager nm = mock(NotificationManager.class); mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, nm); setupFakePmQuery(); when(sMockPlugin.getVersion()).thenReturn(2); Loading @@ -136,10 +143,12 @@ public class PluginInstanceManagerTest extends SysuiTestCase { // Plugin shouldn't be connected because it is the wrong version. verify(mMockListener, Mockito.never()).onPluginConnected( ArgumentCaptor.forClass(Plugin.class).capture()); verify(nm).notifyAsUser(eq(TestPlugin.class.getName()), eq(R.id.notification_plugin), any(), eq(UserHandle.ALL)); } @Test public void testReloadOnChange() { public void testReloadOnChange() throws Exception { createPlugin(); // Get into valid created state. mPluginInstanceManager.onPackageChange("com.android.systemui"); Loading @@ -159,7 +168,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testNonDebuggable() { public void testNonDebuggable() throws Exception { // Create a version that thinks the build is not debuggable. mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction", mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, false); Loading @@ -176,7 +185,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testCheckAndDisable() { public void testCheckAndDisable() throws Exception { createPlugin(); // Get into valid created state. // Start with an unrelated class. Loading @@ -197,7 +206,7 @@ public class PluginInstanceManagerTest extends SysuiTestCase { } @Test public void testDisableAll() { public void testDisableAll() throws Exception { createPlugin(); // Get into valid created state. mPluginInstanceManager.disableAll(); Loading @@ -208,29 +217,26 @@ public class PluginInstanceManagerTest extends SysuiTestCase { ArgumentCaptor.forClass(int.class).capture()); } private void setupFakePmQuery() { private void setupFakePmQuery() throws Exception { List<ResolveInfo> list = new ArrayList<>(); ResolveInfo info = new ResolveInfo(); info.serviceInfo = new ServiceInfo(); info.serviceInfo = mock(ServiceInfo.class); info.serviceInfo.packageName = "com.android.systemui"; info.serviceInfo.name = TestPlugin.class.getName(); when(info.serviceInfo.loadLabel(any())).thenReturn("Test Plugin"); list.add(info); when(mMockPm.queryIntentServices(Mockito.any(), Mockito.anyInt())).thenReturn(list); when(mMockPm.queryIntentServices(any(), Mockito.anyInt())).thenReturn(list); when(mMockPm.getServiceInfo(any(), anyInt())).thenReturn(info.serviceInfo); when(mMockPm.checkPermission(Mockito.anyString(), Mockito.anyString())).thenReturn( PackageManager.PERMISSION_GRANTED); try { ApplicationInfo appInfo = getContext().getApplicationInfo(); when(mMockPm.getApplicationInfo(Mockito.anyString(), Mockito.anyInt())).thenReturn( appInfo); } catch (NameNotFoundException e) { // Shouldn't be possible, but if it is, we want to fail. throw new RuntimeException(e); } } private void createPlugin() { private void createPlugin() throws Exception { setupFakePmQuery(); mPluginInstanceManager.loadAll(); Loading
packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java +25 −0 Original line number Diff line number Diff line Loading @@ -13,10 +13,17 @@ */ package com.android.systemui.plugins; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; Loading Loading @@ -113,6 +120,24 @@ public class PluginManagerTest extends SysuiTestCase { ArgumentCaptor.forClass(Throwable.class).capture()); } @Test public void testDisableIntent() { NotificationManager nm = mock(NotificationManager.class); PackageManager pm = mock(PackageManager.class); mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, nm); mContext.setMockPackageManager(pm); ComponentName testComponent = new ComponentName(getContext().getPackageName(), PluginManagerTest.class.getName()); Intent intent = new Intent(PluginManager.DISABLE_PLUGIN); intent.setData(Uri.parse("package://" + testComponent.flattenToString())); mPluginManager.onReceive(mContext, intent); verify(nm).cancel(eq(testComponent.getClassName()), eq(R.id.notification_plugin)); verify(pm).setComponentEnabledSetting(eq(testComponent), eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED), eq(PackageManager.DONT_KILL_APP)); } private void resetExceptionHandler() { mPluginExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); // Set back the real exception handler so the test can crash if it wants to. Loading