providers) throws RemoteException;
+ public PendingIntent getRunningServiceControlPanel(ComponentName service)
+ throws RemoteException;
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType) throws RemoteException;
public int stopService(IApplicationThread caller, Intent service,
@@ -367,7 +369,7 @@ public interface IActivityManager extends IInterface {
int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
int SET_PERSISTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
int FINISH_SUB_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
-
+ int GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
int START_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
int STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
int BIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 87a8f391bb371..1d1161eab4cc0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2044,6 +2044,24 @@ public class Intent implements Parcelable {
public static final String EXTRA_CHANGED_COMPONENT_NAME =
"android.intent.extra.changed_component_name";
+ /**
+ * @hide
+ * Magic extra system code can use when binding, to give a label for
+ * who it is that has bound to a service. This is an integer giving
+ * a framework string resource that can be displayed to the user.
+ */
+ public static final String EXTRA_CLIENT_LABEL =
+ "android.intent.extra.client_label";
+
+ /**
+ * @hide
+ * Magic extra system code can use when binding, to give a PendingIntent object
+ * that can be launched for the user to disable the system's use of this
+ * service.
+ */
+ public static final String EXTRA_CLIENT_INTENT =
+ "android.intent.extra.client_intent";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 5ffe9629786c2..6d27bc78bbd2e 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1064,6 +1064,10 @@ class SyncManager implements OnAccountsUpdatedListener {
Intent intent = new Intent();
intent.setAction("android.content.SyncAdapter");
intent.setComponent(info.componentName);
+ intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.sync_binding_label);
+ intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
return mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 125ed0b5f8ad8..64e47eb94b680 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -118,6 +118,20 @@ public final class Settings {
public static final String ACTION_AIRPLANE_MODE_SETTINGS =
"android.settings.AIRPLANE_MODE_SETTINGS";
+ /**
+ * Activity Action: Show settings for accessibility modules.
+ *
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ *
+ * Input: Nothing.
+ *
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ACCESSIBILITY_SETTINGS =
+ "android.settings.ACCESSIBILITY_SETTINGS";
+
/**
* Activity Action: Show settings to allow configuration of security and
* location privacy.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 70c9385e7752c..3333915ecdd7a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1943,25 +1943,34 @@
-
- checked
+
+ checked
-
- not checked
+
+ not checked
- The
- listed applications are requesting permission to access the login credentials for account %1$s from
- %2$s. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
- again.
+ The
+ listed applications are requesting permission to access the login credentials for account %1$s from
+ %2$s. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
+ again.
- The
- listed applications are requesting permission to access the %1$s login credentials for account %2$s from
- %3$s. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
- again.
+ The
+ listed applications are requesting permission to access the %1$s login credentials for account %2$s from
+ %3$s. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
+ again.
- Allow
- Deny
- Permission Requested
- for account %s
+ Allow
+ Deny
+ Permission Requested
+ for account %s
+
+ Input method
+
+ Sync
+
+ Accessibility
+
+ Wallpaper
+
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 55007ba701751..f67a7aec48ccf 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -25,6 +25,7 @@ import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.IEventListener;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -615,6 +616,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mId = sIdCounter++;
mComponentName = componentName;
mIntent = new Intent().setComponent(mComponentName);
+ mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.accessibility_binding_label);
+ mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
}
/**
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 558a024b0c7c8..1da2b47d14465 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -32,6 +32,7 @@ import org.xmlpull.v1.XmlPullParserException;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -765,6 +766,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
mCurIntent.setComponent(info.getComponent());
+ mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.input_method_binding_label);
+ mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE)) {
mLastBindTime = SystemClock.uptimeMillis();
mHaveConnection = true;
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index c101463b2a301..cc977b09808e6 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -21,6 +21,7 @@ import static android.os.ParcelFileDescriptor.*;
import android.app.IWallpaperManager;
import android.app.IWallpaperManagerCallback;
+import android.app.PendingIntent;
import android.backup.BackupManager;
import android.content.ComponentName;
import android.content.Context;
@@ -40,6 +41,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.provider.Settings;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService;
@@ -376,6 +378,10 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
// Bind the service!
WallpaperConnection newConn = new WallpaperConnection();
intent.setComponent(realName);
+ intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.wallpaper_binding_label);
+ intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Intent.ACTION_SET_WALLPAPER), 0));
if (!mContext.bindService(intent, newConn,
Context.BIND_AUTO_CREATE)) {
throw new IllegalArgumentException("Unable to bind service: "
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 03ebf0c9c2a3d..9554a22a2ae87 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -8866,6 +8866,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
} else {
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
}
+ currApp.importanceReasonCode = app.adjTypeCode;
+ if (app.adjSource instanceof ProcessRecord) {
+ currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
+ } else if (app.adjSource instanceof HistoryRecord) {
+ HistoryRecord r = (HistoryRecord)app.adjSource;
+ if (r.app != null) currApp.importanceReasonPid = r.app.pid;
+ }
+ if (app.adjTarget instanceof ComponentName) {
+ currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
+ }
//Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
// + " lru=" + currApp.lru);
if (runList == null) {
@@ -9888,6 +9898,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (r.app != null && r.app.persistent) {
info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
}
+ for (ConnectionRecord conn : r.connections.values()) {
+ if (conn.clientLabel != 0) {
+ info.clientPackage = conn.binding.client.info.packageName;
+ info.clientLabel = conn.clientLabel;
+ break;
+ }
+ }
return info;
}
@@ -9916,6 +9933,20 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ public PendingIntent getRunningServiceControlPanel(ComponentName name) {
+ synchronized (this) {
+ ServiceRecord r = mServices.get(name);
+ if (r != null) {
+ for (ConnectionRecord conn : r.connections.values()) {
+ if (conn.clientIntent != null) {
+ return conn.clientIntent;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
private final ServiceRecord findServiceLocked(ComponentName name,
IBinder token) {
ServiceRecord r = mServices.get(name);
@@ -10783,6 +10814,29 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
activity = (HistoryRecord)mHistory.get(aindex);
}
+ int clientLabel = 0;
+ PendingIntent clientIntent = null;
+
+ if (callerApp.info.uid == Process.SYSTEM_UID) {
+ // Hacky kind of thing -- allow system stuff to tell us
+ // what they are, so we can report this elsewhere for
+ // others to know why certain services are running.
+ try {
+ clientIntent = (PendingIntent)service.getParcelableExtra(
+ Intent.EXTRA_CLIENT_INTENT);
+ } catch (RuntimeException e) {
+ }
+ if (clientIntent != null) {
+ clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
+ if (clientLabel != 0) {
+ // There are no useful extras in the intent, trash them.
+ // System code calling with this stuff just needs to know
+ // this will happen.
+ service = service.cloneFilter();
+ }
+ }
+ }
+
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
Binder.getCallingPid(), Binder.getCallingUid());
@@ -10803,7 +10857,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
- connection, flags);
+ connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
s.connections.put(binder, c);
@@ -12776,6 +12830,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return (app.curAdj=app.maxAdj);
}
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
app.adjSource = null;
app.adjTarget = null;
@@ -12909,6 +12964,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
adj = clientAdj > VISIBLE_APP_ADJ
? clientAdj : VISIBLE_APP_ADJ;
app.adjType = "service";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
app.adjTarget = s.serviceInfo.name;
}
@@ -12922,6 +12979,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|| a.state == ActivityState.PAUSING)) {
adj = FOREGROUND_APP_ADJ;
app.adjType = "service";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE;
app.adjSource = a;
app.adjTarget = s.serviceInfo.name;
}
@@ -12964,6 +13023,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
adj = clientAdj > FOREGROUND_APP_ADJ
? clientAdj : FOREGROUND_APP_ADJ;
app.adjType = "provider";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_PROVIDER_IN_USE;
app.adjSource = client;
app.adjTarget = cpr.info.name;
}
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index b3343dd51eb25..f613b001e9150 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.app.IServiceConnection;
+import android.app.PendingIntent;
import java.io.PrintWriter;
@@ -28,6 +29,8 @@ class ConnectionRecord {
final HistoryRecord activity; // If non-null, the owning activity.
final IServiceConnection conn; // The client connection.
final int flags; // Binding options.
+ final int clientLabel; // String resource labeling this client.
+ final PendingIntent clientIntent; // How to launch the client.
String stringName; // Caching of toString.
void dump(PrintWriter pw, String prefix) {
@@ -40,11 +43,14 @@ class ConnectionRecord {
}
ConnectionRecord(AppBindRecord _binding, HistoryRecord _activity,
- IServiceConnection _conn, int _flags) {
+ IServiceConnection _conn, int _flags,
+ int _clientLabel, PendingIntent _clientIntent) {
binding = _binding;
activity = _activity;
conn = _conn;
flags = _flags;
+ clientLabel = _clientLabel;
+ clientIntent = _clientIntent;
}
public String toString() {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 76fdf09baec00..d05b44ba76e5c 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -75,6 +75,7 @@ class ProcessRecord implements Watchdog.PssRequestor {
boolean reportLowMemory; // Set to true when waiting to report low mem
int lastPss; // Last pss size reported by app.
String adjType; // Debugging: primary thing impacting oom_adj.
+ int adjTypeCode; // Debugging: adj code to report to app.
Object adjSource; // Debugging: option dependent object.
Object adjTarget; // Debugging: target component impacting oom_adj.