diff options
author | Hui Yu <huiyu@google.com> | 2018-12-06 16:59:18 -0800 |
---|---|---|
committer | Hui Yu <huiyu@google.com> | 2018-12-06 16:59:18 -0800 |
commit | 1ea855202fcc0006a6fa304fd686642dc2b9dc1e (patch) | |
tree | 2daa9d3aaea7a84e993cb96aba1a015bc0b1629f | |
parent | cd504bbedd41df7402163f3bb73b270aa3e0ef61 (diff) |
Add manifest service attribute foregroundServiceType
Foreground service must use attribute foregroundServiceType to
specify its foreground service type in <sevice> element of manifest
file, otherwise a warning message is printed when startForeground()
method is called. (We will replace the warning message with a security
exception when the feature is formally activiated.)
The manifest attribute is:
android:foregroundServiceType="<type>"
Allowed types are: "sync", "mediaPlay", "phoneCall",
"location", "deviceCompanion", "ongoingProcess".
Bug: 111453223
Test: atest frameworks/base/tests/FrameworkPerf
Change-Id: I5d2ab203d400f3c549cd153480b6252a2f9adb3c
-rw-r--r-- | api/current.txt | 13 | ||||
-rw-r--r-- | core/java/android/app/Service.java | 9 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 4 | ||||
-rw-r--r-- | core/java/android/content/pm/ServiceInfo.java | 88 | ||||
-rw-r--r-- | core/res/res/values/attrs_manifest.xml | 25 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 1 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActiveServices.java | 18 | ||||
-rw-r--r-- | tests/FrameworkPerf/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java | 8 |
9 files changed, 160 insertions, 9 deletions
diff --git a/api/current.txt b/api/current.txt index f7060f341ace..01ff469e2281 100644 --- a/api/current.txt +++ b/api/current.txt @@ -644,6 +644,7 @@ package android { field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521 field public static final int foreground = 16843017; // 0x1010109 field public static final int foregroundGravity = 16843264; // 0x1010200 + field public static final int foregroundServiceType = 16844191; // 0x101059f field public static final int foregroundTint = 16843885; // 0x101046d field public static final int foregroundTintMode = 16843886; // 0x101046e field public static final int format = 16843013; // 0x1010105 @@ -11724,12 +11725,20 @@ package android.content.pm { ctor public ServiceInfo(android.content.pm.ServiceInfo); method public int describeContents(); method public void dump(android.util.Printer, java.lang.String); + method public int getForegroundServiceType(); field public static final android.os.Parcelable.Creator<android.content.pm.ServiceInfo> CREATOR; field public static final int FLAG_EXTERNAL_SERVICE = 4; // 0x4 field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2 field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000 field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1 field public static final int FLAG_USE_APP_ZYGOTE = 8; // 0x8 + field public static final int FOREGROUND_SERVICE_TYPE_DEVICE_COMPANION = 5; // 0x5 + field public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 4; // 0x4 + field public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PLAY = 2; // 0x2 + field public static final int FOREGROUND_SERVICE_TYPE_ONGOING_PROCESS = 6; // 0x6 + field public static final int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 3; // 0x3 + field public static final int FOREGROUND_SERVICE_TYPE_SYNC = 1; // 0x1 + field public static final int FOREGROUND_SERVICE_TYPE_UNSPECIFIED = 0; // 0x0 field public int flags; field public java.lang.String permission; } @@ -53234,7 +53243,7 @@ package android.webkit { method public abstract boolean getDomStorageEnabled(); method public abstract java.lang.String getFantasyFontFamily(); method public abstract java.lang.String getFixedFontFamily(); - method public abstract int getForceDarkMode(); + method public int getForceDarkMode(); method public abstract boolean getJavaScriptCanOpenWindowsAutomatically(); method public abstract boolean getJavaScriptEnabled(); method public abstract android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm(); @@ -53281,7 +53290,7 @@ package android.webkit { method public abstract deprecated void setEnableSmoothTransition(boolean); method public abstract void setFantasyFontFamily(java.lang.String); method public abstract void setFixedFontFamily(java.lang.String); - method public abstract void setForceDarkMode(int); + method public void setForceDarkMode(int); method public abstract deprecated void setGeolocationDatabasePath(java.lang.String); method public abstract void setGeolocationEnabled(boolean); method public abstract void setJavaScriptCanOpenWindowsAutomatically(boolean); diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 16f6bdaa4313..5fa8526b5a24 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -685,6 +685,13 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac * the permission {@link android.Manifest.permission#FOREGROUND_SERVICE} in order to use * this API.</p> * + * <p>To use this API, apps targeting API {@link android.os.Build.VERSION_CODES#Q} or later must + * specify the foreground service type using attribute + * {@link android.R.attr#foregroundServiceType} in service element of manifest file, otherwise + * a SecurityException is thrown when this API is called. Apps targeting API older than + * {@link android.os.Build.VERSION_CODES#Q} do not need to specify the foreground service type + * </p> + * * @param id The identifier for this notification as per * {@link NotificationManager#notify(int, Notification) * NotificationManager.notify(int, Notification)}; must not be 0. @@ -700,7 +707,7 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac } catch (RemoteException ex) { } } - + /** * Synonym for {@link #stopForeground(int)}. * @param removeNotification If true, the {@link #STOP_FOREGROUND_REMOVE} flag diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ac18dca74950..d0de9a1d2a76 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -5380,6 +5380,10 @@ public class PackageParser { s.info.splitName = sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0); + s.info.mForegroundServiceType = sa.getInt( + com.android.internal.R.styleable.AndroidManifestService_foregroundServiceType, + ServiceInfo.FOREGROUND_SERVICE_TYPE_UNSPECIFIED); + s.info.flags = 0; if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestService_stopWithTask, diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index ad2c72274c07..8300c0c8d472 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -16,10 +16,14 @@ package android.content.pm; +import android.annotation.IntDef; import android.os.Parcel; import android.os.Parcelable; import android.util.Printer; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Information you can retrieve about a particular application * service. This corresponds to information collected from the @@ -94,6 +98,81 @@ public class ServiceInfo extends ComponentInfo */ public int flags; + /** + * The default foreground service type if not been set in manifest file. + */ + public static final int FOREGROUND_SERVICE_TYPE_UNSPECIFIED = 0; + + /** + * Constant corresponding to <code>sync</code> in + * the {@link android.R.attr#foregroundServiceType} attribute. + * Data(photo, file, account) upload/download, backup/restore, import/export, fetch, + * transfer over network between device and cloud. + */ + public static final int FOREGROUND_SERVICE_TYPE_SYNC = 1; + + /** + * Constant corresponding to <code>mediaPlay</code> in + * the {@link android.R.attr#foregroundServiceType} attribute. + * Music, video, news or other media play. + */ + public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PLAY = 2; + + /** + * Constant corresponding to <code>phoneCall</code> in + * the {@link android.R.attr#foregroundServiceType} attribute. + * Ongoing phone call or video conference. + */ + public static final int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 3; + + /** + * Constant corresponding to <code>location</code> in + * the {@link android.R.attr#foregroundServiceType} attribute. + * GPS, map, navigation location update. + */ + public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 4; + + /** + * Constant corresponding to <code>deviceCompanion</code> in + * the {@link android.R.attr#foregroundServiceType} attribute. + * Auto, bluetooth, TV or other devices connection, monitoring and interaction. + */ + public static final int FOREGROUND_SERVICE_TYPE_DEVICE_COMPANION = 5; + + /** + * Constant corresponding to <code>ongoingProcess</code> in + * the {@link android.R.attr#foregroundServiceType} attribute. + * Process that should not be interrupted, including installation, setup, photo + * compression etc. + */ + public static final int FOREGROUND_SERVICE_TYPE_ONGOING_PROCESS = 6; + + /** + * The enumeration of values for foreground service type. + * The foreground service type is set in {@link android.R.attr#foregroundServiceType} + * attribute. + * @hide + */ + @IntDef(flag = false, prefix = { "FOREGROUND_SERVICE_TYPE_" }, value = { + FOREGROUND_SERVICE_TYPE_UNSPECIFIED, + FOREGROUND_SERVICE_TYPE_SYNC, + FOREGROUND_SERVICE_TYPE_MEDIA_PLAY, + FOREGROUND_SERVICE_TYPE_PHONE_CALL, + FOREGROUND_SERVICE_TYPE_LOCATION, + FOREGROUND_SERVICE_TYPE_DEVICE_COMPANION, + FOREGROUND_SERVICE_TYPE_ONGOING_PROCESS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ForegroundServiceType {} + + /** + * The type of foreground service, set in + * {@link android.R.attr#foregroundServiceType} attribute, one value in + * {@link ForegroundServiceType} + * @hide + */ + public @ForegroundServiceType int mForegroundServiceType = FOREGROUND_SERVICE_TYPE_UNSPECIFIED; + public ServiceInfo() { } @@ -101,6 +180,15 @@ public class ServiceInfo extends ComponentInfo super(orig); permission = orig.permission; flags = orig.flags; + mForegroundServiceType = orig.mForegroundServiceType; + } + + /** + * Return the current foreground service type. + * @return the current foreground service type. + */ + public int getForegroundServiceType() { + return mForegroundServiceType; } public void dump(Printer pw, String prefix) { diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 089c59f3a09f..854582b21340 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1394,6 +1394,29 @@ <attr name="usesNonSdkApi" format="boolean" /> + <!-- Specify the type of foreground service. Apps targeting API + {@link android.os.Build.VERSION_CODES#Q} or later must specify foreground service type, + otherwise a SecurityException is thrown when + {@link android.app.Service#startForeground(int, Notification)} on this service is called. + --> + <attr name="foregroundServiceType"> + <!-- Data (photo, file, account) upload/download, backup/restore, import/export, fetch, + transfer over network between device and cloud. --> + <enum name="sync" value="1" /> + <!-- Music, video, news or other media play. --> + <enum name="mediaPlay" value="2" /> + <!-- Ongoing phone call or video conference. --> + <enum name="phoneCall" value="3" /> + <!-- GPS, map, navigation location update. --> + <enum name="location" value="4" /> + <!-- Auto, bluetooth, TV or other devices connection, monitoring and interaction. --> + <enum name="deviceCompanion" value="5" /> + <!-- Process that should not be interrupted, including installation, setup, photo + compression etc. --> + <enum name="ongoingProcess" value="6" /> + </attr> + + <!-- The <code>manifest</code> tag is the root of an <code>AndroidManifest.xml</code> file, describing the contents of an Android package (.apk) file. One @@ -2242,6 +2265,8 @@ recommended to measure memory usage under typical workloads to determine whether it makes sense to use this flag. --> <attr name="useAppZygote" format="boolean" /> + <!-- If this is a foreground service, specify its category. --> + <attr name="foregroundServiceType" /> </declare-styleable> <!-- The <code>receiver</code> tag declares an diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 5e8af62d1da9..d480121fc998 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2929,6 +2929,7 @@ <public name="dataUsedForMonetization" /> <public name="dataRetentionTime" /> <public name="selectionDividerHeight" /> + <public name="foregroundServiceType" /> </public-group> <public-group type="drawable" first-id="0x010800b4"> diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 23287cf399ca..f7acf7e83200 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1205,10 +1205,20 @@ public final class ActiveServices { android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE, r.app.pid, r.appInfo.uid, "startForeground"); } - } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.P) { - mAm.enforcePermission( - android.Manifest.permission.FOREGROUND_SERVICE, - r.app.pid, r.appInfo.uid, "startForeground"); + } else { + if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.P) { + mAm.enforcePermission( + android.Manifest.permission.FOREGROUND_SERVICE, + r.app.pid, r.appInfo.uid, "startForeground"); + } + if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q) { + if (r.serviceInfo.getForegroundServiceType() + == ServiceInfo.FOREGROUND_SERVICE_TYPE_UNSPECIFIED) { + // STOPSHIP(b/120611119): replace log message with SecurityException. + Slog.w(TAG, "missing foregroundServiceType attribute in " + + "service element of manifest file"); + } + } } boolean alreadyStartedOp = false; boolean stopProcStatsOp = false; diff --git a/tests/FrameworkPerf/AndroidManifest.xml b/tests/FrameworkPerf/AndroidManifest.xml index d62ef9ec210c..ca25386a992c 100644 --- a/tests/FrameworkPerf/AndroidManifest.xml +++ b/tests/FrameworkPerf/AndroidManifest.xml @@ -13,7 +13,8 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <service android:name="SchedulerService"> + <service android:name="SchedulerService" + android:foregroundServiceType="sync"> </service> <service android:name="TestService" android:process=":test"> </service> diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java index fc3f39027348..d4cbbf9c8271 100644 --- a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java +++ b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java @@ -17,16 +17,22 @@ package com.android.frameworkperf; import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class SchedulerService extends Service { + private static final String NOTIFICATION_CHANNEL_ID = SchedulerService.class.getSimpleName(); @Override public int onStartCommand(Intent intent, int flags, int startId) { - Notification status = new Notification.Builder(this) + getSystemService(NotificationManager.class).createNotificationChannel( + new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID, + NotificationManager.IMPORTANCE_DEFAULT)); + Notification status = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID) .setSmallIcon(R.drawable.stat_happy) .setWhen(System.currentTimeMillis()) .setContentTitle("Scheduler Test running") |