Do not show static overlays as a theme

Static overlays aren't changeable by a user. So we shouldn't list them
as a theme.

This CL fixed b/36812704 as well to run unit tests.

Test: building succeeded and tested on sailfish.
      make RunSettingsRoboTests
      adb shell am instrument -w -e class \
          com.android.settings.display.ThemePreferenceControllerTest \
          com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
Bug: 37480890
Bug: 36812704

Change-Id: I8c13b6956083095dceaab3da6642bef1647d6a30
diff --git a/src/com/android/settings/display/ThemePreferenceController.java b/src/com/android/settings/display/ThemePreferenceController.java
index a8d47d6..b535993 100644
--- a/src/com/android/settings/display/ThemePreferenceController.java
+++ b/src/com/android/settings/display/ThemePreferenceController.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.content.om.IOverlayManager;
 import android.content.om.OverlayInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.RemoteException;
@@ -35,6 +36,7 @@
 
 import libcore.util.Objects;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class ThemePreferenceController extends PreferenceController implements
@@ -109,12 +111,22 @@
         return true;
     }
 
+    private boolean isChangeableOverlay(String packageName) {
+        try {
+            PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+            return pi != null && !pi.isStaticOverlay;
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
     private String getTheme() {
         try {
             List<OverlayInfo> infos = mOverlayService.getOverlayInfosForTarget("android",
                     UserHandle.myUserId());
             for (int i = 0, size = infos.size(); i < size; i++) {
-                if (infos.get(i).isEnabled()) {
+                if (infos.get(i).isEnabled() &&
+                         isChangeableOverlay(infos.get(i).packageName)) {
                     return infos.get(i).packageName;
                 }
             }
@@ -141,11 +153,13 @@
         try {
             List<OverlayInfo> infos = mOverlayService.getOverlayInfosForTarget("android",
                     UserHandle.myUserId());
-            String[] pkgs = new String[infos.size()];
+            List<String> pkgs = new ArrayList(infos.size());
             for (int i = 0, size = infos.size(); i < size; i++) {
-                pkgs[i] = infos.get(i).packageName;
+                if (isChangeableOverlay(infos.get(i).packageName)) {
+                    pkgs.add(infos.get(i).packageName);
+                }
             }
-            return pkgs;
+            return pkgs.toArray(new String[pkgs.size()]);
         } catch (RemoteException e) {
         }
         return new String[0];
diff --git a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
index 3137d59..69c8c54 100644
--- a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
@@ -16,11 +16,10 @@
 
 package com.android.settings.display;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -29,6 +28,7 @@
 import android.content.ContextWrapper;
 import android.content.om.OverlayInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
@@ -58,7 +58,7 @@
     public void setup() {
         mMockOverlayManager = mock(OverlayManager.class);
         mMockPackageManager = mock(PackageManager.class);
-        mContext = new ContextWrapper(InstrumentationRegistry.getContext()) {
+        mContext = new ContextWrapper(InstrumentationRegistry.getTargetContext()) {
             @Override
             public PackageManager getPackageManager() {
                 return mMockPackageManager;
@@ -82,6 +82,8 @@
             }
             return info;
         });
+        when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
+                new PackageInfo());
         when(mMockOverlayManager.getOverlayInfosForTarget(any(), anyInt())).thenReturn(
                 list(info1, info2));
         ListPreference pref = mock(ListPreference.class);
@@ -91,31 +93,71 @@
 
 
         CharSequence[] entries = arg.getValue();
-        assertEquals(2, entries.length);
-        assertEquals("Theme1", entries[0]);
-        assertEquals("Theme2", entries[1]);
+        assertThat(entries).asList().containsExactly("Theme1", "Theme2");
 
         verify(pref).setEntryValues(arg.capture());
         CharSequence[] entryValues = arg.getValue();
-        assertEquals("com.android.Theme1", entryValues[0]);
-        assertEquals("com.android.Theme2", entryValues[1]);
+        assertThat(entryValues).asList().containsExactly(
+                "com.android.Theme1", "com.android.Theme2");
 
         verify(pref).setValue(eq("com.android.Theme1"));
     }
 
     @Test
+    public void testUpdateState_withStaticOverlay() throws Exception {
+        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android",
+                "", OverlayInfo.STATE_ENABLED, 0);
+        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android",
+                "", OverlayInfo.STATE_ENABLED, 0);
+        when(mMockPackageManager.getApplicationInfo(any(), anyInt())).thenAnswer(inv -> {
+            ApplicationInfo info = mock(ApplicationInfo.class);
+            if ("com.android.Theme1".equals(inv.getArguments()[0])) {
+                when(info.loadLabel(any())).thenReturn("Theme1");
+            } else {
+                when(info.loadLabel(any())).thenReturn("Theme2");
+            }
+            return info;
+        });
+        PackageInfo pi = new PackageInfo();
+        pi.isStaticOverlay = true;
+        when(mMockPackageManager.getPackageInfo(eq("com.android.Theme1"), anyInt())).thenReturn(pi);
+        when(mMockPackageManager.getPackageInfo(eq("com.android.Theme2"), anyInt())).thenReturn(
+                new PackageInfo());
+        when(mMockOverlayManager.getOverlayInfosForTarget(any(), anyInt())).thenReturn(
+                list(info1, info2));
+        ListPreference pref = mock(ListPreference.class);
+        mPreferenceController.updateState(pref);
+        ArgumentCaptor<String[]> arg = ArgumentCaptor.forClass(String[].class);
+        verify(pref).setEntries(arg.capture());
+
+
+        CharSequence[] entries = arg.getValue();
+        assertThat(entries).asList().containsExactly("Theme2");
+
+        verify(pref).setEntryValues(arg.capture());
+        CharSequence[] entryValues = arg.getValue();
+        assertThat(entryValues).asList().containsExactly("com.android.Theme2");
+
+        verify(pref).setValue(eq("com.android.Theme2"));
+    }
+
+    @Test
     public void testAvailable_false() throws Exception {
+        when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
+                new PackageInfo());
         when(mMockOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
                 .thenReturn(list(new OverlayInfo("", "", "", 0, 0)));
-        assertFalse(mPreferenceController.isAvailable());
+        assertThat(mPreferenceController.isAvailable()).isFalse();
     }
 
     @Test
     public void testAvailable_true() throws Exception {
+        when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
+                 new PackageInfo());
         when(mMockOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
                 .thenReturn(list(new OverlayInfo("", "", "", 0, 0),
                         new OverlayInfo("", "", "", 0, 0)));
-        assertTrue(mPreferenceController.isAvailable());
+        assertThat(mPreferenceController.isAvailable()).isTrue();
     }
 
     private ArrayList<OverlayInfo> list(OverlayInfo... infos) {