diff options
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | api/lineage_current.txt | 24 | ||||
-rw-r--r-- | lineage/lib/main/java/org/lineageos/platform/internal/TrustInterfaceService.java | 349 | ||||
-rw-r--r-- | lineage/res/AndroidManifest.xml | 7 | ||||
-rw-r--r-- | lineage/res/res/drawable/ic_trust.xml | 11 | ||||
-rw-r--r-- | lineage/res/res/drawable/ic_warning.xml | 11 | ||||
-rw-r--r-- | lineage/res/res/values/colors.xml | 20 | ||||
-rw-r--r-- | lineage/res/res/values/config.xml | 5 | ||||
-rw-r--r-- | lineage/res/res/values/strings.xml | 16 | ||||
-rw-r--r-- | lineage/res/res/values/symbols.xml | 17 | ||||
-rw-r--r-- | sdk/src/java/lineageos/app/LineageContextConstants.java | 19 | ||||
-rw-r--r-- | sdk/src/java/lineageos/providers/LineageSettings.java | 33 | ||||
-rw-r--r-- | sdk/src/java/lineageos/trust/ITrustInterface.aidl | 26 | ||||
-rw-r--r-- | sdk/src/java/lineageos/trust/TrustInterface.java | 217 |
14 files changed, 755 insertions, 2 deletions
@@ -25,7 +25,7 @@ LOCAL_PATH := $(call my-dir) lineage_platform_res := APPS/org.lineageos.platform-res_intermediates/src # List of packages used in lineage-api-stubs -lineage_stub_packages := lineageos.app:lineageos.content:lineageos.hardware:lineageos.media:lineageos.os:lineageos.preference:lineageos.profiles:lineageos.providers:lineageos.platform:lineageos.power:lineageos.util:lineageos.weather:lineageos.weatherservice:lineageos.style +lineage_stub_packages := lineageos.app:lineageos.content:lineageos.hardware:lineageos.media:lineageos.os:lineageos.preference:lineageos.profiles:lineageos.providers:lineageos.platform:lineageos.power:lineageos.util:lineageos.weather:lineageos.weatherservice:lineageos.style:lineageos.trust # The LineageOS Platform Framework Library # ============================================================ diff --git a/api/lineage_current.txt b/api/lineage_current.txt index 9f363065..e9b5e32f 100644 --- a/api/lineage_current.txt +++ b/api/lineage_current.txt @@ -335,6 +335,7 @@ package lineageos.os { field public static final int FIG = 6; // 0x6 field public static final int GUAVA = 7; // 0x7 field public static final int HACKBERRY = 8; // 0x8 + field public static final int ILAMA = 9; // 0x9 } public final class Concierge { @@ -368,6 +369,7 @@ package lineageos.platform { field public static final java.lang.String PROTECTED_APP = "lineageos.permission.PROTECTED_APP"; field public static final java.lang.String READ_DATAUSAGE = "lineageos.permission.READ_DATAUSAGE"; field public static final java.lang.String READ_WEATHER = "lineageos.permission.READ_WEATHER"; + field public static final java.lang.String TRUST_INTERFACE = "lineageos.permission.TRUST_INTERFACE"; field public static final java.lang.String WRITE_DATAUSAGE = "lineageos.permission.WRITE_DATAUSAGE"; field public static final java.lang.String WRITE_SECURE_SETTINGS = "lineageos.permission.WRITE_SECURE_SETTINGS"; field public static final java.lang.String WRITE_SETTINGS = "lineageos.permission.WRITE_SETTINGS"; @@ -775,6 +777,7 @@ package lineageos.providers { method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String); field public static final android.net.Uri CONTENT_URI; field public static final java.lang.String SYS_PROP_LINEAGE_SETTING_VERSION = "sys.lineage_settings_secure_version"; + field public static final java.lang.String TRUST_NOTIFICATIONS = "trust_notifications"; } public static final class LineageSettings.System extends android.provider.Settings.NameValueTable { @@ -1016,6 +1019,27 @@ package lineageos.style { } +package lineageos.trust { + + public class TrustInterface { + method public static lineageos.trust.TrustInterface getInstance(android.content.Context); + method public int getLevelForFeature(int); + method public boolean postNotificationForFeature(int); + method public boolean removeNotificationForFeature(int); + field public static final int ERROR_UNDEFINED = -1; // 0xffffffff + field public static final int TRUST_FEATURE_ENCRYPTION = 4; // 0x4 + field public static final int TRUST_FEATURE_LEVEL_BAD = 2; // 0x2 + field public static final int TRUST_FEATURE_LEVEL_GOOD = 0; // 0x0 + field public static final int TRUST_FEATURE_LEVEL_POOR = 1; // 0x1 + field public static final int TRUST_FEATURE_PLATFORM_SECURITY_PATCH = 2; // 0x2 + field public static final int TRUST_FEATURE_ROOT = 1; // 0x1 + field public static final int TRUST_FEATURE_SELINUX = 0; // 0x0 + field public static final int TRUST_FEATURE_VENDOR_SECURITY_PATCH = 3; // 0x3 + field public static final java.lang.String TRUST_INTERFACE_PERMISSION = "lineageos.permission.TRUST_INTERFACE"; + } + +} + package lineageos.util { public class ColorUtils { diff --git a/lineage/lib/main/java/org/lineageos/platform/internal/TrustInterfaceService.java b/lineage/lib/main/java/org/lineageos/platform/internal/TrustInterfaceService.java new file mode 100644 index 00000000..41956b08 --- /dev/null +++ b/lineage/lib/main/java/org/lineageos/platform/internal/TrustInterfaceService.java @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2018 The LineageOS 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.platform.internal; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.admin.DevicePolicyManager; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.SELinux; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.util.Log; +import android.util.Pair; +import android.text.TextUtils; + +import lineageos.app.LineageContextConstants; +import lineageos.providers.LineageSettings; +import lineageos.trust.ITrustInterface; +import lineageos.trust.TrustInterface; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** @hide **/ +public class TrustInterfaceService extends LineageSystemService { + private static final String TAG = "LineageTrustInterfaceService"; + private static final String PLATFORM_SECURITY_PATCHES = "ro.build.version.security_patch"; + private static final String VENDOR_SECURITY_PATCHES = "ro.vendor.build.security_patch"; + private static final String LINEAGE_VENDOR_SECURITY_PATCHES = + "ro.lineage.build.vendor_security_patch"; + private static final String INTENT_PARTS = "org.lineageos.lineageparts.TRUST_INTERFACE"; + private static final String INTENT_ONBOARDING = "org.lineageos.lineageparts.TRUST_HINT"; + private static final String CHANNEL_NAME = "TrustInterface"; + private static final int ONBOARDING_NOTIFCATION_ID = 89; + + private Context mContext; + private NotificationManager mNotificationManager = null; + + public TrustInterfaceService(Context context) { + super(context); + mContext = context; + if (context.getPackageManager().hasSystemFeature(LineageContextConstants.Features.TRUST)) { + publishBinderService(LineageContextConstants.LINEAGE_TRUST_INTERFACE, mService); + } else { + Log.wtf(TAG, "Lineage Trust service started by system server but feature xml not" + + " declared. Not publishing binder service!"); + } + } + + @Override + public String getFeatureDeclaration() { + return LineageContextConstants.Features.TRUST; + } + + @Override + public void onStart() { + mNotificationManager = mContext.getSystemService(NotificationManager.class); + // Onboard + if (!hasOnboardedUser()) { + postOnBoardingNotification(); + return; + } + + int selinuxStatus = getSELinuxStatus(); + if (selinuxStatus != TrustInterface.TRUST_FEATURE_LEVEL_GOOD) { + postNotificationForFeatureInternal(TrustInterface.TRUST_FEATURE_SELINUX); + } + } + + /* Public methods implementation */ + + private boolean postNotificationForFeatureInternal(int feature) { + if (!hasOnboardedUser() || !userAllowsTrustNotifications()) { + return false; + } + + Pair<Integer, Integer> strings = getNotificationStringsForFeature(feature); + if (strings == null) { + return false; + } + + String title = mContext.getString(strings.first); + String message = mContext.getString(strings.second); + Intent intent = new Intent(INTENT_PARTS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + PendingIntent pIntent = PendingIntent.getActivity(mContext, 0, intent, 0); + + Notification.Builder notification = new Notification.Builder(mContext, CHANNEL_NAME) + .setContentTitle(title) + .setContentText(message) + .setStyle(new Notification.BigTextStyle().bigText(message)) + .setAutoCancel(true) + .setContentIntent(pIntent) + .setColor(mContext.getColor(R.color.color_error)) + .setSmallIcon(R.drawable.ic_warning); + + createNotificationChannelIfNeeded(); + mNotificationManager.notify(feature, notification.build()); + return true; + } + + private boolean removeNotificationForFeatureInternal(int feature) { + if (!userAllowsTrustNotifications()) { + return false; + } + + mNotificationManager.cancel(feature); + return true; + } + + private boolean postOnBoardingNotification() { + if (hasOnboardedUser()) { + return false; + } + + String title = mContext.getString(R.string.trust_notification_title_onboarding); + String message = mContext.getString(R.string.trust_notification_content_onboarding); + Intent intent = new Intent(INTENT_ONBOARDING); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + PendingIntent pIntent = PendingIntent.getActivity(mContext, 0, intent, 0); + + Notification.Builder notification = new Notification.Builder(mContext, CHANNEL_NAME) + .setContentTitle(title) + .setContentText(message) + .setStyle(new Notification.BigTextStyle().bigText(message)) + .setAutoCancel(true) + .setContentIntent(pIntent) + .setSmallIcon(R.drawable.ic_trust); + + createNotificationChannelIfNeeded(); + mNotificationManager.notify(ONBOARDING_NOTIFCATION_ID, notification.build()); + return true; + } + + private int getLevelForFeatureInternal(int feature) { + switch (feature) { + case TrustInterface.TRUST_FEATURE_SELINUX: + return getSELinuxStatus(); + case TrustInterface.TRUST_FEATURE_ROOT: + return getRootStatus(); + case TrustInterface.TRUST_FEATURE_PLATFORM_SECURITY_PATCH: + return getSecurityPatchStatus(PLATFORM_SECURITY_PATCHES); + case TrustInterface.TRUST_FEATURE_VENDOR_SECURITY_PATCH: + return getSecurityPatchStatus(VENDOR_SECURITY_PATCHES); + case TrustInterface.TRUST_FEATURE_ENCRYPTION: + return getEncryptionStatus(); + default: + return TrustInterface.ERROR_UNDEFINED; + } + } + + /* Utils */ + + private void enforceTrustPermission() { + mContext.enforceCallingOrSelfPermission(TrustInterface.TRUST_INTERFACE_PERMISSION, + "You do not have permissions to use the Trust interface"); + } + + private boolean userAllowsTrustNotifications() { + return LineageSettings.Secure.getInt(mContext.getContentResolver(), + LineageSettings.Secure.TRUST_NOTIFICATIONS, 1) == 1; + } + + private Pair<Integer, Integer> getNotificationStringsForFeature(int feature) { + int title = 0; + int message = 0; + + switch (feature) { + case TrustInterface.TRUST_FEATURE_SELINUX: + title = R.string.trust_notification_title_selinux; + message = R.string.trust_notification_content_selinux; + break; + case TrustInterface.TRUST_FEATURE_ROOT: + title = R.string.trust_notification_title_root; + message = R.string.trust_notification_content_root; + break; + } + + return title == 0 ? null : new Pair(title, message); + } + + private void createNotificationChannelIfNeeded() { + NotificationChannel channel = mNotificationManager.getNotificationChannel(CHANNEL_NAME); + if (channel != null) { + return; + } + + String name = mContext.getString(R.string.trust_notification_channel); + int importance = NotificationManager.IMPORTANCE_HIGH; + NotificationChannel trustChannel = new NotificationChannel(CHANNEL_NAME, + name, importance); + trustChannel.setBlockableSystem(true); + mNotificationManager.createNotificationChannel(trustChannel); + } + + private int getSELinuxStatus() { + return SELinux.isSELinuxEnforced() ? + TrustInterface.TRUST_FEATURE_LEVEL_GOOD : + TrustInterface.TRUST_FEATURE_LEVEL_BAD; + } + + private int getRootStatus() { + String status = SystemProperties.get("persist.sys.root_access"); + switch (status) { + case "0": + return TrustInterface.TRUST_FEATURE_LEVEL_GOOD; + case "1": + case "3": + return TrustInterface.TRUST_FEATURE_LEVEL_BAD; + case "2": + return TrustInterface.TRUST_FEATURE_LEVEL_POOR; + default: + return TrustInterface.ERROR_UNDEFINED; + } + } + + private int getSecurityPatchStatus(String target) { + String patchLevel = SystemProperties.get(target); + if (TextUtils.isEmpty(patchLevel)) { + // Try to fallback to Lineage vendor prop + if (VENDOR_SECURITY_PATCHES.equals(target)) { + patchLevel = SystemProperties.get(LINEAGE_VENDOR_SECURITY_PATCHES); + if (TextUtils.isEmpty(patchLevel)) { + return TrustInterface.ERROR_UNDEFINED; + } + } else { + return TrustInterface.ERROR_UNDEFINED; + } + } + + Calendar today = Calendar.getInstance(); + Calendar patchCal = Calendar.getInstance(); + + try { + Date date = new SimpleDateFormat("yyyy-MM-dd").parse(patchLevel); + patchCal.setTime(date); + + int diff = (today.get(Calendar.YEAR) - patchCal.get(Calendar.YEAR)) * 12 + + today.get(Calendar.MONTH) - patchCal.get(Calendar.MONTH); + if (diff < 0) { + // This is a blatant lie + return TrustInterface.TRUST_FEATURE_LEVEL_BAD; + } else if (diff < 6) { + return TrustInterface.TRUST_FEATURE_LEVEL_GOOD; + } else if (diff < 12) { + return TrustInterface.TRUST_FEATURE_LEVEL_POOR; + } + return TrustInterface.TRUST_FEATURE_LEVEL_BAD; + } catch (ParseException e) { + Log.e(TAG, e.getLocalizedMessage(), e); + } + return TrustInterface.ERROR_UNDEFINED; + } + + private int getEncryptionStatus() { + DevicePolicyManager policyManager = mContext.getSystemService(DevicePolicyManager.class); + if (policyManager == null) { + return TrustInterface.ERROR_UNDEFINED; + } + + boolean isOldDevice = + mContext.getResources().getBoolean(R.bool.config_trustLegacyEncryption); + int status = policyManager.getStorageEncryptionStatus(); + + switch (status) { + case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: + case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER: + return TrustInterface.TRUST_FEATURE_LEVEL_GOOD; + case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY: + return TrustInterface.TRUST_FEATURE_LEVEL_POOR; + case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE: + return isOldDevice ? + TrustInterface.TRUST_FEATURE_LEVEL_POOR : + TrustInterface.TRUST_FEATURE_LEVEL_BAD; + default: + return TrustInterface.ERROR_UNDEFINED; + } + } + + private boolean hasOnboardedUser() { + return LineageSettings.System.getInt(mContext.getContentResolver(), + LineageSettings.System.TRUST_INTERFACE_HINTED, 0) == 1; + } + + /* Service */ + + private final IBinder mService = new ITrustInterface.Stub() { + @Override + public boolean postNotificationForFeature(int feature) { + enforceTrustPermission(); + /* + * We need to clear the caller's identity in order to + * allow this method call to modify settings + * not allowed by the caller's permissions. + */ + long token = clearCallingIdentity(); + boolean success = postNotificationForFeatureInternal(feature); + restoreCallingIdentity(token); + return success; + } + + @Override + public boolean removeNotificationForFeature(int feature) { + enforceTrustPermission(); + /* + * We need to clear the caller's identity in order to + * allow this method call to modify settings + * not allowed by the caller's permissions. + */ + long token = clearCallingIdentity(); + boolean success = removeNotificationForFeatureInternal(feature); + restoreCallingIdentity(token); + return success; + } + + @Override + public int getLevelForFeature(int feature) { + /* + * No need to require permission for this one because it's harmless + */ + return getLevelForFeatureInternal(feature); + } + }; +}
\ No newline at end of file diff --git a/lineage/res/AndroidManifest.xml b/lineage/res/AndroidManifest.xml index f3a5346a..aa4e0f59 100644 --- a/lineage/res/AndroidManifest.xml +++ b/lineage/res/AndroidManifest.xml @@ -124,6 +124,13 @@ android:icon="@drawable/ic_launcher_lineageos" android:protectionLevel="dangerous" /> + <!-- Allows an application to access the Trust interface --> + <permission android:name="lineageos.permission.TRUST_INTERFACE" + android:label="@string/permlab_trustInterface" + android:description="@string/permdesc_trustInterface" + android:icon="@drawable/ic_trust" + android:protectionLevel="signature|privileged" /> + <application android:process="system" android:persistent="true" android:hasCode="false" diff --git a/lineage/res/res/drawable/ic_trust.xml b/lineage/res/res/drawable/ic_trust.xml new file mode 100644 index 00000000..f896d50d --- /dev/null +++ b/lineage/res/res/drawable/ic_trust.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="?android:attr/colorAccent" + android:pathData="M5,3L19,3C20.105,3 21,3.895 21,5L21,12C21,16.971 16.971,21 12,21C7.029,21 3,16.971 3,12L3,5C3,3.895 3.895,3 5,3ZM18.902,13.168C18.994,12.624 18.627,12.108 18.082,12.016C17.538,11.925 17.022,12.292 16.93,12.837C16.528,15.225 14.45,17 12,17C9.55,17 7.472,15.226 7.069,12.838C6.978,12.294 6.462,11.927 5.917,12.018C5.373,12.11 5.005,12.626 5.097,13.171C5.661,16.517 8.57,19 12,19C15.43,19 18.339,16.516 18.902,13.168ZM11.046,5.698L9.127,11.297C9.045,11.516 9,11.753 9,12C9,13.104 9.895,14 11,14C11.01,14 11.019,14 11.029,14L13,14C13.55,14 14.05,13.78 14.41,13.41C14.78,13.05 15,12.55 15,12L12.6,12L11,11.999L11.438,10.724L11.646,10.116L12.938,6.346C12.978,6.238 13,6.121 13,6C13,5.448 12.552,5 12,5C11.553,5 11.174,5.293 11.046,5.698Z" /> +</vector>
\ No newline at end of file diff --git a/lineage/res/res/drawable/ic_warning.xml b/lineage/res/res/drawable/ic_warning.xml new file mode 100644 index 00000000..e711b296 --- /dev/null +++ b/lineage/res/res/drawable/ic_warning.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="@color/color_error" + android:pathData="M4.47,21 L19.53,21 C21.07,21,22.03,19.33,21.26,18 L13.73,4.99 C12.96,3.66,11.04,3.66,10.27,4.99 L2.74,18 C1.97,19.33,2.93,21,4.47,21 Z M12,14 L12,14 C11.45,14,11,13.55,11,13 L11,11 C11,10.45,11.45,10,12,10 L12,10 C12.55,10,13,10.45,13,11 L13,13 C13,13.55,12.55,14,12,14 Z M13,18 L11,18 L11,16 L13,16 L13,18 Z" /> +</vector> diff --git a/lineage/res/res/values/colors.xml b/lineage/res/res/values/colors.xml new file mode 100644 index 00000000..8ff675b2 --- /dev/null +++ b/lineage/res/res/values/colors.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 The LineageOS 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. +--> +<resources> + + <color name="color_error">#FF5630</color> +</resources> diff --git a/lineage/res/res/values/config.xml b/lineage/res/res/values/config.xml index 32257b25..1faefa98 100644 --- a/lineage/res/res/values/config.xml +++ b/lineage/res/res/values/config.xml @@ -109,6 +109,7 @@ <item>org.lineageos.platform.internal.display.LiveDisplayService</item> <item>org.lineageos.platform.internal.LineageAudioService</item> <item>org.lineageos.platform.internal.StyleInterfaceService</item> + <item>org.lineageos.platform.internal.TrustInterfaceService</item> </string-array> <!-- The LineageSystemServer class that is invoked from Android's SystemServer --> @@ -235,4 +236,8 @@ platform signatures, specifically for use on devices with a vendor partition. --> <string-array name="config_vendorPlatformSignatures"> </string-array> + + <!-- Indicate whether encryption causes significant performances loss. + This MUST NOT be set to true on devices produced in 2016 or later --> + <bool name="config_trustLegacyEncryption">false</bool> </resources> diff --git a/lineage/res/res/values/strings.xml b/lineage/res/res/values/strings.xml index 43fd1417..f44ed0ca 100644 --- a/lineage/res/res/values/strings.xml +++ b/lineage/res/res/values/strings.xml @@ -176,4 +176,20 @@ <string name="accent_purple">Lavender</string> <string name="accent_red">Tomato</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 + to a different meaning of the word "trust" in your language --> + <string name="trust_feature_name">Trust</string> + <string name="permlab_trustInterface">access Trust interface</string> + <string name="permdesc_trustInterface">Allows an app to display Trust warnings and suggestions</string> + <string name="trust_notification_channel">Trust alerts</string> + <string name="trust_notification_title_selinux">Trust \u2022 System security</string> + <string name="trust_notification_content_selinux">SELinux is not enforcing, your security has been weakened</string> + <string name="trust_notification_title_root">Trust \u2022 Root access</string> + <string name="trust_notification_content_root">An app is using the root privileges right now</string> + <string name="trust_notification_title_onboarding">Discover Trust</string> + <string name="trust_notification_content_onboarding">Get to know how to assure your device is safe</string> + <string name="trust_notification_action_later">Not now</string> </resources> diff --git a/lineage/res/res/values/symbols.xml b/lineage/res/res/values/symbols.xml index 1bf265ce..0e8f6243 100644 --- a/lineage/res/res/values/symbols.xml +++ b/lineage/res/res/values/symbols.xml @@ -162,4 +162,21 @@ <java-symbol type="string" name="accent_yellow" /> <java-symbol type="array" name="config_vendorPlatformSignatures" /> + + <!-- Colors --> + <java-symbol type="color" name="color_error" /> + + <!-- Trust interface --> + <java-symbol type="bool" name="config_trustLegacyEncryption" /> + <java-symbol type="drawable" name="ic_trust" /> + <java-symbol type="drawable" name="ic_warning" /> + <java-symbol type="string" name="trust_feature_name" /> + <java-symbol type="string" name="trust_notification_channel" /> + <java-symbol type="string" name="trust_notification_title_selinux" /> + <java-symbol type="string" name="trust_notification_content_selinux" /> + <java-symbol type="string" name="trust_notification_title_root" /> + <java-symbol type="string" name="trust_notification_content_root" /> + <java-symbol type="string" name="trust_notification_title_onboarding" /> + <java-symbol type="string" name="trust_notification_content_onboarding" /> + <java-symbol type="string" name="trust_notification_action_later" /> </resources> diff --git a/sdk/src/java/lineageos/app/LineageContextConstants.java b/sdk/src/java/lineageos/app/LineageContextConstants.java index 640e308b..33fd85bb 100644 --- a/sdk/src/java/lineageos/app/LineageContextConstants.java +++ b/sdk/src/java/lineageos/app/LineageContextConstants.java @@ -108,6 +108,17 @@ public final class LineageContextConstants { public static final String LINEAGE_STYLE_INTERFACE = "lineagestyle"; /** + * Use with {@link android.content.Context#getSystemService} to retrieve a + * {@link lineageos.trust.TrustInterface} to access the Trust interface. + * + * @see android.content.Context#getSystemService + * @see lineageos.trust.TrustInterface + * + * @hide + */ + public static final String LINEAGE_TRUST_INTERFACE = "lineagetrust"; + + /** * Features supported by the Lineage SDK. */ public static class Features { @@ -166,5 +177,13 @@ public final class LineageContextConstants { */ @SdkConstant(SdkConstant.SdkConstantType.FEATURE) public static final String STYLES = "org.lineageos.style"; + + /** + * Feature for {@link PackageManager#getSystemAvailableFeatures} and + * {@link PackageManager#hasSystemFeature}: The device includes the lineage trust service + * utilized by the lineage sdk. + */ + @SdkConstant(SdkConstant.SdkConstantType.FEATURE) + public static final String TRUST = "org.lineageos.trust"; } } diff --git a/sdk/src/java/lineageos/providers/LineageSettings.java b/sdk/src/java/lineageos/providers/LineageSettings.java index ac48c996..81dbb738 100644 --- a/sdk/src/java/lineageos/providers/LineageSettings.java +++ b/sdk/src/java/lineageos/providers/LineageSettings.java @@ -79,6 +79,16 @@ public final class LineageSettings { public static final String ACTION_LIVEDISPLAY_SETTINGS = "lineageos.settings.LIVEDISPLAY_SETTINGS"; + /** + * Activity Action: Show Trust interface settings + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + public static final String ACTION_TRUST_INTERFACE = + "lineageos.settings.TRUST_INTERFACE"; + // region Call Methods /** @@ -1529,6 +1539,15 @@ public final class LineageSettings { new InclusiveIntegerRangeValidator(-3, 1); /** + * Did we tell the user about the trust brand and interface? + * @hide + */ + public static final String TRUST_INTERFACE_HINTED = "trust_interface_hinted"; + + /** @hide */ + public static final Validator TRUST_INTERFACE_HINTED_VALIDATOR = sBooleanValidator; + + /** * Enable statusbar double tap gesture on to put device to sleep * 0 = 0ff, 1 = on */ @@ -1550,7 +1569,7 @@ public final class LineageSettings { /** * Show search bar in recents - * 0 = 0ff, 1 = on + * 0 = Off, 1 = on */ public static final String RECENTS_SHOW_SEARCH_BAR = "recents_show_search_bar"; @@ -2232,6 +2251,7 @@ public final class LineageSettings { VALIDATORS.put(DISPLAY_COLOR_ENHANCE, DISPLAY_COLOR_ENHANCE_VALIDATOR); VALIDATORS.put(DISPLAY_COLOR_ADJUSTMENT, DISPLAY_COLOR_ADJUSTMENT_VALIDATOR); VALIDATORS.put(LIVE_DISPLAY_HINTED, LIVE_DISPLAY_HINTED_VALIDATOR); + VALIDATORS.put(TRUST_INTERFACE_HINTED, TRUST_INTERFACE_HINTED_VALIDATOR); VALIDATORS.put(DOUBLE_TAP_SLEEP_GESTURE, DOUBLE_TAP_SLEEP_GESTURE_VALIDATOR); VALIDATORS.put(STATUS_BAR_SHOW_WEATHER, STATUS_BAR_SHOW_WEATHER_VALIDATOR); VALIDATORS.put(RECENTS_SHOW_SEARCH_BAR, RECENTS_SHOW_SEARCH_BAR_VALIDATOR); @@ -3019,6 +3039,16 @@ public final class LineageSettings { /** @hide */ public static final Validator NETWORK_TRAFFIC_SHOW_UNITS_VALIDATOR = sBooleanValidator; + /** + * Enable displaying the Trust service's notifications + * 0 = 0ff, 1 = on + */ + public static final String TRUST_NOTIFICATIONS = "trust_notifications"; + + /** @hide */ + public static final Validator TRUST_NOTIFICATIONS_VALIDATOR = + sBooleanValidator; + // endregion /** @@ -3128,6 +3158,7 @@ public final class LineageSettings { VALIDATORS.put(NETWORK_TRAFFIC_AUTOHIDE, NETWORK_TRAFFIC_AUTOHIDE_VALIDATOR); VALIDATORS.put(NETWORK_TRAFFIC_UNITS, NETWORK_TRAFFIC_UNITS_VALIDATOR); VALIDATORS.put(NETWORK_TRAFFIC_SHOW_UNITS, NETWORK_TRAFFIC_SHOW_UNITS_VALIDATOR); + VALIDATORS.put(TRUST_NOTIFICATIONS, TRUST_NOTIFICATIONS_VALIDATOR); } /** diff --git a/sdk/src/java/lineageos/trust/ITrustInterface.aidl b/sdk/src/java/lineageos/trust/ITrustInterface.aidl new file mode 100644 index 00000000..385d8e0e --- /dev/null +++ b/sdk/src/java/lineageos/trust/ITrustInterface.aidl @@ -0,0 +1,26 @@ +/* +** +** Copyright (C) 2018 The LineageOS 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 lineageos.trust; + +/** {@hide} */ +interface ITrustInterface { + + boolean postNotificationForFeature(int feature); + boolean removeNotificationForFeature(int feature); + int getLevelForFeature(int feature); +} diff --git a/sdk/src/java/lineageos/trust/TrustInterface.java b/sdk/src/java/lineageos/trust/TrustInterface.java new file mode 100644 index 00000000..9f3c7d8d --- /dev/null +++ b/sdk/src/java/lineageos/trust/TrustInterface.java @@ -0,0 +1,217 @@ +/** + * Copyright (c) 2015, The LineageOS 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 lineageos.trust; + +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +import lineageos.app.LineageContextConstants; + +public class TrustInterface { + /** + * Allows an application to use the Trust interface to display trusted + * security messages to the user. + * This is a system-only permission, user-installed apps cannot use it + */ + public static final String TRUST_INTERFACE_PERMISSION = "lineageos.permission.TRUST_INTERFACE"; + + /** + * Unable to determine status, an error occured + * + * @see #getLevelForFeature + */ + public static final int ERROR_UNDEFINED = -1; + + /** + * Trust feature status: good. The feature is in a configuration + * that will help protect the user's data + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_LEVEL_GOOD = 0; + + /** + * Trust feature status: poor. The feature is in a configuration + * that might be used to harm the user's data + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_LEVEL_POOR = 1; + + /** + * Trust feature status: bad. The feature is in a configuration + * that is dangerous for the user's data + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_LEVEL_BAD = 2; + + /** + * Trust feature indicator: SELinux status + * + * Possible status: + * * {@link #TRUST_FEATURE_LEVEL_GOOD}: enforcing + * * {@link #TRUST_FEATURE_LEVEL_BAD}: permissive / disabled + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_SELINUX = 0; + + /** + * Trust feature indicator: Root access + * + * Possible status: + * * {@link #TRUST_FEATURE_LEVEL_GOOD}: disabled + * * {@link #TRUST_FEATURE_LEVEL_POOR}: ADB only + * * {@link #TRUST_FEATURE_LEVEL_BAD}: apps and ADB + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_ROOT = 1; + + /** + * Trust feature indicator: Platform Security patches + * + * Possible status: + * * {@link #TRUST_FEATURE_LEVEL_GOOD}: less than 3 months old + * * {@link #TRUST_FEATURE_LEVEL_POOR}: less than 9 months old + * * {@link #TRUST_FEATURE_LEVEL_BAD}: older than 9 months + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_PLATFORM_SECURITY_PATCH = 2; + + /** + * Trust feature indicator: Vendor Security patches + * + * Possible status: + * * {@link #TRUST_FEATURE_LEVEL_GOOD}: less than 3 months old + * * {@link #TRUST_FEATURE_LEVEL_POOR}: less than 9 months old + * * {@link #TRUST_FEATURE_LEVEL_BAD}: older than 9 months + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_VENDOR_SECURITY_PATCH = 3; + + /** + * Trust feature indicator: Encryption + * + * Some older devices have a significant performance loss when running + * encrypted, so the status will be different when Trust is executed on + * these devices. + * + * Possible status for old device: + * * {@link #TRUST_FEATURE_LEVEL_GOOD}: enabled + * * {@link #TRUST_FEATURE_LEVEL_POOR}: disabled + * + * Possible status for recent device: + * * {@link #TRUST_FEATURE_LEVEL_GOOD}: enabled + * * {@link #TRUST_FEATURE_LEVEL_BAD}: disabled + * + * @see #getLevelForFeature + */ + public static final int TRUST_FEATURE_ENCRYPTION = 4; + + private static final String TAG = "TrustInterface"; + + private static ITrustInterface sService; + private static TrustInterface sInstance; + + private Context mContext; + + private TrustInterface(Context context) { + Context appContext = context.getApplicationContext(); + mContext = appContext == null ? context : appContext; + sService = getService(); + if (context.getPackageManager().hasSystemFeature( + LineageContextConstants.Features.TRUST) && sService == null) { + throw new RuntimeException("Unable to get TrustInterfaceService. The service" + + " either crashed, was not started, or the interface has been called to early" + + " in SystemServer init"); + } + } + + /** + * Get or create an instance of the {@link lineageos.trust.TrustInterface} + * + * @param context Used to get the service + * @return {@link TrustInterface} + */ + public static TrustInterface getInstance(Context context) { + if (sInstance == null) { + sInstance = new TrustInterface(context); + } + return sInstance; + } + + /** @hide **/ + public static ITrustInterface getService() { + if (sService != null) { + return sService; + } + IBinder b = ServiceManager.getService(LineageContextConstants.LINEAGE_TRUST_INTERFACE); + sService = ITrustInterface.Stub.asInterface(b); + + if (b == null) { + Log.e(TAG, "null service. SAD!"); + return null; + } + + sService = ITrustInterface.Stub.asInterface(b); + return sService; + } + + public boolean postNotificationForFeature(int feature) { + if (sService == null) { + return false; + } + try { + return sService.postNotificationForFeature(feature); + } catch (RemoteException e) { + Log.e(TAG, e.getLocalizedMessage(), e); + } + return false; + } + + public boolean removeNotificationForFeature(int feature) { + if (sService == null) { + return false; + } + try { + return sService.removeNotificationForFeature(feature); + } catch (RemoteException e) { + Log.e(TAG, e.getLocalizedMessage(), e); + } + return false; + } + + public int getLevelForFeature(int feature) { + if (sService == null) { + return ERROR_UNDEFINED; + } + try { + return sService.getLevelForFeature(feature); + } catch (RemoteException e) { + Log.e(TAG, e.getLocalizedMessage(), e); + } + return ERROR_UNDEFINED; + } +} + |