From eb8d1be6acad180eabde84f19196b9ecaba81353 Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Wed, 25 Jun 2014 17:46:15 -0400 Subject: [PATCH] Add a BIND_DREAM_SERVICE signature-level permission. Starting in api 21, will be required to bind to a declared dream or doze service. Also added to aapt dump badging output. Bug:15862654 Change-Id: Ifa0a594eeecf21e6146176c7810a847e1d08fe3b --- api/current.txt | 1 + .../android/service/dreams/DreamService.java | 13 +++++++ core/res/AndroidManifest.xml | 7 ++++ core/res/res/values/strings.xml | 5 +++ packages/SystemUI/AndroidManifest.xml | 4 +- .../server/dreams/DreamManagerService.java | 37 +++++++++++++++---- tools/aapt/Command.cpp | 13 +++++++ 7 files changed, 71 insertions(+), 9 deletions(-) diff --git a/api/current.txt b/api/current.txt index 8add79c143401..f5b510725e470 100644 --- a/api/current.txt +++ b/api/current.txt @@ -21,6 +21,7 @@ package android { field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE"; field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET"; field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN"; + field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE"; field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD"; field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE"; field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"; diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 9da3a5190d426..6bb34587c13f2 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -124,6 +124,19 @@ import com.android.internal.util.DumpUtils.Dump; * } * } * + * + *

When targeting api level 21 and above, you must declare the service in your manifest file + * with the {@link android.Manifest.permission#BIND_DREAM_SERVICE} permission. For example:

+ *
+ * <service
+ *     android:name=".MyDream"
+ *     android:exported="true"
+ *     android:icon="@drawable/my_icon"
+ *     android:label="@string/my_dream_label"
+ *     android:permission="android.permission.BIND_DREAM_SERVICE" >
+ *  ...
+ * </service>
+ * 
*/ public class DreamService extends Service implements Window.Callback { private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]"; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ca897d5efb62d..7db478d7a9d2c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2719,6 +2719,13 @@ android:description="@string/permdesc_bindConditionProviderService" android:protectionLevel="signature" /> + + + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index db02279792fda..a3262ed783243 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2121,6 +2121,11 @@ Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps. + + bind to a dream service + + Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps. + invoke the carrier-provided configuration app diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 0df6c7426a932..e12549ac9af79 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -267,6 +267,7 @@ android:name=".DessertCaseDream" android:exported="true" android:label="@string/dessert_case" + android:permission="android.permission.BIND_DREAM_SERVICE" android:enabled="false" android:process=":sweetsweetdesserts" > @@ -305,6 +306,7 @@ + android:exported="true" + android:permission="android.permission.BIND_DREAM_SERVICE" /> diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index ed4ccfc8a9d71..a35e2bac898d2 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -16,6 +16,8 @@ package com.android.server.dreams; +import static android.Manifest.permission.BIND_DREAM_SERVICE; + import com.android.internal.util.DumpUtils; import com.android.server.FgThread; import com.android.server.SystemService; @@ -29,6 +31,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ServiceInfo; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -193,7 +196,7 @@ public final class DreamManagerService extends SystemService { private void startDreamInternal(boolean doze) { final int userId = ActivityManager.getCurrentUser(); - final ComponentName dream = doze ? getDozeComponent() : chooseDreamForUser(userId); + final ComponentName dream = chooseDreamForUser(doze, userId); if (dream != null) { synchronized (mLock) { startDreamLocked(dream, false /*isTest*/, doze, userId); @@ -245,11 +248,31 @@ public final class DreamManagerService extends SystemService { } } - private ComponentName chooseDreamForUser(int userId) { + private ComponentName chooseDreamForUser(boolean doze, int userId) { + if (doze) { + ComponentName dozeComponent = getDozeComponent(); + return validateDream(dozeComponent) ? dozeComponent : null; + } ComponentName[] dreams = getDreamComponentsForUser(userId); return dreams != null && dreams.length != 0 ? dreams[0] : null; } + private boolean validateDream(ComponentName component) { + if (component == null) return false; + final ServiceInfo serviceInfo = getServiceInfo(component); + if (serviceInfo == null) { + Slog.w(TAG, "Dream " + component + " does not exist"); + return false; + } else if (serviceInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.L + && !BIND_DREAM_SERVICE.equals(serviceInfo.permission)) { + Slog.w(TAG, "Dream " + component + + " is not available because its manifest is missing the " + BIND_DREAM_SERVICE + + " permission on the dream service declaration."); + return false; + } + return true; + } + private ComponentName[] getDreamComponentsForUser(int userId) { String names = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENTS, @@ -260,10 +283,8 @@ public final class DreamManagerService extends SystemService { List validComponents = new ArrayList(); if (components != null) { for (ComponentName component : components) { - if (serviceExists(component)) { + if (validateDream(component)) { validComponents.add(component); - } else { - Slog.w(TAG, "Dream " + component + " does not exist"); } } } @@ -307,11 +328,11 @@ public final class DreamManagerService extends SystemService { return TextUtils.isEmpty(name) ? null : ComponentName.unflattenFromString(name); } - private boolean serviceExists(ComponentName name) { + private ServiceInfo getServiceInfo(ComponentName name) { try { - return name != null && mContext.getPackageManager().getServiceInfo(name, 0) != null; + return name != null ? mContext.getPackageManager().getServiceInfo(name, 0) : null; } catch (NameNotFoundException e) { - return false; + return null; } } diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 816033ed5ab93..5fefab66b3312 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -819,6 +819,7 @@ int doDump(Bundle* bundle) bool hasCameraSecureActivity = false; bool hasLauncher = false; bool hasNotificationListenerService = false; + bool hasDreamService = false; bool actMainActivity = false; bool actWidgetReceivers = false; @@ -831,6 +832,7 @@ int doDump(Bundle* bundle) bool actOffHostApduService = false; bool actDocumentsProvider = false; bool actNotificationListenerService = false; + bool actDreamService = false; bool actCamera = false; bool actCameraSecure = false; bool catLauncher = false; @@ -846,6 +848,7 @@ int doDump(Bundle* bundle) bool hasBindNfcServicePermission = false; bool hasRequiredSafAttributes = false; bool hasBindNotificationListenerServicePermission = false; + bool hasBindDreamServicePermission = false; // These two implement the implicit permissions that are granted // to pre-1.6 applications. @@ -1007,6 +1010,7 @@ int doDump(Bundle* bundle) hasPrintService |= (actPrintService && hasBindPrintServicePermission); hasNotificationListenerService |= actNotificationListenerService && hasBindNotificationListenerServicePermission; + hasDreamService |= actDreamService && hasBindDreamServicePermission; hasOtherServices |= (!actImeService && !actWallpaperService && !actAccessibilityService && !actPrintService && !actHostApduService && !actOffHostApduService && @@ -1389,6 +1393,7 @@ int doDump(Bundle* bundle) hasBindNfcServicePermission = false; hasRequiredSafAttributes = false; hasBindNotificationListenerServicePermission = false; + hasBindDreamServicePermission = false; if (withinApplication) { if(tag == "activity") { withinActivity = true; @@ -1486,6 +1491,8 @@ int doDump(Bundle* bundle) hasBindNfcServicePermission = true; } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { hasBindNotificationListenerServicePermission = true; + } else if (permission == "android.permission.BIND_DREAM_SERVICE") { + hasBindDreamServicePermission = true; } } else { fprintf(stderr, "ERROR getting 'android:permission' attribute for" @@ -1569,6 +1576,7 @@ int doDump(Bundle* bundle) actOffHostApduService = false; actDocumentsProvider = false; actNotificationListenerService = false; + actDreamService = false; actCamera = false; actCameraSecure = false; catLauncher = false; @@ -1654,6 +1662,8 @@ int doDump(Bundle* bundle) actOffHostApduService = true; } else if (action == "android.service.notification.NotificationListenerService") { actNotificationListenerService = true; + } else if (action == "android.service.dreams.DreamService") { + actDreamService = true; } } else if (withinProvider) { if (action == "android.content.action.DOCUMENTS_PROVIDER") { @@ -1889,6 +1899,9 @@ int doDump(Bundle* bundle) if (hasNotificationListenerService) { printComponentPresence("notification-listener"); } + if (hasDreamService) { + printComponentPresence("dream"); + } if (hasCameraActivity) { printComponentPresence("camera"); }