aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael W <baddaemon87@gmail.com>2019-01-06 19:36:00 +0100
committerMichael W <baddaemon87@gmail.com>2019-01-06 19:36:06 +0100
commit034c3c79dc788173929492f98ae36d1c78269c9c (patch)
treec0d8728b28efce880a2193da0bffdb1bcf286fdd
parent915e52eda2602558843fa5355861e79e993c65d9 (diff)
downloadlineage-sdk-034c3c79dc788173929492f98ae36d1c78269c9c.tar.gz
lineage-sdk-034c3c79dc788173929492f98ae36d1c78269c9c.tar.bz2
lineage-sdk-034c3c79dc788173929492f98ae36d1c78269c9c.zip
Revert "Automatic translation import"
This reverts commit 5f06011a755307465238b04a6ce933472a7d9321. Change-Id: I1b951cb63fd0b6628d87243a068ab4c083075f5a
-rw-r--r--lineage/res/res/values-ar/strings.xml49
-rw-r--r--lineage/res/res/values-ast-rES/strings.xml57
-rw-r--r--lineage/res/res/values-cy/strings.xml83
-rw-r--r--lineage/res/res/values-sc-rIT/strings.xml9
-rw-r--r--packages/LineageSettingsProvider/res/values-ar/strings.xml4
-rw-r--r--packages/LineageSettingsProvider/res/values-cy/strings.xml4
-rw-r--r--packages/LineageSettingsProvider/res/values-sc-rIT/strings.xml4
-rw-r--r--packages/LineageSettingsProvider/tests/Android.mk56
-rw-r--r--packages/LineageSettingsProvider/tests/AndroidManifest.xml34
-rw-r--r--packages/LineageSettingsProvider/tests/README.md7
-rw-r--r--packages/LineageSettingsProvider/tests/proguard.flags50
-rw-r--r--packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsGlobalTests.java126
-rw-r--r--packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderDefaultsTest.java272
-rw-r--r--packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderTest.java325
-rw-r--r--packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSecureTests.java126
-rw-r--r--packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSystemTests.java126
-rw-r--r--sdk/src/java/org/lineageos/internal/util/TelephonyExtUtils.java53
-rw-r--r--tests/Android.mk56
-rw-r--r--tests/AndroidManifest.xml86
-rw-r--r--tests/README.md7
-rw-r--r--tests/proguard.flags56
-rw-r--r--tests/res/drawable-hdpi/ic_launcher.pngbin0 -> 3418 bytes
-rw-r--r--tests/res/drawable-hdpi/ic_whatshot_white_24dp.pngbin0 -> 468 bytes
-rw-r--r--tests/res/drawable-mdpi/ic_launcher.pngbin0 -> 2206 bytes
-rw-r--r--tests/res/drawable-mdpi/ic_whatshot_white_24dp.pngbin0 -> 334 bytes
-rw-r--r--tests/res/drawable-xhdpi/ic_launcher.pngbin0 -> 4842 bytes
-rw-r--r--tests/res/drawable-xhdpi/ic_whatshot_white_24dp.pngbin0 -> 595 bytes
-rw-r--r--tests/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 7718 bytes
-rw-r--r--tests/res/drawable-xxhdpi/ic_whatshot_white_24dp.pngbin0 -> 866 bytes
-rw-r--r--tests/res/drawable-xxxhdpi/ic_whatshot_white_24dp.pngbin0 -> 1129 bytes
-rw-r--r--tests/res/layout/main.xml49
-rw-r--r--tests/res/layout/remote_view.xml45
-rw-r--r--tests/res/values/strings.xml6
-rw-r--r--tests/src/org/lineageos/tests/LineageOSTestApplication.java37
-rw-r--r--tests/src/org/lineageos/tests/TestActivity.java63
-rw-r--r--tests/src/org/lineageos/tests/common/MockIBinderStubForInterface.java59
-rw-r--r--tests/src/org/lineageos/tests/common/ThreadServiceTestCase.java200
-rw-r--r--tests/src/org/lineageos/tests/hardware/LineageHardwareTest.java388
-rw-r--r--tests/src/org/lineageos/tests/hardware/unit/DisplayModeTest.java60
-rw-r--r--tests/src/org/lineageos/tests/hardware/unit/LineageHardwareManagerTest.java50
-rw-r--r--tests/src/org/lineageos/tests/hardware/unit/LiveDisplayManagerTest.java152
-rw-r--r--tests/src/org/lineageos/tests/media/unit/LineageAudioManagerTest.java260
-rw-r--r--tests/src/org/lineageos/tests/power/unit/PerfomanceManagerTest.java111
-rw-r--r--tests/src/org/lineageos/tests/profiles/ProfileTest.java185
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/AirplaneModeSettingsTest.java52
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/BrightnessSettingsTest.java49
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/ConnectionSettingsTest.java71
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/LockSettingsTest.java39
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/ProfileManagerTest.java225
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/ProfileTest.java539
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/RingModeSettingsTest.java49
-rw-r--r--tests/src/org/lineageos/tests/profiles/unit/StreamSettingsTest.java58
-rw-r--r--tests/src/org/lineageos/tests/providers/LineageSettingsTest.java177
-rw-r--r--tests/src/org/lineageos/tests/util/ColorUtilTest.java123
-rw-r--r--tests/src/org/lineageos/tests/versioning/VersioningTest.java61
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/BinderTransactionTest.java206
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/BuildTest.java67
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/ClassPathException.java26
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/ClassPathTest.java108
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/MagicalDexHelper.java55
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java131
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/apiv4/ApiV4PriorReleaseInterfaces.java107
-rw-r--r--tests/src/org/lineageos/tests/versioning/unit/apiv5/ApiV5PriorReleaseInterfaces.java113
-rw-r--r--tests/src/org/lineageos/tests/weather/unit/DayForecastBuilderTest.java108
-rw-r--r--tests/src/org/lineageos/tests/weather/unit/LineageWeatherManagerTest.java242
-rw-r--r--tests/src/org/lineageos/tests/weather/unit/MockWeatherProviderService.java54
-rw-r--r--tests/src/org/lineageos/tests/weather/unit/ServiceRequestResultBuilderTest.java96
-rw-r--r--tests/src/org/lineageos/tests/weather/unit/WeatherInfoBuilderTest.java252
-rw-r--r--tests/src/org/lineageos/tests/weather/unit/WeatherLocationBuilderTest.java129
-rw-r--r--tests/src/org/lineageos/tests/weather/unit/WeatherProviderServiceTest.java303
70 files changed, 6450 insertions, 245 deletions
diff --git a/lineage/res/res/values-ar/strings.xml b/lineage/res/res/values-ar/strings.xml
index d4bb25be..180b5c33 100644
--- a/lineage/res/res/values-ar/strings.xml
+++ b/lineage/res/res/values-ar/strings.xml
@@ -18,28 +18,20 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Label for the LineageOS system components when they are shown to the user. -->
- <string name="lineageos_system_label">نظام LineageOS</string>
<!-- Labels for the MODIFY_PROFILES permission. -->
<string name="permlab_modifyProfiles">تعديل الملفات التعريفية للنظام</string>
<string name="permdesc_modifyProfiles">السماح للتطبيق بتعديل الملفات التعريفية للنظام.</string>
<!-- Labels for the HARDWARE_ABSTRACTION_ACCESS permission. -->
<string name="permlab_useHardwareFramework">استخدام إطار عمل الجهاز</string>
- <string name="permdesc_useHardwareFramework">السماح لأي تطبيق بالدخول إلى مكونات أجهزة النظام.</string>
<!-- Labels for the WRITE_SETTINGS permission -->
- <string name="permlab_writeSettings">تعديل اعدادات نظام Lineage</string>
- <string name="permdesc_writeSettings">السماح لأي تطبيق بتعديل إعدادات نظام Lineage.</string>
<!-- Labels for the WRITE_SECURE_SETTINGS permission -->
- <string name="permlab_writeSecureSettings">تعديل تأمين اعدادات نظام Lineage</string>
- <string name="permdesc_writeSecureSettings">للسماح لأي تطبيق بتعديل إعدادات أمان نظام Lineage. لا تستخدم التطبيقات العادية.</string>
<!-- Labels for the PROTECTED_APP permission. -->
<string name="permlab_protectedApp">إضافة وإزالة تطبيقات إلى التطبيقات المحمية</string>
<string name="permdesc_protectedApp">يسمح للتطبيق بوضع علامة على تطبيقات أخرى كمحمية مع قفلها.</string>
<!-- Labels for CHANGE_STYLE permission -->
- <string name="permlab_changeStyle">تغيير شكل النظام</string>
<!-- this is wrong, but google's package manager uses the android:description
attribute as description for the runtime permission request dialog
with non-default dangerous permissions -->
- <string name="permdesc_changeStyle">تخصيص الوان النظام</string>
<!-- Profiles -->
<!-- Names of default profiles. -->
<string name="profileNameDefault">افتراضي</string>
@@ -63,11 +55,6 @@
<string name="perf_profile_bias_power">الكفاءة</string>
<string name="perf_profile_bias_perf">سريع</string>
<!-- Performance profiles -->
- <string name="perf_profile_pwrsv_summary">الحد الأقصى لتوفير الطاقة، يقلل من أداء الجهاز</string>
- <string name="perf_profile_bal_summary">التوازن بين الأداء الأمثل وخصائص الطاقة</string>
- <string name="perf_profile_perf_summary">وضع الأداء العالي. مفيد للتطبيقات التي تتطلب زمن تأخير منخفض وإنتاجية أعلى وذلك عندما يكون استهلاك الطاقة ليس بمصدر قلق</string>
- <string name="perf_profile_bias_power_summary">تفضيل حفظ الطاقة. يحدد الحد الأقصى من الطاقة لوحدة المعالجة المركزية و تحسين التوفير على حساب زمن التأخير العالي</string>
- <string name="perf_profile_bias_perf_summary">تفضيل الأداء. تقليل زمن التأخير وزيادة استهلاك الطاقة بشكل طفيف</string>
<!-- LiveDisplay strings -->
<string name="live_display_auto">تلقائي</string>
<string name="live_display_auto_summary">ضبط درجة الحرارة اللونية للشاشة تلقائياً بعد غروب الشمس وشروق الشمس</string>
@@ -118,54 +105,18 @@
<string name="permlab_observe_audio_sessions">ملاحظة تغييرات جلسة عمل الصوت</string>
<string name="permdesc_observe_audio_sessions">يسمح لتطبيق معين لملاحظة تدفقات الصوت الجاري إنشاؤها وتدميرها.</string>
<!-- Privacy Guard -->
- <string name="privacy_guard_manager_title">حارس الخصوصية</string>
<!-- Permissions used by remote preferences -->
- <string name="permlab_manageRemotePrefs">إعدادات التحكم عن بعد</string>
- <string name="permdesc_manageRemotePrefs">السماح للتطبيق بإدارة الإعدادات عن بعد</string>
<!-- About device screen, build date -->
- <string name="build_date">تاريخ الإنشاء</string>
<!-- About device screen, LineageOS API Level -->
- <string name="lineage_api_level">مستوى LineageOS API</string>
<!-- About device screen, LineageOS updates -->
- <string name="lineage_updates">تحديثات LineageOS</string>
<!-- About device screen, LineageOS version -->
- <string name="lineage_version">إصدار LineageOS</string>
<!-- About device screen, vendor security patch -->
- <string name="lineage_vendor_security_patch">‏مستوى رمز تصحيح أمان المورد</string>
<!-- General purpose use "unknown" string -->
- <string name="unknown">غير معروف</string>
<!-- Long-press back kill application -->
- <string name="app_killed_message">تم إنهاء التطبيق</string>
<!-- Status bar network traffic monitor strings -->
- <string name="kilobitspersecond_short">kb/s</string>
- <string name="megabitspersecond_short">Mb/s</string>
- <string name="kilobytespersecond_short">kB/s</string>
- <string name="megabytespersecond_short">MB/s</string>
<!-- Accent colors -->
- <string name="accent_black">الكربون</string>
- <string name="accent_blue">توت ازرق</string>
- <string name="accent_brown">الكاكاو</string>
- <string name="accent_cyan">سماوي</string>
- <string name="accent_green">الغابة</string>
- <string name="accent_orange">يقطين</string>
- <string name="accent_pink">كرز</string>
- <string name="accent_purple">خزامي</string>
- <string name="accent_red">طماطم</string>
- <string name="accent_yellow">الموز</string>
<!-- Trust interface -->
<!-- This string will be referenced from other apps when they're referring to the Trust interface.
Trust is a feature name, it's not suggested to translate this unless there are conflicts due
to a different meaning of the word "trust" in your language -->
- <string name="trust_feature_name">الائتمان</string>
- <string name="permlab_trustInterface">الوصول إلى واجهة الائتمان</string>
- <string name="permdesc_trustInterface">السماح لأحد التطبيقات بعرض تحذيرات واقتراحات الائتمان</string>
- <string name="trust_notification_channel">تحذيرات الائتمان</string>
- <string name="trust_notification_title_security">ائتمان حماية النظام</string>
- <string name="trust_notification_content_selinux">SELinux ليس فرض، تم إضعاف الأمان الخاص بك</string>
- <string name="trust_notification_title_root">ائتمان الوصول الى الروت</string>
- <string name="trust_notification_content_root">يستخدم أحد التطبيقات امتيازات الجذر في الوقت الحالي</string>
- <string name="trust_notification_content_keys">تم توقيع هذا الإصدار باستخدام مفاتيح عامة</string>
- <string name="trust_notification_title_onboarding">اكتشف الائتمان</string>
- <string name="trust_notification_content_onboarding">تعرف على كيفية التأكد من سلامة جهازك</string>
- <string name="trust_notification_action_manage">إدارة التنبيهات</string>
</resources>
diff --git a/lineage/res/res/values-ast-rES/strings.xml b/lineage/res/res/values-ast-rES/strings.xml
index 9fce7cfc..924d0325 100644
--- a/lineage/res/res/values-ast-rES/strings.xml
+++ b/lineage/res/res/values-ast-rES/strings.xml
@@ -18,34 +18,24 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Label for the LineageOS system components when they are shown to the user. -->
- <string name="lineageos_system_label">Sistema LineageOS</string>
<!-- Labels for the MODIFY_PROFILES permission. -->
<string name="permlab_modifyProfiles">modificar perfiles del sistema</string>
<string name="permdesc_modifyProfiles">Permite qu\'una aplicación modifique los perfiles del sistema.</string>
<!-- Labels for the HARDWARE_ABSTRACTION_ACCESS permission. -->
<string name="permlab_useHardwareFramework">usar framework de hardware</string>
- <string name="permdesc_useHardwareFramework">Permite qu\'una aplicación acceda al framework de hardware de LineageOS.</string>
<!-- Labels for the WRITE_SETTINGS permission -->
- <string name="permlab_writeSettings">modificar la configuración del sistema de Lineage</string>
- <string name="permdesc_writeSettings">Permite qu\'una aplicación modifique los axustes del sistema de Lineage.</string>
<!-- Labels for the WRITE_SECURE_SETTINGS permission -->
- <string name="permlab_writeSecureSettings">modificar la configuración segura del sistema de Lineage</string>
- <string name="permdesc_writeSecureSettings">Permite qu\'una aplicación modifique la configuración segura del sistema de Lineage. Nun s\'usa pa les aplicaciones normales.</string>
<!-- Labels for the PROTECTED_APP permission. -->
- <string name="permlab_protectedApp">amestar y desaniciar aplicaciones p\'aplicaciones protexíes</string>
<string name="permdesc_protectedApp">Permite qu\'una aplicación conseñe a otres como protexíes y blóquiales.</string>
<!-- Labels for CHANGE_STYLE permission -->
- <string name="permlab_changeStyle">camudar l\'estilu del sistema</string>
<!-- this is wrong, but google's package manager uses the android:description
attribute as description for the runtime permission request dialog
with non-default dangerous permissions -->
- <string name="permdesc_changeStyle">personalizar los colores del sistema</string>
<!-- Profiles -->
<!-- Names of default profiles. -->
<string name="profileNameDefault">Por defeutu</string>
<string name="profileNameWork">Trabayu</string>
<string name="profileNameHome">Home</string>
- <string name="profileNameSilent">Silenciu</string>
<string name="profileNameNight">Nueche</string>
<string name="profileNameAutomobile">Automóvil</string>
<!-- Names of application groups. -->
@@ -55,13 +45,11 @@
<string name="profileGroupEmail">Corréu</string>
<string name="profileGroupSMS">SMS</string>
<!-- Name of wildcard profile. -->
- <string name="wildcardProfile">Otru</string>
<!-- Performance profiles -->
<string name="perf_profile_pwrsv">Aforru d\'enerxía</string>
<string name="perf_profile_bal">Balanceáu</string>
<string name="perf_profile_perf">Rindimientu</string>
<string name="perf_profile_bias_power">Eficiencia</string>
- <string name="perf_profile_bias_perf">Rápidu</string>
<!-- Performance profiles -->
<string name="perf_profile_pwrsv_summary">Aforros máximos d\'enerxía, amenorga\'l rindimientu del preséu</string>
<string name="perf_profile_bal_summary">Equilibriu de rindimientu óptimu y carauterístiques d\'enerxía</string>
@@ -69,7 +57,6 @@
<string name="perf_profile_bias_power_summary">Favorez los aforros d\'enerxía. Llenda la potencia máximo de la CPU y optimízala pa un aforru d\'enerxía empara d\'una llatencia mayor</string>
<string name="perf_profile_bias_perf_summary">Favorez el rindimientu. Amenorga la llatencia con un consumu d\'enerxía llixeramente aumentáu</string>
<!-- LiveDisplay strings -->
- <string name="live_display_auto">Automáticu</string>
<string name="live_display_auto_summary">Axusta automáticamente la temperatura de color de la pantalla dempués del tapecer y l\'aséu</string>
<string name="live_display_off">Non</string>
<string name="live_display_off_summary">Deshabilita tolos axustes</string>
@@ -77,15 +64,12 @@
<string name="live_display_day_summary">Usa namái los axustes de día</string>
<string name="live_display_night">Nueche</string>
<string name="live_display_night_summary">Usa namái los axustes de nueche</string>
- <string name="live_display_outdoor">Esterior (lluz solar)</string>
<string name="live_display_outdoor_summary">Usa namái los axustes d\'esteriores</string>
<string name="live_display_hint">LiveDisplay pue ayudar a amenorgar el cansanciu de güeyos y ayudate a dormir pela nueche. ¡Primi equí pa probalu!</string>
- <string name="accessibility_quick_settings_live_display_off">LiveDisplay desactiváu.</string>
<string name="accessibility_quick_settings_live_display_auto">LiveDisplay: mou auto.</string>
<string name="accessibility_quick_settings_live_display_day">LiveDisplay: mou diurnu.</string>
<string name="accessibility_quick_settings_live_display_night">LiveDisplay: mou nocherniegu.</string>
<string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: mou esterior.</string>
- <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay desactiváu.</string>
<string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay camudó al mou auto.</string>
<string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay camudó al mou diurnu.</string>
<string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay camudó al mou nocherniegu.</string>
@@ -95,14 +79,6 @@
<!-- Performance manager permission description -->
<string name="permdesc_perfAccessDesc">Permite qu\'una aplicación acceda al serviciu de rindimientu. Enxamás debería precisase p\'aplicaciones normales.</string>
<!-- Weather Service strings -->
- <string name="permlab_weather_read">lleer la metereoloxía</string>
- <string name="permdesc_weather_read">Permite qu\'una aplicación llea\'l conteníu del fornidor meteorolóxicu.</string>
- <string name="permlab_weather_write">anovar el fornidor meteorolóxicu</string>
- <string name="permdesc_weather_write">Permite qu\'una aplicación anueve\'l conteníu del fornidor meteorolóxicu.</string>
- <string name="permlab_weather_bind">arreyar como serviciu fornidor de metereoloxía</string>
- <string name="permdesc_weather_bind">Permite qu\'una aplicación s\'identifique como un serviciu fornidor de meteoroloxía.</string>
- <string name="permlab_weather_access_mgr">acceder al serviciu de metereoloxía</string>
- <string name="permdesc_weather_access_mgr">Permite qu\'una aplicación acceda al serviciu meteorolóxicu nel sistema. Enxamás debería precisase p\'aplicaciones normales.</string>
<!-- DataUsageProvider write permission title -->
<string name="permlab_dataUsageWrite">modificar base de datos d\'usu de datos</string>
<!-- DataUsageProvider write permission description -->
@@ -123,49 +99,16 @@
<string name="permlab_manageRemotePrefs">xestionar axustes remotos</string>
<string name="permdesc_manageRemotePrefs">Permite qu\'una aplicación xestione axustes remotos</string>
<!-- About device screen, build date -->
- <string name="build_date">Data de la compilación</string>
<!-- About device screen, LineageOS API Level -->
- <string name="lineage_api_level">Nivel de l\'API de LineageOS</string>
<!-- About device screen, LineageOS updates -->
- <string name="lineage_updates">Anovamientos de LineageOS</string>
<!-- About device screen, LineageOS version -->
- <string name="lineage_version">Versión de LineageOS</string>
<!-- About device screen, vendor security patch -->
- <string name="lineage_vendor_security_patch">Nivel de parche de seguridá del fornidor</string>
<!-- General purpose use "unknown" string -->
- <string name="unknown">Desconozse</string>
<!-- Long-press back kill application -->
- <string name="app_killed_message">Aplicación matada</string>
<!-- Status bar network traffic monitor strings -->
- <string name="kilobitspersecond_short">kb/s</string>
- <string name="megabitspersecond_short">Mb/s</string>
- <string name="kilobytespersecond_short">kB/s</string>
- <string name="megabytespersecond_short">MB/s</string>
<!-- Accent colors -->
- <string name="accent_black">Carbón</string>
- <string name="accent_blue">Arándanu</string>
- <string name="accent_brown">Cacáu</string>
- <string name="accent_cyan">Cianu</string>
- <string name="accent_green">Viesca</string>
- <string name="accent_orange">Calabaza</string>
- <string name="accent_pink">Zreza</string>
- <string name="accent_purple">Llavanda</string>
- <string name="accent_red">Tomate</string>
- <string name="accent_yellow">Plátanu</string>
<!-- Trust interface -->
<!-- This string will be referenced from other apps when they're referring to the Trust interface.
Trust is a feature name, it's not suggested to translate this unless there are conflicts due
to a different meaning of the word "trust" in your language -->
- <string name="trust_feature_name">Trust</string>
- <string name="permlab_trustInterface">acceder a interface Trust</string>
- <string name="permdesc_trustInterface">Permite qu\'una aplicación amuese avisos y suxerencies Trust</string>
- <string name="trust_notification_channel">Alertes Trust</string>
- <string name="trust_notification_title_security">Trust \u2022 Seguridá del sistema</string>
- <string name="trust_notification_content_selinux">SELinux nun se ta aplicando, la seguranza ye reducida</string>
- <string name="trust_notification_title_root">Trust \u2022 Accesu root</string>
- <string name="trust_notification_content_root">Una aplicación ta usando los privilexos root nesti momentu</string>
- <string name="trust_notification_content_keys">Esta compilación asignóse con claves públiques</string>
- <string name="trust_notification_title_onboarding">Descubri Trust</string>
- <string name="trust_notification_content_onboarding">Conoz como caltener seguru el dispositivu</string>
- <string name="trust_notification_action_manage">Xestionar alertes</string>
</resources>
diff --git a/lineage/res/res/values-cy/strings.xml b/lineage/res/res/values-cy/strings.xml
index 2bf2cd4b..86c07d1b 100644
--- a/lineage/res/res/values-cy/strings.xml
+++ b/lineage/res/res/values-cy/strings.xml
@@ -18,50 +18,22 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Label for the LineageOS system components when they are shown to the user. -->
- <string name="lineageos_system_label">System LineageOS</string>
<!-- Labels for the MODIFY_PROFILES permission. -->
- <string name="permlab_modifyProfiles">addasu proffiliau system</string>
- <string name="permdesc_modifyProfiles">Mae\'n caniatáu i ap addasu proffiliau system.</string>
<!-- Labels for the HARDWARE_ABSTRACTION_ACCESS permission. -->
<string name="permlab_useHardwareFramework">defnyddio fframwaith caledwedd</string>
- <string name="permdesc_useHardwareFramework">Mae\'n caniatáu i ap gyrchu fframwaith caledwedd Lineage.</string>
<!-- Labels for the WRITE_SETTINGS permission -->
- <string name="permlab_writeSettings">addasu gosodiadau system Lineage</string>
- <string name="permdesc_writeSettings">Mae\'n caniatáu i ap addasu gosodiadau system LineageOS.</string>
<!-- Labels for the WRITE_SECURE_SETTINGS permission -->
- <string name="permlab_writeSecureSettings">addasu gosodiadau system ddiogel Lineage</string>
- <string name="permdesc_writeSecureSettings">Mae\'n caniatáu i ap addasu gosodiadau system ddiogel LineageOS. Dim i\'w ddefnyddio gan apiau arferol.</string>
<!-- Labels for the PROTECTED_APP permission. -->
- <string name="permlab_protectedApp">ychwanegu a thynnu apiau i warchod apiau</string>
- <string name="permdesc_protectedApp">Mae\'n caniatáu i ap nodi apiau eraill fel wedi eu diogelu ac i\'w cloi nhw.</string>
<!-- Labels for CHANGE_STYLE permission -->
- <string name="permlab_changeStyle">newid arddull system</string>
<!-- this is wrong, but google's package manager uses the android:description
attribute as description for the runtime permission request dialog
with non-default dangerous permissions -->
- <string name="permdesc_changeStyle">addasu lliwiau\'r system</string>
<!-- Profiles -->
<!-- Names of default profiles. -->
- <string name="profileNameDefault">Rhagosodiad</string>
<string name="profileNameWork">Gwaith</string>
- <string name="profileNameHome">Cartref</string>
- <string name="profileNameSilent">Distaw</string>
- <string name="profileNameNight">Nos</string>
- <string name="profileNameAutomobile">Cerbyd</string>
<!-- Names of application groups. -->
- <string name="profileGroupPhone">Ffôn</string>
- <string name="profileGroupCalendar">Calendr</string>
- <string name="profileGroupGmail">Gmail</string>
- <string name="profileGroupEmail">Ebost</string>
- <string name="profileGroupSMS">SMS</string>
<!-- Name of wildcard profile. -->
- <string name="wildcardProfile">Arall</string>
<!-- Performance profiles -->
- <string name="perf_profile_pwrsv">Arbed pŵer</string>
- <string name="perf_profile_bal">Cytbwys</string>
- <string name="perf_profile_perf">Perfformiad</string>
- <string name="perf_profile_bias_power">Effeithlonrwydd</string>
- <string name="perf_profile_bias_perf">Cyflym</string>
<!-- Performance profiles -->
<string name="perf_profile_pwrsv_summary">Arbedion pŵer gorau, gan leihau perfformiad y ddyfais.</string>
<string name="perf_profile_bal_summary">Cydbwysedd o berfformiad optimaidd a nodweddion pŵer.</string>
@@ -69,54 +41,19 @@
<string name="perf_profile_bias_power_summary">Ffafrio arbedion pŵer. Mae hyn yn cyfyngu pŵer y prosesydd ac yn ei optimeiddio ar gyfer arbed defnydd pŵer ar draul cuddni uwch.</string>
<string name="perf_profile_bias_perf_summary">Ffafrio perfformiad da. Mae\'n lleihau cuddni gyda defnydd pŵer uwch.</string>
<!-- LiveDisplay strings -->
- <string name="live_display_auto">Awtomatig</string>
- <string name="live_display_auto_summary">Addasu tymheredd lliw\'r sgrin yn awtomatig ar ôl machlud a gwawr</string>
- <string name="live_display_off">I ffwrdd</string>
- <string name="live_display_off_summary">Analluogi pob addasiad</string>
- <string name="live_display_day">Dydd</string>
<string name="live_display_day_summary">Defnyddio gosodiadau dydd yn unig</string>
- <string name="live_display_night">Nos</string>
<string name="live_display_night_summary">Defnyddio gosodiadau nos yn unig</string>
- <string name="live_display_outdoor">Awyr agored (heulwen)</string>
<string name="live_display_outdoor_summary">Defnyddio gosodiadau awyr agored yn unig</string>
- <string name="live_display_hint">Gall LiveDisplay helpu lleihau straen ar y llygaid a dy helpu i gysgu gyda\'r nos. Clicia yma i roi cynnig arno!</string>
- <string name="accessibility_quick_settings_live_display_off">LiveDisplay i ffwrdd.</string>
- <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modd awtomatig.</string>
- <string name="accessibility_quick_settings_live_display_day">LiveDisplay: modd dydd.</string>
- <string name="accessibility_quick_settings_live_display_night">LiveDisplay: modd nos.</string>
- <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: modd awyr agored.</string>
- <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay wedi\'i droi i ffwrdd.</string>
- <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay wedi\'i newid i fodd awtomatig.</string>
- <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay wedi\'i newid i fodd dydd.</string>
- <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay wedi\'i newid i fodd nos.</string>
- <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay wedi\'i newid i fodd awyr agored.</string>
<!-- Performance manager permission title -->
- <string name="permlab_perfAccess">mynediad at reolwr perfformiad</string>
<!-- Performance manager permission description -->
- <string name="permdesc_perfAccessDesc">Mae\'n caniatáu i ap gyrchu\'r gwasanaeth perfformiad. Ni ddylai apiau arferol byth fod ei angen.</string>
<!-- Weather Service strings -->
- <string name="permlab_weather_read">darllen y tywydd</string>
- <string name="permdesc_weather_read">Mae\'n caniatáu i ap ddarllen cynnwys gan y darparydd tywydd.</string>
<string name="permlab_weather_write">diweddaru darparwr tywydd</string>
- <string name="permdesc_weather_write">Mae\'n caniatáu i ap ddiweddaru cynnwys y darparydd tywydd.</string>
- <string name="permlab_weather_bind">clymu fel gwasanaeth darparu tywydd</string>
- <string name="permdesc_weather_bind">Mae\'n galluogi ap i gael ei adnabod fel gwasanaeth darparu tywydd.</string>
- <string name="permlab_weather_access_mgr">mynediad at wasanaeth tywydd</string>
- <string name="permdesc_weather_access_mgr">Mae\'n caniatáu i ap gyrchu\'r gwasanaeth tywydd yn y system. Ni ddylai apiau arferol byth fod ei angen.</string>
<!-- DataUsageProvider write permission title -->
- <string name="permlab_dataUsageWrite">addasu\'r gronfa ddata defnydd data</string>
<!-- DataUsageProvider write permission description -->
- <string name="permdesc_dataUsageWrite">Mae\'n caniatáu i ap ddiweddaru cynnwys y gronfa ddata defnydd data.</string>
<!-- DataUsageProvider read permission title -->
- <string name="permlab_dataUsageRead">darllen cronfa ddata defnydd data</string>
<!-- DataUsageProvider read permission description -->
- <string name="permdesc_dataUsageRead">Mae\'n caniatáu i ap ddarllen cynnwys y gronfa ddata defnydd data.</string>
<!-- LiveDisplay manager permission -->
- <string name="permlab_manageLiveDisplay">rheoli gosodiadau LiveDisplay</string>
- <string name="permdesc_manageLiveDisplay">Mae\'n caniatáu i ap ffurfweddu gosodiadau dangosydd uwch.</string>
<!-- LineageAudioService - observe session changes permission -->
- <string name="permlab_observe_audio_sessions">gwylio newidiadau sesiynau sain</string>
- <string name="permdesc_observe_audio_sessions">Mae\'n caniatáu i ap wylio ffrydiau sain yn cael eu creu a\'u dinistrio.</string>
<!-- Privacy Guard -->
<string name="privacy_guard_manager_title">Gwarchodydd Preifatrwydd</string>
<!-- Permissions used by remote preferences -->
@@ -125,37 +62,17 @@
<!-- About device screen, build date -->
<string name="build_date">Dyddiad adeiledd</string>
<!-- About device screen, LineageOS API Level -->
- <string name="lineage_api_level">Lefel API LineageOS</string>
<!-- About device screen, LineageOS updates -->
- <string name="lineage_updates">Diweddariadau LineageOS</string>
<!-- About device screen, LineageOS version -->
- <string name="lineage_version">Fersiwn LineageOS</string>
<!-- About device screen, vendor security patch -->
- <string name="lineage_vendor_security_patch">Lefel patsh diogelwch gwneuthurwr</string>
<!-- General purpose use "unknown" string -->
<string name="unknown">Anhysybys</string>
<!-- Long-press back kill application -->
- <string name="app_killed_message">Lladdwyd yr ap</string>
<!-- Status bar network traffic monitor strings -->
- <string name="kilobitspersecond_short">kb/e</string>
- <string name="megabitspersecond_short">Mb/e</string>
- <string name="kilobytespersecond_short">kB/e</string>
- <string name="megabytespersecond_short">MB/e</string>
<!-- Accent colors -->
- <string name="accent_black">Carbon</string>
- <string name="accent_blue">Llusen</string>
- <string name="accent_brown">Coco</string>
- <string name="accent_cyan">Gwyrddlas</string>
- <string name="accent_green">Pys</string>
- <string name="accent_orange">Moron</string>
- <string name="accent_pink">Mafon</string>
- <string name="accent_purple">Betys</string>
<string name="accent_red">Tomato</string>
- <string name="accent_yellow">Cennin Pedr</string>
<!-- Trust interface -->
<!-- This string will be referenced from other apps when they're referring to the Trust interface.
Trust is a feature name, it's not suggested to translate this unless there are conflicts due
to a different meaning of the word "trust" in your language -->
- <string name="permdesc_trustInterface">Mae\'n caniatáu i ap ddangos rhybuddion ac awgrymiadau Trust.</string>
- <string name="trust_notification_content_selinux">Dyw SELinux ddim yn gorfodi. Mae dy ddiogelwch wedi\'i wanhau.</string>
</resources>
diff --git a/lineage/res/res/values-sc-rIT/strings.xml b/lineage/res/res/values-sc-rIT/strings.xml
index d6e69035..9f84b86b 100644
--- a/lineage/res/res/values-sc-rIT/strings.xml
+++ b/lineage/res/res/values-sc-rIT/strings.xml
@@ -18,14 +18,9 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Label for the LineageOS system components when they are shown to the user. -->
- <string name="lineageos_system_label">Sistema LineageOS</string>
<!-- Labels for the MODIFY_PROFILES permission. -->
- <string name="permlab_modifyProfiles">modìfica sos profilos de sistema</string>
- <string name="permdesc_modifyProfiles">Permitit a un\'aplicatzione de modificare sos profilos de sistema.</string>
<!-- Labels for the HARDWARE_ABSTRACTION_ACCESS permission. -->
<!-- Labels for the WRITE_SETTINGS permission -->
- <string name="permlab_writeSettings">modìfica sas impostatziones de sistema de Lineage</string>
- <string name="permdesc_writeSettings">Permitit a un\'aplicatzione de modificare sas impostatziones de sistema de Lineage.</string>
<!-- Labels for the WRITE_SECURE_SETTINGS permission -->
<!-- Labels for the PROTECTED_APP permission. -->
<!-- Labels for CHANGE_STYLE permission -->
@@ -43,8 +38,6 @@
<!-- Names of application groups. -->
<string name="profileGroupPhone">Telèfonu</string>
<string name="profileGroupCalendar">Calendàriu</string>
- <string name="profileGroupGmail">Gmail</string>
- <string name="profileGroupSMS">SMS</string>
<!-- Name of wildcard profile. -->
<string name="wildcardProfile">Àteru</string>
<!-- Performance profiles -->
@@ -83,7 +76,6 @@
<!-- Permissions used by remote preferences -->
<!-- About device screen, build date -->
<!-- About device screen, LineageOS API Level -->
- <string name="lineage_api_level">Livellu de s\'API de LineageOS</string>
<!-- About device screen, LineageOS updates -->
<!-- About device screen, LineageOS version -->
<!-- About device screen, vendor security patch -->
@@ -93,7 +85,6 @@
<!-- Status bar network traffic monitor strings -->
<!-- Accent colors -->
<string name="accent_cyan">Asulu</string>
- <string name="accent_yellow">Banana</string>
<!-- Trust interface -->
<!-- This string will be referenced from other apps when they're referring to the Trust interface.
Trust is a feature name, it's not suggested to translate this unless there are conflicts due
diff --git a/packages/LineageSettingsProvider/res/values-ar/strings.xml b/packages/LineageSettingsProvider/res/values-ar/strings.xml
index 233a8314..0647eaf6 100644
--- a/packages/LineageSettingsProvider/res/values-ar/strings.xml
+++ b/packages/LineageSettingsProvider/res/values-ar/strings.xml
@@ -15,6 +15,4 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <string name="app_name">اعدادت تخزين Lineage</string>
-</resources>
+<resources></resources>
diff --git a/packages/LineageSettingsProvider/res/values-cy/strings.xml b/packages/LineageSettingsProvider/res/values-cy/strings.xml
index ef925ae2..0647eaf6 100644
--- a/packages/LineageSettingsProvider/res/values-cy/strings.xml
+++ b/packages/LineageSettingsProvider/res/values-cy/strings.xml
@@ -15,6 +15,4 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <string name="app_name">Storfa Gosodiadau Lineage</string>
-</resources>
+<resources></resources>
diff --git a/packages/LineageSettingsProvider/res/values-sc-rIT/strings.xml b/packages/LineageSettingsProvider/res/values-sc-rIT/strings.xml
index 4b7acd94..0647eaf6 100644
--- a/packages/LineageSettingsProvider/res/values-sc-rIT/strings.xml
+++ b/packages/LineageSettingsProvider/res/values-sc-rIT/strings.xml
@@ -15,6 +15,4 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <string name="app_name">Archìviu de impostatziones de Lineage</string>
-</resources>
+<resources></resources>
diff --git a/packages/LineageSettingsProvider/tests/Android.mk b/packages/LineageSettingsProvider/tests/Android.mk
new file mode 100644
index 00000000..31c3aa38
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/Android.mk
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2015 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_PACKAGE_NAME := LineageSettingsProviderTests
+LOCAL_INSTRUMENTATION_FOR := LineageSettingsProvider
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PROGUARD_ENABLED := optimization shrinktests
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ org.lineageos.platform.internal
+
+include $(BUILD_PACKAGE)
+
+# Register as LineageTS
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_PACKAGE_NAME := CmtsLineageSettingsProviderTests
+LOCAL_INSTRUMENTATION_FOR := LineageSettingsProvider
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PROGUARD_ENABLED := optimization shrinktests
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ org.lineageos.platform.internal
+
+include $(BUILD_LineageTS_PACKAGE)
+
diff --git a/packages/LineageSettingsProvider/tests/AndroidManifest.xml b/packages/LineageSettingsProvider/tests/AndroidManifest.xml
new file mode 100644
index 00000000..ec333a69
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.lineageos.lineagesettings.tests">
+
+ <uses-permission android:name="lineageos.permission.WRITE_SETTINGS"/>
+ <uses-permission android:name="lineageos.permission.WRITE_SECURE_SETTINGS"/>
+ <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="org.lineageos.lineagesettings.tests"
+ android:label="Lineage Settings Provider Tests" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+</manifest>
diff --git a/packages/LineageSettingsProvider/tests/README.md b/packages/LineageSettingsProvider/tests/README.md
new file mode 100644
index 00000000..5b91285e
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/README.md
@@ -0,0 +1,7 @@
+## Lineage Settings Provider Tests
+The tests package contains coverage for the Lineage Settings provider as well as
+its public interfaces.
+
+To run the tests (on a live device):
+
+ ```adb shell am instrument -w org.lineageos.lineagesettings.tests/android.test.InstrumentationTestRunner```
diff --git a/packages/LineageSettingsProvider/tests/proguard.flags b/packages/LineageSettingsProvider/tests/proguard.flags
new file mode 100644
index 00000000..d9e855cb
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/proguard.flags
@@ -0,0 +1,50 @@
+# Copyright (C) 2016 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Don't skip non public library classes, make sure we're not keeping anything which will get mapped against api verification.
+-dontskipnonpubliclibraryclasses
+
+# Do the same with class members
+-dontskipnonpubliclibraryclassmembers
+
+# Keep test packages
+-keep class android.support.** { *; }
+-keep class android.test.** { *; }
+-keep public class * extends android.support.** { *; }
+-keep public class * extends android.test.** { *; }
+-keep interface android.support.** { *; }
+-keep interface android.test.** { *; }
+
+# Keep all junit classes
+-keep class junit.** { *; }
+-keep class org.junit.** { *; }
+-keep interface junit.** { *; }
+-keep interface org.junit.** { *; }
+
+# Keep compiled java classes from declared aidl's within the test package
+-keep public class * extends android.os.IInterface { *; }
+
+# Don't warn about the Android Support Test JUnit Runner
+-dontwarn android.support.**
+-dontwarn android.test.**
+
+# Don't warn about junit
+-dontwarn junit.**
+-dontwarn org.junit.**
+
+# Always process
+-forceprocessing
+
+# Make sure not to obfuscate the output
+-dontobfuscate
diff --git a/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsGlobalTests.java b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsGlobalTests.java
new file mode 100644
index 00000000..619580bb
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsGlobalTests.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.lineagesettings.tests;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.providers.LineageSettings;
+
+public class LineageSettingsGlobalTests extends AndroidTestCase {
+ private ContentResolver mContentResolver;
+
+ private static final String UNREALISTIC_SETTING = "_______UNREAL_______";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContentResolver = mContext.getContentResolver();
+ }
+
+ @SmallTest
+ public void testFloat() {
+ final float expectedFloatValue = 1.0f;
+ LineageSettings.Global.putFloat(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER, expectedFloatValue);
+
+ try {
+ float actualValue = LineageSettings.Global.getFloat(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedFloatValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testFloatWithDefault() {
+ final float expectedDefaultFloatValue = 1.5f;
+ float actualValue = LineageSettings.Global.getFloat(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultFloatValue);
+ assertEquals(expectedDefaultFloatValue, actualValue);
+ }
+
+ @SmallTest
+ public void testInt() {
+ final int expectedIntValue = 2;
+ LineageSettings.Global.putInt(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER, expectedIntValue);
+
+ try {
+ int actualValue = LineageSettings.Global.getInt(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedIntValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testIntWithDefault() {
+ final int expectedDefaultIntValue = 11;
+ int actualValue = LineageSettings.Global.getInt(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultIntValue);
+ assertEquals(expectedDefaultIntValue, actualValue);
+ }
+
+ @SmallTest
+ public void testLong() {
+ final long expectedLongValue = 3l;
+ LineageSettings.Global.putLong(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER, expectedLongValue);
+
+ try {
+ long actualValue = LineageSettings.Global.getLong(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedLongValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testLongWithDefault() {
+ final long expectedDefaultLongValue = 17l;
+ long actualValue = LineageSettings.Global.getLong(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultLongValue);
+ assertEquals(expectedDefaultLongValue, actualValue);
+ }
+
+ @SmallTest
+ public void testString() {
+ final String expectedStringValue = "4";
+ LineageSettings.Global.putString(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER, expectedStringValue);
+
+ String actualValue = LineageSettings.Global.getString(mContentResolver,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedStringValue, actualValue);
+ }
+
+ @SmallTest
+ public void testGetUri() {
+ final Uri expectedUri = Uri.withAppendedPath(LineageSettings.Global.CONTENT_URI,
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER);
+
+ final Uri actualUri = LineageSettings.Global.getUriFor(
+ LineageSettings.Global.__MAGICAL_TEST_PASSING_ENABLER);
+
+ assertEquals(expectedUri, actualUri);
+ }
+}
diff --git a/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderDefaultsTest.java b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderDefaultsTest.java
new file mode 100644
index 00000000..f5c7ba37
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderDefaultsTest.java
@@ -0,0 +1,272 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.lineagesettings.tests;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.TypedValue;
+import lineageos.providers.LineageSettings;
+import org.lineageos.lineagesettings.LineageDatabaseHelper;
+import org.lineageos.lineagesettings.LineageSettingsProvider;
+import org.lineageos.lineagesettings.R;
+
+/**
+ * Created by adnan on 1/25/16.
+ */
+public class LineageSettingsProviderDefaultsTest extends AndroidTestCase {
+ private ContentResolver mContentResolver;
+ private boolean mHasMigratedSettings;
+ private Resources mRemoteResources;
+
+ // These data structures are set up in a way that is easier for manual input of new defaults
+ private static ArrayList<Setting> SYSTEM_SETTINGS_DEFAULTS = new ArrayList<Setting>();
+ private static ArrayList<Setting> SECURE_SETTINGS_DEFAULTS = new ArrayList<Setting>();
+ private static ArrayList<Setting> GLOBAL_SETTINGS_DEFAULTS = new ArrayList<Setting>();
+
+ //SYSTEM
+ static {
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.STATUS_BAR_QUICK_QS_PULLDOWN,
+ "R.integer.def_qs_quick_pulldown"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
+ "R.integer.def_notification_brightness_level"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.ENABLE_FORWARD_LOOKUP,
+ "R.integer.def_forward_lookup"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.ENABLE_PEOPLE_LOOKUP,
+ "R.integer.def_people_lookup"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.ENABLE_REVERSE_LOOKUP,
+ "R.integer.def_reverse_lookup"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.SYSTEM_PROFILES_ENABLED,
+ "R.bool.def_profiles_enabled"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE,
+ "R.bool.def_notification_pulse_custom_enable"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.SWAP_VOLUME_KEYS_ON_ROTATION,
+ "R.bool.def_swap_volume_keys_on_rotation"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES,
+ "R.string.def_notification_pulse_custom_value"));
+ SYSTEM_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.System.STATUS_BAR_BATTERY_STYLE,
+ "R.integer.def_battery_style"));
+ }
+
+ //SECURE
+ static {
+ SECURE_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Secure.ADVANCED_MODE,
+ "R.bool.def_advanced_mode"));
+ SECURE_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Secure.QS_USE_MAIN_TILES,
+ "R.bool.def_sysui_qs_main_tiles"));
+ SECURE_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Secure.STATS_COLLECTION,
+ "R.bool.def_stats_collection"));
+ SECURE_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Secure.LOCKSCREEN_VISUALIZER_ENABLED,
+ "R.bool.def_lockscreen_visualizer"));
+ SECURE_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Secure.PROTECTED_COMPONENT_MANAGERS,
+ "R.string.def_protected_component_managers"));
+ }
+
+ //GLOBAL
+ static {
+ GLOBAL_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Global.POWER_NOTIFICATIONS_ENABLED,
+ "R.bool.def_power_notifications_enabled"));
+ GLOBAL_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Global.POWER_NOTIFICATIONS_VIBRATE,
+ "R.bool.def_power_notifications_vibrate"));
+ GLOBAL_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Global.POWER_NOTIFICATIONS_RINGTONE,
+ "R.string.def_power_notifications_ringtone"));
+ GLOBAL_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Global.WEATHER_TEMPERATURE_UNIT,
+ "R.integer.def_temperature_unit"));
+ GLOBAL_SETTINGS_DEFAULTS.add(new Setting(
+ LineageSettings.Global.DEV_FORCE_SHOW_NAVBAR,
+ "R.integer.def_force_show_navbar"));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContentResolver = getContext().getContentResolver();
+ mHasMigratedSettings = getContext().getSharedPreferences(LineageSettingsProvider.TAG,
+ Context.MODE_PRIVATE).getBoolean(LineageSettingsProvider.PREF_HAS_MIGRATED_LINEAGE_SETTINGS,
+ false);
+ mRemoteResources = getRemoteResources("org.lineageos.lineagesettings");
+ }
+
+ @SmallTest
+ public void testVerifySystemSettingsDefault() {
+ if (verifyNotMigratedSettings()) {
+ for (Setting setting : SYSTEM_SETTINGS_DEFAULTS) {
+ verifyDefaultSettingForTable(setting, LineageDatabaseHelper.LineageTableNames.TABLE_SYSTEM);
+ }
+ }
+ }
+
+ @SmallTest
+ public void testVerifySecureSettingsDefaults() {
+ if (verifyNotMigratedSettings()) {
+ for (Setting setting : SECURE_SETTINGS_DEFAULTS) {
+ verifyDefaultSettingForTable(setting, LineageDatabaseHelper.LineageTableNames.TABLE_SECURE);
+ }
+ }
+ }
+
+ @SmallTest
+ public void testVerifyGlobalSettingsDefaults() {
+ if (verifyNotMigratedSettings()) {
+ for (Setting setting : GLOBAL_SETTINGS_DEFAULTS) {
+ verifyDefaultSettingForTable(setting, LineageDatabaseHelper.LineageTableNames.TABLE_GLOBAL);
+ }
+ }
+ }
+
+ private boolean verifyNotMigratedSettings() {
+ return !mHasMigratedSettings;
+ }
+
+ private void verifyDefaultSettingForTable(Setting setting, String table) {
+ TypedValue value = new TypedValue();
+ try {
+ int identifier = mRemoteResources.getIdentifier(
+ setting.mDefResName, setting.mType, "org.lineageos.lineagesettings");
+ mRemoteResources.getValue(identifier, value, true);
+ } catch (Resources.NotFoundException e) {
+ // Resource not found, can't verify because it probably wasn't loaded in
+ throw new AssertionError("Unable to find resource for " + setting.mKey);
+ }
+
+ try {
+ switch (value.type) {
+ case TypedValue.TYPE_INT_DEC:
+ int actualValue = getIntForTable(setting, table);
+ try {
+ assertEquals(value.data, actualValue);
+ } catch (AssertionError e) {
+ throw new AssertionError("Compared value of " + setting.mKey + " expected "
+ + value.data + " got " + actualValue);
+ }
+ break;
+ case TypedValue.TYPE_INT_BOOLEAN:
+ int actualBooleanValue = getIntForTable(setting, table);
+ try {
+ //This is gross
+ //Boolean can be "true" as long as it isn't 0
+ if (value.data != 0) {
+ value.data = 1;
+ }
+ assertEquals(value.data, actualBooleanValue);
+ } catch (AssertionError e) {
+ throw new AssertionError("Compared value of " + setting.mKey + " expected "
+ + value.data + " got " + actualBooleanValue);
+ }
+ break;
+ case TypedValue.TYPE_STRING:
+ if (!TextUtils.isEmpty(value.string)) {
+ //This should really be done as a parameterized test
+ String actualStringValue = getStringForTable(setting, table);
+ try {
+ assertEquals(value.string, actualStringValue);
+ } catch (AssertionError e) {
+ throw new AssertionError("Compared value of " + setting.mKey
+ + " expected " + value.string + " got " + actualStringValue);
+ }
+ }
+ break;
+ case TypedValue.TYPE_NULL:
+ break;
+ }
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ e.printStackTrace();
+ throw new AssertionError("Setting " + setting.mKey + " not found!");
+ }
+ }
+
+ private int getIntForTable(Setting setting, String table)
+ throws LineageSettings.LineageSettingNotFoundException {
+ switch (table) {
+ case LineageDatabaseHelper.LineageTableNames.TABLE_SYSTEM:
+ return LineageSettings.System.getIntForUser(mContentResolver, setting.mKey,
+ UserHandle.USER_OWNER);
+ case LineageDatabaseHelper.LineageTableNames.TABLE_SECURE:
+ return LineageSettings.Secure.getIntForUser(mContentResolver, setting.mKey,
+ UserHandle.USER_OWNER);
+ case LineageDatabaseHelper.LineageTableNames.TABLE_GLOBAL:
+ return LineageSettings.Global.getIntForUser(mContentResolver, setting.mKey,
+ UserHandle.USER_OWNER);
+ default:
+ throw new AssertionError("Invalid or empty table!");
+ }
+ }
+
+ private String getStringForTable(Setting setting, String table)
+ throws LineageSettings.LineageSettingNotFoundException {
+ switch (table) {
+ case LineageDatabaseHelper.LineageTableNames.TABLE_SYSTEM:
+ return LineageSettings.System.getStringForUser(mContentResolver, setting.mKey,
+ UserHandle.USER_OWNER);
+ case LineageDatabaseHelper.LineageTableNames.TABLE_SECURE:
+ return LineageSettings.Secure.getStringForUser(mContentResolver, setting.mKey,
+ UserHandle.USER_OWNER);
+ case LineageDatabaseHelper.LineageTableNames.TABLE_GLOBAL:
+ return LineageSettings.Global.getStringForUser(mContentResolver, setting.mKey,
+ UserHandle.USER_OWNER);
+ default:
+ throw new AssertionError("Invalid or empty table!");
+ }
+ }
+
+ private static class Setting {
+ public String mKey;
+ public String mDefResName;
+ public String mType;
+
+ public Setting(String key, String defResId) {
+ mKey = key;
+ String[] parts = defResId.split("\\.");
+ mType = parts[1];
+ mDefResName = parts[2];
+ }
+ }
+
+ private Resources getRemoteResources(String packageName)
+ throws PackageManager.NameNotFoundException {
+ PackageManager packageManager = mContext.getPackageManager();
+ return packageManager.getResourcesForApplication(packageName);
+ }
+}
diff --git a/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderTest.java b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderTest.java
new file mode 100644
index 00000000..17908ffe
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsProviderTest.java
@@ -0,0 +1,325 @@
+ /**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.lineagesettings.tests;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.IContentProvider;
+import android.content.pm.UserInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import lineageos.providers.LineageSettings;
+import org.lineageos.lineagesettings.LineageSettingsProvider;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+ public class LineageSettingsProviderTest extends AndroidTestCase {
+ private static final String TAG = "LineageSettingsProviderTest";
+
+ private static final LinkedHashMap<String, String> sMap = new LinkedHashMap<String, String>();
+
+ static {
+ sMap.put("testKey1", "value1");
+ sMap.put("testKey2", "value2");
+ sMap.put("testKey3", "value3");
+ }
+
+ private static final String[] PROJECTIONS = new String[] { Settings.NameValueTable.NAME,
+ Settings.NameValueTable.VALUE };
+
+ private ContentResolver mContentResolver;
+ private UserManager mUserManager;
+ private UserInfo mGuest;
+
+ @Override
+ public void setUp() {
+ mContentResolver = mContext.getContentResolver();
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ }
+
+ @Override
+ public void tearDown() {
+ if (mGuest != null) {
+ mUserManager.removeUser(mGuest.id);
+ }
+ }
+
+ @MediumTest
+ public void testMigrateLineageSettingsForOtherUser() {
+ // Make sure there's an owner
+ assertTrue(findUser(mUserManager, UserHandle.USER_OWNER));
+
+ mGuest = mUserManager.createGuest(mContext, "GuestUser1");
+ assertNotNull(mGuest);
+
+ testMigrateSettingsForUser(mGuest.id);
+ }
+
+ /**
+ * make sure that queries to SettingsProvider are forwarded to LineageSettingsProvider as needed
+ * See {@link lineageos.providers.LineageSettings.System#shouldInterceptSystemProvider(String)}
+ *
+ * Currently this test only checks that
+ * {@link lineageos.providers.LineageSettings.System#SYSTEM_PROFILES_ENABLED} is expected to
+ * be forwarded, and is forwarded.
+ */
+ @SmallTest
+ public void testSettingsProviderKeyForwarding() {
+ String forwardedKey = LineageSettings.System.SYSTEM_PROFILES_ENABLED;
+
+ // make sure the key should be forwarded
+ assertTrue(LineageSettings.System.shouldInterceptSystemProvider(forwardedKey));
+
+ // put value 1 into Settings provider:
+ // let's try to disable the profiles via the Settings provider
+ Settings.System.putStringForUser(mContentResolver,
+ forwardedKey, "0", UserHandle.USER_CURRENT);
+
+ // assert this is what we just put in there
+ assertEquals("0", Settings.System.getStringForUser(getContext().getContentResolver(),
+ forwardedKey, UserHandle.USER_CURRENT));
+
+ // put value 2 into LineageSettings provider
+ LineageSettings.System.putStringForUser(mContentResolver,
+ forwardedKey, "1", UserHandle.USER_CURRENT);
+
+ assertEquals("1", LineageSettings.System.getStringForUser(getContext().getContentResolver(),
+ forwardedKey, UserHandle.USER_CURRENT));
+
+ // assert reading from both returns value 2
+ final String lineageProviderValue = LineageSettings.System.getStringForUser(
+ getContext().getContentResolver(), forwardedKey, UserHandle.USER_CURRENT);
+ final String settingsProviderValue = Settings.System.getStringForUser(
+ getContext().getContentResolver(), forwardedKey, UserHandle.USER_CURRENT);
+ assertEquals(lineageProviderValue, settingsProviderValue);
+ }
+
+ /**
+ * The new {@link LineageSettings.Secure#LINEAGE_SETUP_WIZARD_COMPLETED} lineage specific provisioned flag
+ * should be equal to the old {@link Settings.Global#DEVICE_PROVISIONED} flag on boot, or on
+ * upgrade. These flags will almost always be equal, except during the provisioning process,
+ * they may change at slightly different times.
+ *
+ * Test whether the setting was properly set and is not null.
+ *
+ * @deprecated Replaced by {@link Settings.Global#DEVICE_PROVISIONED}
+ * or {@link Settings.Secure#USER_SETUP_COMPLETE}
+ */
+ @Deprecated
+ @SmallTest
+ public void testLineageProvisionedFlagFallbackSet() {
+ final String newLineageFlag = LineageSettings.Secure.getStringForUser(
+ getContext().getContentResolver(), LineageSettings.Secure.LINEAGE_SETUP_WIZARD_COMPLETED,
+ UserHandle.USER_OWNER);
+ assertNotNull(newLineageFlag);
+
+ final String previousFlag = Settings.Global.getStringForUser(
+ getContext().getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
+ UserHandle.USER_OWNER);
+ assertEquals(previousFlag, newLineageFlag);
+ }
+
+ private void testMigrateSettingsForUser(int userId) {
+ // Setup values in Settings
+ /*final String expectedPullDownValue = "testQuickPullDownValue";
+ Settings.System.putStringForUser(mContentResolver,
+ LineageSettingsProvider.LegacyLineageSettings.STATUS_BAR_QUICK_QS_PULLDOWN,
+ expectedPullDownValue, userId);
+
+ final int expectedKeyboardBrightness = 4;
+ Settings.Secure.putIntForUser(mContentResolver,
+ LineageSettingsProvider.LegacyLineageSettings.KEYBOARD_BRIGHTNESS,
+ expectedKeyboardBrightness, userId);
+
+ Bundle arg = new Bundle();
+ arg.putInt(LineageSettings.CALL_METHOD_USER_KEY, userId);
+ IContentProvider contentProvider = mContentResolver.acquireProvider(
+ LineageSettings.AUTHORITY);
+
+ try{
+ // Trigger migrate settings for guest
+ contentProvider.call(mContentResolver.getPackageName(),
+ LineageSettings.CALL_METHOD_MIGRATE_SETTINGS_FOR_USER, null, arg);
+ } catch (RemoteException ex) {
+ fail("Failed to trigger settings migration due to RemoteException");
+ }
+
+ // Check values
+ final String actualPullDownValue = LineageSettings.System.getStringForUser(mContentResolver,
+ LineageSettings.System.QS_QUICK_PULLDOWN, userId);
+ assertEquals(expectedPullDownValue, actualPullDownValue);
+
+ final int actualKeyboardBrightness = LineageSettings.Secure.getIntForUser(mContentResolver,
+ LineageSettings.Secure.KEYBOARD_BRIGHTNESS, -1, userId);
+ assertEquals(expectedKeyboardBrightness, actualKeyboardBrightness);*/
+ }
+
+ private boolean findUser(UserManager userManager, int userHandle) {
+ for (UserInfo user : userManager.getUsers()) {
+ if (user.id == userHandle) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @MediumTest
+ public void testBulkInsertSuccess() {
+ ContentValues[] contentValues = new ContentValues[sMap.size()];
+ String[] keyValues = new String[sMap.size()];
+ int count = 0;
+ for (Map.Entry<String, String> kVPair : sMap.entrySet()) {
+ ContentValues contentValue = new ContentValues();
+
+ final String key = kVPair.getKey();
+ contentValue.put(Settings.NameValueTable.NAME, key);
+ keyValues[count] = key;
+
+ contentValue.put(Settings.NameValueTable.VALUE, kVPair.getValue());
+ contentValues[count++] = contentValue;
+ }
+
+ testBulkInsertForUri(LineageSettings.System.CONTENT_URI, contentValues, keyValues);
+ testBulkInsertForUri(LineageSettings.Secure.CONTENT_URI, contentValues, keyValues);
+ testBulkInsertForUri(LineageSettings.Global.CONTENT_URI, contentValues, keyValues);
+ }
+
+ private void testBulkInsertForUri(Uri uri, ContentValues[] contentValues, String[] keyValues) {
+ int rowsInserted = mContentResolver.bulkInsert(uri, contentValues);
+ assertEquals(sMap.size(), rowsInserted);
+
+ final String placeholderSymbol = "?";
+ String[] placeholders = new String[contentValues.length];
+ for (int i = 0; i < placeholders.length; i++) {
+ placeholders[i] = placeholderSymbol;
+ }
+
+ final String placeholdersString = TextUtils.join(",", placeholders);
+
+ Cursor queryCursor = mContentResolver.query(uri, PROJECTIONS,
+ Settings.NameValueTable.NAME + " IN (" + placeholdersString + ")", keyValues,
+ null);
+ assertEquals(contentValues.length, queryCursor.getCount());
+ try {
+ while (queryCursor.moveToNext()) {
+ assertEquals(PROJECTIONS.length, queryCursor.getColumnCount());
+
+ String actualKey = queryCursor.getString(0);
+ assertTrue(sMap.containsKey(actualKey));
+
+ assertEquals(sMap.get(actualKey), queryCursor.getString(1));
+ }
+ }
+ finally {
+ queryCursor.close();
+ }
+
+ // TODO: Find a better way to cleanup database/use ProviderTestCase2 without process crash
+ for (String key : sMap.keySet()) {
+ mContentResolver.delete(uri, Settings.NameValueTable.NAME + " = ?",
+ new String[]{ key });
+ }
+ }
+
+ @MediumTest
+ public void testInsertUpdateDeleteSuccess() {
+ //testInsertUpdateDeleteForUri(LineageSettings.System.CONTENT_URI);
+ testInsertUpdateDeleteForUri(LineageSettings.Secure.CONTENT_URI);
+ testInsertUpdateDeleteForUri(LineageSettings.Global.CONTENT_URI);
+ }
+
+ private void testInsertUpdateDeleteForUri(Uri uri) {
+ String key = "key";
+ String value1 = "value1";
+ String value2 = "value2";
+
+ // test insert
+ ContentValues contentValue = new ContentValues();
+ contentValue.put(Settings.NameValueTable.NAME, key);
+ contentValue.put(Settings.NameValueTable.VALUE, value1);
+
+ Uri expectedUri = uri.withAppendedPath(uri, key);
+ Uri returnUri = mContentResolver.insert(uri, contentValue);
+ assertEquals(expectedUri, returnUri);
+
+ Cursor queryCursor = null;
+ try {
+ // check insert
+ queryCursor = mContentResolver.query(uri, PROJECTIONS, Settings.NameValueTable.NAME +
+ " = ?", new String[]{ key }, null);
+ assertEquals(1, queryCursor.getCount());
+
+ assertExpectedKeyValuePair(queryCursor, key, value1);
+
+ // check insert with returned uri
+ queryCursor = mContentResolver.query(returnUri, PROJECTIONS, null, null, null);
+ assertEquals(1, queryCursor.getCount());
+
+ assertExpectedKeyValuePair(queryCursor, key, value1);
+
+ // test update
+ contentValue.clear();
+ contentValue.put(Settings.NameValueTable.VALUE, value2);
+
+ int rowsAffected = mContentResolver.update(uri, contentValue,
+ Settings.NameValueTable.NAME + " = ?", new String[]{ key });
+ assertEquals(1, rowsAffected);
+
+ // check update
+ queryCursor = mContentResolver.query(uri, PROJECTIONS, Settings.NameValueTable.NAME +
+ " = ?", new String[]{ key }, null);
+ assertEquals(1, queryCursor.getCount());
+
+ assertExpectedKeyValuePair(queryCursor, key, value2);
+
+ // test delete
+ rowsAffected = mContentResolver.delete(uri, Settings.NameValueTable.NAME + " = ?",
+ new String[]{ key });
+ assertEquals(1, rowsAffected);
+
+ // check delete
+ queryCursor = mContentResolver.query(uri, PROJECTIONS, Settings.NameValueTable.NAME +
+ " = ?", new String[]{ key }, null);
+ assertEquals(0, queryCursor.getCount());
+ } finally {
+ if (queryCursor != null) {
+ queryCursor.close();
+ }
+ }
+ }
+
+ private void assertExpectedKeyValuePair(Cursor cursor, String expectedKey,
+ String expectedValue) {
+ cursor.moveToNext();
+ assertEquals(PROJECTIONS.length, cursor.getColumnCount());
+
+ String actualKey = cursor.getString(0);
+ assertEquals(expectedKey, actualKey);
+ assertEquals(expectedValue, cursor.getString(1));
+ }
+ }
diff --git a/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSecureTests.java b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSecureTests.java
new file mode 100644
index 00000000..b27accad
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSecureTests.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.lineagesettings.tests;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.providers.LineageSettings;
+
+public class LineageSettingsSecureTests extends AndroidTestCase {
+ private ContentResolver mContentResolver;
+
+ private static final String UNREALISTIC_SETTING = "_______UNREAL_______";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContentResolver = mContext.getContentResolver();
+ }
+
+ @SmallTest
+ public void testFloat() {
+ final float expectedFloatValue = 1.0f;
+ LineageSettings.Secure.putFloat(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER, expectedFloatValue);
+
+ try {
+ float actualValue = LineageSettings.Secure.getFloat(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedFloatValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testFloatWithDefault() {
+ final float expectedDefaultFloatValue = 1.5f;
+ float actualValue = LineageSettings.Secure.getFloat(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultFloatValue);
+ assertEquals(expectedDefaultFloatValue, actualValue);
+ }
+
+ @SmallTest
+ public void testInt() {
+ final int expectedIntValue = 2;
+ LineageSettings.Secure.putInt(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER, expectedIntValue);
+
+ try {
+ int actualValue = LineageSettings.Secure.getInt(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedIntValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testIntWithDefault() {
+ final int expectedDefaultIntValue = 11;
+ int actualValue = LineageSettings.Secure.getInt(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultIntValue);
+ assertEquals(expectedDefaultIntValue, actualValue);
+ }
+
+ @SmallTest
+ public void testLong() {
+ final long expectedLongValue = 3l;
+ LineageSettings.Secure.putLong(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER, expectedLongValue);
+
+ try {
+ long actualValue = LineageSettings.Secure.getLong(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedLongValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testLongWithDefault() {
+ final long expectedDefaultLongValue = 17l;
+ long actualValue = LineageSettings.Secure.getLong(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultLongValue);
+ assertEquals(expectedDefaultLongValue, actualValue);
+ }
+
+ @SmallTest
+ public void testString() {
+ final String expectedStringValue = "4";
+ LineageSettings.Secure.putString(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER, expectedStringValue);
+
+ String actualValue = LineageSettings.Secure.getString(mContentResolver,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedStringValue, actualValue);
+ }
+
+ @SmallTest
+ public void testGetUri() {
+ final Uri expectedUri = Uri.withAppendedPath(LineageSettings.Secure.CONTENT_URI,
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER);
+
+ final Uri actualUri = LineageSettings.Secure.getUriFor(
+ LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER);
+
+ assertEquals(expectedUri, actualUri);
+ }
+}
diff --git a/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSystemTests.java b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSystemTests.java
new file mode 100644
index 00000000..101a60f4
--- /dev/null
+++ b/packages/LineageSettingsProvider/tests/src/org/lineageos/lineagesettings/tests/LineageSettingsSystemTests.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.lineagesettings.tests;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.providers.LineageSettings;
+
+public class LineageSettingsSystemTests extends AndroidTestCase {
+ private ContentResolver mContentResolver;
+
+ private static final String UNREALISTIC_SETTING = "_______UNREAL_______";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContentResolver = mContext.getContentResolver();
+ }
+
+ @SmallTest
+ public void testFloat() {
+ final float expectedFloatValue = 1.0f;
+ LineageSettings.System.putFloat(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER, expectedFloatValue);
+
+ try {
+ float actualValue = LineageSettings.System.getFloat(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedFloatValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testFloatWithDefault() {
+ final float expectedDefaultFloatValue = 1.5f;
+ float actualValue = LineageSettings.System.getFloat(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultFloatValue);
+ assertEquals(expectedDefaultFloatValue, actualValue);
+ }
+
+ @SmallTest
+ public void testInt() {
+ final int expectedIntValue = 2;
+ LineageSettings.System.putInt(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER, expectedIntValue);
+
+ try {
+ int actualValue = LineageSettings.System.getInt(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedIntValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testIntWithDefault() {
+ final int expectedDefaultIntValue = 11;
+ int actualValue = LineageSettings.System.getInt(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultIntValue);
+ assertEquals(expectedDefaultIntValue, actualValue);
+ }
+
+ @SmallTest
+ public void testLong() {
+ final long expectedLongValue = 3l;
+ LineageSettings.System.putLong(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER, expectedLongValue);
+
+ try {
+ long actualValue = LineageSettings.System.getLong(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedLongValue, actualValue);
+ } catch (LineageSettings.LineageSettingNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testLongWithDefault() {
+ final long expectedDefaultLongValue = 17l;
+ long actualValue = LineageSettings.System.getLong(mContentResolver,
+ UNREALISTIC_SETTING, expectedDefaultLongValue);
+ assertEquals(expectedDefaultLongValue, actualValue);
+ }
+
+ @SmallTest
+ public void testString() {
+ final String expectedStringValue = "4";
+ LineageSettings.System.putString(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER, expectedStringValue);
+
+ String actualValue = LineageSettings.System.getString(mContentResolver,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER);
+ assertEquals(expectedStringValue, actualValue);
+ }
+
+ @SmallTest
+ public void testGetUri() {
+ final Uri expectedUri = Uri.withAppendedPath(LineageSettings.System.CONTENT_URI,
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER);
+
+ final Uri actualUri = LineageSettings.System.getUriFor(
+ LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER);
+
+ assertEquals(expectedUri, actualUri);
+ }
+}
diff --git a/sdk/src/java/org/lineageos/internal/util/TelephonyExtUtils.java b/sdk/src/java/org/lineageos/internal/util/TelephonyExtUtils.java
index 831f7578..59f6d10f 100644
--- a/sdk/src/java/org/lineageos/internal/util/TelephonyExtUtils.java
+++ b/sdk/src/java/org/lineageos/internal/util/TelephonyExtUtils.java
@@ -20,10 +20,8 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.telephony.SubscriptionManager;
import android.util.Log;
@@ -33,8 +31,6 @@ import org.codeaurora.internal.IExtTelephony;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.TimeUnit;
public final class TelephonyExtUtils {
private static final boolean DEBUG = false;
@@ -45,9 +41,6 @@ public final class TelephonyExtUtils {
public static final String EXTRA_NEW_PROVISION_STATE = "newProvisionState";
- private static final int ACTIVATE_TIME_OUT = 30000;
- private static final String PROP_TIME_OUT = "sys.uicc.activate.timeout";
-
// This is the list of possible values that
// IExtTelephony.getCurrentUiccCardProvisioningStatus() can return
public static final int CARD_NOT_PRESENT = -2;
@@ -154,7 +147,15 @@ public final class TelephonyExtUtils {
* @return The result of the activation or -1
*/
public int activateUiccCard(int slotId) {
- return activateDeactivateUiccCard(true, slotId);
+ IExtTelephony service = getService();
+ if (service != null) {
+ try {
+ return mExtTelephony.activateUiccCard(slotId);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Activating sub failed for slotId: " + slotId);
+ }
+ }
+ return -1;
}
/**
@@ -163,38 +164,14 @@ public final class TelephonyExtUtils {
* @return The result of the deactivation or -1
*/
public int deactivateUiccCard(int slotId) {
- return activateDeactivateUiccCard(false, slotId);
- }
-
- private int activateDeactivateUiccCard(boolean activate, int slotId) {
IExtTelephony service = getService();
- if (service == null) {
- return -1;
- }
-
- try {
- AsyncTask<Integer, Void, Integer> task = new AsyncTask<Integer, Void, Integer>() {
- @Override
- protected Integer doInBackground(Integer... params) {
- try {
- return params[0] == 1
- ? mExtTelephony.activateUiccCard(params[1])
- : mExtTelephony.deactivateUiccCard(params[1]);
- } catch (RemoteException ex) {
- Log.e(TAG, "Changing activation for sub failed for slotId: " + params[1]);
- }
- return -1;
- }
- };
- task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, activate ? 1 : 0, slotId)
- .get(ACTIVATE_TIME_OUT, TimeUnit.MILLISECONDS);
- } catch (TimeoutException ex) {
- Log.e(TAG, "Changing activation for sub timed out for slotId: " + slotId);
- SystemProperties.set(PROP_TIME_OUT , Integer.toString(slotId + 1));
- } catch (Exception ex) {
- Log.e(TAG, "Changing activation for sub task failed for slotId: " + slotId);
+ if (service != null) {
+ try {
+ return mExtTelephony.deactivateUiccCard(slotId);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Deactivating sub failed for slotId: " + slotId);
+ }
}
-
return -1;
}
diff --git a/tests/Android.mk b/tests/Android.mk
new file mode 100644
index 00000000..2cbb309f
--- /dev/null
+++ b/tests/Android.mk
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2015 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ org.lineageos.platform.sdk \
+ android-support-test \
+ mockito-target
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files, src/)
+
+LOCAL_PACKAGE_NAME := LineagePlatformTests
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PROGUARD_ENABLED := optimization shrinktests
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+include $(BUILD_PACKAGE)
+
+# Register as LineageTS
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ org.lineageos.platform.sdk \
+ android-support-test \
+ mockito-target
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files, src/)
+
+LOCAL_PACKAGE_NAME := CmtsPlatformSDKTests
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PROGUARD_ENABLED := optimization shrinktests
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+include $(BUILD_LineageTS_PACKAGE)
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
new file mode 100644
index 00000000..174a1600
--- /dev/null
+++ b/tests/AndroidManifest.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.lineageos.tests"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-permission android:name="android.permission.REBOOT" />
+ <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <uses-permission android:name="lineageos.permission.BIND_CUSTOM_TILE_LISTENER_SERVICE"/>
+ <uses-permission android:name="lineageos.permission.PUBLISH_CUSTOM_TILE"/>
+ <uses-permission android:name="lineageos.permission.WRITE_SETTINGS"/>
+ <uses-permission android:name="lineageos.permission.WRITE_SECURE_SETTINGS"/>
+ <uses-permission android:name="lineageos.permission.MODIFY_NETWORK_SETTINGS" />
+ <uses-permission android:name="lineageos.permission.MODIFY_SOUND_SETTINGS" />
+ <uses-permission android:name="lineageos.permission.MANAGE_ALARMS" />
+ <uses-permission android:name="lineageos.permission.READ_ALARMS" />
+ <uses-permission android:name="lineageos.permission.MODIFY_MSIM_PHONE_STATE" />
+ <uses-permission android:name="lineageos.permission.READ_MSIM_PHONE_STATE" />
+ <uses-permission android:name="lineageos.permission.HARDWARE_ABSTRACTION_ACCESS" />
+ <uses-permission android:name="lineageos.permission.MODIFY_PROFILES" />
+ <uses-permission android:name="lineageos.permission.MANAGE_PERSISTENT_STORAGE" />
+ <uses-permission android:name="lineageos.permission.PERFORMANCE_ACCESS" />
+ <uses-permission android:name="lineageos.permission.MANAGE_LIVEDISPLAY" />
+ <uses-permission android:name="lineageos.permission.OBSERVE_AUDIO_SESSIONS" />
+ <uses-permission android:name="lineageos.permission.ACCESS_WEATHER_MANAGER" />
+ <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+
+ <application android:name=".LineageOSTestApplication"
+ android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".customtiles.LineageStatusBarTest"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".alarmclock.LineageAlarmClockTest"
+ android:label="@string/alarm_tests_activity_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".telephony.LineageTelephonyTest"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".profiles.ProfileTest"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".versioning.VersioningTest"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".hardware.LineageHardwareTest"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".customtiles.DummySettings"
+ android:label="@string/app_name" />
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="org.lineageos.tests" />
+</manifest>
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 00000000..9aebffc8
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,7 @@
+## Lineage Platform SDK Tests
+The tests package contains both functional manual tests as well as unit
+tests which can be ran utilizing the InstrumentationTestRunner from android.
+
+To run the tests (on a live device):
+
+ ```adb shell am instrument -w org.lineageos.tests/android.support.test.runner.AndroidJUnitRunner```
diff --git a/tests/proguard.flags b/tests/proguard.flags
new file mode 100644
index 00000000..fd080271
--- /dev/null
+++ b/tests/proguard.flags
@@ -0,0 +1,56 @@
+# Copyright (C) 2016 The CyanogenMod Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Don't skip non public library classes, make sure we're not keeping anything which will get mapped against api verification.
+-dontskipnonpubliclibraryclasses
+
+# Do the same with class members
+-dontskipnonpubliclibraryclassmembers
+
+# Keep test packages
+-keep class android.support.** { *; }
+-keep class android.test.** { *; }
+-keep public class * extends android.support.** { *; }
+-keep public class * extends android.test.** { *; }
+-keep interface android.support.** { *; }
+-keep interface android.test.** { *; }
+
+# Keep all junit classes
+-keep class junit.** { *; }
+-keep class org.junit.** { *; }
+-keep interface junit.** { *; }
+-keep interface org.junit.** { *; }
+
+# Keep compiled java classes from declared aidl's within the test package
+-keep public class * extends android.os.IInterface { *; }
+
+# Don't warn about the Android Support Test JUnit Runner
+-dontwarn android.support.**
+-dontwarn android.test.**
+
+# Don't warn about junit
+-dontwarn junit.**
+-dontwarn org.junit.**
+
+# keep mockito methods
+-keep class org.mockito.** { *; }
+-keep interface org.mockito.** { *; }
+-keep class com.google.dexmaker.** { *; }
+-keep interface com.google.dexmaker.** { *; }
+
+# Always process
+-forceprocessing
+
+# Make sure not to obfuscate the output
+-dontobfuscate
diff --git a/tests/res/drawable-hdpi/ic_launcher.png b/tests/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..cde69bcc
--- /dev/null
+++ b/tests/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/res/drawable-hdpi/ic_whatshot_white_24dp.png b/tests/res/drawable-hdpi/ic_whatshot_white_24dp.png
new file mode 100644
index 00000000..46ed1f8b
--- /dev/null
+++ b/tests/res/drawable-hdpi/ic_whatshot_white_24dp.png
Binary files differ
diff --git a/tests/res/drawable-mdpi/ic_launcher.png b/tests/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..c133a0cb
--- /dev/null
+++ b/tests/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/res/drawable-mdpi/ic_whatshot_white_24dp.png b/tests/res/drawable-mdpi/ic_whatshot_white_24dp.png
new file mode 100644
index 00000000..4cf6f85f
--- /dev/null
+++ b/tests/res/drawable-mdpi/ic_whatshot_white_24dp.png
Binary files differ
diff --git a/tests/res/drawable-xhdpi/ic_launcher.png b/tests/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..bfa42f0e
--- /dev/null
+++ b/tests/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/res/drawable-xhdpi/ic_whatshot_white_24dp.png b/tests/res/drawable-xhdpi/ic_whatshot_white_24dp.png
new file mode 100644
index 00000000..3651d061
--- /dev/null
+++ b/tests/res/drawable-xhdpi/ic_whatshot_white_24dp.png
Binary files differ
diff --git a/tests/res/drawable-xxhdpi/ic_launcher.png b/tests/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..324e72cd
--- /dev/null
+++ b/tests/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/res/drawable-xxhdpi/ic_whatshot_white_24dp.png b/tests/res/drawable-xxhdpi/ic_whatshot_white_24dp.png
new file mode 100644
index 00000000..8eaf3755
--- /dev/null
+++ b/tests/res/drawable-xxhdpi/ic_whatshot_white_24dp.png
Binary files differ
diff --git a/tests/res/drawable-xxxhdpi/ic_whatshot_white_24dp.png b/tests/res/drawable-xxxhdpi/ic_whatshot_white_24dp.png
new file mode 100644
index 00000000..5c5d8687
--- /dev/null
+++ b/tests/res/drawable-xxxhdpi/ic_whatshot_white_24dp.png
Binary files differ
diff --git a/tests/res/layout/main.xml b/tests/res/layout/main.xml
new file mode 100644
index 00000000..15b422cd
--- /dev/null
+++ b/tests/res/layout/main.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center_horizontal"
+ >
+ <Button android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TEST PUBLISH TILE"
+ android:onClick="testPublishTile"/>
+ <Button android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TEST PUBLISH SETTINGS TILE"
+ android:onClick="testPublishTileWithSettings"/>
+ <Button android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TEST UPDATE TILE"
+ android:onClick="testUpdateTile"/>
+ <Button android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TEST REMOVE TILE"
+ android:onClick="testRemoveTile"/>
+
+ <Button android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TEST PUBLISH MULTIPLE"
+ android:onClick="testMultipleTilePublish"/>
+ <Button android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TEST REMOVE MULTIPLE"
+ android:onClick="testMultipleTileRemove"/>
+</LinearLayout>
+
diff --git a/tests/res/layout/remote_view.xml b/tests/res/layout/remote_view.xml
new file mode 100644
index 00000000..6988cf95
--- /dev/null
+++ b/tests/res/layout/remote_view.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal">
+
+ <ImageView
+ android:src="@drawable/ic_whatshot_white_24dp"
+ android:layout_width="48dp"
+ android:layout_height="48dp" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:text="THIS IS A REMOTEVIEW"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <Button
+ android:id="@+id/whats_hot_click"
+ android:text="CLICK ME"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
new file mode 100644
index 00000000..5cbd37c5
--- /dev/null
+++ b/tests/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Lineage Platform Tests</string>
+ <string name="settings_tests_activity_name">Lineage Platform Settings Tests</string>
+ <string name="alarm_tests_activity_name">Lineage Platform Alarm Clock Tests</string>
+</resources>
diff --git a/tests/src/org/lineageos/tests/LineageOSTestApplication.java b/tests/src/org/lineageos/tests/LineageOSTestApplication.java
new file mode 100644
index 00000000..0eb754e9
--- /dev/null
+++ b/tests/src/org/lineageos/tests/LineageOSTestApplication.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests;
+
+import android.app.Application;
+import android.content.Context;
+
+/**
+ * Created by adnan on 2/4/16.
+ */
+public class LineageOSTestApplication extends Application {
+ private static Context sApplicationContext;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ sApplicationContext = getApplicationContext();
+ }
+
+ public static Context getStaticApplicationContext() {
+ return sApplicationContext;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/TestActivity.java b/tests/src/org/lineageos/tests/TestActivity.java
new file mode 100644
index 00000000..9c8d8604
--- /dev/null
+++ b/tests/src/org/lineageos/tests/TestActivity.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public abstract class TestActivity extends ListActivity
+{
+ Test[] mTests;
+
+ protected abstract String tag();
+ protected abstract Test[] tests();
+
+ protected abstract class Test {
+ protected String name;
+ protected Test(String n) {
+ name = n;
+ }
+ protected abstract void run();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mTests = tests();
+
+ String[] labels = new String[mTests.length];
+ for (int i=0; i<mTests.length; i++) {
+ labels[i] = mTests[i].name;
+ }
+
+ setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, labels));
+ }
+
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id)
+ {
+ Test t = mTests[position];
+ android.util.Log.d(tag(), "Test: " + t.name);
+ t.run();
+ }
+
+} \ No newline at end of file
diff --git a/tests/src/org/lineageos/tests/common/MockIBinderStubForInterface.java b/tests/src/org/lineageos/tests/common/MockIBinderStubForInterface.java
new file mode 100644
index 00000000..79c61744
--- /dev/null
+++ b/tests/src/org/lineageos/tests/common/MockIBinderStubForInterface.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.common;
+
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteCallbackList;
+import org.junit.Assert;
+import org.mockito.Mockito;
+
+import java.lang.reflect.Field;
+
+/**
+ * Helper class to mock stubs for IInterfaces
+ * Ensures that when querying the local interface
+ * we return the instance itself as to preserve the mock instance
+ */
+public final class MockIBinderStubForInterface {
+ private MockIBinderStubForInterface() {}
+
+ private static <T extends IBinder> String getStubDescriptor(Class<T> stubClass) {
+ String descriptor = null;
+ try {
+ Field f = stubClass.getDeclaredField("DESCRIPTOR");
+ f.setAccessible(true);
+ descriptor = (String) f.get(stubClass);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ Assert.fail(e.getMessage());
+ }
+ return descriptor;
+ }
+
+ public static <T extends IBinder> T getMockInterface(Class<T> stub) {
+ String descriptor = getStubDescriptor(stub);
+ T mockInterface = Mockito.mock(stub);
+ Mockito.doReturn(mockInterface)
+ .when(mockInterface)
+ .queryLocalInterface(descriptor == null ?
+ Mockito.anyString() : Mockito.eq(descriptor));
+ Mockito.doReturn(Mockito.mock(IBinder.class))
+ .when((IInterface) mockInterface)
+ .asBinder();
+ return mockInterface;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/common/ThreadServiceTestCase.java b/tests/src/org/lineageos/tests/common/ThreadServiceTestCase.java
new file mode 100644
index 00000000..55807c5c
--- /dev/null
+++ b/tests/src/org/lineageos/tests/common/ThreadServiceTestCase.java
@@ -0,0 +1,200 @@
+package org.lineageos.tests.common;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.test.InstrumentationTestCase;
+import android.test.ServiceTestCase;
+
+/**
+ * Tests a service in its own Thread.
+ *
+ *
+ * <p>
+ * The {@link ServiceTestCase} class creates the service in the same thread the
+ * test is running. In consequence Handlers and other constructs that depend on
+ * the fact that the service methods are always run on the <em>main thread</em>
+ * won't work.
+ * </p>
+ *
+ * <p>
+ * To circumvent this, this test class creates a {@link HandlerThread} on setup
+ * to simulate the main tread and provides helper constructs to ease the
+ * communication between the Service and the test class :
+ * </p>
+ *
+ * <ul>
+ * <li>The {@link #runOnServiceThread(Runnable)} methods allows to run code on
+ * the service pseudo-main thread.</li>
+ * <li>The {@link #startService(boolean, ServiceRunnable)} mehod allows starting
+ * the service in its own thread with some additional initialization code.</li>
+ * </ul>
+ *
+ *
+ * @author Antoine Martin
+ *
+ */
+public abstract class ThreadServiceTestCase<T extends Service> extends ServiceTestCase<T> {
+
+ /** Typical maximum wait time for something to happen on the service */
+ public static final long WAIT_TIME = 5 * 1000;
+
+ /*
+ * This class provides final mutable values through indirection
+ */
+ static class Holder<H> {
+ H value;
+ }
+
+ protected Handler serviceHandler;
+ protected Looper serviceLooper;
+ /*
+ * Got to catch this again because of damn package visibility of
+ * mServiceClass in base class.
+ */
+ protected Class<T> serviceClass;
+
+ public ThreadServiceTestCase(Class<T> serviceClass) {
+ super(serviceClass);
+ this.serviceClass = serviceClass;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Setup service thread
+ HandlerThread serviceThread = new HandlerThread("[" + serviceClass.getSimpleName() + "Thread]");
+ serviceThread.start();
+ serviceLooper = serviceThread.getLooper();
+ serviceHandler = new Handler(serviceLooper);
+ }
+
+ @Override
+ public void testServiceTestCaseSetUpProperly() throws Exception {
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ // teardown service thread
+ if (serviceLooper != null)
+ serviceLooper.quit();
+ serviceHandler = null;
+ }
+
+ /**
+ * Runs the specified runnable on the service tread and waits for its
+ * completion.
+ *
+ * @see InstrumentationTestCase#runTestOnUiThread(Runnable)
+ * @param r
+ * The runnable to run on the pseudo-main thread.
+ */
+ protected void runOnServiceThread(final Runnable r) {
+ final CountDownLatch serviceSignal = new CountDownLatch(1);
+ serviceHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ r.run();
+ serviceSignal.countDown();
+ }
+ });
+
+ try {
+ serviceSignal.await();
+ } catch (InterruptedException ie) {
+ fail("The Service thread has been interrupted");
+ }
+ }
+
+ /**
+ * Runnable interface allowing service initialization personalization.
+ *
+ * @author Antoine Martin
+ *
+ */
+ protected interface ServiceRunnable {
+ public void run(Service service);
+ }
+
+ /**
+ * Initialize the service in its own thread and returns it.
+ *
+ * @param bound
+ * if {@code true}, the service will be created as if it was
+ * bound by a client. if {@code false}, it will be created by a
+ * {@code startService} call.
+ * @param r
+ * {@link ServiceRunnable} instance that will be called with the
+ * created service.
+ * @return The created service.
+ */
+ protected T startService(final ServiceRunnable r) {
+ final Holder<T> serviceHolder = new Holder<T>();
+
+ // I want to create my service in its own 'Main thread'
+ // So it can use its handler
+ runOnServiceThread(new Runnable() {
+
+ @Override
+ public void run() {
+ T service = null;
+ startService(new Intent(getContext(), serviceClass));
+ service = getService();
+ if (r != null)
+ r.run(service);
+ serviceHolder.value = service;
+ }
+ });
+
+ return serviceHolder.value;
+ }
+
+ protected IBinder bindService(final ServiceRunnable r) {
+ final Holder<IBinder> serviceHolder = new Holder<IBinder>();
+
+ // I want to create my service in its own 'Main thread'
+ // So it can use its handler
+ runOnServiceThread(new Runnable() {
+
+ @Override
+ public void run() {
+ T service = null;
+ IBinder binder = bindService(new Intent(getContext(), serviceClass));
+ service = getService();
+ if (r != null)
+ r.run(service);
+ serviceHolder.value = binder;
+ }
+ });
+
+ return serviceHolder.value;
+ }
+
+ public static class ServiceSyncHelper {
+ // The semaphore will wakeup clients
+ protected final Semaphore semaphore = new Semaphore(0);
+
+ /**
+ * Waits for some response coming from the service.
+ *
+ * @param timeout
+ * The maximum time to wait.
+ * @throws InterruptedException
+ * if the Thread is interrupted or reaches the timeout.
+ */
+ public synchronized void waitListener(long timeout) throws InterruptedException {
+ if (!semaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS))
+ throw new InterruptedException();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/tests/src/org/lineageos/tests/hardware/LineageHardwareTest.java b/tests/src/org/lineageos/tests/hardware/LineageHardwareTest.java
new file mode 100644
index 00000000..6d247473
--- /dev/null
+++ b/tests/src/org/lineageos/tests/hardware/LineageHardwareTest.java
@@ -0,0 +1,388 @@
+/**
+ * Copyright (c) 2015-2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.hardware;
+
+import android.os.Bundle;
+
+import android.widget.Toast;
+
+import java.util.Arrays;
+import java.util.List;
+
+import lineageos.hardware.LineageHardwareManager;
+import lineageos.hardware.DisplayMode;
+
+import org.lineageos.tests.TestActivity;
+
+/**
+ * Created by adnan on 8/31/15.
+ */
+public class LineageHardwareTest extends TestActivity {
+ private LineageHardwareManager mHardwareManager;
+
+ private static final List<Integer> FEATURES = Arrays.asList(
+ LineageHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT,
+ LineageHardwareManager.FEATURE_COLOR_ENHANCEMENT,
+ LineageHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION,
+ LineageHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION,
+ LineageHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY,
+ LineageHardwareManager.FEATURE_KEY_DISABLE,
+ LineageHardwareManager.FEATURE_LONG_TERM_ORBITS,
+ LineageHardwareManager.FEATURE_SERIAL_NUMBER,
+ LineageHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT,
+ LineageHardwareManager.FEATURE_TOUCH_HOVERING,
+ LineageHardwareManager.FEATURE_AUTO_CONTRAST,
+ LineageHardwareManager.FEATURE_DISPLAY_MODES,
+ LineageHardwareManager.FEATURE_PERSISTENT_STORAGE
+ );
+
+ private static final List<String> FEATURE_STRINGS = Arrays.asList(
+ "FEATURE_ADAPTIVE_BACKLIGHT",
+ "FEATURE_COLOR_ENHANCEMENT",
+ "FEATURE_DISPLAY_COLOR_CALIBRATION",
+ "FEATURE_DISPLAY_GAMMA_CALIBRATION",
+ "FEATURE_HIGH_TOUCH_SENSITIVITY",
+ "FEATURE_KEY_DISABLE",
+ "FEATURE_LONG_TERM_ORBITS",
+ "FEATURE_SERIAL_NUMBER",
+ "FEATURE_SUNLIGHT_ENHANCEMENT",
+ "FEATURE_TOUCH_HOVERING",
+ "FEATURE_AUTO_CONTRAST",
+ "FEATURE_DISPLAY_MODES",
+ "FEATURE_PERSISTENT_STORAGE"
+ );
+
+ private static final List<Integer> BOOLEAN_FEATURES = Arrays.asList(
+ LineageHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT,
+ LineageHardwareManager.FEATURE_COLOR_ENHANCEMENT,
+ LineageHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY,
+ LineageHardwareManager.FEATURE_KEY_DISABLE,
+ LineageHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT,
+ LineageHardwareManager.FEATURE_TOUCH_HOVERING,
+ LineageHardwareManager.FEATURE_AUTO_CONTRAST
+ );
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mHardwareManager = LineageHardwareManager.getInstance(this);
+ }
+
+ @Override
+ protected String tag() {
+ return null;
+ }
+
+ @Override
+ protected Test[] tests() {
+ return mTests;
+ }
+
+ private boolean vibratorSupported() {
+ if (mHardwareManager.isSupported(LineageHardwareManager.FEATURE_VIBRATOR)) {
+ return true;
+ } else {
+ Toast.makeText(LineageHardwareTest.this, "Vibrator not supported",
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ private boolean displayColorCalibrationSupported() {
+ if (mHardwareManager.isSupported(LineageHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION)) {
+ return true;
+ } else {
+ Toast.makeText(LineageHardwareTest.this, "Display Color Calibration not supported",
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ private boolean ltoSupported() {
+ if (mHardwareManager.isSupported(LineageHardwareManager.FEATURE_LONG_TERM_ORBITS)) {
+ return true;
+ } else {
+ Toast.makeText(LineageHardwareTest.this, "Long Term Orbits not supported",
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ private boolean serialSupported() {
+ if (mHardwareManager.isSupported(LineageHardwareManager.FEATURE_SERIAL_NUMBER)) {
+ return true;
+ } else {
+ Toast.makeText(LineageHardwareTest.this, "Serial number not supported",
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ private boolean uniqueDeviceIdSupported() {
+ if (mHardwareManager.isSupported(LineageHardwareManager.FEATURE_UNIQUE_DEVICE_ID)) {
+ return true;
+ } else {
+ Toast.makeText(LineageHardwareTest.this, "Unique device ID not supported",
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ private boolean displayModesSupported() {
+ if (mHardwareManager.isSupported(LineageHardwareManager.FEATURE_DISPLAY_MODES)) {
+ return true;
+ } else {
+ Toast.makeText(LineageHardwareTest.this, "Display modes not supported",
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ private boolean persistentStorageSupported() {
+ if (mHardwareManager.isSupported(LineageHardwareManager.FEATURE_PERSISTENT_STORAGE)) {
+ return true;
+ } else {
+ Toast.makeText(LineageHardwareTest.this, "Persistent storage not supported",
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ private Test[] mTests = new Test[] {
+ new Test("Test get supported features") {
+ public void run() {
+ Toast.makeText(LineageHardwareTest.this, "Supported features " +
+ mHardwareManager.getSupportedFeatures(),
+ Toast.LENGTH_SHORT).show();
+ }
+ },
+ new Test("Test features supported") {
+ @Override
+ protected void run() {
+ StringBuilder builder = new StringBuilder();
+ int i = 0;
+ for (int feature : FEATURES) {
+ boolean supported = mHardwareManager.isSupported(feature);
+ if (mHardwareManager.isSupported(FEATURE_STRINGS.get(i)) != supported) {
+ throw new RuntimeException("Internal error, feature string lookup failed");
+ }
+ i++;
+ builder.append("Feature " + feature + "\n")
+ .append("is supported " + supported + "\n");
+ }
+ Toast.makeText(LineageHardwareTest.this, "Supported features " +
+ builder.toString(),
+ Toast.LENGTH_SHORT).show();
+ }
+ },
+ new Test("Test boolean features enabled") {
+ @Override
+ protected void run() {
+ StringBuilder builder = new StringBuilder();
+ for (int feature : BOOLEAN_FEATURES) {
+ builder.append("Feature " + feature + "\n")
+ .append("is enabled " + mHardwareManager.isSupported(feature)
+ + "\n");
+ }
+ Toast.makeText(LineageHardwareTest.this, "Features " +
+ builder.toString(),
+ Toast.LENGTH_SHORT).show();
+ }
+ },
+ new Test("Test get vibrator intensity") {
+ @Override
+ protected void run() {
+ if (vibratorSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Vibrator intensity " +
+ mHardwareManager.getVibratorIntensity(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test get vibrator default intensity") {
+ @Override
+ protected void run() {
+ if (vibratorSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Vibrator default intensity " +
+ mHardwareManager.getVibratorDefaultIntensity(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test get vibrator max intensity") {
+ @Override
+ protected void run() {
+ if (vibratorSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Vibrator max intensity " +
+ mHardwareManager.getVibratorMaxIntensity(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test get vibrator min intensity") {
+ @Override
+ protected void run() {
+ if (vibratorSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Vibrator min intensity " +
+ mHardwareManager.getVibratorMinIntensity(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test get vibrator min intensity") {
+ @Override
+ protected void run() {
+ if (vibratorSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Vibrator min intensity " +
+ mHardwareManager.getVibratorWarningIntensity(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Display Color Calibration") {
+ @Override
+ protected void run() {
+ if (displayColorCalibrationSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Display Color Calibration " +
+ mHardwareManager.getDisplayColorCalibration(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Default Display Color Calibration") {
+ @Override
+ protected void run() {
+ if (displayColorCalibrationSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Default Display Color Calibration " +
+ mHardwareManager.getDisplayColorCalibrationDefault(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Display Color Calibration Max") {
+ @Override
+ protected void run() {
+ if (displayColorCalibrationSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Display Color Calibration Max " +
+ mHardwareManager.getDisplayColorCalibrationMax(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Display Color Calibration Min") {
+ @Override
+ protected void run() {
+ if (displayColorCalibrationSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Display Color Calibration Min " +
+ mHardwareManager.getDisplayColorCalibrationMin(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Set Display Color Calibration") {
+ @Override
+ protected void run() {
+ if (displayColorCalibrationSupported()) {
+ mHardwareManager.setDisplayColorCalibration(new int[] {0,0,0});
+ }
+ }
+ },
+ new Test("Test Get Long Term Orbits Source") {
+ @Override
+ protected void run() {
+ if (ltoSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Long Term Orbit Source " +
+ mHardwareManager.getLtoSource(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Get Long Term Orbits Destination") {
+ @Override
+ protected void run() {
+ if (ltoSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Long Term Orbit Destination " +
+ mHardwareManager.getLtoDestination(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Get Long Term Orbits Interval") {
+ @Override
+ protected void run() {
+ if (ltoSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Long Term Orbit Download Interval " +
+ mHardwareManager.getLtoDownloadInterval(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Get Serial Number") {
+ @Override
+ protected void run() {
+ if (serialSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Serial number " +
+ mHardwareManager.getSerialNumber(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Get Unique Device ID") {
+ @Override
+ protected void run() {
+ if (uniqueDeviceIdSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Unique Device ID " +
+ mHardwareManager.getUniqueDeviceId(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Get Display Modes") {
+ @Override
+ protected void run() {
+ if (displayModesSupported()) {
+ StringBuilder builder = new StringBuilder();
+ for (DisplayMode displayMode : mHardwareManager.getDisplayModes()) {
+ builder.append("Display mode " + displayMode.name + "\n");
+ }
+ Toast.makeText(LineageHardwareTest.this, "Display modes: \n"
+ + builder.toString(), Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Get Current Display Mode") {
+ @Override
+ protected void run() {
+ if (displayModesSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Default Display Mode " +
+ mHardwareManager.getCurrentDisplayMode(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ new Test("Test Get Default Display Mode") {
+ @Override
+ protected void run() {
+ if (displayModesSupported()) {
+ Toast.makeText(LineageHardwareTest.this, "Default Display Mode " +
+ mHardwareManager.getCurrentDisplayMode(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ },
+ };
+}
diff --git a/tests/src/org/lineageos/tests/hardware/unit/DisplayModeTest.java b/tests/src/org/lineageos/tests/hardware/unit/DisplayModeTest.java
new file mode 100644
index 00000000..01a24771
--- /dev/null
+++ b/tests/src/org/lineageos/tests/hardware/unit/DisplayModeTest.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.hardware.unit;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.app.LineageContextConstants;
+import lineageos.hardware.DisplayMode;
+
+/**
+ * Created by adnan on 9/1/15.
+ */
+public class DisplayModeTest extends AndroidTestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Only run this if we support hardware abstraction
+ org.junit.Assume.assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ LineageContextConstants.Features.HARDWARE_ABSTRACTION));
+ }
+
+ @SmallTest
+ public void testDisplayModeUnravelFromParcel() {
+ int expectedId = 1337;
+ String expectedName = "test";
+ DisplayMode expectedDisplayMode = new DisplayMode(expectedId, expectedName);
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ expectedDisplayMode.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ DisplayMode fromParcel = DisplayMode.CREATOR.createFromParcel(parcel);
+
+ assertNotNull(expectedDisplayMode.id);
+ assertNotNull(expectedDisplayMode.name);
+
+ assertEquals(expectedDisplayMode.id, fromParcel.id );
+ assertEquals(expectedDisplayMode.name,
+ fromParcel.name);
+ }
+}
diff --git a/tests/src/org/lineageos/tests/hardware/unit/LineageHardwareManagerTest.java b/tests/src/org/lineageos/tests/hardware/unit/LineageHardwareManagerTest.java
new file mode 100644
index 00000000..01a8145f
--- /dev/null
+++ b/tests/src/org/lineageos/tests/hardware/unit/LineageHardwareManagerTest.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.hardware.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import lineageos.app.LineageContextConstants;
+import lineageos.hardware.LineageHardwareManager;
+import lineageos.hardware.ILineageHardwareService;
+
+/**
+ * Created by adnan on 9/1/15.
+ */
+public class LineageHardwareManagerTest extends AndroidTestCase {
+ private LineageHardwareManager mLineageHardwareManager;
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Only run this if we support hardware abstraction
+ org.junit.Assume.assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ LineageContextConstants.Features.HARDWARE_ABSTRACTION));
+ mLineageHardwareManager = LineageHardwareManager.getInstance(mContext);
+ }
+
+ @SmallTest
+ public void testManagerExists() {
+ assertNotNull(mLineageHardwareManager);
+ }
+
+ @SmallTest
+ public void testManagerServiceIsAvailable() {
+ ILineageHardwareService ilineageStatusBarManager = mLineageHardwareManager.getService();
+ assertNotNull(ilineageStatusBarManager);
+ }
+}
diff --git a/tests/src/org/lineageos/tests/hardware/unit/LiveDisplayManagerTest.java b/tests/src/org/lineageos/tests/hardware/unit/LiveDisplayManagerTest.java
new file mode 100644
index 00000000..2f0eec9c
--- /dev/null
+++ b/tests/src/org/lineageos/tests/hardware/unit/LiveDisplayManagerTest.java
@@ -0,0 +1,152 @@
+package org.lineageos.tests.hardware.unit;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Assume;
+
+import lineageos.app.LineageContextConstants;
+import lineageos.hardware.LineageHardwareManager;
+import lineageos.hardware.ILiveDisplayService;
+import lineageos.hardware.LiveDisplayConfig;
+import lineageos.hardware.LiveDisplayManager;
+import lineageos.util.ColorUtils;
+
+public class LiveDisplayManagerTest extends AndroidTestCase {
+
+ private static final String TAG = "LiveDisplayManagerTest";
+
+ private LiveDisplayManager mLiveDisplay;
+ private LineageHardwareManager mHardware;
+
+ private PowerManager mPower;
+ private PowerManager.WakeLock mWakeLock;
+
+ private LiveDisplayConfig mConfig;
+ private int mInitialMode;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ Assume.assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ LineageContextConstants.Features.LIVEDISPLAY));
+
+ mLiveDisplay = LiveDisplayManager.getInstance(mContext);
+ if (mLiveDisplay.getConfig().hasModeSupport()) {
+ mInitialMode = mLiveDisplay.getMode();
+ }
+ mConfig = mLiveDisplay.getConfig();
+
+ mHardware = LineageHardwareManager.getInstance(mContext);
+ mPower = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = mPower.newWakeLock(
+ PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, TAG);
+ mWakeLock.acquire();
+ }
+
+ @Override
+ protected void tearDown() {
+ mLiveDisplay.setMode(mInitialMode);
+ mWakeLock.release();
+ }
+
+ @SmallTest
+ public void testManagerExists() {
+ assertNotNull(mLiveDisplay);
+ }
+
+ @SmallTest
+ public void testManagerServiceIsAvailable() {
+ ILiveDisplayService service = LiveDisplayManager.getService();
+ assertNotNull(service);
+ }
+
+ @SmallTest
+ public void testConfig() {
+ assertNotNull(mConfig);
+
+ // at least GPU mode should be available
+ assertTrue(mConfig.isAvailable());
+ }
+
+ @SmallTest
+ public void testNightMode() throws Exception {
+ Assume.assumeTrue(mConfig.hasModeSupport());
+
+ int day = mLiveDisplay.getDayColorTemperature();
+ int night = mLiveDisplay.getNightColorTemperature();
+
+ mLiveDisplay.setMode(LiveDisplayManager.MODE_NIGHT);
+ assertColorTemperature(night);
+
+ // custom value
+ mLiveDisplay.setNightColorTemperature(3300);
+ assertColorTemperature(3300);
+
+ // "default"
+ mLiveDisplay.setNightColorTemperature(mConfig.getDefaultNightTemperature());
+ assertColorTemperature(mConfig.getDefaultNightTemperature());
+
+ mLiveDisplay.setNightColorTemperature(night);
+
+ // day should not have changed
+ assertEquals(day, mLiveDisplay.getDayColorTemperature());
+ }
+
+ @SmallTest
+ public void testDayMode() throws Exception {
+ Assume.assumeTrue(mConfig.hasModeSupport());
+
+ int day = mLiveDisplay.getDayColorTemperature();
+ int night = mLiveDisplay.getNightColorTemperature();
+
+ mLiveDisplay.setMode(LiveDisplayManager.MODE_DAY);
+ assertColorTemperature(day);
+
+ // custom value
+ mLiveDisplay.setDayColorTemperature(8000);
+ assertColorTemperature(8000);
+
+ // "default"
+ mLiveDisplay.setDayColorTemperature(mConfig.getDefaultDayTemperature());
+ assertColorTemperature(mConfig.getDefaultDayTemperature());
+
+ mLiveDisplay.setDayColorTemperature(day);
+
+ // night should not have changed
+ assertEquals(night, mLiveDisplay.getNightColorTemperature());
+ }
+
+ @SmallTest
+ public void testOutdoorMode() throws Exception {
+ Assume.assumeTrue(mConfig.hasFeature(LiveDisplayManager.MODE_OUTDOOR));
+
+ assertTrue(mHardware.isSupported(LineageHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT));
+
+ mLiveDisplay.setMode(LiveDisplayManager.MODE_OUTDOOR);
+ Thread.sleep(1000);
+ assertTrue(mHardware.get(LineageHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT));
+
+ mLiveDisplay.setMode(LiveDisplayManager.MODE_OFF);
+ Thread.sleep(1000);
+ assertFalse(mHardware.get(LineageHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT));
+ }
+
+ private void assertColorTemperature(int degK) throws Exception {
+ Thread.sleep(2000);
+ assertEquals(degK, LiveDisplayManager.getService().getColorTemperature());
+ checkHardwareValue(ColorUtils.temperatureToRGB(degK));
+ }
+
+ private void checkHardwareValue(float[] expected) {
+ int[] hardware = mHardware.getDisplayColorCalibration();
+ int max = mHardware.getDisplayColorCalibrationMax();
+ assertEquals((int)Math.floor(expected[0] * max), hardware[0]);
+ assertEquals((int)Math.floor(expected[1] * max), hardware[1]);
+ assertEquals((int)Math.floor(expected[2] * max), hardware[2]);
+ }
+}
diff --git a/tests/src/org/lineageos/tests/media/unit/LineageAudioManagerTest.java b/tests/src/org/lineageos/tests/media/unit/LineageAudioManagerTest.java
new file mode 100644
index 00000000..e35d3c88
--- /dev/null
+++ b/tests/src/org/lineageos/tests/media/unit/LineageAudioManagerTest.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.lineageos.tests.media.unit;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import org.junit.Assume;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import lineageos.app.LineageContextConstants;
+import lineageos.media.AudioSessionInfo;
+import lineageos.media.LineageAudioManager;
+import lineageos.media.ILineageAudioService;
+
+public class LineageAudioManagerTest extends AndroidTestCase {
+
+ private static final String TAG = "LineageAudioManagerTest";
+
+ private LineageAudioManager mLineageAudioManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ Assume.assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ LineageContextConstants.Features.AUDIO));
+
+ mLineageAudioManager = LineageAudioManager.getInstance(mContext);
+ }
+
+ /**
+ * EXPECT: The platform should return a valid manager instance.
+ */
+ @SmallTest
+ public void testManagerExists() {
+ assertNotNull(mLineageAudioManager);
+ }
+
+ /**
+ * EXPECT: The service in the manager should also be valid.
+ */
+ @SmallTest
+ public void testManagerServiceIsAvailable() {
+ ILineageAudioService service = LineageAudioManager.getService();
+ assertNotNull(service);
+ }
+
+ /**
+ * EXPECT: listAudioSessions should be populated when a new stream is
+ * created, and it's session ID should match what AudioTrack says it is.
+ *
+ * We simply create an audio track, and query the policy for sessions.
+ */
+ @SmallTest
+ public void testSessionList() {
+
+ AudioTrack track = createTestTrack();
+ int session = track.getAudioSessionId();
+
+ AudioSessionInfo info = findAudioSessionInfo(session);
+ assertNotNull(info);
+ assertEquals(session, info.getSessionId());
+ assertEquals(3, info.getChannelMask());
+
+ track.release();
+
+ info = findAudioSessionInfo(session);
+ assertNull(info);
+ }
+
+ /**
+ * EXPECT: LineageAudioManager.ACTION_AUDIO_SESSIONS_CHANGED should be broadcast when
+ * audio sessions are opened and closed.
+ *
+ * We register a receiver for the broadcast, create an AudioTrack, and wait to
+ * observe both the open and close session events. The info in the returned
+ * AudioSessionInfo should match our expectations.
+ */
+ @SmallTest
+ public void testSessionInfoBroadcast() throws Exception {
+
+ IntentFilter filter = new IntentFilter(LineageAudioManager.ACTION_AUDIO_SESSIONS_CHANGED);
+ AudioSessionReceiver receiver = new AudioSessionReceiver(2);
+ mContext.registerReceiver(receiver, filter);
+
+ AudioTrack track = createTestTrack();
+ track.play();
+ track.release();
+
+ receiver.waitForSessions();
+
+ mContext.unregisterReceiver(receiver);
+
+ assertEquals(1, receiver.getNumAdded());
+ assertEquals(1, receiver.getNumRemoved());
+
+ assertEquals(1, receiver.getSessions().size());
+
+ AudioSessionInfo info = receiver.getSessions().get(0);
+ assertNotNull(info);
+ assertNotNull(info.toString());
+ assertEquals(track.getAudioSessionId(), info.getSessionId());
+ assertEquals(3, info.getChannelMask());
+ assertEquals(AudioManager.STREAM_MUSIC, info.getStream());
+
+ }
+
+ private static final int SESSIONS = 50;
+
+ /**
+ * EXPECT: The ACTION_AUDIO_SESSIONS_CHANGED broadcast and associated backend should
+ * be resilent to multithreaded and/or aggressive/destructive usage. A single add
+ * and a single remove event should be broadcast for the lifecycle of a stream.
+ *
+ * We register a receiver for session events, spawn a small thread pool, and create
+ * up to SESSIONS AudioTracks and play + release them on the thread. A small delay
+ * is inserted to prevent AudioFlinger from running out of tracks. Once the expected
+ * number of sessions arrives, we verify our expectation regarding event counts,
+ * and additionally verify that all the session ids we saw when creating our
+ * AudioTracks were returned in the AudioSessionInfo broadcasts.
+ */
+ @SmallTest
+ public void testSymphonyOfDestruction() throws Exception {
+ IntentFilter filter = new IntentFilter(LineageAudioManager.ACTION_AUDIO_SESSIONS_CHANGED);
+ AudioSessionReceiver receiver = new AudioSessionReceiver(SESSIONS * 2);
+ mContext.registerReceiver(receiver, filter);
+
+ final List<Integer> sessions = new ArrayList<Integer>();
+
+ ExecutorService sexecutioner = Executors.newFixedThreadPool(5);
+ for (int i = 0; i < SESSIONS; i++) {
+ sexecutioner.submit(new Runnable() {
+ @Override
+ public void run() {
+ AudioTrack track = createTestTrack();
+ synchronized (sessions) {
+ sessions.add(track.getAudioSessionId());
+ }
+ track.play();
+ track.release();
+ }
+ });
+ if ((i % 2) == 0) {
+ Thread.sleep(100);
+ }
+ }
+
+ receiver.waitForSessions();
+ sexecutioner.shutdown();
+
+ assertEquals(SESSIONS, sessions.size());
+ assertEquals(SESSIONS, receiver.getNumAdded());
+ assertEquals(SESSIONS, receiver.getNumRemoved());
+
+ for (AudioSessionInfo info : receiver.getSessions()) {
+ assertTrue(sessions.contains(info.getSessionId()));
+ }
+ }
+
+ private static class AudioSessionReceiver extends BroadcastReceiver {
+
+ private int mAdded = 0;
+ private int mRemoved = 0;
+
+ private final CountDownLatch mLatch;
+
+ private List<AudioSessionInfo> mSessions = new ArrayList<AudioSessionInfo>();
+
+ public AudioSessionReceiver(int count) {
+ mLatch = new CountDownLatch(count);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ assertNotNull(intent);
+
+ boolean added = intent.getBooleanExtra(LineageAudioManager.EXTRA_SESSION_ADDED, false);
+
+ AudioSessionInfo info = intent.getParcelableExtra(LineageAudioManager.EXTRA_SESSION_INFO);
+ Log.d(TAG, "onReceive: " + info);
+
+ assertNotNull(info);
+
+ synchronized (mSessions) {
+ if (added) {
+ mAdded++;
+ mSessions.add(info);
+ } else {
+ mRemoved++;
+ }
+ }
+
+ mLatch.countDown();
+ }
+
+ public int getNumAdded() {
+ return mAdded;
+ }
+
+ public int getNumRemoved() {
+ return mRemoved;
+ }
+
+ public List<AudioSessionInfo> getSessions() {
+ return mSessions;
+ }
+
+ public void waitForSessions() throws InterruptedException {
+ mLatch.await(60, TimeUnit.SECONDS);
+ }
+ };
+
+ private AudioSessionInfo findAudioSessionInfo(int sessionId) {
+ List<AudioSessionInfo> infos = mLineageAudioManager.listAudioSessions(AudioManager.STREAM_MUSIC);
+ for (AudioSessionInfo info : infos) {
+ if (info.getSessionId() == sessionId) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ private AudioTrack createTestTrack() {
+ int bytes = 2 * 44100 / 1000;
+ AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
+ AudioFormat.CHANNEL_OUT_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT,
+ bytes,
+ AudioTrack.STATE_INITIALIZED);
+ return track;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/power/unit/PerfomanceManagerTest.java b/tests/src/org/lineageos/tests/power/unit/PerfomanceManagerTest.java
new file mode 100644
index 00000000..4259ef62
--- /dev/null
+++ b/tests/src/org/lineageos/tests/power/unit/PerfomanceManagerTest.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.lineageos.tests.power.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import lineageos.app.LineageContextConstants;
+import lineageos.power.IPerformanceManager;
+import lineageos.power.PerformanceManager;
+import lineageos.power.PerformanceProfile;
+
+/**
+ * Code coverage for public facing {@link PerformanceManager} interfaces.
+ * The test below will save and restore the current performance profile to
+ * not impact successive tests.
+ */
+public class PerfomanceManagerTest extends AndroidTestCase {
+ private static final String TAG = PerfomanceManagerTest.class.getSimpleName();
+ private static final int IMPOSSIBLE_POWER_PROFILE = -1;
+ private PerformanceManager mLineagePerformanceManager;
+ private PerformanceProfile mSavedPerfProfile;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Only run this if we support performance abstraction
+ org.junit.Assume.assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ LineageContextConstants.Features.PERFORMANCE));
+ mLineagePerformanceManager = PerformanceManager.getInstance(mContext);
+ // Save the perf profile for later restore.
+ mSavedPerfProfile = mLineagePerformanceManager.getPowerProfile(
+ mLineagePerformanceManager.getPowerProfile());
+ }
+
+ @SmallTest
+ public void testManagerExists() {
+ assertNotNull(mLineagePerformanceManager);
+ }
+
+ @SmallTest
+ public void testManagerServiceIsAvailable() {
+ IPerformanceManager ilineageStatusBarManager = mLineagePerformanceManager.getService();
+ assertNotNull(ilineageStatusBarManager);
+ }
+
+ @SmallTest
+ public void testPowerProfileCantBeSetIfNoneSupported() {
+ // Assert that if we attempt to set a power profile if none supported
+ // then we receive a failed response from the service.
+ if (mLineagePerformanceManager.getNumberOfProfiles() == 0) {
+ for (int powerProfile = 0; powerProfile <
+ PerformanceManager.POSSIBLE_POWER_PROFILES.length; powerProfile++) {
+ assertFalse(mLineagePerformanceManager.setPowerProfile(powerProfile));
+ }
+ }
+ }
+
+ @SmallTest
+ public void testGetPowerProfile() {
+ assertNotSame(IMPOSSIBLE_POWER_PROFILE, mSavedPerfProfile);
+ }
+
+ @SmallTest
+ public void testSetAndGetPowerProfile() {
+ // Identify what power profiles are supported. The api currently returns
+ // the total number of profiles supported in an ordered manner, thus we can
+ // assume what they are and if we can set everything correctly.
+ // TODO: Don't skip powersave. Skipped due to powersave being ignored while device plugged
+ for (int powerProfile = 1; powerProfile <
+ PerformanceManager.POSSIBLE_POWER_PROFILES.length; powerProfile++) {
+ if (powerProfile < mLineagePerformanceManager.getNumberOfProfiles()) {
+ //It is supported, set it and test if it was set
+ if (mLineagePerformanceManager.getPowerProfile() != powerProfile) {
+ mLineagePerformanceManager.setPowerProfile(powerProfile);
+ // Verify that it was set correctly.
+ assertEquals(powerProfile, mLineagePerformanceManager.getPowerProfile());
+ }
+ } else {
+ assertFalse(mLineagePerformanceManager.setPowerProfile(powerProfile));
+ }
+ }
+ }
+
+ @SmallTest
+ public void testGetPerfProfileHasAppProfiles() {
+ // No application has power save by default
+ assertEquals(false, mLineagePerformanceManager.getProfileHasAppProfiles(
+ PerformanceManager.PROFILE_POWER_SAVE));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ // Reset
+ mLineagePerformanceManager.setPowerProfile(mSavedPerfProfile.getId());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/ProfileTest.java b/tests/src/org/lineageos/tests/profiles/ProfileTest.java
new file mode 100644
index 00000000..1e77538d
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/ProfileTest.java
@@ -0,0 +1,185 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles;
+
+import android.media.AudioManager;
+import android.os.Bundle;
+
+import lineageos.app.Profile;
+import lineageos.app.Profile.Type;
+
+import lineageos.app.ProfileManager;
+import lineageos.profiles.AirplaneModeSettings;
+import lineageos.profiles.BrightnessSettings;
+import lineageos.profiles.ConnectionSettings;
+import lineageos.profiles.LockSettings;
+import lineageos.profiles.RingModeSettings;
+import lineageos.profiles.StreamSettings;
+import org.lineageos.tests.TestActivity;
+
+import java.util.ArrayList;
+import java.util.UUID;
+
+/**
+ * Created by adnan on 6/26/15.
+ */
+public class ProfileTest extends TestActivity {
+ private ProfileManager mProfileManager;
+ private ArrayList<UUID> mProfileUuidList;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mProfileManager = ProfileManager.getInstance(this);
+ mProfileUuidList = new ArrayList<UUID>();
+ }
+
+ @Override
+ protected Test[] tests() {
+ return mTests;
+ }
+
+ @Override
+ protected String tag() {
+ return null;
+ }
+
+ private Test[] mTests = new Test[] {
+ new Test("test create random Profile") {
+ public void run() {
+ Profile profile = new Profile("Test Profile");
+ profile.setProfileType(Type.TOGGLE);
+ profile.setExpandedDesktopMode(Profile.ExpandedDesktopMode.ENABLE);
+ profile.setDozeMode(Profile.DozeMode.DEFAULT);
+ profile.setScreenLockMode(new LockSettings(Profile.LockMode.DISABLE));
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ }
+ },
+ new Test("test add static Profile") {
+ public void run() {
+ Profile profile = new Profile("Test Profile-Active",
+ 0, UUID.fromString("65cd0d0c-1c42-11e5-9a21-1697f925ec7b"));
+ profile.setProfileType(Type.TOGGLE);
+ profile.setExpandedDesktopMode(Profile.ExpandedDesktopMode.ENABLE);
+ profile.setDozeMode(Profile.DozeMode.DEFAULT);
+ profile.setScreenLockMode(new LockSettings(Profile.LockMode.DISABLE));
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ mProfileManager.setActiveProfile(profile.getUuid());
+ }
+ },
+ new Test("test remove static Profile") {
+ public void run() {
+ mProfileManager.removeProfile(
+ mProfileManager.getProfile("65cd0d0c-1c42-11e5-9a21-1697f925ec7b"));
+ }
+ },
+ new Test("test create Profile and Set Active") {
+ public void run() {
+ Profile profile = new Profile("Test Profile-Active");
+ profile.setProfileType(Type.TOGGLE);
+ profile.setExpandedDesktopMode(Profile.ExpandedDesktopMode.ENABLE);
+ profile.setDozeMode(Profile.DozeMode.DEFAULT);
+ profile.setScreenLockMode(new LockSettings(Profile.LockMode.DISABLE));
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ mProfileManager.setActiveProfile(profile.getUuid());
+ }
+ },
+ new Test("test create Profile, override airplane settings, and set active") {
+ @Override
+ protected void run() {
+ Profile profile = new Profile("Test Profile-Override-AIR-Active");
+ profile.setProfileType(Type.TOGGLE);
+ AirplaneModeSettings airplaneModeSettings =
+ new AirplaneModeSettings(
+ AirplaneModeSettings.BooleanState.STATE_ENABLED, true);
+ profile.setAirplaneMode(airplaneModeSettings);
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ mProfileManager.setActiveProfile(profile.getUuid());
+ }
+ },
+ new Test("test create Profile, override ring stream settings, and set active") {
+ @Override
+ protected void run() {
+ Profile profile = new Profile("Test Profile-Override-RNG-Active");
+ profile.setProfileType(Type.TOGGLE);
+ StreamSettings streamSettings =
+ new StreamSettings(AudioManager.STREAM_RING, 0, true);
+ profile.setStreamSettings(streamSettings);
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ mProfileManager.setActiveProfile(profile.getUuid());
+ }
+ },
+ new Test("test create Profile, override BT connection settings, and set active") {
+ @Override
+ protected void run() {
+ Profile profile = new Profile("Test Profile-Override-CNNCT-Active");
+ profile.setProfileType(Type.TOGGLE);
+ ConnectionSettings connectionSettings =
+ new ConnectionSettings(ConnectionSettings.PROFILE_CONNECTION_BLUETOOTH,
+ ConnectionSettings.BooleanState.STATE_ENABLED, true);
+ profile.setConnectionSettings(connectionSettings);
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ mProfileManager.setActiveProfile(profile.getUuid());
+ }
+ },
+ new Test("test create Profile, override brightness settings, and set active") {
+ @Override
+ protected void run() {
+ Profile profile = new Profile("Test Profile-Override-BRGHT-Active");
+ profile.setProfileType(Type.TOGGLE);
+ BrightnessSettings brightnessSettings =
+ new BrightnessSettings(0, true);
+ profile.setBrightness(brightnessSettings);
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ mProfileManager.setActiveProfile(profile.getUuid());
+ }
+ },
+ new Test("test create Profile, override ringmode settings, and set active") {
+ @Override
+ protected void run() {
+ Profile profile = new Profile("Test Profile-Override-RNGMD-Active");
+ profile.setProfileType(Type.TOGGLE);
+ RingModeSettings ringSettings = new RingModeSettings(
+ RingModeSettings.RING_MODE_MUTE, true);
+ profile.setRingMode(ringSettings);
+ mProfileUuidList.add(profile.getUuid());
+ mProfileManager.addProfile(profile);
+ mProfileManager.setActiveProfile(profile.getUuid());
+ }
+ },
+ new Test("Reset All") {
+ @Override
+ protected void run() {
+ // make sure we remove our own
+ for (UUID uuid: mProfileUuidList) {
+ Profile profile = mProfileManager.getProfile(uuid);
+ if (profile != null) {
+ mProfileManager.removeProfile(profile);
+ }
+ }
+ mProfileManager.resetAll();
+ }
+ }
+ };
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/AirplaneModeSettingsTest.java b/tests/src/org/lineageos/tests/profiles/unit/AirplaneModeSettingsTest.java
new file mode 100644
index 00000000..25a0fb1e
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/AirplaneModeSettingsTest.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.profiles.AirplaneModeSettings;
+
+public class AirplaneModeSettingsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testConstructWholly() {
+ AirplaneModeSettings airplaneModeSettings =
+ new AirplaneModeSettings(
+ AirplaneModeSettings.BooleanState.STATE_ENABLED, true);
+ assertEquals(AirplaneModeSettings.BooleanState.STATE_ENABLED, airplaneModeSettings.getValue());
+ assertEquals(true, airplaneModeSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyOverride() {
+ AirplaneModeSettings airplaneModeSettings =
+ new AirplaneModeSettings(
+ AirplaneModeSettings.BooleanState.STATE_ENABLED, true);
+ airplaneModeSettings.setOverride(false);
+ assertEquals(false, airplaneModeSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyValue() {
+ int expectedValue = AirplaneModeSettings.BooleanState.STATE_DISALED;
+ AirplaneModeSettings airplaneModeSettings =
+ new AirplaneModeSettings(
+ AirplaneModeSettings.BooleanState.STATE_ENABLED, true);
+ airplaneModeSettings.setValue(expectedValue);
+ assertEquals(expectedValue, airplaneModeSettings.getValue());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/BrightnessSettingsTest.java b/tests/src/org/lineageos/tests/profiles/unit/BrightnessSettingsTest.java
new file mode 100644
index 00000000..73814d88
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/BrightnessSettingsTest.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.profiles.BrightnessSettings;
+
+public class BrightnessSettingsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testConstructWholly() {
+ BrightnessSettings brightnessSettings =
+ new BrightnessSettings(0, true);
+ assertEquals(0, brightnessSettings.getValue());
+ assertEquals(true, brightnessSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyOverride() {
+ BrightnessSettings brightnessSettings =
+ new BrightnessSettings(0, true);
+ brightnessSettings.setOverride(false);
+ assertEquals(false, brightnessSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyValue() {
+ int expectedValue = 30;
+ BrightnessSettings brightnessSettings =
+ new BrightnessSettings(0, true);
+ brightnessSettings.setValue(expectedValue);
+ assertEquals(expectedValue, brightnessSettings.getValue());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/ConnectionSettingsTest.java b/tests/src/org/lineageos/tests/profiles/unit/ConnectionSettingsTest.java
new file mode 100644
index 00000000..4564727e
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/ConnectionSettingsTest.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.lineageos.tests.profiles.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.profiles.ConnectionSettings;
+
+public class ConnectionSettingsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testConstructManually() {
+ ConnectionSettings connectionSettings = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_GPS);
+ assertEquals(ConnectionSettings.PROFILE_CONNECTION_GPS,
+ connectionSettings.getConnectionId());
+ assertNotNull(connectionSettings);
+ }
+
+ @SmallTest
+ public void testConstructWholly() {
+ ConnectionSettings connectionSettings =
+ new ConnectionSettings(ConnectionSettings.PROFILE_CONNECTION_GPS,
+ ConnectionSettings.BooleanState.STATE_DISALED, true);
+ assertEquals(true, connectionSettings.isOverride());
+ assertEquals(ConnectionSettings.BooleanState.STATE_DISALED,
+ connectionSettings.getValue());
+ assertEquals(ConnectionSettings.PROFILE_CONNECTION_GPS,
+ connectionSettings.getConnectionId());
+ assertNotNull(connectionSettings);
+ }
+
+ @SmallTest
+ public void testVerifyOverride() {
+ ConnectionSettings connectionSettings = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_GPS);
+ connectionSettings.setOverride(true);
+ assertEquals(true, connectionSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifySubId() {
+ int expectedSubId = 2;
+ ConnectionSettings connectionSettings = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_2G3G4G);
+ connectionSettings.setSubId(expectedSubId);
+ assertEquals(expectedSubId, connectionSettings.getSubId());
+ }
+
+ @SmallTest
+ public void testVerifyValue() {
+ int expectedValue = ConnectionSettings.BooleanState.STATE_DISALED;
+ ConnectionSettings connectionSettings = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_2G3G4G);
+ connectionSettings.setValue(expectedValue);
+ assertEquals(expectedValue, connectionSettings.getValue());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/LockSettingsTest.java b/tests/src/org/lineageos/tests/profiles/unit/LockSettingsTest.java
new file mode 100644
index 00000000..f3a47570
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/LockSettingsTest.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.app.Profile;
+import lineageos.profiles.LockSettings;
+
+public class LockSettingsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testConstructWholly() {
+ LockSettings lockSettings = new LockSettings(Profile.LockMode.INSECURE);
+ assertEquals(Profile.LockMode.INSECURE, lockSettings.getValue());
+ }
+
+ @SmallTest
+ public void testVerifyValue() {
+ int expectedValue = Profile.LockMode.DEFAULT;
+ LockSettings lockSettings = new LockSettings(Profile.LockMode.INSECURE);
+ lockSettings.setValue(expectedValue);
+ assertEquals(expectedValue, lockSettings.getValue());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/ProfileManagerTest.java b/tests/src/org/lineageos/tests/profiles/unit/ProfileManagerTest.java
new file mode 100644
index 00000000..c507e80b
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/ProfileManagerTest.java
@@ -0,0 +1,225 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles.unit;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import lineageos.app.LineageContextConstants;
+import lineageos.app.Profile;
+import lineageos.app.ProfileManager;
+import lineageos.app.IProfileManager;
+import lineageos.providers.LineageSettings;
+
+import java.util.Arrays;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+
+public class ProfileManagerTest extends AndroidTestCase {
+ private static final String TAG = ProfileManagerTest.class.getSimpleName();
+ private static final int COUNTDOWN = 1;
+ private ProfileManager mProfileManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mProfileManager = ProfileManager.getInstance(mContext);
+ // Only run this if we support profiles service
+ org.junit.Assume.assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ LineageContextConstants.Features.PROFILES));
+ }
+
+ @SmallTest
+ public void testManagerExists() {
+ assertNotNull(mProfileManager);
+ }
+
+ @SmallTest
+ public void testManagerServiceIsAvailable() {
+ IProfileManager iProfileManager = mProfileManager.getService();
+ assertNotNull(iProfileManager);
+ }
+
+ @SmallTest
+ public void testManagerProfileIsEnabled() {
+ // first enable profiles
+ final String enabledValue = "1";
+ assertTrue(LineageSettings.System.putString(getContext().getContentResolver(),
+ LineageSettings.System.SYSTEM_PROFILES_ENABLED, enabledValue));
+
+ // check that we successfully enabled them via system setting
+ assertEquals(enabledValue, LineageSettings.System.getString(getContext().getContentResolver(),
+ LineageSettings.System.SYSTEM_PROFILES_ENABLED));
+
+ // check that profile manger returns true
+ assertTrue(mProfileManager.isProfilesEnabled());
+
+ // now disable the setting
+ final String disabledValue = "0";
+ assertTrue(LineageSettings.System.putString(getContext().getContentResolver(),
+ LineageSettings.System.SYSTEM_PROFILES_ENABLED, disabledValue));
+
+ // check that we successfully disable them via system setting
+ assertEquals(disabledValue, LineageSettings.System.getString(getContext().getContentResolver(),
+ LineageSettings.System.SYSTEM_PROFILES_ENABLED));
+
+ assertFalse(mProfileManager.isProfilesEnabled());
+ }
+
+ private void ensureProfilesEnabled() {
+ final String enabledValue = "1";
+ assertTrue(LineageSettings.System.putString(getContext().getContentResolver(),
+ LineageSettings.System.SYSTEM_PROFILES_ENABLED, enabledValue));
+ }
+
+ @SmallTest
+ public void testGetActiveProfile() {
+ ensureProfilesEnabled();
+ final CountDownLatch signal = new CountDownLatch(COUNTDOWN);
+ final Profile expectedActiveProfile = new Profile("TEST ACTIVE PROFILE");
+ mProfileManager.addProfile(expectedActiveProfile);
+
+ BroadcastReceiver intentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ signal.countDown();
+ }
+ };
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ProfileManager.INTENT_ACTION_PROFILE_SELECTED);
+ intentFilter.addAction(ProfileManager.INTENT_ACTION_PROFILE_UPDATED);
+
+ mContext.registerReceiver(intentReceiver, intentFilter);
+
+ mProfileManager.setActiveProfile(expectedActiveProfile.getName());
+
+ // Lock
+ try {
+ signal.await();
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+
+ assertEquals(expectedActiveProfile.getName(),
+ mProfileManager.getActiveProfile().getName());
+ mProfileManager.resetAll();
+
+ mContext.unregisterReceiver(intentReceiver);
+ }
+
+ @SmallTest
+ public void testGetProfileNames() {
+ ensureProfilesEnabled();
+ String[] expectedProfileNames = new String[5];
+ // These defaults are pulled from the default xml in the lineage platform resource package
+ Profile expectedProfile1 = mProfileManager.getProfile(
+ UUID.fromString("6a181391-12ef-4f43-a701-32b11ed69449"));
+ Profile expectedProfile2 = mProfileManager.getProfile(
+ UUID.fromString("0230226d-0d05-494a-a9bd-d222a1117655"));
+ Profile expectedProfile3 = mProfileManager.getProfile(
+ UUID.fromString("e4e77d03-82ce-4417-9257-7d6c9ffb8fd1"));
+
+ // Add extras
+ Profile expectedProfile4 = new Profile("PROFILE 1");
+ Profile expectedProfile5 = new Profile("PROFILE 2");
+
+ expectedProfileNames[0] = expectedProfile1.getName();
+ expectedProfileNames[1] = expectedProfile2.getName();
+ expectedProfileNames[2] = expectedProfile3.getName();
+ expectedProfileNames[3] = expectedProfile4.getName();
+ expectedProfileNames[4] = expectedProfile5.getName();
+
+ mProfileManager.addProfile(expectedProfile1);
+ mProfileManager.addProfile(expectedProfile2);
+
+ String[] actualProfileNames = mProfileManager.getProfileNames();
+ for (int i = 0; i < actualProfileNames.length; i++) {
+ assertEquals(expectedProfileNames[i], actualProfileNames[i]);
+ }
+ mProfileManager.resetAll();
+ }
+
+ @SmallTest
+ public void testGetProfiles() {
+ ensureProfilesEnabled();
+ Profile[] expectedProfiles = new Profile[5];
+ // These defaults are pulled from the default xml in the lineage platform resource package
+ Profile expectedProfile1 = mProfileManager.getProfile(
+ UUID.fromString("6a181391-12ef-4f43-a701-32b11ed69449"));
+ Profile expectedProfile2 = mProfileManager.getProfile(
+ UUID.fromString("0230226d-0d05-494a-a9bd-d222a1117655"));
+ Profile expectedProfile3 = mProfileManager.getProfile(
+ UUID.fromString("e4e77d03-82ce-4417-9257-7d6c9ffb8fd1"));
+
+ // Add extras
+ Profile expectedProfile4 = new Profile("PROFILE 1");
+ Profile expectedProfile5 = new Profile("PROFILE 2");
+
+ expectedProfiles[0] = expectedProfile1;
+ expectedProfiles[1] = expectedProfile2;
+ expectedProfiles[2] = expectedProfile3;
+ expectedProfiles[3] = expectedProfile4;
+ expectedProfiles[4] = expectedProfile5;
+
+ // The actual results come back in alphabetical order, :/
+ Arrays.sort(expectedProfiles);
+
+ mProfileManager.addProfile(expectedProfile4);
+ mProfileManager.addProfile(expectedProfile5);
+
+ Profile[] actualProfiles = mProfileManager.getProfiles();
+ for (int i = 0; i < actualProfiles.length; i++) {
+ assertEquals(expectedProfiles[i].getName(), actualProfiles[i].getName());
+ }
+ mProfileManager.resetAll();
+ }
+
+ @SmallTest
+ public void testProfileExists() {
+ ensureProfilesEnabled();
+ assertTrue(mProfileManager.profileExists(
+ UUID.fromString("6a181391-12ef-4f43-a701-32b11ed69449")));
+ assertTrue(mProfileManager.profileExists(
+ UUID.fromString("0230226d-0d05-494a-a9bd-d222a1117655")));
+ assertTrue(mProfileManager.profileExists(
+ UUID.fromString("e4e77d03-82ce-4417-9257-7d6c9ffb8fd1")));
+ String expectedProfileName = "PROFILE 1";
+ Profile expectedProfile = new Profile(expectedProfileName);
+ mProfileManager.addProfile(expectedProfile);
+ assertTrue(mProfileManager.profileExists(expectedProfileName));
+ mProfileManager.resetAll();
+ }
+
+ @SmallTest
+ public void testUpdateProfile() {
+ ensureProfilesEnabled();
+ String originalProfileName = "PROFILE 1";
+ String expectedProfileName = "PROFILE 2";
+ Profile expectedProfile = new Profile(originalProfileName);
+ mProfileManager.addProfile(expectedProfile);
+ expectedProfile.setName(expectedProfileName);
+ mProfileManager.updateProfile(expectedProfile);
+ assertNotSame(originalProfileName, expectedProfile.getName());
+ assertEquals(expectedProfileName, expectedProfile.getName());
+ mProfileManager.resetAll();
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/ProfileTest.java b/tests/src/org/lineageos/tests/profiles/unit/ProfileTest.java
new file mode 100644
index 00000000..899b0066
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/ProfileTest.java
@@ -0,0 +1,539 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles.unit;
+
+import android.media.AudioManager;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import lineageos.app.LineageContextConstants;
+import lineageos.app.Profile;
+import lineageos.profiles.AirplaneModeSettings;
+import lineageos.profiles.BrightnessSettings;
+import lineageos.profiles.ConnectionSettings;
+import lineageos.profiles.LockSettings;
+import lineageos.profiles.RingModeSettings;
+import lineageos.profiles.StreamSettings;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+public class ProfileTest extends AndroidTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Only run this if we support profiles service
+ org.junit.Assume.assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ LineageContextConstants.Features.PROFILES));
+ }
+
+ @MediumTest
+ public void testProfileConnectionSettingsUnravelFromParcel() {
+ Profile profile = new Profile("Connection Profile");
+ ConnectionSettings expectedConnectionSettings =
+ new ConnectionSettings(ConnectionSettings.PROFILE_CONNECTION_GPS,
+ ConnectionSettings.BooleanState.STATE_DISALED, true);
+ profile.setConnectionSettings(expectedConnectionSettings);
+
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ profile.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ Profile fromParcel = Profile.CREATOR.createFromParcel(parcel);
+
+ assertNotNull(fromParcel);
+ ConnectionSettings actualConnectionSettings = fromParcel.getSettingsForConnection(
+ expectedConnectionSettings.getConnectionId());
+
+ assertEquals(expectedConnectionSettings.getConnectionId(),
+ actualConnectionSettings.getConnectionId());
+ assertEquals(expectedConnectionSettings.getValue(),
+ actualConnectionSettings.getValue());
+ assertEquals(expectedConnectionSettings.isDirty(),
+ actualConnectionSettings.isDirty());
+ assertEquals(expectedConnectionSettings.isOverride(),
+ actualConnectionSettings.isOverride());
+ }
+
+ @MediumTest
+ public void testProfileAirplaneModeSettingsUnravelFromParcel() {
+ Profile profile = new Profile("AirplaneMode Profile");
+ AirplaneModeSettings expectedAirplaneModeSettings =
+ new AirplaneModeSettings(AirplaneModeSettings.BooleanState.STATE_ENABLED, true);
+ profile.setAirplaneMode(expectedAirplaneModeSettings);
+
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ profile.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ Profile fromParcel = Profile.CREATOR.createFromParcel(parcel);
+
+ assertNotNull(fromParcel);
+ AirplaneModeSettings actualAirplaneModeSettings = fromParcel.getAirplaneMode();
+
+ assertEquals(expectedAirplaneModeSettings.getValue(),
+ actualAirplaneModeSettings.getValue());
+ assertEquals(expectedAirplaneModeSettings.isDirty(),
+ actualAirplaneModeSettings.isDirty());
+ assertEquals(expectedAirplaneModeSettings.isOverride(),
+ expectedAirplaneModeSettings.isOverride());
+ }
+
+ @MediumTest
+ public void testProfileBrightnessSettingsUnravelFromParcel() {
+ Profile profile = new Profile("Brightness Profile");
+ BrightnessSettings expectedBrightnessSettings = new BrightnessSettings(0, true);
+ profile.setBrightness(expectedBrightnessSettings);
+
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ profile.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ Profile fromParcel = Profile.CREATOR.createFromParcel(parcel);
+
+ assertNotNull(fromParcel);
+ BrightnessSettings actualBrightnessSettings = fromParcel.getBrightness();
+
+ assertEquals(expectedBrightnessSettings.getValue(), actualBrightnessSettings.getValue());
+ assertEquals(expectedBrightnessSettings.isOverride(),
+ actualBrightnessSettings.isOverride());
+ assertEquals(expectedBrightnessSettings.isDirty(), actualBrightnessSettings.isDirty());
+ }
+
+ @MediumTest
+ public void testProfileRingmodeSettingsUnravelFromParcel() {
+ Profile profile = new Profile("Ringmode Profile");
+ RingModeSettings expectedRingModeSettings =
+ new RingModeSettings(RingModeSettings.RING_MODE_MUTE, true);
+ profile.setRingMode(expectedRingModeSettings);
+
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ profile.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ Profile fromParcel = Profile.CREATOR.createFromParcel(parcel);
+
+ RingModeSettings actualRingModeSettings = fromParcel.getRingMode();
+
+ assertNotNull(fromParcel);
+ assertEquals(expectedRingModeSettings.getValue(), actualRingModeSettings.getValue());
+ assertEquals(expectedRingModeSettings.isDirty(), actualRingModeSettings.isDirty());
+ assertEquals(expectedRingModeSettings.isOverride(), actualRingModeSettings.isOverride());
+ }
+
+ @MediumTest
+ public void testProfileStreamSettingsUnravelFromParcel() {
+ Profile profile = new Profile("Stream Profile");
+ StreamSettings expectedStreamSettings =
+ new StreamSettings(AudioManager.STREAM_RING, 0, true);
+ profile.setStreamSettings(expectedStreamSettings);
+
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ profile.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ Profile fromParcel = Profile.CREATOR.createFromParcel(parcel);
+
+ StreamSettings actualStreamSettings = fromParcel.getSettingsForStream(
+ expectedStreamSettings.getStreamId());
+
+ assertNotNull(fromParcel);
+ assertEquals(expectedStreamSettings.getValue(), actualStreamSettings.getValue());
+ assertEquals(expectedStreamSettings.isOverride(), actualStreamSettings.isOverride());
+ assertEquals(expectedStreamSettings.isDirty(), actualStreamSettings.isDirty());
+ }
+
+ @MediumTest
+ public void testProfileLockSettingsUnravelFromParcel() {
+ Profile profile = new Profile("Lock Profile");
+ LockSettings expectedLockSettings = new LockSettings(Profile.LockMode.INSECURE);
+ profile.setScreenLockMode(expectedLockSettings);
+
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ profile.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ Profile fromParcel = Profile.CREATOR.createFromParcel(parcel);
+
+ LockSettings actualLockSettings = fromParcel.getScreenLockMode();
+
+ assertNotNull(fromParcel);
+ assertEquals(expectedLockSettings.getValue(), actualLockSettings.getValue());
+ assertEquals(expectedLockSettings.isDirty(), actualLockSettings.isDirty());
+ }
+
+ @MediumTest
+ public void testProfileUnravelFromParcel() {
+ Profile profile = new Profile("Single Profile");
+ profile.setProfileType(Profile.Type.TOGGLE);
+ profile.setDozeMode(Profile.DozeMode.ENABLE);
+ profile.setStatusBarIndicator(true);
+
+ // Write to parcel
+ Parcel parcel = Parcel.obtain();
+ profile.writeToParcel(parcel, 0);
+
+ // Rewind
+ parcel.setDataPosition(0);
+
+ // Verify data when unraveling
+ Profile fromParcel = Profile.CREATOR.createFromParcel(parcel);
+
+ assertNotNull(fromParcel);
+ assertEquals(profile.getName(), fromParcel.getName());
+ assertEquals(profile.getProfileType(), fromParcel.getProfileType());
+ assertEquals(profile.getDozeMode(), fromParcel.getDozeMode());
+ assertEquals(profile.getStatusBarIndicator(), fromParcel.getStatusBarIndicator());
+ }
+
+ private static final int EXPECTED_PROFILE_TRIGGER_TYPE = Profile.TriggerType.WIFI;
+ private static final String EXPECTED_PROFILE_TRIGGER_ID = "1337";
+ private static final int EXPECTED_PROFILE_TRIGGER_STATE = Profile.TriggerState.ON_CONNECT;
+ private static final String EXPECTED_PROFILE_TRIGGER_NAME = "ON_CONNECT_WIFI_TRIGGER";
+ private Profile.ProfileTrigger createSampleProfileTrigger() {
+ return new Profile.ProfileTrigger(EXPECTED_PROFILE_TRIGGER_TYPE,
+ EXPECTED_PROFILE_TRIGGER_ID, EXPECTED_PROFILE_TRIGGER_STATE,
+ EXPECTED_PROFILE_TRIGGER_NAME);
+ }
+
+ @SmallTest
+ public void testProfileTriggerId() {
+ Profile.ProfileTrigger profileTrigger = createSampleProfileTrigger();
+ assertEquals(EXPECTED_PROFILE_TRIGGER_ID, profileTrigger.getId());
+ }
+
+ @SmallTest
+ public void testProfileTriggerName() {
+ Profile.ProfileTrigger profileTrigger = createSampleProfileTrigger();
+ assertEquals(EXPECTED_PROFILE_TRIGGER_NAME, profileTrigger.getName());
+ }
+
+ @SmallTest
+ public void testProfileTriggerState() {
+ Profile.ProfileTrigger profileTrigger = createSampleProfileTrigger();
+ assertEquals(EXPECTED_PROFILE_TRIGGER_STATE, profileTrigger.getState());
+ }
+
+ @SmallTest
+ public void testProfileTriggerType() {
+ Profile.ProfileTrigger profileTrigger = createSampleProfileTrigger();
+ assertEquals(EXPECTED_PROFILE_TRIGGER_STATE, profileTrigger.getType());
+ }
+
+ @SmallTest
+ public void testProfileConstructor() {
+ String expectedName = "PROFILE_NAME";
+ Profile profile = new Profile(expectedName);
+ assertEquals(expectedName, profile.getName());
+ }
+
+ @SmallTest
+ public void testProfileAddSecondaryUuid() {
+ UUID[] expectedUUIDs = new UUID[2];
+ UUID expectedUUID1 = UUID.randomUUID();
+ UUID expectedUUID2 = UUID.randomUUID();
+ expectedUUIDs[0] = expectedUUID1;
+ expectedUUIDs[1] = expectedUUID2;
+
+ Profile profile = new Profile("Single Profile");
+ profile.addSecondaryUuid(expectedUUID1);
+ profile.addSecondaryUuid(expectedUUID2);
+
+ UUID[] actualUUIDs = profile.getSecondaryUuids();
+ for (int i = 0; i < actualUUIDs.length; i++) {
+ assertEquals(actualUUIDs[i], expectedUUIDs[i]);
+ }
+
+ profile.setSecondaryUuids(Arrays.asList(expectedUUIDs));
+ for (int i = 0; i < actualUUIDs.length; i++) {
+ assertEquals(actualUUIDs[i], expectedUUIDs[i]);
+ }
+ }
+
+ @SmallTest
+ public void testProfileGetAirplaneMode() {
+ Profile profile = new Profile("AirplaneMode Profile");
+ AirplaneModeSettings expectedAirplaneModeSettings =
+ new AirplaneModeSettings(AirplaneModeSettings.BooleanState.STATE_ENABLED, true);
+ profile.setAirplaneMode(expectedAirplaneModeSettings);
+
+ AirplaneModeSettings actualAirplaneModeSettings = profile.getAirplaneMode();
+ assertEquals(expectedAirplaneModeSettings.getValue(),
+ actualAirplaneModeSettings.getValue());
+ assertEquals(expectedAirplaneModeSettings.isOverride(),
+ actualAirplaneModeSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testProfileGetBrightness() {
+ Profile profile = new Profile("Brightness Profile");
+ BrightnessSettings expectedBrightnessSettings = new BrightnessSettings(0, true);
+ profile.setBrightness(expectedBrightnessSettings);
+
+ BrightnessSettings actualBrightnessSettings = profile.getBrightness();
+ assertEquals(expectedBrightnessSettings.getValue(), actualBrightnessSettings.getValue());
+ assertEquals(expectedBrightnessSettings.isOverride(), actualBrightnessSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testProfileGetConnectionSettingsWithSubId() {
+ int targetSubId = 0;
+ Profile profile = new Profile("Connection Sub Id Profile");
+ ConnectionSettings expectedConnectionSettings = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_2G3G4G,
+ ConnectionSettings.BooleanState.STATE_ENABLED, true);
+ expectedConnectionSettings.setSubId(targetSubId);
+ profile.setConnectionSettings(expectedConnectionSettings);
+
+ ConnectionSettings actualConnectionSettings =
+ profile.getConnectionSettingWithSubId(targetSubId);
+ assertEquals(expectedConnectionSettings.getConnectionId(),
+ actualConnectionSettings.getConnectionId());
+ assertEquals(expectedConnectionSettings.getValue(), actualConnectionSettings.getValue());
+ assertEquals(expectedConnectionSettings.isOverride(),
+ actualConnectionSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testProfileGetConnectionSettings() {
+ Profile profile = new Profile("Connection Profile");
+
+ ConnectionSettings expectedConnectionSettings1 = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_2G3G4G,
+ ConnectionSettings.BooleanState.STATE_ENABLED, true);
+ profile.setConnectionSettings(expectedConnectionSettings1);
+ ConnectionSettings expectedConnectionSettings2 = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_BLUETOOTH,
+ ConnectionSettings.BooleanState.STATE_DISALED, false);
+ profile.setConnectionSettings(expectedConnectionSettings2);
+
+ List<ConnectionSettings> expectedConnectionSettings = new ArrayList<>();
+ // inverted because the backing structure does it this way :/
+ expectedConnectionSettings.add(expectedConnectionSettings2);
+ expectedConnectionSettings.add(expectedConnectionSettings1);
+
+ List<ConnectionSettings> actualConnectionSettings = new ArrayList<>(
+ profile.getConnectionSettings());
+ for (int i = 0; i < actualConnectionSettings.size(); i++) {
+ ConnectionSettings expectedConnectionSetting = expectedConnectionSettings.get(i);
+ ConnectionSettings actualConnectionSetting = actualConnectionSettings.get(i);
+ assertEquals(expectedConnectionSetting.getConnectionId(),
+ actualConnectionSetting.getConnectionId());
+ assertEquals(expectedConnectionSetting.getValue(), actualConnectionSetting.getValue());
+ assertEquals(expectedConnectionSetting.isOverride(),
+ actualConnectionSetting.isOverride());
+ }
+ }
+
+ @SmallTest
+ public void testProfileGetDozeMode() {
+ int expectedDozeMode = Profile.DozeMode.ENABLE;
+ Profile profile = new Profile("Doze Mode Profile");
+ profile.setDozeMode(expectedDozeMode);
+ assertEquals(expectedDozeMode, profile.getDozeMode());
+ }
+
+ @SmallTest
+ public void testProfileGetExpandedDesktopMode() {
+ int expectedExpandedDesktopMode = Profile.ExpandedDesktopMode.ENABLE;
+ Profile profile = new Profile("Desktop Mode Profile");
+ profile.setExpandedDesktopMode(expectedExpandedDesktopMode);
+ assertEquals(expectedExpandedDesktopMode, profile.getExpandedDesktopMode());
+ }
+
+ @SmallTest
+ public void testProfileGetNotificationLightMode() {
+ int expectedNotificationLightMode = Profile.NotificationLightMode.ENABLE;
+ Profile profile = new Profile("Notification Light Mode Profile");
+ profile.setNotificationLightMode(expectedNotificationLightMode);
+ assertEquals(expectedNotificationLightMode, profile.getNotificationLightMode());
+ }
+
+ @SmallTest
+ public void testProfileGetProfileType() {
+ int expectedProfileType = Profile.Type.CONDITIONAL;
+ Profile profile = new Profile("Profile Type Profile");
+ profile.setProfileType(expectedProfileType);
+ assertEquals(expectedProfileType, profile.getProfileType());
+ }
+
+ @SmallTest
+ public void testProfileGetRingMode() {
+ Profile profile = new Profile("Ringmode Profile");
+ RingModeSettings expectedRingModeSettings =
+ new RingModeSettings(RingModeSettings.RING_MODE_MUTE, true);
+ profile.setRingMode(expectedRingModeSettings);
+
+ RingModeSettings actualRingModeSettings = profile.getRingMode();
+ assertEquals(expectedRingModeSettings.getValue(), actualRingModeSettings.getValue());
+ assertEquals(expectedRingModeSettings.isDirty(), actualRingModeSettings.isDirty());
+ assertEquals(expectedRingModeSettings.isOverride(), actualRingModeSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testProfileGetLockScreenMode() {
+ Profile profile = new Profile("Lock Profile");
+ LockSettings expectedLockSettings = new LockSettings(Profile.LockMode.INSECURE);
+ profile.setScreenLockMode(expectedLockSettings);
+
+ LockSettings actualLockSettings = profile.getScreenLockMode();
+ assertEquals(expectedLockSettings.getValue(), actualLockSettings.getValue());
+ assertEquals(expectedLockSettings.isDirty(), actualLockSettings.isDirty());
+ }
+
+ @SmallTest
+ public void testProfileGetSettingForConnection() {
+ Profile profile = new Profile("Connection Profile");
+ ConnectionSettings expectedConnectionSettings = new ConnectionSettings(
+ ConnectionSettings.PROFILE_CONNECTION_2G3G4G,
+ ConnectionSettings.BooleanState.STATE_ENABLED, true);
+ profile.setConnectionSettings(expectedConnectionSettings);
+
+ ConnectionSettings actualConnectionSettings =
+ profile.getSettingsForConnection(ConnectionSettings.PROFILE_CONNECTION_2G3G4G);
+ assertEquals(expectedConnectionSettings.getConnectionId(),
+ actualConnectionSettings.getConnectionId());
+ assertEquals(expectedConnectionSettings.getValue(), actualConnectionSettings.getValue());
+ assertEquals(expectedConnectionSettings.isOverride(),
+ actualConnectionSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testProfileGetSettingForStream() {
+ Profile profile = new Profile("Stream Profile");
+ StreamSettings expectedStreamSettings =
+ new StreamSettings(AudioManager.STREAM_RING, 0, true);
+ profile.setStreamSettings(expectedStreamSettings);
+
+ StreamSettings actualStreamSettings = profile.getSettingsForStream(
+ expectedStreamSettings.getStreamId());
+
+ assertEquals(expectedStreamSettings.getValue(), actualStreamSettings.getValue());
+ assertEquals(expectedStreamSettings.isOverride(), actualStreamSettings.isOverride());
+ assertEquals(expectedStreamSettings.isDirty(), actualStreamSettings.isDirty());
+ }
+
+ @SmallTest
+ public void testProfileGetStreamSettings() {
+ Profile profile = new Profile("Stream Profile");
+ StreamSettings expectedStreamSettings1 =
+ new StreamSettings(AudioManager.STREAM_RING, 0, true);
+ profile.setStreamSettings(expectedStreamSettings1);
+ StreamSettings expectedStreamSettings2 =
+ new StreamSettings(AudioManager.STREAM_RING, 0, true);
+ profile.setStreamSettings(expectedStreamSettings2);
+
+ List<StreamSettings> expectedStreamSettings = new ArrayList<>();
+ expectedStreamSettings.add(expectedStreamSettings1);
+ expectedStreamSettings.add(expectedStreamSettings2);
+
+ List<StreamSettings> actualStreamSettings = new ArrayList<>(
+ profile.getStreamSettings());
+
+ for (int i = 0; i < actualStreamSettings.size(); i++) {
+ StreamSettings expectedStreamSetting = actualStreamSettings.get(i);
+ StreamSettings actualStreamSetting = actualStreamSettings.get(i);
+ assertEquals(expectedStreamSetting.getStreamId(),
+ actualStreamSetting.getStreamId());
+ assertEquals(expectedStreamSetting.getValue(), actualStreamSetting.getValue());
+ assertEquals(expectedStreamSetting.isOverride(),
+ actualStreamSetting.isOverride());
+ }
+ }
+
+ @SmallTest
+ public void testProfileGetTriggerState() {
+ Profile profile = new Profile("ProfileTrigger Profile");
+ Profile.ProfileTrigger profileTrigger = createSampleProfileTrigger();
+ profile.setTrigger(profileTrigger);
+ assertEquals(EXPECTED_PROFILE_TRIGGER_STATE,
+ profile.getTriggerState(EXPECTED_PROFILE_TRIGGER_TYPE,
+ EXPECTED_PROFILE_TRIGGER_ID));
+ }
+
+ @SmallTest
+ public void testProfileGetTriggersFromType() {
+ Profile profile = new Profile("ProfileTrigger Profile");
+ Profile.ProfileTrigger profileTrigger1 = createSampleProfileTrigger();
+ Profile.ProfileTrigger profileTrigger2 = createSampleProfileTrigger();
+ profile.setTrigger(profileTrigger1);
+ profile.setTrigger(profileTrigger2);
+
+ List<Profile.ProfileTrigger> expectedProfileTriggers = new ArrayList<>();
+ expectedProfileTriggers.add(profileTrigger1);
+ expectedProfileTriggers.add(profileTrigger2);
+
+ List<Profile.ProfileTrigger> actualProfileTriggers = new ArrayList<>(
+ profile.getTriggersFromType(EXPECTED_PROFILE_TRIGGER_TYPE));
+
+ for (int i = 0; i < actualProfileTriggers.size(); i++) {
+ Profile.ProfileTrigger expectedProfileTrigger = expectedProfileTriggers.get(i);
+ Profile.ProfileTrigger actualProfileTrigger = expectedProfileTriggers.get(i);
+ assertEquals(expectedProfileTrigger.getId(), actualProfileTrigger.getId());
+ assertEquals(expectedProfileTrigger.getName(), actualProfileTrigger.getName());
+ assertEquals(expectedProfileTrigger.getState(), actualProfileTrigger.getState());
+ assertEquals(expectedProfileTrigger.getType(), actualProfileTrigger.getType());
+ }
+ }
+
+ @SmallTest
+ public void testProfileIsConditionalType() {
+ Profile profile = new Profile("Mutable Profile");
+ profile.setProfileType(Profile.Type.TOGGLE);
+ assertFalse(profile.isConditionalType());
+ profile.setProfileType(Profile.Type.CONDITIONAL);
+ assertTrue(profile.isConditionalType());
+ }
+
+ @SmallTest
+ public void testProfileSetName() {
+ String expectedProfileName = "MUTABLE Profile";
+ Profile profile = new Profile("Mutable Profile");
+ profile.setName(expectedProfileName);
+ assertEquals(expectedProfileName, profile.getName());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/RingModeSettingsTest.java b/tests/src/org/lineageos/tests/profiles/unit/RingModeSettingsTest.java
new file mode 100644
index 00000000..4c1bfd6e
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/RingModeSettingsTest.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.profiles.RingModeSettings;
+
+public class RingModeSettingsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testConstructWholly() {
+ RingModeSettings ringSettings = new RingModeSettings(
+ RingModeSettings.RING_MODE_MUTE, true);
+ assertEquals(RingModeSettings.RING_MODE_MUTE, ringSettings.getValue());
+ assertEquals(true, ringSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyOverride() {
+ RingModeSettings ringSettings = new RingModeSettings(
+ RingModeSettings.RING_MODE_MUTE, true);
+ ringSettings.setOverride(false);
+ assertEquals(false, ringSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyValue() {
+ String expectedValue = RingModeSettings.RING_MODE_NORMAL;
+ RingModeSettings ringSettings = new RingModeSettings(
+ RingModeSettings.RING_MODE_MUTE, true);
+ ringSettings.setValue(expectedValue);
+ assertEquals(expectedValue, ringSettings.getValue());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/profiles/unit/StreamSettingsTest.java b/tests/src/org/lineageos/tests/profiles/unit/StreamSettingsTest.java
new file mode 100644
index 00000000..783d293e
--- /dev/null
+++ b/tests/src/org/lineageos/tests/profiles/unit/StreamSettingsTest.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.profiles.unit;
+
+import android.media.AudioManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.profiles.StreamSettings;
+
+public class StreamSettingsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testConstructManually() {
+ StreamSettings streamSettings =
+ new StreamSettings(AudioManager.STREAM_RING);
+ assertEquals(AudioManager.STREAM_RING, streamSettings.getStreamId());
+ }
+
+ @SmallTest
+ public void testConstructWholly() {
+ StreamSettings streamSettings =
+ new StreamSettings(AudioManager.STREAM_RING, 0, true);
+ assertEquals(AudioManager.STREAM_RING, streamSettings.getStreamId());
+ assertEquals(0, streamSettings.getValue());
+ assertEquals(true, streamSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyOverride() {
+ StreamSettings streamSettings =
+ new StreamSettings(AudioManager.STREAM_RING);
+ streamSettings.setOverride(true);
+ assertEquals(true, streamSettings.isOverride());
+ }
+
+ @SmallTest
+ public void testVerifyValue() {
+ int expectedValue = AudioManager.STREAM_ALARM;
+ StreamSettings streamSettings =
+ new StreamSettings(AudioManager.STREAM_RING);
+ streamSettings.setValue(expectedValue);
+ assertEquals(expectedValue, streamSettings.getValue());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/providers/LineageSettingsTest.java b/tests/src/org/lineageos/tests/providers/LineageSettingsTest.java
new file mode 100644
index 00000000..d6f61e80
--- /dev/null
+++ b/tests/src/org/lineageos/tests/providers/LineageSettingsTest.java
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.providers;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import lineageos.providers.LineageSettings;
+
+public class LineageSettingsTest extends AndroidTestCase{
+ private ContentResolver mContentResolver;
+ private LineageSettingsTestObserver mTestObserver;
+
+ private static boolean sIsOnChangedCalled = false;
+ private static Uri sExpectedUriChange = null;
+
+ @Override
+ public void setUp() {
+ mContentResolver = getContext().getContentResolver();
+ mTestObserver = new LineageSettingsTestObserver(null);
+ }
+
+ @Override
+ public void tearDown() {
+ mContentResolver.unregisterContentObserver(mTestObserver);
+ }
+
+ @MediumTest
+ public void testPutAndGetSystemString() {
+ final String key = LineageSettings.System.__MAGICAL_TEST_PASSING_ENABLER;
+
+ // put
+ final String expectedValue = "1";
+ boolean isPutSuccessful = LineageSettings.System.putString(mContentResolver, key, expectedValue);
+ assertTrue(isPutSuccessful);
+
+ // get
+ String actualValue = LineageSettings.System.getString(mContentResolver, key);
+ assertEquals(expectedValue, actualValue);
+
+ // setup observer
+ sIsOnChangedCalled = false;
+ sExpectedUriChange = LineageSettings.System.getUriFor(key);
+ mContentResolver.registerContentObserver(sExpectedUriChange, false, mTestObserver,
+ UserHandle.USER_ALL);
+
+ // replace
+ final String expectedReplaceValue = "0";
+ isPutSuccessful = LineageSettings.System.putString(mContentResolver, key, expectedReplaceValue);
+ assertTrue(isPutSuccessful);
+
+ // get
+ actualValue = LineageSettings.System.getString(mContentResolver, key);
+ assertEquals(expectedReplaceValue, actualValue);
+
+ // delete to clean up
+ int rowsAffected = mContentResolver.delete(LineageSettings.System.CONTENT_URI,
+ Settings.NameValueTable.NAME + " = ?", new String[]{ key });
+ assertEquals(1, rowsAffected);
+
+ if (!sIsOnChangedCalled) {
+ fail("On change was never called or was called with the wrong uri");
+ }
+ }
+
+ @MediumTest
+ public void testPutAndGetSecureString() {
+ /* TODO: FIXME
+ final String key = LineageSettings.Secure.__MAGICAL_TEST_PASSING_ENABLER;
+
+ // put
+ final String expectedValue = "0";
+ boolean isPutSuccessful = LineageSettings.Secure.putString(mContentResolver, key, expectedValue);
+ assertTrue(isPutSuccessful);
+
+ // get
+ String actualValue = LineageSettings.Secure.getString(mContentResolver, key);
+ assertEquals(expectedValue, actualValue);
+
+ // setup observer
+ sIsOnChangedCalled = false;
+ sExpectedUriChange = LineageSettings.Secure.getUriFor(key);
+ mContentResolver.registerContentObserver(sExpectedUriChange, false, mTestObserver,
+ UserHandle.USER_ALL);
+
+ // replace
+ final String expectedReplaceValue = "1";
+ isPutSuccessful = LineageSettings.Secure.putString(mContentResolver, key, expectedReplaceValue);
+ assertTrue(isPutSuccessful);
+
+ // get
+ actualValue = LineageSettings.Secure.getString(mContentResolver, key);
+ assertEquals(expectedReplaceValue, actualValue);
+
+ // delete to clean up
+ int rowsAffected = mContentResolver.delete(LineageSettings.Secure.CONTENT_URI,
+ Settings.NameValueTable.NAME + " = ?", new String[]{ key });
+ assertEquals(1, rowsAffected);
+
+ if (!sIsOnChangedCalled) {
+ fail("On change was never called or was called with the wrong uri");
+ } */
+ }
+
+ @MediumTest
+ public void testPutAndGetGlobalString() {
+ final String key = "key";
+
+ // put
+ final String expectedValue = "globalTestValue1";
+ boolean isPutSuccessful = LineageSettings.Global.putString(mContentResolver, key, expectedValue);
+ assertTrue(isPutSuccessful);
+
+ // get
+ String actualValue = LineageSettings.Global.getString(mContentResolver, key);
+ assertEquals(expectedValue, actualValue);
+
+ // setup observer
+ sIsOnChangedCalled = false;
+ sExpectedUriChange = LineageSettings.Global.getUriFor(key);
+ mContentResolver.registerContentObserver(sExpectedUriChange, false, mTestObserver,
+ UserHandle.USER_OWNER);
+
+ // replace
+ final String expectedReplaceValue = "globalTestValue2";
+ isPutSuccessful = LineageSettings.Global.putString(mContentResolver, key, expectedReplaceValue);
+ assertTrue(isPutSuccessful);
+
+ // get
+ actualValue = LineageSettings.Global.getString(mContentResolver, key);
+ assertEquals(expectedReplaceValue, actualValue);
+
+ // delete to clean up
+ int rowsAffected = mContentResolver.delete(LineageSettings.Global.CONTENT_URI,
+ Settings.NameValueTable.NAME + " = ?", new String[]{ key });
+ assertEquals(1, rowsAffected);
+
+ if (!sIsOnChangedCalled) {
+ fail("On change was never called or was called with the wrong uri");
+ }
+ }
+
+ private class LineageSettingsTestObserver extends ContentObserver {
+
+ public LineageSettingsTestObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (sExpectedUriChange.equals(uri)) {
+ sIsOnChangedCalled = true;
+ }
+ }
+ }
+
+ // TODO Add tests for other users
+}
diff --git a/tests/src/org/lineageos/tests/util/ColorUtilTest.java b/tests/src/org/lineageos/tests/util/ColorUtilTest.java
new file mode 100644
index 00000000..9ce91f96
--- /dev/null
+++ b/tests/src/org/lineageos/tests/util/ColorUtilTest.java
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.util;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.test.AndroidTestCase;
+import lineageos.util.ColorUtils;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class ColorUtilTest extends AndroidTestCase {
+ private ColorUtils mColorUtils;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mColorUtils = new ColorUtils();
+ }
+
+ public void testDropAlpha() {
+ // With pre-existing alpha
+ int color = 0xBBCCDD;
+ int alpha = 0xAA000000;
+ int result = mColorUtils.dropAlpha(color | alpha);
+ // Assert alpha was removed
+ assertEquals(Color.alpha(result), 0);
+ // Ensure color is preserved
+ assertEquals(result & color, color);
+
+ // Without pre-existing alpha
+ color = Color.argb(0, 100, 200 ,300);
+ result = mColorUtils.dropAlpha(color);
+ // Assert alpha was removed
+ assertEquals(Color.alpha(result), 0);
+ // Ensure color is preserved
+ assertEquals(result, color);
+ }
+
+ public void testGenerateAlertColorFromDrawable() {
+ // Test null drawable
+ int color = mColorUtils.generateAlertColorFromDrawable(null);
+ assertEquals(color, Color.BLACK);
+
+ Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
+ bitmapDrawable.setBounds(0, 0, 10, 10);
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawColor(Color.RED);
+
+ // Test fully red bitmap
+ color = mColorUtils.generateAlertColorFromDrawable(bitmapDrawable);
+ assertEquals(color, Color.RED);
+ color = mColorUtils.generateAlertColorFromDrawable(
+ getColorDrawableFromBitmapDrawable(bitmapDrawable));
+ assertEquals(color, Color.RED);
+
+ // Test blue/red bitmap with blue dominating
+ Paint p = new Paint();
+ p.setColor(Color.BLUE);
+ p.setStyle(Paint.Style.FILL_AND_STROKE);
+ canvas.drawRect(0, 0, 8, 8, p);
+ color = mColorUtils.generateAlertColorFromDrawable(bitmapDrawable);
+ assertEquals(color, Color.BLUE);
+ color = mColorUtils.generateAlertColorFromDrawable(
+ getColorDrawableFromBitmapDrawable(bitmapDrawable));
+ assertEquals(color, Color.BLUE);
+
+ // Test large white + small blue scenario
+ canvas.drawColor(Color.WHITE);
+ canvas.drawRect(0, 0, 2, 2, p);
+ color = mColorUtils.generateAlertColorFromDrawable(bitmapDrawable);
+ assertEquals(color, Color.BLUE);
+ color = mColorUtils.generateAlertColorFromDrawable(
+ getColorDrawableFromBitmapDrawable(bitmapDrawable));
+ assertEquals(color, Color.BLUE);
+
+ // Test large white + small black scenario
+ canvas.drawColor(Color.WHITE);
+ p.setColor(Color.BLACK);
+ canvas.drawRect(0, 0, 2, 2, p);
+ color = mColorUtils.generateAlertColorFromDrawable(bitmapDrawable);
+ assertEquals(color, Color.WHITE);
+ color = mColorUtils.generateAlertColorFromDrawable(
+ getColorDrawableFromBitmapDrawable(bitmapDrawable));
+ assertEquals(color, Color.WHITE);
+
+ assertEquals(bitmap.isRecycled(), false);
+ bitmap.recycle();
+ }
+
+ private ColorDrawable getColorDrawableFromBitmapDrawable(final BitmapDrawable bitmapDrawable) {
+ ColorDrawable colorDrawable = Mockito.mock(ColorDrawable.class);
+ Mockito.doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Canvas canvas = (Canvas) invocation.getArguments()[0];
+ bitmapDrawable.draw(canvas);
+ return null;
+ }
+ }).when(colorDrawable).draw(Mockito.any(Canvas.class));
+ return colorDrawable;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/VersioningTest.java b/tests/src/org/lineageos/tests/versioning/VersioningTest.java
new file mode 100644
index 00000000..9cbf2752
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/VersioningTest.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning;
+
+import android.widget.Toast;
+import lineageos.os.Build;
+
+import org.lineageos.tests.TestActivity;
+
+public class VersioningTest extends TestActivity {
+ @Override
+ protected String tag() {
+ return null;
+ }
+
+ @Override
+ protected Test[] tests() {
+ return mTests;
+ }
+
+ private Test[] mTests = new Test[] {
+ new Test("test retrieve version") {
+ public void run() {
+ Toast.makeText(VersioningTest.this,
+ "Current API version is " + Build.LINEAGE_VERSION.SDK_INT + " which is "
+ + Build.getNameForSDKInt(Build.LINEAGE_VERSION.SDK_INT),
+ Toast.LENGTH_SHORT).show();
+ }
+ },
+ new Test("test target version larger") {
+ public void run() {
+ int currentapiVersion = Build.LINEAGE_VERSION.SDK_INT;
+ if (currentapiVersion >= Build.LINEAGE_VERSION_CODES.APRICOT){
+ Toast.makeText(VersioningTest.this,
+ "Current API version is greater or equal to "
+ + Build.getNameForSDKInt(Build.LINEAGE_VERSION_CODES.APRICOT),
+ Toast.LENGTH_LONG).show();
+ } else{
+ Toast.makeText(VersioningTest.this,
+ "Current API version is below target SKD version "
+ + Build.LINEAGE_VERSION_CODES.APRICOT,
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ };
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/BinderTransactionTest.java b/tests/src/org/lineageos/tests/versioning/unit/BinderTransactionTest.java
new file mode 100644
index 00000000..47032bd1
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/BinderTransactionTest.java
@@ -0,0 +1,206 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning.unit;
+
+import android.content.Context;
+import android.os.Binder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.util.Pair;
+import org.lineageos.tests.LineageOSTestApplication;
+import org.lineageos.tests.versioning.unit.apiv2.ApiV2PriorReleaseInterfaces;
+import org.lineageos.tests.versioning.unit.apiv4.ApiV4PriorReleaseInterfaces;
+import org.lineageos.tests.versioning.unit.apiv5.ApiV5PriorReleaseInterfaces;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.runner.AndroidJUnitRunner;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * These tests validate the enumerated binder transaction call ids per each
+ * release api level against the current framework.
+ *
+ * This is to validate that no interface contracts are broken in terms of binder
+ * call method mapping between releases.
+ *
+ * After too much searching on the internet, I found that no one was bored enough to
+ * spend time on this awesomely boring concept. But I am.
+ *
+ * Also this is a fun endeavour into parameterized unit testing, and by fun, I mean
+ * horrible and full of drinking.
+ *
+ * If you need to blame anyone for this concept, look no further than danesh@cyngn.com
+ */
+@RunWith(Parameterized.class)
+@LargeTest
+public class BinderTransactionTest extends AndroidTestCase {
+ private static final String TAG = BinderTransactionTest.class.getSimpleName();
+ private static final String STUB_SUFFIX = "$Stub";
+ private static final String LINEAGEOS_NAMESPACE = "lineageos";
+ private static final String TRANSACTION_PREFIX = "TRANSACTION_";
+
+ private static final int NOT_FROM_PRIOR_RELEASE = -1;
+
+ private String mField;
+ private int mExpectedValue;
+ private int mActualValue;
+ private static Context sContext;
+
+ private static ArrayList<String> mKnownSdkClasses;
+ private static Map<String, Map<String, Integer>> mApiMethodsAndValues =
+ new HashMap<String, Map<String, Integer>>();
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Test
+ public void testClassLoaderGivesSDKClasses() {
+ /**
+ * Verify we can retrieve our sdk classes from this package
+ */
+ assertNotNull(mKnownSdkClasses);
+ assertTrue(mKnownSdkClasses.size() > 0);
+ }
+
+ private static void doSetup() {
+ mKnownSdkClasses = MagicalDexHelper.getLoadedClasses(
+ LineageOSTestApplication.getStaticApplicationContext(), LINEAGEOS_NAMESPACE);
+ sContext = LineageOSTestApplication.getStaticApplicationContext();
+ addInterfaces(ApiV2PriorReleaseInterfaces.getInterfaces());
+ addInterfaces(ApiV4PriorReleaseInterfaces.getInterfaces());
+ addInterfaces(ApiV5PriorReleaseInterfaces.getInterfaces());
+ }
+
+ private static void addInterfaces(Map<String, Map<String, Integer>> mapToAdd) {
+ for (String key : mapToAdd.keySet()) {
+ if (mApiMethodsAndValues.get(key) != null) {
+ Map<String, Integer> internalMap = mApiMethodsAndValues.get(key);
+ internalMap.putAll(mapToAdd.get(key));
+ } else {
+ Map<String, Integer> internalMap = mapToAdd.get(key);
+ mApiMethodsAndValues.put(key, internalMap);
+ }
+ }
+ }
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> data() {
+ doSetup();
+ //Ughhh, lets pretend this never happened
+ ArrayList<Pair<String, String>> targetClassAndFields =
+ new ArrayList<Pair<String, String>>();
+ ArrayList<Integer> actualValues = new ArrayList<Integer>();
+
+ for (String sClazz : mKnownSdkClasses) {
+ if (sClazz.endsWith(STUB_SUFFIX)) {
+ try {
+ Class clazz = MagicalDexHelper.loadClassForNameSpace(LineageOSTestApplication
+ .getStaticApplicationContext(), sClazz);
+ Field[] fields = clazz.getDeclaredFields();
+ Pattern pattern = Pattern.compile("\\.([\\w]+)\\$");
+ Matcher matcher = pattern.matcher(clazz.getName());
+ String className = null;
+ if (matcher.find()) {
+ className = matcher.group(1).substring(0, matcher.group(1).length());
+ }
+
+ for (Field field : fields) {
+ if (field.getName().startsWith(TRANSACTION_PREFIX)) {
+ field.setAccessible(true);
+ String fieldName = field.getName().substring(
+ TRANSACTION_PREFIX.length());
+ fieldName = fieldName.split("_")[0];
+ Pair<String, String> classAndField = new Pair<String, String>(
+ className, fieldName);
+ Log.d(TAG, "Adding: " + classAndField.first + " with field "
+ + classAndField.second);
+ targetClassAndFields.add(classAndField);
+ try {
+ actualValues.add(field.getInt(clazz));
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("Unable to access " + field.getName());
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new AssertionError("Unable to load class " + sClazz);
+ }
+ }
+ }
+ Object[][] values = new Object[targetClassAndFields.size()][3];
+
+ for (int i = 0; i < targetClassAndFields.size(); i++) {
+ Pair<String, String> targetClassAndField = targetClassAndFields.get(i);
+ values[i][0] = targetClassAndField.second;
+ values[i][1] = lookupValueForField(targetClassAndField.first,
+ targetClassAndField.second);
+ values[i][2] = actualValues.get(i);
+ }
+ return Arrays.asList(values);
+ }
+
+ //Look up the target fields value from a prior release
+ private static Object lookupValueForField(String clazz, String fieldName) {
+ Log.d(TAG, "Looking up: " + clazz + " with field "
+ + fieldName);
+ Map<String, Integer> internalMap = mApiMethodsAndValues.get(clazz);
+ if (internalMap == null || !internalMap.containsKey(fieldName)) {
+ Log.d(TAG, "Internal map for " + clazz + " is null or doesn't contain entry");
+ return NOT_FROM_PRIOR_RELEASE;
+ }
+ return internalMap.get(fieldName);
+ }
+
+ public BinderTransactionTest(String targetField, Integer expectedValue, Integer actualValue) {
+ mField = targetField;
+ mExpectedValue = expectedValue;
+ mActualValue = actualValue;
+ }
+
+ @Test
+ public void testBinderTransactionValidation() {
+ Log.d(TAG, "Testing: " + mField + " with expected value of " + mExpectedValue
+ + " and actual value of " + mActualValue);
+ if (mExpectedValue == NOT_FROM_PRIOR_RELEASE) {
+ //This is a new interface, no need to test against
+ return;
+ }
+ try {
+ assertEquals(mExpectedValue, mActualValue);
+ } catch (AssertionError e) {
+ throw new AssertionError("For the field " + mField + " expected value "
+ + mExpectedValue + " but got " + mActualValue);
+ }
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/BuildTest.java b/tests/src/org/lineageos/tests/versioning/unit/BuildTest.java
new file mode 100644
index 00000000..02bdf9a9
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/BuildTest.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning.unit;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.os.Build;
+
+import android.test.AndroidTestCase;
+import lineageos.os.Concierge;
+
+/**
+ * Created by adnan on 7/14/15.
+ */
+public class BuildTest extends AndroidTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @SmallTest
+ public void testFetchSdkApiLevelExists() {
+ assertNotNull(Build.LINEAGE_VERSION.SDK_INT);
+ }
+
+ @SmallTest
+ public void testSdkApiLevelCurrent() {
+ assertEquals(Concierge.PARCELABLE_VERSION, Build.LINEAGE_VERSION.SDK_INT);
+ }
+
+ @SmallTest
+ public void testSdkApiLevelCanMatch() {
+ String apiName = Build.getNameForSDKInt(Build.LINEAGE_VERSION.SDK_INT);
+ assertNotNull(apiName);
+ assertEquals(Build.getNameForSDKInt(Concierge.PARCELABLE_VERSION), apiName);
+ }
+
+ @SmallTest
+ public void testSdkApiLevelSkippedIfGreaterThanAllowed() {
+ int i = 0;
+ if (Build.LINEAGE_VERSION.SDK_INT > Concierge.PARCELABLE_VERSION + 1) {
+ i++;
+ }
+ assertEquals(0, i);
+ }
+
+ @SmallTest
+ public void testSdkLevelRetrieveNameImpossible() {
+ String name = Build.getNameForSDKInt(Integer.MAX_VALUE);
+ assertNotNull(name);
+ assertEquals(Build.UNKNOWN, name);
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/ClassPathException.java b/tests/src/org/lineageos/tests/versioning/unit/ClassPathException.java
new file mode 100644
index 00000000..7acfc640
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/ClassPathException.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.lineageos.tests.versioning.unit;
+
+/**
+ * Created by Adnan on 9/25/15.
+ */
+public class ClassPathException extends Exception {
+
+ public ClassPathException(String message) {
+ super("should not have " + message + " !");
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/ClassPathTest.java b/tests/src/org/lineageos/tests/versioning/unit/ClassPathTest.java
new file mode 100644
index 00000000..b5c041ed
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/ClassPathTest.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning.unit;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import dalvik.system.DexFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Created by adnan on 9/22/15.
+ */
+public class ClassPathTest extends AndroidTestCase {
+
+ private static final String LINEAGEOS_NAMESPACE = "lineageos";
+ private static final String PATH_TO_SYSTEM_FRAMEWORK = "/system/framework";
+
+ private ArrayList<String> mKnownSdkClasses;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mKnownSdkClasses = MagicalDexHelper.getLoadedClasses(mContext, LINEAGEOS_NAMESPACE);
+ }
+
+ @SmallTest
+ public void testClassLoaderGivesSDKClasses() {
+ /**
+ * Verify we can retrieve our sdk classes from this package
+ */
+ assertNotNull(mKnownSdkClasses);
+ assertTrue(mKnownSdkClasses.size() > 0);
+ }
+
+ @LargeTest
+ public void testBootClassPathIsClean() {
+ File path = new File(PATH_TO_SYSTEM_FRAMEWORK);
+ File[] files = path.listFiles();
+ assertNotNull(files);
+
+ /**
+ * Everything in the in the boot class path needs to not
+ * contain the sdk. Verify integrity of runtime below.
+ */
+ final String bootClassPath = System.getenv("BOOTCLASSPATH");
+
+ ArrayList<String> classPathJars = new ArrayList<String>();
+
+ if (bootClassPath != null) {
+ String[] bootClassPathElements = bootClassPath.split(":");
+ for (String element : bootClassPathElements) {
+ classPathJars.add(element);
+ }
+ } else {
+ throw new AssertionError("No BOOTCLASSPATH defined! ");
+ }
+
+ for (String classPathJar : classPathJars) {
+ try {
+ File jar = new File(classPathJar);
+ DexFile dexFile = new DexFile(jar);
+ assertTrue(isJarClean(dexFile));
+ } catch (IOException e) {
+ throw new AssertionError("Unable to find jar! " + classPathJar +
+ "\nException " + e.toString());
+ }
+ }
+ }
+
+ private void processAndCompare(String name) throws ClassPathException {
+ if (mKnownSdkClasses.contains(name)) {
+ throw new ClassPathException(name);
+ }
+ }
+
+ private boolean isJarClean(DexFile dexFile) throws AssertionError {
+ Enumeration<String> enumeration = dexFile.entries();
+
+ while (enumeration.hasMoreElements()) {
+ try {
+ processAndCompare(enumeration.nextElement());
+ } catch (ClassPathException e) {
+ throw new AssertionError("Jar file "
+ + dexFile.getName() + " " + e.getMessage());
+ }
+ }
+ return true;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/MagicalDexHelper.java b/tests/src/org/lineageos/tests/versioning/unit/MagicalDexHelper.java
new file mode 100644
index 00000000..ae414f38
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/MagicalDexHelper.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning.unit;
+
+import android.content.Context;
+import dalvik.system.DexFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Created by adnan on 2/3/16.
+ */
+public class MagicalDexHelper {
+
+ public static ArrayList<String> getLoadedClasses(Context context, String targetNameSpace) {
+ ArrayList<String> listOfClasses = new ArrayList<String>();
+ try {
+ DexFile dexFile = new DexFile(new File(context.getPackageCodePath()));
+ Enumeration<String> enumeration = dexFile.entries();
+
+ while (enumeration.hasMoreElements()){
+ String className = enumeration.nextElement();
+ if (className.startsWith(targetNameSpace)) {
+ listOfClasses.add(className);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return listOfClasses;
+ }
+
+ public static Class loadClassForNameSpace(Context context,
+ String classToLoad) throws IOException {
+ DexFile dexFile = new DexFile(new File(context.getPackageCodePath()));
+ return dexFile.loadClass(classToLoad, context.getClassLoader());
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java b/tests/src/org/lineageos/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java
new file mode 100644
index 00000000..ce98bf6f
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/apiv2/ApiV2PriorReleaseInterfaces.java
@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning.unit.apiv2;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by adnan on 2/4/16.
+ */
+public class ApiV2PriorReleaseInterfaces {
+ private static Map<String, Map<String, Integer>> mApiMethodsAndValues =
+ new HashMap<String, Map<String, Integer>>();
+
+ //Profiles Aidl (IProfileManager)
+ static {
+ Map<String, Integer> profilesMap = getInternalInterfaceMap("IProfileManager");
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ profilesMap.put("setActiveProfile", 1);
+ profilesMap.put("etActiveProfileByName", 2);
+ profilesMap.put("getActiveProfile", 3);
+ profilesMap.put("addProfile", 4);
+ profilesMap.put("removeProfile", 5);
+ profilesMap.put("updateProfile", 6);
+ profilesMap.put("getProfile", 7);
+ profilesMap.put("getProfileByName", 8);
+ profilesMap.put("getProfiles", 9);
+ profilesMap.put("profileExists", 10);
+ profilesMap.put("profileExistsByName", 11);
+ profilesMap.put("notificationGroupExistsByName", 12);
+ profilesMap.put("getNotificationGroups", 13);
+ profilesMap.put("addNotificationGroup", 14);
+ profilesMap.put("removeNotificationGroup", 15);
+ profilesMap.put("updateNotificationGroup", 16);
+ profilesMap.put("getNotificationGroupForPackage", 17);
+ profilesMap.put("getNotificationGroup", 18);
+ profilesMap.put("resetAll", 19);
+ }
+
+ //LineageHardwareManager Aidl (ILineageHardwareService)
+ static {
+ Map<String, Integer> hardwareMap = getInternalInterfaceMap("ILineageHardwareService");
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ hardwareMap.put("getSupportedFeatures", 1);
+ hardwareMap.put("get", 2);
+ hardwareMap.put("set", 3);
+ hardwareMap.put("getDisplayColorCalibration", 4);
+ hardwareMap.put("setDisplayColorCalibration", 5);
+ hardwareMap.put("getNumGammaControls", 6);
+ hardwareMap.put("getDisplayGammaCalibration", 7);
+ hardwareMap.put("setDisplayGammaCalibration", 8);
+ hardwareMap.put("getVibratorIntensity", 9);
+ hardwareMap.put("setVibratorIntensity", 10);
+ hardwareMap.put("getLtoSource", 11);
+ hardwareMap.put("getLtoDestination", 12);
+ hardwareMap.put("getLtoDownloadInterval", 13);
+ hardwareMap.put("getSerialNumber", 14);
+ hardwareMap.put("requireAdaptiveBacklightForSunlightEnhancement", 15);
+ hardwareMap.put("getDisplayModes", 16);
+ hardwareMap.put("getCurrentDisplayMode", 17);
+ hardwareMap.put("getDefaultDisplayMode", 18);
+ hardwareMap.put("setDisplayMode", 19);
+ hardwareMap.put("writePersistentBytes", 20);
+ hardwareMap.put("readPersistentBytes", 21);
+ hardwareMap.put("getThermalState", 22);
+ hardwareMap.put("registerThermalListener", 23);
+ hardwareMap.put("unRegisterThermalListener", 24);
+ }
+
+ //LineageStatusBarManager Aidl (ILineageStatusBarManager)
+ static {
+ Map<String, Integer> statusBarMap = getInternalInterfaceMap("ILineageStatusBarManager");
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ statusBarMap.put("createCustomTileWithTag", 1);
+ statusBarMap.put("removeCustomTileWithTag", 2);
+ statusBarMap.put("registerListener", 3);
+ statusBarMap.put("unregisterListener", 4);
+ statusBarMap.put("removeCustomTileFromListener", 5);
+ }
+
+ //AppSuggestManager Aidl (IAppSuggestManager)
+ static {
+ Map<String, Integer> suggestMap = getInternalInterfaceMap("IAppSuggestManager");
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ suggestMap.put("handles", 1);
+ suggestMap.put("getSuggestions", 2);
+ }
+
+ //LineageTelephonyManager Aidl (ILineageTelephonyManager)
+ static {
+ Map<String, Integer> telephonyMap = getInternalInterfaceMap("ILineageTelephonyManager");
+ // APRICOT + BOYSENBERRY + CANTALOUPE
+ telephonyMap.put("getSubInformation", 1);
+ telephonyMap.put("isSubActive", 2);
+ telephonyMap.put("isDataConnectionSelectedOnSub", 3);
+ telephonyMap.put("isDataConnectionEnabled", 4);
+ telephonyMap.put("setSubState", 5);
+ telephonyMap.put("setDataConnectionSelectedOnSub", 6);
+ telephonyMap.put("setDataConnectionState", 7);
+ telephonyMap.put("setDefaultPhoneSub", 8);
+ telephonyMap.put("setDefaultSmsSub", 9);
+ }
+
+ protected static Map<String, Integer> getInternalInterfaceMap(String targetInterface) {
+ Map<String, Integer> internalMap = mApiMethodsAndValues.get(targetInterface);
+ if (internalMap == null) {
+ internalMap = new HashMap<String, Integer>();
+ mApiMethodsAndValues.put(targetInterface, internalMap);
+ return internalMap;
+ }
+ return internalMap;
+ }
+
+ public static Map<String, Map<String, Integer>> getInterfaces() {
+ return mApiMethodsAndValues;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/apiv4/ApiV4PriorReleaseInterfaces.java b/tests/src/org/lineageos/tests/versioning/unit/apiv4/ApiV4PriorReleaseInterfaces.java
new file mode 100644
index 00000000..3e29d58b
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/apiv4/ApiV4PriorReleaseInterfaces.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning.unit.apiv4;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ApiV4PriorReleaseInterfaces {
+ private static Map<String, Map<String, Integer>> mApiMethodsAndValues =
+ new HashMap<String, Map<String, Integer>>();
+
+ //Profiles Aidl (IProfileManager)
+ static {
+ Map<String, Integer> profilesMap = getInternalInterfaceMap("IProfileManager");
+ // APRICOT + BOYSENBERRY + CANTALOUPE to 19
+ // DRAGONFRUIT BEGIN
+ profilesMap.put("isEnabled", 20);
+ }
+
+ //LineageHardwareManager Aidl (ILineageHardwareService)
+ static {
+ Map<String, Integer> hardwareMap = getInternalInterfaceMap("ILineageHardwareService");
+ // APRICOT + BOYSENBERRY + CANTALOUPE to 24
+ // DRAGONFRUIT BEGIN
+ hardwareMap.put("isSunlightEnhancementSelfManaged", 25);
+ hardwareMap.put("getUniqueDeviceId", 26);
+ }
+
+ //LineageStatusBarManager Aidl (ILineageStatusBarManager)
+ static {
+ // APRICOT + BOYSENBERRY + CANTALOUPE to 5
+ // DRAGONFRUIT BEGIN
+ }
+
+ //AppSuggestManager Aidl (IAppSuggestManager)
+ static {
+ // APRICOT + BOYSENBERRY + CANTALOUPE to 2
+ // DRAGONFRUIT BEGIN
+ }
+
+ //LineageTelephonyManager Aidl (ILineageTelephonyManager)
+ static {
+ // APRICOT + BOYSENBERRY + CANTALOUPE to 9
+ // DRAGONFRUIT BEGIN
+ }
+
+ //PerformanceManager Aidl (IPerformanceManager)
+ static {
+ Map<String, Integer> perfMap = getInternalInterfaceMap("IPerformanceManager");
+ // DRAGONFRUIT BEGIN
+ perfMap.put("cpuBoost", 1);
+ perfMap.put("setPowerProfile", 2);
+ perfMap.put("getPowerProfile", 3);
+ perfMap.put("getNumberOfProfiles", 4);
+ perfMap.put("getProfileHasAppProfiles", 5);
+ }
+
+ //ExternalViewProviderFactory Aidl (IExternalViewProviderFactory)
+ static {
+ Map<String, Integer> extProviderMap =
+ getInternalInterfaceMap("IExternalViewProviderFactory");
+ // DRAGONFRUIT BEGIN
+ extProviderMap.put("createExternalView", 1);
+ }
+
+ //ExternalViewProvider Aidl (IExternalViewProvider)
+ static {
+ Map<String, Integer> extViewProviderMap =
+ getInternalInterfaceMap("IExternalViewProvider");
+ // DRAGONFRUIT BEGIN
+ extViewProviderMap.put("onAttach", 1);
+ extViewProviderMap.put("onStart", 2);
+ extViewProviderMap.put("onResume", 3);
+ extViewProviderMap.put("onPause", 4);
+ extViewProviderMap.put("onStop", 5);
+ extViewProviderMap.put("onDetach", 6);
+ extViewProviderMap.put("alterWindow", 7);
+ }
+
+ protected static Map<String, Integer> getInternalInterfaceMap(String targetInterface) {
+ Map<String, Integer> internalMap = mApiMethodsAndValues.get(targetInterface);
+ if (internalMap == null) {
+ internalMap = new HashMap<String, Integer>();
+ mApiMethodsAndValues.put(targetInterface, internalMap);
+ return internalMap;
+ }
+ return internalMap;
+ }
+
+ public static Map<String, Map<String, Integer>> getInterfaces() {
+ return mApiMethodsAndValues;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/versioning/unit/apiv5/ApiV5PriorReleaseInterfaces.java b/tests/src/org/lineageos/tests/versioning/unit/apiv5/ApiV5PriorReleaseInterfaces.java
new file mode 100644
index 00000000..898dbfad
--- /dev/null
+++ b/tests/src/org/lineageos/tests/versioning/unit/apiv5/ApiV5PriorReleaseInterfaces.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.versioning.unit.apiv5;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ApiV5PriorReleaseInterfaces {
+ private static Map<String, Map<String, Integer>> mApiMethodsAndValues =
+ new HashMap<String, Map<String, Integer>>();
+
+ //ExternalViewProviderFactory Aidl (IExternalViewProviderFactory)
+ static {
+ Map<String, Integer> extProviderMap =
+ getInternalInterfaceMap("IExternalViewProviderFactory");
+ // DRAGONFRUIT TO 1
+ // ELDERBERRY BEGIN
+ }
+
+ //ExternalViewProvider Aidl (IExternalViewProvider)
+ static {
+ Map<String, Integer> extViewProviderMap =
+ getInternalInterfaceMap("IExternalViewProvider");
+ // DRAGONFRUIT TO 7
+ // ELDERBERRY BEGIN
+ }
+
+ //LineageAudioManager Aidl (ILineageAudioService)
+ static {
+ Map<String, Integer> lineageAudioService =
+ getInternalInterfaceMap("ILineageAudioService");
+ //ELDERBERRY BEGIN
+ lineageAudioService.put("listAudioSessions", 1);
+ }
+
+ //LineageWeatherManager Aidl (ILineageWeatherManager)
+ static {
+ Map<String, Integer> ilineageWeatherManager =
+ getInternalInterfaceMap("ILineageWeatherManager");
+ //ELDERBERRY BEGIN
+ ilineageWeatherManager.put("updateWeather", 1);
+ ilineageWeatherManager.put("lookupCity ", 2);
+ ilineageWeatherManager.put("registerWeatherServiceProviderChangeListener", 3);
+ ilineageWeatherManager.put("unregisterWeatherServiceProviderChangeListener", 4);
+ ilineageWeatherManager.put("getActiveWeatherServiceProviderLabel", 5);
+ ilineageWeatherManager.put("cancelRequest", 6);
+ }
+
+ //RequestInfoListener Aidl (IRequestInfoListener)
+ static {
+ Map<String, Integer> requestInfoListener =
+ getInternalInterfaceMap("IRequestInfoListener");
+ //ELDERBERRY BEGIN
+ requestInfoListener.put("onWeatherRequestCompleted", 1);
+ requestInfoListener.put("onLookupCityRequestCompleted ", 2);
+ }
+
+ //WeatherServiceProviderChangeListener Aidl (IWeatherServiceProviderChangeListener)
+ static {
+ Map<String, Integer> weatherServiceProviderChangeListener =
+ getInternalInterfaceMap("IWeatherServiceProviderChangeListener");
+ //ELDERBERRY BEGIN
+ weatherServiceProviderChangeListener.put("onWeatherServiceProviderChanged", 1);
+ }
+
+ //WeatherProviderService Aidl (IWeatherProviderService)
+ static {
+ Map<String, Integer> weatherProviderService =
+ getInternalInterfaceMap("IWeatherProviderService");
+ //ELDERBERRY BEGIN
+ weatherProviderService.put("processWeatherUpdateRequest", 1);
+ weatherProviderService.put("processCityNameLookupRequest ", 2);
+ weatherProviderService.put("setServiceClient", 3);
+ weatherProviderService.put("cancelOngoingRequests", 4);
+ weatherProviderService.put("cancelRequest", 5);
+ }
+
+ //WeatherProviderServiceClient Aidl (IWeatherProviderServiceClient)
+ static {
+ Map<String, Integer> weatherProviderServiceClient =
+ getInternalInterfaceMap("IWeatherProviderServiceClient");
+ //ELDERBERRY BEGIN
+ weatherProviderServiceClient.put("setServiceRequestState", 1);
+ }
+
+ protected static Map<String, Integer> getInternalInterfaceMap(String targetInterface) {
+ Map<String, Integer> internalMap = mApiMethodsAndValues.get(targetInterface);
+ if (internalMap == null) {
+ internalMap = new HashMap<String, Integer>();
+ mApiMethodsAndValues.put(targetInterface, internalMap);
+ return internalMap;
+ }
+ return internalMap;
+ }
+
+ public static Map<String, Map<String, Integer>> getInterfaces() {
+ return mApiMethodsAndValues;
+ }
+}
diff --git a/tests/src/org/lineageos/tests/weather/unit/DayForecastBuilderTest.java b/tests/src/org/lineageos/tests/weather/unit/DayForecastBuilderTest.java
new file mode 100644
index 00000000..70a8c7ea
--- /dev/null
+++ b/tests/src/org/lineageos/tests/weather/unit/DayForecastBuilderTest.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.weather.unit;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.providers.WeatherContract;
+import lineageos.weather.WeatherInfo.DayForecast;
+
+public class DayForecastBuilderTest extends AndroidTestCase {
+
+ private static final int mConditionCode = WeatherContract.WeatherColumns.WeatherCode.HURRICANE;
+ private static final double mLow = 35;
+ private static final double mHigh = 58;
+
+ @SmallTest
+ public void testUnravelFromParcel() {
+ DayForecast forecast = new DayForecast.Builder(mConditionCode).setHigh(mHigh).setLow(mLow)
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ forecast.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ DayForecast forecastFromParcel = DayForecast.CREATOR.createFromParcel(parcel);
+
+ assertEquals(forecast, forecastFromParcel);
+ assertEquals(forecast.getConditionCode(), forecastFromParcel.getConditionCode());
+ assertEquals(forecast.getHigh(), forecastFromParcel.getHigh());
+ assertEquals(forecast.getLow(), forecastFromParcel.getLow());
+ }
+
+ @SmallTest
+ public void testUnravelFromParcelWithDefaultValues() {
+ //Condition code is required
+ DayForecast forecast = new DayForecast.Builder(mConditionCode).build();
+
+ Parcel parcel = Parcel.obtain();
+ forecast.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ DayForecast forecastFromParcel = DayForecast.CREATOR.createFromParcel(parcel);
+
+ assertEquals(forecast, forecastFromParcel);
+ assertEquals(forecast.getConditionCode(), forecastFromParcel.getConditionCode());
+ assertEquals(forecast.getHigh(), forecastFromParcel.getHigh());
+ assertEquals(forecast.getLow(), forecastFromParcel.getLow());
+ }
+
+ @SmallTest
+ public void testDayForecastBuilder() {
+ DayForecast forecast = new DayForecast.Builder(mConditionCode).setHigh(mHigh).setLow(mLow)
+ .build();
+
+ assertEquals(forecast.getConditionCode(), mConditionCode);
+ assertEquals(forecast.getHigh(), mHigh);
+ assertEquals(forecast.getLow(), mLow);
+ }
+
+ @SmallTest
+ public void testInvalidWeatherConditionCode() {
+ try {
+ DayForecast forecast = new DayForecast.Builder(Integer.MIN_VALUE).build();
+ throw new AssertionError("DayForecast object was built with invalid condition code!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidHighTemperature() {
+ try {
+ DayForecast forecast = new DayForecast.Builder(mConditionCode).setHigh(Double.NaN)
+ .setLow(mLow).build();
+ throw new AssertionError("DayForecast object was built with invalid high temperature!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidLowTemperature() {
+ try {
+ DayForecast forecast = new DayForecast.Builder(mConditionCode).setHigh(mHigh)
+ .setLow(Double.NaN).build();
+ throw new AssertionError("DayForecast object was built with invalid low temperature!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+}
diff --git a/tests/src/org/lineageos/tests/weather/unit/LineageWeatherManagerTest.java b/tests/src/org/lineageos/tests/weather/unit/LineageWeatherManagerTest.java
new file mode 100644
index 00000000..f6b23484
--- /dev/null
+++ b/tests/src/org/lineageos/tests/weather/unit/LineageWeatherManagerTest.java
@@ -0,0 +1,242 @@
+/**
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.weather.unit;
+
+import android.location.Location;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.weather.LineageWeatherManager;
+import lineageos.weather.LineageWeatherManager.LookupCityRequestListener;
+import lineageos.weather.LineageWeatherManager.WeatherServiceProviderChangeListener;
+import lineageos.weather.LineageWeatherManager.WeatherUpdateRequestListener;
+import lineageos.weather.ILineageWeatherManager;
+import lineageos.weather.RequestInfo;
+import lineageos.weather.WeatherInfo;
+import lineageos.weather.WeatherLocation;
+import org.lineageos.tests.common.MockIBinderStubForInterface;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+public class LineageWeatherManagerTest extends AndroidTestCase {
+
+ private LineageWeatherManager mWeatherManager;
+ private static final String CITY_NAME = "Seattle, WA";
+ private static final int COUNTDOWN = 1;
+ private static final int REQUEST_ID = 42;
+ private static final String MOCKED_WEATHER_PROVIDER_LABEL = "Mock'd Weather Service";
+ private ILineageWeatherManager.Stub mILineageWeatherManagerSpy;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ setUpMockILineageWeatherManager();
+ }
+
+ private void setUpMockILineageWeatherManager() {
+ mWeatherManager = LineageWeatherManager.getInstance(getContext());
+ Field f;
+ try {
+ f = mWeatherManager.getClass().getDeclaredField("sWeatherManagerService");
+ f.setAccessible(true);
+
+ mILineageWeatherManagerSpy
+ = MockIBinderStubForInterface.getMockInterface(ILineageWeatherManager.Stub.class);
+ f.set(mWeatherManager, mILineageWeatherManagerSpy);
+
+ Mockito.doAnswer(new WeatherUpdateRequestAnswer())
+ .when(mILineageWeatherManagerSpy).updateWeather(Mockito.any(RequestInfo.class));
+
+ Mockito.doAnswer(new LookUpCityAnswer())
+ .when(mILineageWeatherManagerSpy).lookupCity(Mockito.any(RequestInfo.class));
+
+ Mockito.doAnswer(new GetActiveWeatherServiceProviderLabelAnser())
+ .when(mILineageWeatherManagerSpy).getActiveWeatherServiceProviderLabel();
+
+ Mockito.doAnswer(new CancelRequestAnswer())
+ .when(mILineageWeatherManagerSpy).cancelRequest(Mockito.eq(REQUEST_ID));
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private static class WeatherUpdateRequestAnswer implements Answer<Integer> {
+
+ @Override
+ public Integer answer(InvocationOnMock invocation) throws Throwable {
+ final RequestInfo requestInfo = (RequestInfo) invocation.getArguments()[0];
+ if (requestInfo.getRequestType() == RequestInfo.TYPE_WEATHER_BY_GEO_LOCATION_REQ) {
+ assertNotNull(requestInfo.getLocation());
+ } else {
+ assertNotNull(requestInfo.getWeatherLocation());
+ }
+ final WeatherInfo weatherInfo = new WeatherInfo.Builder(CITY_NAME,
+ 30d, requestInfo.getTemperatureUnit()).build();
+ requestInfo.getRequestListener().onWeatherRequestCompleted(requestInfo,
+ LineageWeatherManager.RequestStatus.COMPLETED, weatherInfo);
+ return REQUEST_ID;
+ }
+ }
+
+ private static class LookUpCityAnswer implements Answer<Integer> {
+
+ @Override
+ public Integer answer(InvocationOnMock invocation) throws Throwable {
+ final RequestInfo requestInfo = (RequestInfo) invocation.getArguments()[0];
+ final List<WeatherLocation> locations = new ArrayList<>();
+ final String cityName = requestInfo.getCityName();
+ assertNotNull(cityName);
+ locations.add(new WeatherLocation.Builder(cityName).build());
+ requestInfo.getRequestListener().onLookupCityRequestCompleted(requestInfo,
+ LineageWeatherManager.RequestStatus.COMPLETED, locations);
+ return REQUEST_ID;
+ }
+ }
+
+ private static class GetActiveWeatherServiceProviderLabelAnser implements Answer<String> {
+
+ @Override
+ public String answer(InvocationOnMock invocation) throws Throwable {
+ return MOCKED_WEATHER_PROVIDER_LABEL;
+ }
+ }
+
+ private static class CancelRequestAnswer implements Answer<Void> {
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ final int requestId = (Integer) invocation.getArguments()[0];
+ assertEquals(requestId, REQUEST_ID);
+ return null;
+ }
+ }
+
+ @SmallTest
+ public void testGetActiveWeatherServiceProviderLabel() {
+ String providerLabel = mWeatherManager.getActiveWeatherServiceProviderLabel();
+ assertEquals(MOCKED_WEATHER_PROVIDER_LABEL, providerLabel);
+ }
+
+ @MediumTest
+ public void testLookupCity() {
+ final CountDownLatch signal = new CountDownLatch(COUNTDOWN);
+ final boolean[] error = {false};
+ mWeatherManager.lookupCity(CITY_NAME,
+ new LookupCityRequestListener() {
+ @Override
+ public void onLookupCityRequestCompleted(int status,
+ List<WeatherLocation> locations) {
+ final int totalLocations = locations != null ? locations.size() : 0;
+ if (status != LineageWeatherManager.RequestStatus.COMPLETED
+ || totalLocations < 1) {
+ error[0] = true;
+ }
+ signal.countDown();
+ }
+ });
+ try {
+ signal.await();
+ assertFalse(error[0]);
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testRegisterListener() {
+ mWeatherManager.registerWeatherServiceProviderChangeListener(mListener);
+
+ try {
+ mWeatherManager.registerWeatherServiceProviderChangeListener(mListener);
+ throw new AssertionError("Listener was registered twice!");
+ } catch (IllegalArgumentException e) {
+ //EXPECTED
+ }
+
+ mWeatherManager.unregisterWeatherServiceProviderChangeListener(mListener);
+
+ try {
+ mWeatherManager.unregisterWeatherServiceProviderChangeListener(mListener);
+ throw new AssertionError("Listener was de-registered twice!");
+ } catch (IllegalArgumentException e) {
+ //EXPECTED
+ }
+ }
+
+ private WeatherServiceProviderChangeListener mListener
+ = new WeatherServiceProviderChangeListener() {
+ @Override
+ public void onWeatherServiceProviderChanged(String providerLabel) {}
+ };
+
+ @MediumTest
+ public void testRequestWeatherUpdateByWeatherLocation() {
+ final CountDownLatch signal = new CountDownLatch(COUNTDOWN);
+ final WeatherLocation weatherLocation = new WeatherLocation.Builder(CITY_NAME).build();
+ final boolean[] error = {false};
+ mWeatherManager.requestWeatherUpdate(weatherLocation, new WeatherUpdateRequestListener() {
+ @Override
+ public void onWeatherRequestCompleted(int status, WeatherInfo weatherInfo) {
+ if (status != LineageWeatherManager.RequestStatus.COMPLETED
+ || !weatherInfo.getCity().equals(CITY_NAME)) {
+ error[0] = true;
+ }
+ signal.countDown();
+ }
+ });
+ try {
+ signal.await();
+ assertFalse(error[0]);
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @MediumTest
+ public void testRequestWeatherUpdateByLocation() {
+ final CountDownLatch signal = new CountDownLatch(COUNTDOWN);
+ final Location location = new Location("test_location_provider");
+ final boolean[] error = {false};
+ mWeatherManager.requestWeatherUpdate(location, new WeatherUpdateRequestListener() {
+ @Override
+ public void onWeatherRequestCompleted(int status, WeatherInfo weatherInfo) {
+ if (status != LineageWeatherManager.RequestStatus.COMPLETED
+ || !weatherInfo.getCity().equals(CITY_NAME)) {
+ error[0] = true;
+ }
+ signal.countDown();
+ }
+ });
+ try {
+ signal.await();
+ assertFalse(error[0]);
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @SmallTest
+ public void testCancelRequest() {
+ mWeatherManager.cancelRequest(REQUEST_ID);
+ }
+}
diff --git a/tests/src/org/lineageos/tests/weather/unit/MockWeatherProviderService.java b/tests/src/org/lineageos/tests/weather/unit/MockWeatherProviderService.java
new file mode 100644
index 00000000..83f6d6ea
--- /dev/null
+++ b/tests/src/org/lineageos/tests/weather/unit/MockWeatherProviderService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.weather.unit;
+
+import lineageos.weatherservice.ServiceRequest;
+import lineageos.weatherservice.WeatherProviderService;
+import org.mockito.Mockito;
+
+public class MockWeatherProviderService extends WeatherProviderService {
+
+ private MockWeatherProviderService mCallTracker;
+
+ public MockWeatherProviderService() {
+ mCallTracker = Mockito.mock(MockWeatherProviderService.class);
+ }
+
+ public MockWeatherProviderService getCallTracker() {
+ return mCallTracker;
+ }
+
+ @Override
+ protected void onConnected() {
+ mCallTracker.onConnected();
+ }
+
+ @Override
+ protected void onDisconnected() {
+ mCallTracker.onDisconnected();
+ }
+
+ @Override
+ protected void onRequestSubmitted(ServiceRequest request) {
+ mCallTracker.onRequestSubmitted(request);
+ }
+
+ @Override
+ protected void onRequestCancelled(ServiceRequest request) {
+ mCallTracker.onRequestCancelled(request);
+ }
+}
diff --git a/tests/src/org/lineageos/tests/weather/unit/ServiceRequestResultBuilderTest.java b/tests/src/org/lineageos/tests/weather/unit/ServiceRequestResultBuilderTest.java
new file mode 100644
index 00000000..1befff61
--- /dev/null
+++ b/tests/src/org/lineageos/tests/weather/unit/ServiceRequestResultBuilderTest.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.weather.unit;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.providers.WeatherContract;
+import lineageos.weather.WeatherInfo;
+import lineageos.weather.WeatherLocation;
+import lineageos.weatherservice.ServiceRequestResult;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ServiceRequestResultBuilderTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testUnravelFromParcelWithWeatherInfo() {
+ final String cityName = "Cancun";
+ final double temperature = 70;
+ final int temperatureUnit = WeatherContract.WeatherColumns.TempUnit.CELSIUS;
+
+ WeatherInfo info = new WeatherInfo.Builder(cityName, temperature, temperatureUnit)
+ .build();
+
+ ServiceRequestResult result = new ServiceRequestResult.Builder(info).build();
+
+ Parcel parcel = Parcel.obtain();
+ result.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ ServiceRequestResult resultFromParcel
+ = ServiceRequestResult.CREATOR.createFromParcel(parcel);
+
+ assertEquals(result, resultFromParcel);
+ assertEquals(result.getWeatherInfo(), resultFromParcel.getWeatherInfo());
+ }
+
+ @SmallTest
+ public void testsUnravelFromParcelWithWeatherLocationList() {
+
+ List<WeatherLocation> weatherLocationList = new ArrayList<>();
+ weatherLocationList.add(new WeatherLocation.Builder("Cancun").build());
+ ServiceRequestResult result = new ServiceRequestResult.Builder(weatherLocationList).build();
+
+ Parcel parcel = Parcel.obtain();
+ result.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ ServiceRequestResult resultFromParcel
+ = ServiceRequestResult.CREATOR.createFromParcel(parcel);
+
+ assertEquals(result, resultFromParcel);
+ assertEquals(result.getLocationLookupList(), resultFromParcel.getLocationLookupList());
+ }
+
+ @SmallTest
+ public void testNullWeatherInfo() {
+ try {
+ WeatherInfo info = null;
+ ServiceRequestResult result = new ServiceRequestResult.Builder(info).build();
+ throw new AssertionError("ServiceRequestResult object was built with null WeatherInfo");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testNullWeatherLocationList() {
+ try {
+ List<WeatherLocation> list = null;
+ ServiceRequestResult result = new ServiceRequestResult.Builder(list).build();
+ throw new AssertionError("ServiceRequestResult object was built with null "
+ + "WeatherLocation list");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+}
diff --git a/tests/src/org/lineageos/tests/weather/unit/WeatherInfoBuilderTest.java b/tests/src/org/lineageos/tests/weather/unit/WeatherInfoBuilderTest.java
new file mode 100644
index 00000000..bc1dd100
--- /dev/null
+++ b/tests/src/org/lineageos/tests/weather/unit/WeatherInfoBuilderTest.java
@@ -0,0 +1,252 @@
+/**
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.weather.unit;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.providers.WeatherContract;
+import lineageos.weather.WeatherInfo;
+
+public class WeatherInfoBuilderTest extends AndroidTestCase {
+
+ private static final String mCityName = "Cancun";
+ private static final double mTemperature = 70;
+ private static final int mTemperatureUnit = WeatherContract.WeatherColumns.TempUnit.CELSIUS;
+ private static final double mHumidity = 45;
+ private static final double mWindSpeed = 15;
+ private static final double mWindDirection = 150;
+ private static final int mWindSpeedUnit = WeatherContract.WeatherColumns.WindSpeedUnit.KPH;
+ private static final long mTimestamp = System.currentTimeMillis();
+ private static final double mTodaysHigh = 80;
+ private static final double mTodaysLow = 65;
+ private static final int mWeatherConditionCode
+ = WeatherContract.WeatherColumns.WeatherCode.SUNNY;
+
+ @SmallTest
+ public void testUnravelFromParcelWithDefaultValues() {
+ //City name, temp and unit are required
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature, mTemperatureUnit)
+ .build();
+ Parcel parcel = Parcel.obtain();
+ info.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ WeatherInfo weatherInfoFromParcel = WeatherInfo.CREATOR.createFromParcel(parcel);
+ assertNotNull(weatherInfoFromParcel);
+
+ assertEquals(info, weatherInfoFromParcel);
+ //City name
+ assertEquals(info.getCity(), weatherInfoFromParcel.getCity());
+ //Forecast list
+ assertEquals(info.getForecasts(), weatherInfoFromParcel.getForecasts());
+ //Humidity
+ assertEquals(info.getHumidity(), weatherInfoFromParcel.getHumidity());
+ //Temp
+ assertEquals(info.getConditionCode(), weatherInfoFromParcel.getConditionCode());
+ assertEquals(info.getTemperature(), weatherInfoFromParcel.getTemperature());
+ assertEquals(info.getTemperatureUnit(), weatherInfoFromParcel.getTemperatureUnit());
+ //Timestamp
+ assertEquals(info.getTimestamp(), weatherInfoFromParcel.getTimestamp());
+ //Today's low/high
+ assertEquals(info.getTodaysHigh(), weatherInfoFromParcel.getTodaysHigh());
+ assertEquals(info.getTodaysLow(), weatherInfoFromParcel.getTodaysLow());
+ //Wind
+ assertEquals(info.getWindDirection(), weatherInfoFromParcel.getWindDirection());
+ assertEquals(info.getWindSpeed(), weatherInfoFromParcel.getWindDirection());
+ assertEquals(info.getWindSpeedUnit(), weatherInfoFromParcel.getWindSpeedUnit());
+ //Verify default values
+ assertEquals(info.getTodaysHigh(), Double.NaN);
+ }
+
+ @SmallTest
+ public void testWeatherInfoBuilder() {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature, mTemperatureUnit)
+ .setHumidity(mHumidity)
+ .setWind(mWindSpeed, mWindDirection, mWindSpeedUnit)
+ .setTimestamp(mTimestamp)
+ .setTodaysHigh(mTodaysHigh)
+ .setTodaysLow(mTodaysLow)
+ .setWeatherCondition(mWeatherConditionCode).build();
+
+ assertEquals(info.getCity(), mCityName);
+ assertEquals(info.getTemperature(), mTemperature);
+ assertEquals(info.getTemperatureUnit(), mTemperatureUnit);
+ assertEquals(info.getHumidity(), mHumidity);
+ assertEquals(info.getWindSpeed(), mWindSpeed);
+ assertEquals(info.getWindDirection(), mWindDirection);
+ assertEquals(info.getWindSpeedUnit(), mWindSpeedUnit);
+ assertEquals(info.getTimestamp(), mTimestamp);
+ assertEquals(info.getTodaysHigh(), mTodaysHigh);
+ assertEquals(info.getTodaysLow(), mTodaysLow);
+ assertEquals(info.getConditionCode(), mWeatherConditionCode);
+ }
+
+ @SmallTest
+ public void testUnravelFromParcel() {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature, mTemperatureUnit)
+ .setHumidity(mHumidity)
+ .setWind(mWindSpeed, mWindDirection, mWindSpeedUnit)
+ .setTimestamp(mTimestamp)
+ .setTodaysHigh(mTodaysHigh)
+ .setTodaysLow(mTodaysLow)
+ .setWeatherCondition(mWeatherConditionCode).build();
+
+ Parcel parcel = Parcel.obtain();
+ info.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ WeatherInfo infoFromParcel = WeatherInfo.CREATOR.createFromParcel(parcel);
+ assertEquals(info.getCity(), infoFromParcel.getCity());
+ assertEquals(info.getTemperature(), infoFromParcel.getTemperature());
+ assertEquals(info.getTemperatureUnit(), infoFromParcel.getTemperatureUnit());
+ assertEquals(info.getHumidity(), infoFromParcel.getHumidity());
+ assertEquals(info.getWindSpeed(), infoFromParcel.getWindSpeed());
+ assertEquals(info.getWindDirection(), infoFromParcel.getWindDirection());
+ assertEquals(info.getWindSpeedUnit(), infoFromParcel.getWindSpeedUnit());
+ assertEquals(info.getTimestamp(), infoFromParcel.getTimestamp());
+ assertEquals(info.getTodaysHigh(), infoFromParcel.getTodaysHigh());
+ assertEquals(info.getTodaysLow(), infoFromParcel.getTodaysLow());
+ assertEquals(info.getConditionCode(), infoFromParcel.getConditionCode());
+ }
+
+ @SmallTest
+ public void testNullCityName() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(null, mTemperature, mTemperatureUnit)
+ .build();
+ throw new AssertionError("WeatherInfo object built with null city name!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidTemperature() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, Double.NaN, mTemperatureUnit)
+ .build();
+ throw new AssertionError("WeatherInfo object built with invalid temperature value!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidTemperatureUnit() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,Integer.MIN_VALUE)
+ .build();
+ throw new AssertionError("WeatherInfo object built with invalid temperature unit!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testNullForecastList() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setForecast(null).build();
+ throw new AssertionError("WeatherInfo object built with null forecast list!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidWeatherConditionCode() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setWeatherCondition(Integer.MIN_VALUE).build();
+ throw new AssertionError("WeatherInfo object built with invalid weather "
+ + "condition code!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidHumidity() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setHumidity(Double.NaN).build();
+ throw new AssertionError("WeatherInfo object built with invalid humidity value!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidWindSpeed() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setWind(Double.NaN, mWindDirection, mWindSpeedUnit)
+ .build();
+ throw new AssertionError("WeatherInfo object built with invalid wind speed!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidWindDirection() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setWind(mWindSpeed, Double.NaN, mWindSpeedUnit)
+ .build();
+ throw new AssertionError("WeatherInfo object built with invalid wind direction!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidWindSpeedUnit(){
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setWind(mWindSpeed, mWindDirection, Integer.MIN_VALUE).build();
+ throw new AssertionError("WeatherInfo object built with invalid wind speed unit!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidTodaysLow() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setTodaysLow(Double.NaN).build();
+ throw new AssertionError("WeatherInfo object built with invalid low temp!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+
+ @SmallTest
+ public void testInvalidTodaysHigh() {
+ try {
+ WeatherInfo info = new WeatherInfo.Builder(mCityName, mTemperature,mTemperatureUnit)
+ .setTodaysHigh(Double.NaN).build();
+ throw new AssertionError("WeatherInfo object built with invalid high temp!");
+ } catch (IllegalArgumentException e) {
+ /* EXPECTED */
+ }
+ }
+}
diff --git a/tests/src/org/lineageos/tests/weather/unit/WeatherLocationBuilderTest.java b/tests/src/org/lineageos/tests/weather/unit/WeatherLocationBuilderTest.java
new file mode 100644
index 00000000..b6d9c207
--- /dev/null
+++ b/tests/src/org/lineageos/tests/weather/unit/WeatherLocationBuilderTest.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.weather.unit;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import lineageos.weather.WeatherLocation;
+
+public class WeatherLocationBuilderTest extends AndroidTestCase {
+
+ private static final String mCityId = "can1";
+ private static final String mCityName = "Cancun";
+ private static final String mState = "Quintana Roo";
+ private static final String mCountryId = "MX";
+ private static final String mCountry = "Mexico";
+ private static final String mZipCode = "77510";
+
+ @SmallTest
+ public void testUnravelFromParcelTwoArgsConstructor() {
+ WeatherLocation location = new WeatherLocation.Builder(mCityId, mCityName)
+ .setState(mState).setPostalCode(mZipCode).setCountryId(mCountryId)
+ .setCountry(mCountry).build();
+
+ Parcel parcel = Parcel.obtain();
+ location.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ WeatherLocation locationFromParcel = WeatherLocation.CREATOR.createFromParcel(parcel);
+
+ assertEquals(location, locationFromParcel);
+ assertEquals(location.getCityId(), locationFromParcel.getCityId());
+ assertEquals(location.getCity(), locationFromParcel.getCity());
+ assertEquals(location.getState(), locationFromParcel.getState());
+ assertEquals(location.getPostalCode(), locationFromParcel.getPostalCode());
+ assertEquals(location.getCountry(), locationFromParcel.getCountry());
+ assertEquals(location.getCountryId(), locationFromParcel.getCountryId());
+ }
+
+ @SmallTest
+ public void testUnravelFromParcelOneArgConstructor() {
+ WeatherLocation location = new WeatherLocation.Builder(mCityName)
+ .setState(mState).setPostalCode(mZipCode).setCountryId(mCountryId)
+ .setCountry(mCountry).build();
+
+ Parcel parcel = Parcel.obtain();
+ location.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ WeatherLocation locationFromParcel = WeatherLocation.CREATOR.createFromParcel(parcel);
+
+ assertEquals(location, locationFromParcel);
+ assertEquals(location.getCityId(), locationFromParcel.getCityId());
+ assertEquals(location.getCity(), locationFromParcel.getCity());
+ assertEquals(location.getState(), locationFromParcel.getState());
+ assertEquals(location.getPostalCode(), locationFromParcel.getPostalCode());
+ assertEquals(location.getCountry(), locationFromParcel.getCountry());
+ assertEquals(location.getCountryId(), locationFromParcel.getCountryId());
+ }
+
+ @SmallTest
+ public void testUnravelFromParcelWithDefaultsOneArgConstructor() {
+ WeatherLocation location = new WeatherLocation.Builder(mCityName).build();
+ Parcel parcel = Parcel.obtain();
+ location.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ WeatherLocation locationFromParcel = WeatherLocation.CREATOR.createFromParcel(parcel);
+
+ assertEquals(location, locationFromParcel);
+ assertEquals(location.getCityId(), locationFromParcel.getCityId());
+ assertEquals(location.getCity(), locationFromParcel.getCity());
+ assertEquals(location.getState(), locationFromParcel.getState());
+ assertEquals(location.getPostalCode(), locationFromParcel.getPostalCode());
+ assertEquals(location.getCountry(), locationFromParcel.getCountry());
+ assertEquals(location.getCountryId(), locationFromParcel.getCountryId());
+ }
+
+ @SmallTest
+ public void testUnravelFromParcelWithDefaultsTwoArgsConstructor() {
+ WeatherLocation location = new WeatherLocation.Builder(mCityId, mCityName).build();
+ Parcel parcel = Parcel.obtain();
+ location.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+
+ WeatherLocation locationFromParcel = WeatherLocation.CREATOR.createFromParcel(parcel);
+
+ assertEquals(location, locationFromParcel);
+ assertEquals(location.getCityId(), locationFromParcel.getCityId());
+ assertEquals(location.getCity(), locationFromParcel.getCity());
+ assertEquals(location.getState(), locationFromParcel.getState());
+ assertEquals(location.getPostalCode(), locationFromParcel.getPostalCode());
+ assertEquals(location.getCountry(), locationFromParcel.getCountry());
+ assertEquals(location.getCountryId(), locationFromParcel.getCountryId());
+ }
+
+
+ @SmallTest
+ public void testWeatherLocationBuilder() {
+ WeatherLocation location = new WeatherLocation.Builder(mCityId, mCityName)
+ .setState(mState).setPostalCode(mZipCode).setCountryId(mCountryId)
+ .setCountry(mCountry).build();
+
+ assertEquals(location.getCityId(), mCityId);
+ assertEquals(location.getCity(), mCityName);
+ assertEquals(location.getState(), mState);
+ assertEquals(location.getPostalCode(), mZipCode);
+ assertEquals(location.getCountryId(), mCountryId);
+ assertEquals(location.getCountry(), mCountry);
+ }
+}
diff --git a/tests/src/org/lineageos/tests/weather/unit/WeatherProviderServiceTest.java b/tests/src/org/lineageos/tests/weather/unit/WeatherProviderServiceTest.java
new file mode 100644
index 00000000..bce369d4
--- /dev/null
+++ b/tests/src/org/lineageos/tests/weather/unit/WeatherProviderServiceTest.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.lineageos.tests.weather.unit;
+
+import android.location.Location;
+import android.os.IBinder;
+import lineageos.weather.LineageWeatherManager;
+import lineageos.weather.RequestInfo;
+import lineageos.weather.WeatherLocation;
+import lineageos.weatherservice.IWeatherProviderService;
+import lineageos.weatherservice.IWeatherProviderServiceClient;
+import lineageos.weatherservice.ServiceRequest;
+import lineageos.weatherservice.ServiceRequestResult;
+import org.lineageos.tests.common.MockIBinderStubForInterface;
+import org.lineageos.tests.common.ThreadServiceTestCase;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+public class WeatherProviderServiceTest extends ThreadServiceTestCase<MockWeatherProviderService> {
+
+ public WeatherProviderServiceTest() {
+ super(MockWeatherProviderService.class);
+ }
+
+ private static final String CITY_NAME = "Seattle";
+ private static final int TIMEOUT = 5000;
+
+ public void testCityNameLookupRequest() throws Exception {
+ IBinder binder = bindService((ServiceRunnable) null);
+ assertNotNull(binder);
+
+ final IWeatherProviderService provider = IWeatherProviderService.Stub.asInterface(binder);
+ assertNotNull(provider);
+
+ provider.processCityNameLookupRequest(
+ buildMockdRequestInfo(RequestInfo.TYPE_LOOKUP_CITY_NAME_REQ));
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ ArgumentCaptor<ServiceRequest> params
+ = ArgumentCaptor.forClass(ServiceRequest.class);
+
+ Mockito.verify(getService().getCallTracker(), Mockito.timeout(TIMEOUT).times(1))
+ .onRequestSubmitted(params.capture());
+
+ ServiceRequest request = params.getValue();
+ assertEquals(request.getRequestInfo().getRequestType(),
+ RequestInfo.TYPE_LOOKUP_CITY_NAME_REQ);
+
+ assertEquals(request.getRequestInfo().getCityName(), CITY_NAME);
+ }
+ });
+ }
+
+ public void testWeatherUpdateRequestByWeatherLocation() throws Exception {
+ IBinder binder = bindService((ServiceRunnable) null);
+ assertNotNull(binder);
+
+ final IWeatherProviderService provider = IWeatherProviderService.Stub.asInterface(binder);
+ assertNotNull(provider);
+
+ provider.processWeatherUpdateRequest(
+ buildMockdRequestInfo(RequestInfo.TYPE_WEATHER_BY_WEATHER_LOCATION_REQ));
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ ArgumentCaptor<ServiceRequest> params
+ = ArgumentCaptor.forClass(ServiceRequest.class);
+
+ Mockito.verify(getService().getCallTracker(), Mockito.timeout(TIMEOUT).times(1))
+ .onRequestSubmitted(params.capture());
+
+ ServiceRequest request = params.getValue();
+ assertEquals(request.getRequestInfo().getRequestType(),
+ RequestInfo.TYPE_WEATHER_BY_WEATHER_LOCATION_REQ);
+
+ WeatherLocation weatherLocation = request.getRequestInfo().getWeatherLocation();
+ assertNotNull(weatherLocation);
+ assertEquals(weatherLocation.getCity(), CITY_NAME);
+ }
+ });
+ }
+
+ public void testWeatherUpdateRequestByGeoLocation() throws Exception {
+ IBinder binder = bindService((ServiceRunnable) null);
+ assertNotNull(binder);
+
+ final IWeatherProviderService provider = IWeatherProviderService.Stub.asInterface(binder);
+ assertNotNull(provider);
+
+ provider.processWeatherUpdateRequest(
+ buildMockdRequestInfo(RequestInfo.TYPE_WEATHER_BY_GEO_LOCATION_REQ));
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ ArgumentCaptor<ServiceRequest> params
+ = ArgumentCaptor.forClass(ServiceRequest.class);
+
+ Mockito.verify(getService().getCallTracker(), Mockito.timeout(TIMEOUT).times(1))
+ .onRequestSubmitted(params.capture());
+
+ ServiceRequest request = params.getValue();
+ assertEquals(request.getRequestInfo().getRequestType(),
+ RequestInfo.TYPE_WEATHER_BY_GEO_LOCATION_REQ);
+
+ Location location = request.getRequestInfo().getLocation();
+ assertNotNull(location);
+ }
+ });
+ }
+
+ public void testServiceRequestResult() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(3);
+ IBinder binder = bindService((ServiceRunnable) null);
+ assertNotNull(binder);
+
+ final IWeatherProviderService provider = IWeatherProviderService.Stub.asInterface(binder);
+ assertNotNull(provider);
+
+ IWeatherProviderServiceClient client =
+ MockIBinderStubForInterface.getMockInterface(
+ IWeatherProviderServiceClient.Stub.class);
+
+ Mockito.doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ RequestInfo requestInfo = (RequestInfo) invocation.getArguments()[0];
+ int result = (int) invocation.getArguments()[2];
+
+ assertNotNull(requestInfo);
+ assertEquals(result, LineageWeatherManager.RequestStatus.FAILED);
+
+ latch.countDown();
+ return null;
+ }
+ }).when(client)
+ .setServiceRequestState(Mockito.any(RequestInfo.class),
+ Mockito.any(ServiceRequestResult.class),
+ Mockito.eq(LineageWeatherManager.RequestStatus.FAILED));
+
+ Mockito.doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+
+ RequestInfo requestInfo = (RequestInfo) invocation.getArguments()[0];
+ int result = (int) invocation.getArguments()[2];
+
+ assertNotNull(requestInfo);
+ assertEquals(result, LineageWeatherManager.RequestStatus.SUBMITTED_TOO_SOON);
+
+ latch.countDown();
+ return null;
+ }
+ }).when(client)
+ .setServiceRequestState(Mockito.any(RequestInfo.class),
+ Mockito.any(ServiceRequestResult.class),
+ Mockito.eq(LineageWeatherManager.RequestStatus.SUBMITTED_TOO_SOON));
+
+ Mockito.doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ RequestInfo requestInfo = (RequestInfo) invocation.getArguments()[0];
+ ServiceRequestResult requestResult
+ = (ServiceRequestResult) invocation.getArguments()[1];
+ int result = (int) invocation.getArguments()[2];
+
+ assertNotNull(requestInfo);
+ assertNotNull(requestResult);
+ assertNotNull(requestResult.getLocationLookupList());
+ assertEquals(result, LineageWeatherManager.RequestStatus.COMPLETED);
+
+ latch.countDown();
+ return null;
+ }
+ }).when(client)
+ .setServiceRequestState(Mockito.any(RequestInfo.class),
+ Mockito.any(ServiceRequestResult.class),
+ Mockito.eq(LineageWeatherManager.RequestStatus.COMPLETED));
+
+ provider.setServiceClient(client);
+
+ final RequestInfo requestInfo
+ = buildMockdRequestInfo(RequestInfo.TYPE_LOOKUP_CITY_NAME_REQ);
+
+ Mockito.reset(getService().getCallTracker());
+ provider.processCityNameLookupRequest(requestInfo);
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ ArgumentCaptor<ServiceRequest> params
+ = ArgumentCaptor.forClass(ServiceRequest.class);
+
+ Mockito.verify(getService().getCallTracker(), Mockito.timeout(TIMEOUT).times(1))
+ .onRequestSubmitted(params.capture());
+
+ ServiceRequest request = params.getValue();
+ request.fail();
+ }
+ });
+
+ Mockito.reset(getService().getCallTracker());
+ provider.processCityNameLookupRequest(requestInfo);
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ ArgumentCaptor<ServiceRequest> params
+ = ArgumentCaptor.forClass(ServiceRequest.class);
+
+ Mockito.verify(getService().getCallTracker(), Mockito.timeout(TIMEOUT).times(1))
+ .onRequestSubmitted(params.capture());
+
+ ServiceRequest request = params.getValue();
+ request.reject(LineageWeatherManager.RequestStatus.SUBMITTED_TOO_SOON);
+ }
+ });
+
+ Mockito.reset(getService().getCallTracker());
+ provider.processCityNameLookupRequest(requestInfo);
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ ArgumentCaptor<ServiceRequest> params
+ = ArgumentCaptor.forClass(ServiceRequest.class);
+
+ Mockito.verify(getService().getCallTracker(), Mockito.timeout(TIMEOUT).times(1))
+ .onRequestSubmitted(params.capture());
+
+ ServiceRequest request = params.getValue();
+
+ List<WeatherLocation> locations = new ArrayList<>();
+ locations.add(new WeatherLocation.Builder(CITY_NAME).build());
+ ServiceRequestResult result = new ServiceRequestResult.Builder(locations).build();
+ request.complete(result);
+ }
+ });
+
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+
+ }
+
+ private RequestInfo buildMockdRequestInfo(int requestType) {
+ try {
+ Constructor<RequestInfo> c = RequestInfo.class.getDeclaredConstructor();
+ c.setAccessible(true);
+ RequestInfo info = c.newInstance();
+ Field type;
+ type = info.getClass().getDeclaredField("mRequestType");
+ type.setAccessible(true);
+ type.set(info, requestType);
+ switch (requestType) {
+ case RequestInfo.TYPE_LOOKUP_CITY_NAME_REQ:
+ Field cityName;
+ cityName = info.getClass().getDeclaredField("mCityName");
+ cityName.setAccessible(true);
+ cityName.set(info, CITY_NAME);
+ break;
+ case RequestInfo.TYPE_WEATHER_BY_WEATHER_LOCATION_REQ:
+ Field weatherLocation;
+ weatherLocation = info.getClass().getDeclaredField("mWeatherLocation");
+ weatherLocation.setAccessible(true);
+ weatherLocation.set(info, new WeatherLocation.Builder(CITY_NAME).build());
+ break;
+ case RequestInfo.TYPE_WEATHER_BY_GEO_LOCATION_REQ:
+ Field location;
+ location = info.getClass().getDeclaredField("mLocation");
+ location.setAccessible(true);
+ location.set(info, new Location("dummy_location_provider"));
+ break;
+ default:
+ throw new AssertionError("Unknown request type");
+ }
+ return info;
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+}