summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java117
-rw-r--r--services/core/java/com/android/server/DockObserver.java3
-rw-r--r--services/core/java/com/android/server/MountService.java11
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java100
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java28
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java15
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java183
-rw-r--r--services/core/java/com/android/server/am/BroadcastRecord.java15
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java3
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java64
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java71
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java65
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java13
-rw-r--r--services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java32
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java41
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java1
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java52
-rw-r--r--services/core/java/com/android/server/power/Notifier.java20
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java42
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java29
-rw-r--r--services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java5
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java6
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaManager.java11
-rw-r--r--services/usb/java/com/android/server/usb/UsbDebuggingManager.java13
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java25
-rw-r--r--services/usb/java/com/android/server/usb/UsbHostManager.java7
-rw-r--r--services/usb/java/com/android/server/usb/UsbPortManager.java753
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java274
-rw-r--r--services/usb/java/com/android/server/usb/UsbSettingsManager.java23
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java38
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java25
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java12
34 files changed, 1717 insertions, 384 deletions
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index fde1490..c7c9d29 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -36,6 +36,7 @@ import android.hardware.TriggerEventListener;
import android.hardware.display.DisplayManager;
import android.net.INetworkPolicyManager;
import android.net.Uri;
+import android.os.BatteryStats;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
@@ -54,9 +55,11 @@ import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.KeyValueListParser;
+import android.util.MutableLong;
+import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;
import android.view.Display;
@@ -177,7 +180,13 @@ public class DeviceIdleController extends SystemService
* List of end times for UIDs that are temporarily marked as being allowed to access
* the network and acquire wakelocks. Times are in milliseconds.
*/
- private final SparseLongArray mTempWhitelistAppIdEndTimes = new SparseLongArray();
+ private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
+ = new SparseArray<>();
+
+ /**
+ * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
+ */
+ Runnable mNetworkPolicyTempWhitelistCallback;
/**
* Current app IDs of temporarily whitelist apps for high-priority messages.
@@ -242,6 +251,8 @@ public class DeviceIdleController extends SystemService
private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
"max_temp_app_whitelist_duration";
+ private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
+ "mms_temp_app_whitelist_duration";
/**
* This is the time, after becoming inactive, at which we start looking at the
@@ -339,6 +350,13 @@ public class DeviceIdleController extends SystemService
*/
public long MAX_TEMP_APP_WHITELIST_DURATION;
+ /**
+ * Amount of time we would like to whitelist an app that is receiving an MMS.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
+ */
+ public long MMS_TEMP_APP_WHITELIST_DURATION;
+
private final ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -388,8 +406,10 @@ public class DeviceIdleController extends SystemService
2f);
MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
!COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
- MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(KEY_MAX_TEMP_APP_WHITELIST_DURATION,
- 5 * 60 * 1000L);
+ MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
+ KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
+ MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
+ KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
}
}
@@ -441,6 +461,10 @@ public class DeviceIdleController extends SystemService
pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
pw.println();
+
+ pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
+ TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
+ pw.println();
}
}
@@ -565,7 +589,7 @@ public class DeviceIdleController extends SystemService
}
@Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
- int userId) throws RemoteException {
+ int userId, String reason) throws RemoteException {
getContext().enforceCallingPermission(
Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
"No permission to change device idle whitelist");
@@ -580,12 +604,19 @@ public class DeviceIdleController extends SystemService
final long token = Binder.clearCallingIdentity();
try {
DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid,
- packageName, duration, userId);
+ packageName, duration, userId, true, reason);
} finally {
Binder.restoreCallingIdentity(token);
}
}
+ @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
+ int userId, String reason) throws RemoteException {
+ long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
+ addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
+ return duration;
+ }
+
@Override public void exitIdle(String reason) {
getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
null);
@@ -598,8 +629,13 @@ public class DeviceIdleController extends SystemService
}
public final class LocalService {
- public void addPowerSaveTempWhitelistAppDirect(int appId, long duration) {
- addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration);
+ public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
+ String reason) {
+ addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
+ }
+
+ public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
+ setNetworkPolicyTempWhitelistCallbackInternal(callback);
}
}
@@ -777,11 +813,11 @@ public class DeviceIdleController extends SystemService
* app an exemption to access network and acquire wakelocks.
*/
public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
- long duration, int userId) {
+ long duration, int userId, boolean sync, String reason) {
try {
int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
int appId = UserHandle.getAppId(uid);
- addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration);
+ addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
} catch (NameNotFoundException e) {
}
}
@@ -791,8 +827,9 @@ public class DeviceIdleController extends SystemService
* app an exemption to access network and acquire wakelocks.
*/
public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
- long duration) {
+ long duration, boolean sync, String reason) {
final long timeNow = SystemClock.elapsedRealtime();
+ Runnable networkPolicyTempWhitelistCallback = null;
synchronized (this) {
int callingAppId = UserHandle.getAppId(callingUid);
if (callingAppId >= Process.FIRST_APPLICATION_UID) {
@@ -802,19 +839,45 @@ public class DeviceIdleController extends SystemService
}
}
duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
- long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId);
+ Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
+ final boolean newEntry = entry == null;
// Set the new end time
- mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration);
+ if (newEntry) {
+ entry = new Pair<>(new MutableLong(0), reason);
+ mTempWhitelistAppIdEndTimes.put(appId, entry);
+ }
+ entry.first.value = timeNow + duration;
if (DEBUG) {
Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
}
- if (currentEndTime == 0) {
+ if (newEntry) {
// No pending timeout for the app id, post a delayed message
+ try {
+ mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
+ reason, appId);
+ } catch (RemoteException e) {
+ }
postTempActiveTimeoutMessage(appId, duration);
updateTempWhitelistAppIdsLocked();
+ if (mNetworkPolicyTempWhitelistCallback != null) {
+ if (!sync) {
+ mHandler.post(mNetworkPolicyTempWhitelistCallback);
+ } else {
+ networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
+ }
+ }
reportTempWhitelistChangedLocked();
}
}
+ if (networkPolicyTempWhitelistCallback != null) {
+ networkPolicyTempWhitelistCallback.run();
+ }
+ }
+
+ public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
+ synchronized (this) {
+ mNetworkPolicyTempWhitelistCallback = callback;
+ }
}
private void postTempActiveTimeoutMessage(int uid, long delay) {
@@ -825,21 +888,26 @@ public class DeviceIdleController extends SystemService
void checkTempAppWhitelistTimeout(int uid) {
final long timeNow = SystemClock.elapsedRealtime();
synchronized (this) {
- long endTime = mTempWhitelistAppIdEndTimes.get(uid);
- if (endTime == 0) {
+ Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
+ if (entry == null) {
// Nothing to do
return;
}
- if (timeNow >= endTime) {
+ if (timeNow >= entry.first.value) {
mTempWhitelistAppIdEndTimes.delete(uid);
if (DEBUG) {
Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
}
updateTempWhitelistAppIdsLocked();
reportTempWhitelistChangedLocked();
+ try {
+ mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
+ entry.second, uid);
+ } catch (RemoteException e) {
+ }
} else {
// Need more time
- postTempActiveTimeoutMessage(uid, endTime - timeNow);
+ postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
}
}
}
@@ -1101,7 +1169,7 @@ public class DeviceIdleController extends SystemService
}
void readConfigFileLocked() {
- Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
+ if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
mPowerSaveWhitelistUserApps.clear();
FileInputStream stream;
try {
@@ -1370,11 +1438,14 @@ public class DeviceIdleController extends SystemService
while (i < args.length) {
arg = args[i];
i++;
- addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId);
+ addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true,
+ "shell");
+ pw.println("Added: " + arg);
}
} finally {
Binder.restoreCallingIdentity(token);
}
+ return;
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
pw.println("Unknown option: " + arg);
return;
@@ -1421,8 +1492,10 @@ public class DeviceIdleController extends SystemService
pw.print(" UID=");
pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
pw.print(": ");
- TimeUtils.formatDuration(mTempWhitelistAppIdEndTimes.valueAt(i), timeNow, pw);
- pw.println();
+ Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
+ TimeUtils.formatDuration(entry.first.value, timeNow, pw);
+ pw.print(" - ");
+ pw.println(entry.second);
}
}
size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index 41ce25d..5388f10 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -134,7 +134,8 @@ final class DockObserver extends SystemService {
if (mAllowTheaterModeWakeFromDock
|| Settings.Global.getInt(getContext().getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 0) {
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+ "android.server:DOCK");
}
updateLocked();
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index bc61c3d..0e158a2 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2602,8 +2602,15 @@ class MountService extends IMountService.Stub
boolean foundPrimary = false;
final int userId = UserHandle.getUserId(uid);
- final boolean reportUnmounted = !mMountServiceInternal.hasExternalStorage(
- uid, packageName);
+ final boolean reportUnmounted;
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ reportUnmounted = !mMountServiceInternal.hasExternalStorage(
+ uid, packageName);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5bfca10..3bf6fde 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18,10 +18,7 @@ package com.android.server.am;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
-import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -3516,8 +3513,8 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.setComponent(new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name));
mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo,
- null, null, null, null, 0, 0, 0, null, 0, 0, 0, null, false, null, null,
- null);
+ null, null, null, null, 0, 0, 0, null, 0, 0, 0, null, false, false,
+ null, null, null);
}
}
}
@@ -3803,13 +3800,14 @@ public final class ActivityManagerService extends ActivityManagerNative
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- profilerInfo, null, null, options, userId, null, null);
+ profilerInfo, null, null, options, false, userId, null, null);
}
@Override
public final int startActivityAsCaller(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
+ int startFlags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
+ int userId) {
// This is very dangerous -- it allows you to perform a start activity (including
// permission grants) as any app that may launch one of your own activities. So
@@ -3843,6 +3841,16 @@ public final class ActivityManagerService extends ActivityManagerNative
+ sourceRecord.launchedFromUid);
}
}
+ if (ignoreTargetSecurity) {
+ if (intent.getComponent() == null) {
+ throw new SecurityException(
+ "Component must be specified with ignoreTargetSecurity");
+ }
+ if (intent.getSelector() != null) {
+ throw new SecurityException(
+ "Selector not allowed with ignoreTargetSecurity");
+ }
+ }
targetUid = sourceRecord.launchedFromUid;
targetPackage = sourceRecord.launchedFromPackage;
}
@@ -3855,7 +3863,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
int ret = mStackSupervisor.startActivityMayWait(null, targetUid, targetPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, null,
- null, null, options, userId, null, null);
+ null, null, options, ignoreTargetSecurity, userId, null, null);
return ret;
} catch (SecurityException e) {
// XXX need to figure out how to propagate to original app.
@@ -3884,7 +3892,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// TODO: Switch to user app stacks here.
mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, res, null,
- options, userId, null, null);
+ options, false, userId, null, null);
return res;
}
@@ -3898,7 +3906,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, config, options, userId, null, null);
+ null, null, config, options, false, userId, null, null);
return ret;
}
@@ -3956,7 +3964,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(null, callingUid, callingPackage, intent,
resolvedType, session, interactor, null, null, 0, startFlags, profilerInfo, null,
- null, options, userId, null, null);
+ null, options, false, userId, null, null);
}
@Override
@@ -4067,7 +4075,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int res = mStackSupervisor.startActivityLocked(r.app.thread, intent,
r.resolvedType, aInfo, null, null, resultTo != null ? resultTo.appToken : null,
resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage,
- -1, r.launchedFromUid, 0, options, false, null, null, null);
+ -1, r.launchedFromUid, 0, options, false, false, null, null, null);
Binder.restoreCallingIdentity(origId);
r.finishing = wasFinishing;
@@ -4125,7 +4133,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(null, uid, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, null, options, userId, container, inTask);
+ null, null, null, options, false, userId, container, inTask);
return ret;
}
@@ -6355,7 +6363,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
},
0, null, null,
- android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
+ new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
AppOpsManager.OP_NONE, null, true, false,
MY_PID, Process.SYSTEM_UID, userId);
}
@@ -10801,6 +10809,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// We are now ready to launch the assist activity.
+ IResultReceiver sendReceiver = null;
+ Bundle sendBundle = null;
synchronized (this) {
buildAssistBundleLocked(pae, extras);
boolean exists = mPendingAssistExtras.remove(pae);
@@ -10809,19 +10819,21 @@ public final class ActivityManagerService extends ActivityManagerNative
// Timed out.
return;
}
- if (pae.receiver != null) {
+ if ((sendReceiver=pae.receiver) != null) {
// Caller wants result sent back to them.
- Bundle topBundle = new Bundle();
- topBundle.putBundle("data", pae.extras);
- topBundle.putParcelable("structure", pae.structure);
- topBundle.putParcelable("content", pae.content);
- try {
- pae.receiver.send(0, topBundle);
- } catch (RemoteException e) {
- }
- return;
+ sendBundle = new Bundle();
+ sendBundle.putBundle("data", pae.extras);
+ sendBundle.putParcelable("structure", pae.structure);
+ sendBundle.putParcelable("content", pae.content);
}
}
+ if (sendReceiver != null) {
+ try {
+ sendReceiver.send(0, sendBundle);
+ } catch (RemoteException e) {
+ }
+ return;
+ }
long ident = Binder.clearCallingIdentity();
try {
@@ -11773,7 +11785,7 @@ public final class ActivityManagerService extends ActivityManagerNative
throws RemoteException {
}
}, 0, null, null,
- INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
+ new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
@@ -16327,7 +16339,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle resultExtras, String requiredPermission, int appOp, Bundle options,
+ Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
intent = new Intent(intent);
@@ -16580,9 +16592,9 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- if (requiredPermission != null) {
+ if (requiredPermissions != null && requiredPermissions.length > 0) {
Slog.w(TAG, "Can't broadcast sticky intent " + intent
- + " and enforce permission " + requiredPermission);
+ + " and enforce permissions " + Arrays.toString(requiredPermissions));
return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
if (intent.getComponent() != null) {
@@ -16690,7 +16702,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// components to be launched.
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
- callerPackage, callingPid, callingUid, resolvedType, requiredPermission,
+ callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
@@ -16780,7 +16792,7 @@ public final class ActivityManagerService extends ActivityManagerNative
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
- requiredPermission, appOp, brOptions, receivers, resultTo, resultCode,
+ requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
@@ -16829,7 +16841,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
- String requiredPermission, int appOp, Bundle options,
+ String[] requiredPermissions, int appOp, Bundle options,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
@@ -16842,13 +16854,14 @@ public final class ActivityManagerService extends ActivityManagerNative
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
- requiredPermission, appOp, null, serialized, sticky,
+ requiredPermissions, appOp, null, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
+
int broadcastIntentInPackage(String packageName, int uid,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
@@ -16858,9 +16871,12 @@ public final class ActivityManagerService extends ActivityManagerNative
intent = verifyBroadcastLocked(intent);
final long origId = Binder.clearCallingIdentity();
+ String[] requiredPermissions = requiredPermission == null ? null
+ : new String[] {requiredPermission};
int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
- resultTo, resultCode, resultData, resultExtras, requiredPermission,
- AppOpsManager.OP_NONE, options, serialized, sticky, -1, uid, userId);
+ resultTo, resultCode, resultData, resultExtras,
+ requiredPermissions, AppOpsManager.OP_NONE, options, serialized,
+ sticky, -1, uid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -19795,7 +19811,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int sendingUser) throws RemoteException {
}
}, 0, null, null,
- INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
+ new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
}
@@ -19857,8 +19873,9 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
- android.Manifest.permission.MANAGE_USERS, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ new String[] {android.Manifest.permission.MANAGE_USERS},
+ AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
+ UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -20041,8 +20058,9 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
- android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE,
- null, true, false, MY_PID, Process.SYSTEM_UID, userId);
+ new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
+ AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID,
+ userId);
}
}
}
@@ -20180,7 +20198,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Kick things off.
broadcastIntentLocked(null, null, stoppingIntent,
null, stoppingReceiver, 0, null, null,
- INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
+ new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -20519,7 +20537,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null,
- null, options, callingUser, null, tr);
+ null, options, false, callingUser, null, tr);
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 470bbb0..e57e3ff 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3117,7 +3117,7 @@ final class ActivityStack {
int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
null, aInfo, null, null, parent.appToken, null,
0, -1, parent.launchedFromUid, parent.launchedFromPackage,
- -1, parent.launchedFromUid, 0, null, true, null, null, null);
+ -1, parent.launchedFromUid, 0, null, false, true, null, null, null);
foundParentInTask = res == ActivityManager.START_SUCCESS;
} catch (RemoteException e) {
foundParentInTask = false;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c12aff6..05c58d7 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -911,7 +911,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,
null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,
null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,
- 0 /* startFlags */, null /* options */, false /* componentSpecified */,
+ 0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,
+ false /* componentSpecified */,
null /* outActivity */, null /* container */, null /* inTask */);
if (inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
@@ -926,7 +927,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
- Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
+ Bundle options, boolean ignoreTargetSecurity, int userId,
+ IActivityContainer iContainer, TaskRecord inTask) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -1043,7 +1045,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
- realCallingPid, realCallingUid, startFlags, options,
+ realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
Binder.restoreCallingIdentity(origId);
@@ -1159,7 +1161,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
int res = startActivityLocked(caller, intent, resolvedTypes[i],
aInfo, null, null, resultTo, null, -1, callingPid, callingUid,
callingPackage, callingPid, callingUid,
- 0, theseOptions, componentSpecified, outActivity, null, null);
+ 0, theseOptions, false, componentSpecified, outActivity, null, null);
if (res < 0) {
return res;
}
@@ -1400,8 +1402,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
- boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
- TaskRecord inTask) {
+ boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
+ ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
@@ -1546,7 +1548,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (startAnyPerm != PERMISSION_GRANTED) {
final int componentRestriction = getComponentRestrictionForCallingPackage(
- aInfo, callingPackage, callingPid, callingUid);
+ aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity);
final int actionRestriction = getActionRestrictionForCallingPackage(
intent.getAction(), callingPackage, callingPid, callingUid);
@@ -1675,13 +1677,13 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
private int getComponentRestrictionForCallingPackage(ActivityInfo activityInfo,
- String callingPackage, int callingPid, int callingUid) {
+ String callingPackage, int callingPid, int callingUid, boolean ignoreTargetSecurity) {
if (activityInfo.permission == null) {
return ACTIVITY_RESTRICTION_NONE;
}
- if (mService.checkComponentPermission(activityInfo.permission, callingPid, callingUid,
- activityInfo.applicationInfo.uid, activityInfo.exported)
+ if (!ignoreTargetSecurity && mService.checkComponentPermission(activityInfo.permission,
+ callingPid, callingUid, activityInfo.applicationInfo.uid, activityInfo.exported)
== PackageManager.PERMISSION_DENIED) {
return ACTIVITY_RESTRICTION_PERMISSION;
}
@@ -1693,7 +1695,9 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (mService.mAppOpsService.noteOperation(opCode, callingUid,
callingPackage) != AppOpsManager.MODE_ALLOWED) {
- return ACTIVITY_RESTRICTION_APPOP;
+ if (!ignoreTargetSecurity) {
+ return ACTIVITY_RESTRICTION_APPOP;
+ }
}
return ACTIVITY_RESTRICTION_NONE;
@@ -4296,7 +4300,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
intent.addFlags(FORCE_NEW_TASK_FLAGS);
return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null,
- 0, 0, null, null, null, null, userId, this, null);
+ 0, 0, null, null, null, null, false, userId, this, null);
}
@Override
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 070813b..4b0b924 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -101,8 +101,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mUpdateFlags = 0;
}
updateExternalStats((String)msg.obj, updateFlags);
- synchronized (this) {
- synchronized (mStats) {
+
+ // other parts of the system could be calling into us
+ // from mStats in order to report of changes. We must grab the mStats
+ // lock before grabbing our own or we'll end up in a deadlock.
+ synchronized (mStats) {
+ synchronized (this) {
final int numUidsToRemove = mUidsToRemove.size();
for (int i = 0; i < numUidsToRemove; i++) {
mStats.removeIsolatedUidLocked(mUidsToRemove.get(i));
@@ -489,6 +493,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ public void noteWakeUp(String reason, int reasonUid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteWakeUpLocked(reason, reasonUid);
+ }
+ }
+
public void noteInteractive(boolean interactive) {
enforceCallingPermission();
synchronized (mStats) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 30aa411..91d97ef 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -175,7 +175,7 @@ public final class BroadcastQueue {
DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
if (dic != null) {
dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
- msg.arg2);
+ msg.arg2, true, (String)msg.obj);
}
} break;
}
@@ -493,59 +493,74 @@ public final class BroadcastQueue {
}
}
}
- if (!skip) {
- int perm = mService.checkComponentPermission(r.requiredPermission,
- filter.receiverList.pid, filter.receiverList.uid, -1, true);
- if (perm != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "Permission Denial: receiving "
- + r.intent.toString()
- + " to " + filter.receiverList.app
- + " (pid=" + filter.receiverList.pid
- + ", uid=" + filter.receiverList.uid + ")"
- + " requires " + r.requiredPermission
- + " due to sender " + r.callerPackage
- + " (uid " + r.callingUid + ")");
- skip = true;
- }
- int appOp = AppOpsManager.OP_NONE;
- if (r.requiredPermission != null) {
- appOp = AppOpsManager.permissionToOpCode(r.requiredPermission);
- if (appOp != AppOpsManager.OP_NONE
- && mService.mAppOpsService.noteOperation(appOp,
- filter.receiverList.uid, filter.packageName)
- != AppOpsManager.MODE_ALLOWED) {
- Slog.w(TAG, "Appop Denial: receiving "
+ if (!skip && r.requiredPermissions != null && r.requiredPermissions.length > 0) {
+ for (int i = 0; i < r.requiredPermissions.length; i++) {
+ String requiredPermission = r.requiredPermissions[i];
+ int perm = mService.checkComponentPermission(requiredPermission,
+ filter.receiverList.pid, filter.receiverList.uid, -1, true);
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Permission Denial: receiving "
+ r.intent.toString()
+ " to " + filter.receiverList.app
+ " (pid=" + filter.receiverList.pid
+ ", uid=" + filter.receiverList.uid + ")"
- + " requires appop " + AppOpsManager.permissionToOp(
- r.requiredPermission)
+ + " requires " + requiredPermission
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
+ break;
}
- }
- if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE
- && mService.mAppOpsService.noteOperation(r.appOp,
- filter.receiverList.uid, filter.packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
+ if (appOp != r.appOp
+ && mService.mAppOpsService.noteOperation(appOp,
+ filter.receiverList.uid, filter.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent.toString()
+ " to " + filter.receiverList.app
+ " (pid=" + filter.receiverList.pid
+ ", uid=" + filter.receiverList.uid + ")"
+ " requires appop " + AppOpsManager.permissionToOp(
- r.requiredPermission)
+ requiredPermission)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
+ break;
+ }
}
}
+ if (!skip && (r.requiredPermissions == null || r.requiredPermissions.length == 0)) {
+ int perm = mService.checkComponentPermission(null,
+ filter.receiverList.pid, filter.receiverList.uid, -1, true);
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Permission Denial: security check failed when receiving "
+ + r.intent.toString()
+ + " to " + filter.receiverList.app
+ + " (pid=" + filter.receiverList.pid
+ + ", uid=" + filter.receiverList.uid + ")"
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
+ }
+ if (!skip && r.appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(r.appOp,
+ filter.receiverList.uid, filter.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent.toString()
+ + " to " + filter.receiverList.app
+ + " (pid=" + filter.receiverList.pid
+ + ", uid=" + filter.receiverList.uid + ")"
+ + " requires appop " + AppOpsManager.opToName(r.appOp)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
- if (!skip) {
- skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
- r.callingPid, r.resolvedType, filter.receiverList.uid);
+ if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
+ r.callingPid, r.resolvedType, filter.receiverList.uid)) {
+ return;
}
if (filter.receiverList.app == null || filter.receiverList.app.crashing) {
@@ -597,7 +612,7 @@ public final class BroadcastQueue {
}
}
- final void scheduleTempWhitelistLocked(int uid, long duration) {
+ final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r) {
if (duration > Integer.MAX_VALUE) {
duration = Integer.MAX_VALUE;
}
@@ -607,7 +622,19 @@ public final class BroadcastQueue {
// not that big a deal, however, because the main purpose here is to allow apps
// to hold wake locks, and they will be able to acquire their wake lock immediately
// it just won't be enabled until we get through this work.
- mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration).sendToTarget();
+ StringBuilder b = new StringBuilder();
+ b.append("broadcast:");
+ UserHandle.formatUid(b, r.callingUid);
+ b.append(":");
+ if (r.intent.getAction() != null) {
+ b.append(r.intent.getAction());
+ } else if (r.intent.getComponent() != null) {
+ b.append(r.intent.getComponent().flattenToShortString());
+ } else if (r.intent.getData() != null) {
+ b.append(r.intent.getData());
+ }
+ mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration, b.toString())
+ .sendToTarget();
}
final void processNextBroadcast(boolean fromMsg) {
@@ -807,7 +834,7 @@ public final class BroadcastQueue {
} else {
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(filter.owningUid,
- brOptions.getTemporaryAppWhitelistDuration());
+ brOptions.getTemporaryAppWhitelistDuration(), r);
}
}
return;
@@ -860,51 +887,53 @@ public final class BroadcastQueue {
}
}
if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
- r.requiredPermission != null) {
- try {
- perm = AppGlobals.getPackageManager().
- checkPermission(r.requiredPermission,
- info.activityInfo.applicationInfo.packageName,
- UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
- } catch (RemoteException e) {
- perm = PackageManager.PERMISSION_DENIED;
- }
- if (perm != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "Permission Denial: receiving "
- + r.intent + " to "
- + component.flattenToShortString()
- + " requires " + r.requiredPermission
- + " due to sender " + r.callerPackage
- + " (uid " + r.callingUid + ")");
- skip = true;
- }
- }
- int appOp = AppOpsManager.OP_NONE;
- if (!skip && r.requiredPermission != null) {
- appOp = AppOpsManager.permissionToOpCode(r.requiredPermission);
- if (appOp != AppOpsManager.OP_NONE
- && mService.mAppOpsService.noteOperation(appOp,
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
- != AppOpsManager.MODE_ALLOWED) {
- Slog.w(TAG, "Appop Denial: receiving "
- + r.intent + " to "
- + component.flattenToShortString()
- + " requires appop " + AppOpsManager.permissionToOp(
- r.requiredPermission)
- + " due to sender " + r.callerPackage
- + " (uid " + r.callingUid + ")");
- skip = true;
+ r.requiredPermissions != null && r.requiredPermissions.length > 0) {
+ for (int i = 0; i < r.requiredPermissions.length; i++) {
+ String requiredPermission = r.requiredPermissions[i];
+ try {
+ perm = AppGlobals.getPackageManager().
+ checkPermission(requiredPermission,
+ info.activityInfo.applicationInfo.packageName,
+ UserHandle
+ .getUserId(info.activityInfo.applicationInfo.uid));
+ } catch (RemoteException e) {
+ perm = PackageManager.PERMISSION_DENIED;
+ }
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Permission Denial: receiving "
+ + r.intent + " to "
+ + component.flattenToShortString()
+ + " requires " + requiredPermission
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ break;
+ }
+ int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
+ if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
+ && mService.mAppOpsService.noteOperation(appOp,
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent + " to "
+ + component.flattenToShortString()
+ + " requires appop " + AppOpsManager.permissionToOp(
+ requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ break;
+ }
}
}
- if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE
+ if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(r.appOp,
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
+ component.flattenToShortString()
- + " requires appop " + AppOpsManager.permissionToOp(
- r.requiredPermission)
+ + " requires appop " + AppOpsManager.opToName(r.appOp)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
@@ -988,7 +1017,7 @@ public final class BroadcastQueue {
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(receiverUid,
- brOptions.getTemporaryAppWhitelistDuration());
+ brOptions.getTemporaryAppWhitelistDuration(), r);
}
// Broadcast is being executed, its package can't be stopped.
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index b943222..a7e6471 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -32,6 +32,7 @@ import android.util.PrintWriterPrinter;
import android.util.TimeUtils;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
@@ -51,7 +52,7 @@ final class BroadcastRecord extends Binder {
final boolean initialSticky; // initial broadcast from register to sticky?
final int userId; // user id this broadcast was for
final String resolvedType; // the resolved data type
- final String requiredPermission; // a permission the caller has required
+ final String[] requiredPermissions; // permissions the caller has required
final int appOp; // an app op that is associated with this broadcast
final BroadcastOptions options; // BroadcastOptions supplied by caller
final List receivers; // contains BroadcastFilter and ResolveInfo
@@ -103,9 +104,11 @@ final class BroadcastRecord extends Binder {
pw.print(callerApp != null ? callerApp.toShortString() : "null");
pw.print(" pid="); pw.print(callingPid);
pw.print(" uid="); pw.println(callingUid);
- if (requiredPermission != null || appOp != AppOpsManager.OP_NONE) {
- pw.print(prefix); pw.print("requiredPermission="); pw.print(requiredPermission);
- pw.print(" appOp="); pw.println(appOp);
+ if ((requiredPermissions != null && requiredPermissions.length > 0)
+ || appOp != AppOpsManager.OP_NONE) {
+ pw.print(prefix); pw.print("requiredPermissions=");
+ pw.print(Arrays.toString(requiredPermissions));
+ pw.print(" appOp="); pw.println(appOp);
}
if (options != null) {
pw.print(prefix); pw.print("options="); pw.println(options.toBundle());
@@ -184,7 +187,7 @@ final class BroadcastRecord extends Binder {
BroadcastRecord(BroadcastQueue _queue,
Intent _intent, ProcessRecord _callerApp, String _callerPackage,
- int _callingPid, int _callingUid, String _resolvedType, String _requiredPermission,
+ int _callingPid, int _callingUid, String _resolvedType, String[] _requiredPermissions,
int _appOp, BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo,
int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized,
boolean _sticky, boolean _initialSticky,
@@ -197,7 +200,7 @@ final class BroadcastRecord extends Binder {
callingPid = _callingPid;
callingUid = _callingUid;
resolvedType = _resolvedType;
- requiredPermission = _requiredPermission;
+ requiredPermissions = _requiredPermissions;
appOp = _appOp;
options = _options;
receivers = _receivers;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 458928f..8813a61 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -648,7 +648,8 @@ public final class DreamManagerService extends SystemService {
if (mCurrentDreamName != null && mCurrentDreamCanDoze
&& !mCurrentDreamName.equals(getDozeComponent())) {
// May have updated the doze component, wake up
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+ "android.server.dreams:SYSPROP");
}
}
}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 4d8d105..8871e64 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -86,6 +86,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
private static final int FINGERPRINT_ACQUIRED_GOOD = 0;
Handler mHandler = new Handler() {
+ @Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_USER_SWITCHING:
@@ -274,7 +275,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
Slog.w(TAG, "enroll: no fingeprintd!");
return;
}
- stopPendingOperations();
+ stopPendingOperations(true);
mEnrollClient = new ClientMonitor(token, receiver, groupId, restricted);
final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
try {
@@ -315,17 +316,23 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
return 0;
}
- private void stopPendingOperations() {
+ private void stopPendingOperations(boolean initiatedByClient) {
if (mEnrollClient != null) {
- stopEnrollment(mEnrollClient.token, true);
+ stopEnrollment(mEnrollClient.token, initiatedByClient);
}
if (mAuthClient != null) {
- stopAuthentication(mAuthClient.token, true);
+ stopAuthentication(mAuthClient.token, initiatedByClient);
}
// mRemoveClient is allowed to continue
}
- void stopEnrollment(IBinder token, boolean notify) {
+ /**
+ * Stop enrollment in progress and inform client if they initiated it.
+ *
+ * @param token token for client
+ * @param initiatedByClient if this call is the result of client action (e.g. calling cancel)
+ */
+ void stopEnrollment(IBinder token, boolean initiatedByClient) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "stopEnrollment: no fingeprintd!");
@@ -333,15 +340,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
}
final ClientMonitor client = mEnrollClient;
if (client == null || client.token != token) return;
- try {
- int result = daemon.cancelEnrollment();
- if (result != 0) {
- Slog.w(TAG, "startEnrollCancel failed, result = " + result);
+ if (initiatedByClient) {
+ try {
+ int result = daemon.cancelEnrollment();
+ if (result != 0) {
+ Slog.w(TAG, "startEnrollCancel failed, result = " + result);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "stopEnrollment failed", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "stopEnrollment failed", e);
- }
- if (notify) {
client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
}
removeClient(mEnrollClient);
@@ -354,7 +361,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
Slog.w(TAG, "startAuthentication: no fingeprintd!");
return;
}
- stopPendingOperations();
+ stopPendingOperations(true);
mAuthClient = new ClientMonitor(token, receiver, groupId, restricted);
if (inLockoutMode()) {
Slog.v(TAG, "In lockout mode; disallowing authentication");
@@ -374,7 +381,13 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
}
}
- void stopAuthentication(IBinder token, boolean notify) {
+ /**
+ * Stop authentication in progress and inform client if they initiated it.
+ *
+ * @param token token for client
+ * @param initiatedByClient if this call is the result of client action (e.g. calling cancel)
+ */
+ void stopAuthentication(IBinder token, boolean initiatedByClient) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "stopAuthentication: no fingeprintd!");
@@ -382,15 +395,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
}
final ClientMonitor client = mAuthClient;
if (client == null || client.token != token) return;
- try {
- int result = daemon.cancelAuthentication();
- if (result != 0) {
- Slog.w(TAG, "stopAuthentication failed, result=" + result);
+ if (initiatedByClient) {
+ try {
+ int result = daemon.cancelAuthentication();
+ if (result != 0) {
+ Slog.w(TAG, "stopAuthentication failed, result=" + result);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "stopAuthentication failed", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "stopAuthentication failed", e);
- }
- if (notify) {
client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
}
removeClient(mAuthClient);
@@ -486,12 +499,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
receiver = null;
}
+ @Override
public void binderDied() {
token = null;
removeClient(this);
receiver = null;
}
+ @Override
protected void finalize() throws Throwable {
try {
if (token != null) {
@@ -565,7 +580,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
// For fingerprint devices that support touch-to-wake, this will ensure the device
// wakes up and turns the screen on when fingerprint is authenticated.
if (mIsKeyguard && authenticated) {
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+ "android.server.fingerprint:AUTH");
}
return result;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index c37f619..cfc5f7d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1969,7 +1969,7 @@ public final class HdmiControlService extends SystemService {
void wakeUp() {
assertRunOnServiceThread();
mWakeUpMessageReceived = true;
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.hdmi:WAKE");
// PowerManger will send the broadcast Intent.ACTION_SCREEN_ON and after this gets
// the intent, the sequence will continue at onWakeUp().
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index f8f00ef..395aa27 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -147,6 +147,7 @@ import android.util.SparseIntArray;
import android.util.TrustedTime;
import android.util.Xml;
+import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
import libcore.io.IoUtils;
@@ -462,9 +463,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// listen for changes to power save whitelist
final IntentFilter whitelistFilter = new IntentFilter(
PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
- whitelistFilter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler);
+ DeviceIdleController.LocalService deviceIdleService
+ = LocalServices.getService(DeviceIdleController.LocalService.class);
+ deviceIdleService.setNetworkPolicyTempWhitelistCallback(mTempPowerSaveChangedCallback);
+
// watch for network interfaces to be claimed
final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
@@ -512,7 +516,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
- private IUidObserver mUidObserver = new IUidObserver.Stub() {
+ final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
synchronized (mRulesLock) {
updateUidStateLocked(uid, procState);
@@ -526,24 +530,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
};
- private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
synchronized (mRulesLock) {
- if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(intent.getAction())) {
- updatePowerSaveWhitelistLocked();
- updateRulesForGlobalChangeLocked(false);
- } else {
- updatePowerSaveTempWhitelistLocked();
- updateRulesForTempWhitelistChangeLocked();
- purgePowerSaveTempWhitelistLocked();
- }
+ updatePowerSaveWhitelistLocked();
+ updateRulesForGlobalChangeLocked(false);
}
}
};
- private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
+ final private Runnable mTempPowerSaveChangedCallback = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mRulesLock) {
+ updatePowerSaveTempWhitelistLocked();
+ updateRulesForTempWhitelistChangeLocked();
+ purgePowerSaveTempWhitelistLocked();
+ }
+ }
+ };
+
+ final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// screen-related broadcasts are protected by system, no need
@@ -552,7 +561,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
};
- private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and PACKAGE_ADDED is protected
@@ -572,7 +581,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
};
- private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and UID_REMOVED is protected
@@ -590,7 +599,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
};
- private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and USER_ADDED and USER_REMOVED
@@ -619,7 +628,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Receiver that watches for {@link INetworkStatsService} updates, which we
* use to check against {@link NetworkPolicy#warningBytes}.
*/
- private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified
@@ -637,7 +646,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Receiver that watches for {@link Notification} control of
* {@link #mRestrictBackground}.
*/
- private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified MANAGE_NETWORK_POLICY
@@ -651,7 +660,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Receiver that watches for {@link Notification} control of
* {@link NetworkPolicy#lastWarningSnooze}.
*/
- private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified MANAGE_NETWORK_POLICY
@@ -665,7 +674,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Receiver that watches for {@link WifiConfiguration} to be changed.
*/
- private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
@@ -692,7 +701,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Receiver that watches {@link WifiInfo} state changes to infer metered
* state. Ignores hints when policy is user-defined.
*/
- private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
@@ -732,7 +741,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Observer that watches for {@link INetworkManagementService} alerts.
*/
- private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
+ final private INetworkManagementEventObserver mAlertObserver
+ = new BaseNetworkObserver() {
@Override
public void limitReached(String limitName, String iface) {
// only someone like NMS should be calling us
@@ -1985,6 +1995,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// state changed, push updated rules
mUidState.put(uid, uidState);
updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
+ if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState)
+ != isProcStateAllowedWhileIdle(uidState)) {
+ updateRulesForDeviceIdleLocked();
+ }
}
}
@@ -1996,6 +2010,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
updateRulesForUidStateChangeLocked(uid, oldUidState,
ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ if (mDeviceIdleMode) {
+ updateRulesForDeviceIdleLocked();
+ }
}
}
}
@@ -2033,13 +2050,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ static boolean isProcStateAllowedWhileIdle(int procState) {
+ return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+ }
+
void updateRulesForDeviceIdleLocked() {
if (mDeviceIdleMode) {
// sync the whitelists before enable dozable chain. We don't care about the rules if
// we are disabling the chain.
SparseIntArray uidRules = new SparseIntArray();
final List<UserInfo> users = mUserManager.getUsers();
- for (UserInfo user : users) {
+ for (int ui = users.size() - 1; ui >= 0; ui--) {
+ UserInfo user = users.get(ui);
for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
int uid = UserHandle.getUid(user.id, appId);
@@ -2051,6 +2073,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
uidRules.put(uid, FIREWALL_RULE_ALLOW);
}
}
+ for (int i = mUidState.size() - 1; i >= 0; i--) {
+ if (isProcStateAllowedWhileIdle(mUidState.valueAt(i))) {
+ uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
+ }
+ }
setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
}
enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b23b856..7a6895f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1837,7 +1837,7 @@ public class NotificationManagerService extends SystemService {
void dumpImpl(PrintWriter pw, DumpFilter filter) {
pw.print("Current Notification Manager state");
- if (filter != null) {
+ if (filter.filtered) {
pw.print(" (filtered to "); pw.print(filter); pw.print(")");
}
pw.println(':');
@@ -1865,7 +1865,7 @@ public class NotificationManagerService extends SystemService {
for (int i=0; i<N; i++) {
final NotificationRecord nr = mNotificationList.get(i);
if (filter != null && !filter.matches(nr.sbn)) continue;
- nr.dump(pw, " ", getContext());
+ nr.dump(pw, " ", getContext(), filter.redact);
}
pw.println(" ");
}
@@ -1948,7 +1948,7 @@ public class NotificationManagerService extends SystemService {
pw.println(" " + entry.getKey() + " -> " + r.getKey());
if (mNotificationsByKey.get(r.getKey()) != r) {
pw.println("!!!!!!LEAK: Record not found in mNotificationsByKey.");
- r.dump(pw, " ", getContext());
+ r.dump(pw, " ", getContext(), filter.redact);
}
}
@@ -3499,46 +3499,59 @@ public class NotificationManagerService extends SystemService {
}
public static final class DumpFilter {
+ public boolean filtered = false;
public String pkgFilter;
public boolean zen;
public long since;
public boolean stats;
- private boolean all;
+ public boolean redact = true;
public static DumpFilter parseFromArguments(String[] args) {
- if (args != null && args.length == 2 && "p".equals(args[0])
- && args[1] != null && !args[1].trim().isEmpty()) {
- final DumpFilter filter = new DumpFilter();
- filter.pkgFilter = args[1].trim().toLowerCase();
- return filter;
- }
- if (args != null && args.length == 1 && "zen".equals(args[0])) {
- final DumpFilter filter = new DumpFilter();
- filter.zen = true;
- filter.all = true;
- return filter;
- }
- if (args != null && args.length >= 1 && "--stats".equals(args[0])) {
- final DumpFilter filter = new DumpFilter();
- filter.stats = true;
- filter.since = args.length == 2 ? Long.valueOf(args[1]) : 0;
- filter.all = true;
- return filter;
+ final DumpFilter filter = new DumpFilter();
+ for (int ai = 0; ai < args.length; ai++) {
+ final String a = args[ai];
+ if ("--noredact".equals(a) || "--reveal".equals(a)) {
+ filter.redact = false;
+ } else if ("p".equals(a) || "pkg".equals(a) || "--package".equals(a)) {
+ if (ai < args.length-1) {
+ ai++;
+ filter.pkgFilter = args[ai].trim().toLowerCase();
+ if (filter.pkgFilter.isEmpty()) {
+ filter.pkgFilter = null;
+ } else {
+ filter.filtered = true;
+ }
+ }
+ } else if ("--zen".equals(a) || "zen".equals(a)) {
+ filter.filtered = true;
+ filter.zen = true;
+ } else if ("--stats".equals(a)) {
+ filter.stats = true;
+ if (ai < args.length-1) {
+ ai++;
+ filter.since = Long.valueOf(args[ai]);
+ } else {
+ filter.since = 0;
+ }
+ }
}
- return null;
+ return filter;
}
public boolean matches(StatusBarNotification sbn) {
- return all ? true : sbn != null
+ if (!filtered) return true;
+ return zen ? true : sbn != null
&& (matches(sbn.getPackageName()) || matches(sbn.getOpPkg()));
}
public boolean matches(ComponentName component) {
- return all ? true : component != null && matches(component.getPackageName());
+ if (!filtered) return true;
+ return zen ? true : component != null && matches(component.getPackageName());
}
public boolean matches(String pkg) {
- return all ? true : pkg != null && pkg.toLowerCase().contains(pkgFilter);
+ if (!filtered) return true;
+ return zen ? true : pkg != null && pkg.toLowerCase().contains(pkgFilter);
}
@Override
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index b7aea9d..f37702c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -114,7 +114,7 @@ public final class NotificationRecord {
/** @deprecated Use {@link #getUser()} instead. */
public int getUserId() { return sbn.getUserId(); }
- void dump(PrintWriter pw, String prefix, Context baseContext) {
+ void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
final Notification notification = sbn.getNotification();
final Icon icon = notification.getSmallIcon();
String iconStr = String.valueOf(icon);
@@ -164,7 +164,7 @@ public final class NotificationRecord {
pw.println("null");
} else {
pw.print(val.getClass().getSimpleName());
- if (val instanceof CharSequence || val instanceof String) {
+ if (redact && (val instanceof CharSequence || val instanceof String)) {
// redact contents from bugreports
} else if (val instanceof Bitmap) {
pw.print(String.format(" (%dx%d)",
@@ -172,7 +172,14 @@ public final class NotificationRecord {
((Bitmap) val).getHeight()));
} else if (val.getClass().isArray()) {
final int N = Array.getLength(val);
- pw.println(" (" + N + ")");
+ pw.print(" (" + N + ")");
+ if (!redact) {
+ for (int j=0; j<N; j++) {
+ pw.println();
+ pw.print(String.format("%s [%d] %s",
+ prefix, j, String.valueOf(Array.get(val, j))));
+ }
+ }
} else {
pw.print(" (" + String.valueOf(val) + ")");
}
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index e3c6037..b76db41 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -29,7 +29,6 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
-import android.os.Debug;
import android.os.UserHandle;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
@@ -73,6 +72,7 @@ final class DefaultPermissionGrantPolicy {
static {
CONTACTS_PERMISSIONS.add(Manifest.permission.READ_CONTACTS);
CONTACTS_PERMISSIONS.add(Manifest.permission.WRITE_CONTACTS);
+ CONTACTS_PERMISSIONS.add(Manifest.permission.GET_ACCOUNTS);
}
private static final Set<String> LOCATION_PERMISSIONS = new ArraySet<>();
@@ -118,16 +118,6 @@ final class DefaultPermissionGrantPolicy {
STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
- private static final Set<String> ACCOUNTS_PERMISSIONS = new ArraySet<>();
- static {
- //ACCOUNTS_PERMISSIONS.add(Manifest.permission.GET_ACCOUNTS);
- }
-
- private static final Set<String> SETTINGS_PERMISSIONS = new ArraySet<>();
- static {
- SETTINGS_PERMISSIONS.add(Manifest.permission.WRITE_SETTINGS);
- }
-
private final PackageManagerService mService;
private PackagesProvider mImePackagesProvider;
@@ -161,7 +151,7 @@ final class DefaultPermissionGrantPolicy {
mDialerAppPackagesProvider = provider;
}
- public void setSyncAdapterPackagesProviderrLPw(SyncAdapterPackagesProvider provider) {
+ public void setSyncAdapterPackagesProviderLPw(SyncAdapterPackagesProvider provider) {
mSyncAdapterPackagesProvider = provider;
}
@@ -256,7 +246,7 @@ final class DefaultPermissionGrantPolicy {
// SetupWizard
Intent setupIntent = new Intent(Intent.ACTION_MAIN);
- setupIntent.addCategory(Intent.CATEGORY_HOME);
+ setupIntent.addCategory(Intent.CATEGORY_SETUP_WIZARD);
PackageParser.Package setupPackage = getDefaultSystemHandlerActivityPackageLPr(
setupIntent, userId);
if (setupPackage != null
@@ -358,7 +348,6 @@ final class DefaultPermissionGrantPolicy {
&& doesPackageSupportRuntimePermissions(calendarPackage)) {
grantRuntimePermissionsLPw(calendarPackage, CALENDAR_PERMISSIONS, userId);
grantRuntimePermissionsLPw(calendarPackage, CONTACTS_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(calendarPackage, ACCOUNTS_PERMISSIONS, userId);
}
// Calendar provider
@@ -368,14 +357,12 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(calendarProviderPackage, CONTACTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(calendarProviderPackage, CALENDAR_PERMISSIONS,
true, userId);
- grantRuntimePermissionsLPw(calendarProviderPackage, ACCOUNTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(calendarProviderPackage, STORAGE_PERMISSIONS, userId);
}
// Calendar provider sync adapters
List<PackageParser.Package> calendarSyncAdapters = getHeadlessSyncAdapterPackagesLPr(
- calendarSyncAdapterPackages,
- userId);
+ calendarSyncAdapterPackages, userId);
final int calendarSyncAdapterCount = calendarSyncAdapters.size();
for (int i = 0; i < calendarSyncAdapterCount; i++) {
PackageParser.Package calendarSyncAdapter = calendarSyncAdapters.get(i);
@@ -393,13 +380,11 @@ final class DefaultPermissionGrantPolicy {
&& doesPackageSupportRuntimePermissions(contactsPackage)) {
grantRuntimePermissionsLPw(contactsPackage, CONTACTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(contactsPackage, PHONE_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(contactsPackage, ACCOUNTS_PERMISSIONS, userId);
}
// Contacts provider sync adapters
List<PackageParser.Package> contactsSyncAdapters = getHeadlessSyncAdapterPackagesLPr(
- contactsSyncAdapterPackages,
- userId);
+ contactsSyncAdapterPackages, userId);
final int contactsSyncAdapterCount = contactsSyncAdapters.size();
for (int i = 0; i < contactsSyncAdapterCount; i++) {
PackageParser.Package contactsSyncAdapter = contactsSyncAdapters.get(i);
@@ -416,7 +401,6 @@ final class DefaultPermissionGrantPolicy {
true, userId);
grantRuntimePermissionsLPw(contactsProviderPackage, PHONE_PERMISSIONS,
true, userId);
- grantRuntimePermissionsLPw(contactsProviderPackage, ACCOUNTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(contactsProviderPackage, STORAGE_PERMISSIONS, userId);
}
@@ -427,7 +411,7 @@ final class DefaultPermissionGrantPolicy {
getDefaultSystemHandlerActivityPackageLPr(deviceProvisionIntent, userId);
if (deviceProvisionPackage != null
&& doesPackageSupportRuntimePermissions(deviceProvisionPackage)) {
- grantRuntimePermissionsLPw(deviceProvisionPackage, ACCOUNTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(deviceProvisionPackage, CONTACTS_PERMISSIONS, userId);
}
// Maps
@@ -628,10 +612,12 @@ final class DefaultPermissionGrantPolicy {
List<ResolveInfo> handlers = mService.mActivities.queryIntent(intent,
intent.resolveType(mService.mContext.getContentResolver()),
PackageManager.GET_DISABLED_COMPONENTS, userId);
+ if (handlers == null) {
+ return null;
+ }
final int handlerCount = handlers.size();
for (int i = 0; i < handlerCount; i++) {
ResolveInfo handler = handlers.get(i);
- // TODO: This is a temporary hack to figure out the setup app.
PackageParser.Package handlerPackage = getSystemPackageLPr(
handler.activityInfo.packageName);
if (handlerPackage != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ec40b74..f041d50 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -800,12 +800,9 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private static boolean hasValidDomains(ActivityIntentInfo filter) {
- boolean hasHTTPorHTTPS = filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
- filter.hasDataScheme(IntentFilter.SCHEME_HTTPS);
- if (!hasHTTPorHTTPS) {
- return false;
- }
- return true;
+ return filter.hasCategory(Intent.CATEGORY_BROWSABLE)
+ && (filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
+ filter.hasDataScheme(IntentFilter.SCHEME_HTTPS));
}
private IntentFilterVerifier mIntentFilterVerifier;
@@ -4434,9 +4431,7 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized(mPackages) {
CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
intent, resolvedType, 0, sourceUserId, parent.id);
- return xpDomainInfo != null
- && xpDomainInfo.bestDomainVerificationStatus !=
- INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+ return xpDomainInfo != null;
}
}
return false;
@@ -4593,6 +4588,11 @@ public class PackageManagerService extends IPackageManager.Stub {
result.bestDomainVerificationStatus);
}
}
+ // Don't consider matches with status NEVER across profiles.
+ if (result != null && result.bestDomainVerificationStatus
+ == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
+ return null;
+ }
return result;
}
@@ -4730,8 +4730,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
// Browser/generic handling case. If there's a default browser, go straight
// to that (but only if there is no other higher-priority match).
- final String defaultBrowserPackageName = getDefaultBrowserPackageName(
- UserHandle.myUserId());
+ final String defaultBrowserPackageName = getDefaultBrowserPackageName(userId);
int maxMatchPrio = 0;
ResolveInfo defaultBrowserMatch = null;
final int numCandidates = matchAllList.size();
@@ -9944,7 +9943,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (packageName != null) {
result |= updateIntentVerificationStatus(packageName,
PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS,
- UserHandle.myUserId());
+ userId);
mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultBrowserLPr(
packageName, userId);
}
@@ -10640,6 +10639,12 @@ public class PackageManagerService extends IPackageManager.Stub {
final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
receivers, verificationState);
+ // Apps installed for "all" users use the device owner to verify the app
+ UserHandle verifierUser = getUser();
+ if (verifierUser == UserHandle.ALL) {
+ verifierUser = UserHandle.OWNER;
+ }
+
/*
* If any sufficient verifiers were listed in the package
* manifest, attempt to ask them.
@@ -10655,8 +10660,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final Intent sufficientIntent = new Intent(verification);
sufficientIntent.setComponent(verifierComponent);
-
- mContext.sendBroadcastAsUser(sufficientIntent, getUser());
+ mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
}
}
}
@@ -10671,7 +10675,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* target BroadcastReceivers have run.
*/
verification.setComponent(requiredVerifierComponent);
- mContext.sendOrderedBroadcastAsUser(verification, getUser(),
+ mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
new BroadcastReceiver() {
@Override
@@ -15100,8 +15104,9 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (filters != null && filters.size() > 0) {
for (IntentFilter filter : filters) {
- if (filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
- filter.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
+ if (filter.hasCategory(Intent.CATEGORY_BROWSABLE)
+ && (filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
+ filter.hasDataScheme(IntentFilter.SCHEME_HTTPS))) {
result.addAll(filter.getHostsList());
}
}
@@ -16433,7 +16438,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider) {
synchronized (mPackages) {
- mDefaultPermissionPolicy.setSyncAdapterPackagesProviderrLPw(provider);
+ mDefaultPermissionPolicy.setSyncAdapterPackagesProviderLPw(provider);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 4faf75a..bbdfe31 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -238,6 +238,7 @@ abstract class PackageSettingBase extends SettingBase {
installStatus = base.installStatus;
keySetData = base.keySetData;
verificationInfo = base.verificationInfo;
+ installerPackageName = base.installerPackageName;
}
private PackageUserState modifyUserState(int userId) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9e41f70..13e075c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -126,6 +126,7 @@ import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -753,7 +754,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
synchronized (mLock) {
if (shouldEnableWakeGestureLp()) {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
- wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture);
+ wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
+ "android.policy:GESTURE");
}
}
}
@@ -1874,21 +1876,33 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (permission != null) {
if (permission == android.Manifest.permission.SYSTEM_ALERT_WINDOW) {
final int callingUid = Binder.getCallingUid();
- // check if this is a system uid first before bothering with
- // obtaining package name
+ // system processes will be automatically allowed privilege to draw
if (callingUid == Process.SYSTEM_UID) {
return WindowManagerGlobal.ADD_OKAY;
}
+ // check if user has enabled this operation. SecurityException will be thrown if
+ // this app has not been allowed by the user
final int mode = mAppOpsManager.checkOp(outAppOp[0], callingUid,
attrs.packageName);
- if (mode == AppOpsManager.MODE_DEFAULT) {
- if (mContext.checkCallingPermission(permission) !=
- PackageManager.PERMISSION_GRANTED) {
+ switch (mode) {
+ case AppOpsManager.MODE_ALLOWED:
+ case AppOpsManager.MODE_IGNORED:
+ // although we return ADD_OKAY for MODE_IGNORED, the added window will
+ // actually be hidden in WindowManagerService
+ return WindowManagerGlobal.ADD_OKAY;
+ case AppOpsManager.MODE_ERRORED:
return WindowManagerGlobal.ADD_PERMISSION_DENIED;
- }
+ default:
+ // in the default mode, we will make a decision here based on
+ // checkCallingPermission()
+ if (mContext.checkCallingPermission(permission) !=
+ PackageManager.PERMISSION_GRANTED) {
+ return WindowManagerGlobal.ADD_PERMISSION_DENIED;
+ } else {
+ return WindowManagerGlobal.ADD_OKAY;
+ }
}
- return WindowManagerGlobal.ADD_OKAY;
}
if (mContext.checkCallingOrSelfPermission(permission)
@@ -4691,7 +4705,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateRotation(true);
if (lidOpen) {
- wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch);
+ wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
+ "android.policy:LID");
} else if (!mLidControlsSleep) {
mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
}
@@ -4713,7 +4728,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
}
- wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens);
+ wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
+ "android.policy:CAMERA_COVER");
startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
}
mCameraLensCoverState = lensCoverState;
@@ -4892,7 +4908,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
if (isWakeKey) {
- wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
@@ -5123,7 +5139,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (isWakeKey) {
- wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
@@ -5184,7 +5200,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
if ((policyFlags & FLAG_WAKE) != 0) {
- if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion)) {
+ if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
+ "android.policy:MOTION")) {
return 0;
}
}
@@ -5197,7 +5214,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// there will be no dream to intercept the touch and wake into ambient. The device should
// wake up in this case.
if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
- wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming);
+ wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
+ "android.policy:MOTION");
}
return 0;
@@ -5493,10 +5511,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void wakeUpFromPowerKey(long eventTime) {
- wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
+ wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
}
- private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
+ private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
final boolean theaterModeEnabled = isTheaterModeEnabled();
if (!wakeInTheaterMode && theaterModeEnabled) {
return false;
@@ -5507,7 +5525,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Global.THEATER_MODE_ON, 0);
}
- mPowerManager.wakeUp(wakeTime);
+ mPowerManager.wakeUp(wakeTime, reason);
return true;
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index d21c6d2..c5ad7fe 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -472,6 +472,26 @@ final class Notifier {
}
/**
+ * Called when the screen has turned on.
+ */
+ public void onWakeUp(String reason, int reasonUid, String opPackageName, int opUid) {
+ if (DEBUG) {
+ Slog.d(TAG, "onWakeUp: event=" + reason + ", reasonUid=" + reasonUid
+ + " opPackageName=" + opPackageName + " opUid=" + opUid);
+ }
+
+ try {
+ mBatteryStats.noteWakeUp(reason, reasonUid);
+ if (opPackageName != null) {
+ mAppOps.noteOperation(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
+ }
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+
+ }
+
+ /**
* Called when wireless charging has started so as to provide user feedback.
*/
public void onWirelessChargingStarted() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 3f59755..88476ce 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -830,7 +830,18 @@ public final class PowerManagerService extends SystemService
private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock, int uid) {
if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0
&& isScreenLock(wakeLock)) {
- wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), uid);
+ String opPackageName;
+ int opUid;
+ if (wakeLock.mWorkSource != null && wakeLock.mWorkSource.getName(0) != null) {
+ opPackageName = wakeLock.mWorkSource.getName(0);
+ opUid = wakeLock.mWorkSource.get(0);
+ } else {
+ opPackageName = wakeLock.mPackageName;
+ opUid = wakeLock.mWorkSource != null ? wakeLock.mWorkSource.get(0)
+ : wakeLock.mOwnerUid;
+ }
+ wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), wakeLock.mTag, opUid,
+ opPackageName, opUid);
}
}
@@ -1042,17 +1053,19 @@ public final class PowerManagerService extends SystemService
return false;
}
- private void wakeUpInternal(long eventTime, int uid) {
+ private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,
+ int opUid) {
synchronized (mLock) {
- if (wakeUpNoUpdateLocked(eventTime, uid)) {
+ if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {
updatePowerStateLocked();
}
}
}
- private boolean wakeUpNoUpdateLocked(long eventTime, int uid) {
+ private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
+ String opPackageName, int opUid) {
if (DEBUG_SPEW) {
- Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
+ Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid);
}
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
@@ -1064,21 +1077,22 @@ public final class PowerManagerService extends SystemService
try {
switch (mWakefulness) {
case WAKEFULNESS_ASLEEP:
- Slog.i(TAG, "Waking up from sleep (uid " + uid +")...");
+ Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")...");
break;
case WAKEFULNESS_DREAMING:
- Slog.i(TAG, "Waking up from dream (uid " + uid +")...");
+ Slog.i(TAG, "Waking up from dream (uid " + reasonUid +")...");
break;
case WAKEFULNESS_DOZING:
- Slog.i(TAG, "Waking up from dozing (uid " + uid +")...");
+ Slog.i(TAG, "Waking up from dozing (uid " + reasonUid +")...");
break;
}
mLastWakeTime = eventTime;
setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
+ mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
userActivityNoUpdateLocked(
- eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
+ eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
@@ -1334,7 +1348,8 @@ public final class PowerManagerService extends SystemService
final long now = SystemClock.uptimeMillis();
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
dockedOnWirelessCharger)) {
- wakeUpNoUpdateLocked(now, Process.SYSTEM_UID);
+ wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,
+ mContext.getOpPackageName(), Process.SYSTEM_UID);
}
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
@@ -1788,7 +1803,8 @@ public final class PowerManagerService extends SystemService
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
} else {
- wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
+ wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",
+ Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);
updatePowerStateLocked();
}
} else if (wakefulness == WAKEFULNESS_DOZING) {
@@ -3136,7 +3152,7 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
- public void wakeUp(long eventTime) {
+ public void wakeUp(long eventTime, String reason, String opPackageName) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -3147,7 +3163,7 @@ public final class PowerManagerService extends SystemService
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
- wakeUpInternal(eventTime, uid);
+ wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ec566bc..c776e8f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2543,8 +2543,10 @@ public class WindowManagerService extends IWindowManager.Stub
win.attach();
mWindowMap.put(client.asBinder(), win);
if (win.mAppOp != AppOpsManager.OP_NONE) {
- if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
- != AppOpsManager.MODE_ALLOWED) {
+ int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(),
+ win.getOwningPackage());
+ if ((startOpResult != AppOpsManager.MODE_ALLOWED) &&
+ (startOpResult != AppOpsManager.MODE_DEFAULT)) {
win.setAppOpVisibilityLw(false);
}
}
@@ -2728,10 +2730,10 @@ public class WindowManagerService extends IWindowManager.Stub
wasVisible = win.isWinVisibleLw();
if (wasVisible) {
- int transit = WindowManagerPolicy.TRANSIT_EXIT;
- if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
- transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
- }
+ final int transit = (!startingWindow)
+ ? WindowManagerPolicy.TRANSIT_EXIT
+ : WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
+
// Try starting an animation.
if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
win.mExiting = true;
@@ -2743,12 +2745,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
final AppWindowToken appToken = win.mAppToken;
+ final boolean isAnimating = win.mWinAnimator.isAnimating();
// The starting window is the last window in this app token and it isn't animating.
// Allow it to be removed now as there is no additional window or animation that will
// trigger its removal.
final boolean lastWinStartingNotAnimating = startingWindow && appToken!= null
- && appToken.allAppWindows.size() == 1 && !win.mWinAnimator.isAnimating();
- if (!lastWinStartingNotAnimating && (win.mExiting || win.mWinAnimator.isAnimating())) {
+ && appToken.allAppWindows.size() == 1 && !isAnimating;
+ if (!lastWinStartingNotAnimating && (win.mExiting || isAnimating)) {
// The exit animation is running... wait for it!
win.mExiting = true;
win.mRemoveOnExit = true;
@@ -2899,7 +2902,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.mAppOp != AppOpsManager.OP_NONE) {
final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
win.getOwningPackage());
- win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
+ win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
+ mode == AppOpsManager.MODE_DEFAULT);
}
}
}
@@ -4524,7 +4528,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
wtoken.willBeHidden = false;
- if (wtoken.hidden == visible) {
+ // Allow for state changes and animation to be applied if token is transitioning
+ // visibility state or the token was marked as hidden and is exiting before we had a chance
+ // to play the transition animation.
+ if (wtoken.hidden == visible || (wtoken.hidden && wtoken.mIsExiting)) {
boolean changed = false;
if (DEBUG_APP_TRANSITIONS) Slog.v(
TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
@@ -10307,7 +10314,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_VISIBILITY || DEBUG_POWER) {
Slog.v(TAG, "Turning screen on after layout!");
}
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.wm:TURN_ON");
}
mTurnOnScreen = false;
}
diff --git a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
index ffd1568..757f1c6 100644
--- a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
+++ b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
@@ -139,6 +139,11 @@ public class BroadcastInterceptingContext extends ContextWrapper {
}
@Override
+ public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
+ sendBroadcast(intent);
+ }
+
+ @Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
sendBroadcast(intent);
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index c49a5f9..b0a14c8 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1177,7 +1177,11 @@ public class UsageStatsService extends SystemService implements
@Override
public void whitelistAppTemporarily(String packageName, long duration, int userId)
throws RemoteException {
- mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId);
+ StringBuilder reason = new StringBuilder(32);
+ reason.append("from:");
+ UserHandle.formatUid(reason, Binder.getCallingUid());
+ mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId,
+ reason.toString());
}
@Override
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 638783d..31763e7 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -35,6 +35,7 @@ import android.util.Slog;
import com.android.internal.alsa.AlsaCardsParser;
import com.android.internal.alsa.AlsaDevicesParser;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.audio.AudioService;
import libcore.io.IoUtils;
@@ -502,14 +503,14 @@ public final class UsbAlsaManager {
//
// Logging
//
- public void dump(FileDescriptor fd, PrintWriter pw) {
- pw.println(" USB Audio Devices:");
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("USB Audio Devices:");
for (UsbDevice device : mAudioDevices.keySet()) {
- pw.println(" " + device.getDeviceName() + ": " + mAudioDevices.get(device));
+ pw.println(" " + device.getDeviceName() + ": " + mAudioDevices.get(device));
}
- pw.println(" USB MIDI Devices:");
+ pw.println("USB MIDI Devices:");
for (UsbDevice device : mMidiDevices.keySet()) {
- pw.println(" " + device.getDeviceName() + ": " + mMidiDevices.get(device));
+ pw.println(" " + device.getDeviceName() + ": " + mMidiDevices.get(device));
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index 9a04e8b..ae17fde 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -38,6 +38,7 @@ import android.util.Base64;
import android.util.Slog;
import com.android.internal.R;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
import java.io.File;
@@ -451,17 +452,17 @@ public class UsbDebuggingManager {
mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_CLEAR);
}
- public void dump(FileDescriptor fd, PrintWriter pw) {
- pw.println(" USB Debugging State:");
- pw.println(" Connected to adbd: " + (mThread != null));
- pw.println(" Last key received: " + mFingerprints);
- pw.println(" User keys:");
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("USB Debugging State:");
+ pw.println(" Connected to adbd: " + (mThread != null));
+ pw.println(" Last key received: " + mFingerprints);
+ pw.println(" User keys:");
try {
pw.println(FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
} catch (IOException e) {
pw.println("IOException: " + e);
}
- pw.println(" System keys:");
+ pw.println(" System keys:");
try {
pw.println(FileUtils.readTextFile(new File("/adb_keys"), 0, null));
} catch (IOException e) {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 81b4857..653cbd8 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -45,6 +45,7 @@ import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
import java.io.File;
@@ -807,17 +808,17 @@ public class UsbDeviceManager {
UsbManager.USB_FUNCTION_ADB);
}
- public void dump(FileDescriptor fd, PrintWriter pw) {
- pw.println(" USB Device State:");
- pw.println(" mCurrentFunctions: " + mCurrentFunctions);
- pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
- pw.println(" mConnected: " + mConnected);
- pw.println(" mConfigured: " + mConfigured);
- pw.println(" mCurrentAccessory: " + mCurrentAccessory);
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("USB Device State:");
+ pw.println(" mCurrentFunctions: " + mCurrentFunctions);
+ pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
+ pw.println(" mConnected: " + mConnected);
+ pw.println(" mConfigured: " + mConfigured);
+ pw.println(" mCurrentAccessory: " + mCurrentAccessory);
try {
- pw.println(" Kernel state: "
+ pw.println(" Kernel state: "
+ FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
- pw.println(" Kernel function list: "
+ pw.println(" Kernel function list: "
+ FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
} catch (IOException e) {
pw.println("IOException: " + e);
@@ -908,12 +909,12 @@ public class UsbDeviceManager {
}
}
- public void dump(FileDescriptor fd, PrintWriter pw) {
+ public void dump(IndentingPrintWriter pw) {
if (mHandler != null) {
- mHandler.dump(fd, pw);
+ mHandler.dump(pw);
}
if (mDebuggingManager != null) {
- mDebuggingManager.dump(fd, pw);
+ mDebuggingManager.dump(pw);
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index f5f2b07..6300a9a 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -27,6 +27,7 @@ import android.os.ParcelFileDescriptor;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -283,11 +284,11 @@ public class UsbHostManager {
}
}
- public void dump(FileDescriptor fd, PrintWriter pw) {
+ public void dump(IndentingPrintWriter pw) {
synchronized (mLock) {
- pw.println(" USB Host State:");
+ pw.println("USB Host State:");
for (String name : mDevices.keySet()) {
- pw.println(" " + name + ": " + mDevices.get(name));
+ pw.println(" " + name + ": " + mDevices.get(name));
}
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
new file mode 100644
index 0000000..52abcfe
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2015 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 com.android.server.usb;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.FgThread;
+
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.usb.UsbManager;
+import android.hardware.usb.UsbPort;
+import android.hardware.usb.UsbPortStatus;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UEventObserver;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import libcore.io.IoUtils;
+
+/**
+ * Allows trusted components to control the properties of physical USB ports
+ * via the "/sys/class/dual_role_usb" kernel interface.
+ * <p>
+ * Note: This interface may not be supported on all chipsets since the USB drivers
+ * must be changed to publish this information through the module. At the moment
+ * we only need this for devices with USB Type C ports to allow the System UI to
+ * control USB charging and data direction. On devices that do not support this
+ * interface the list of ports may incorrectly appear to be empty
+ * (but we don't care today).
+ * </p>
+ */
+public class UsbPortManager {
+ private static final String TAG = "UsbPortManager";
+
+ private static final int MSG_UPDATE_PORTS = 1;
+
+ // UEvent path to watch.
+ private static final String UEVENT_FILTER = "SUBSYSTEM=dual_role_usb";
+
+ // SysFS directory that contains USB ports as subdirectories.
+ private static final String SYSFS_CLASS = "/sys/class/dual_role_usb";
+
+ // SysFS file that contains a USB port's supported modes. (read-only)
+ // Contents: "", "ufp", "dfp", or "ufp dfp".
+ private static final String SYSFS_PORT_SUPPORTED_MODES = "supported_modes";
+
+ // SysFS file that contains a USB port's current mode. (read-write if configurable)
+ // Contents: "", "ufp", or "dfp".
+ private static final String SYSFS_PORT_MODE = "mode";
+
+ // SysFS file that contains a USB port's current power role. (read-write if configurable)
+ // Contents: "", "source", or "sink".
+ private static final String SYSFS_PORT_POWER_ROLE = "power_role";
+
+ // SysFS file that contains a USB port's current data role. (read-write if configurable)
+ // Contents: "", "host", or "device".
+ private static final String SYSFS_PORT_DATA_ROLE = "data_role";
+
+ // Port modes: upstream facing port or downstream facing port.
+ private static final String PORT_MODE_DFP = "dfp";
+ private static final String PORT_MODE_UFP = "ufp";
+
+ // Port power roles: source or sink.
+ private static final String PORT_POWER_ROLE_SOURCE = "source";
+ private static final String PORT_POWER_ROLE_SINK = "sink";
+
+ // Port data roles: host or device.
+ private static final String PORT_DATA_ROLE_HOST = "host";
+ private static final String PORT_DATA_ROLE_DEVICE = "device";
+
+ // All non-trivial role combinations.
+ private static final int COMBO_SOURCE_HOST =
+ UsbPort.combineRolesAsBit(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+ private static final int COMBO_SOURCE_DEVICE =
+ UsbPort.combineRolesAsBit(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE);
+ private static final int COMBO_SINK_HOST =
+ UsbPort.combineRolesAsBit(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST);
+ private static final int COMBO_SINK_DEVICE =
+ UsbPort.combineRolesAsBit(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+
+ // The system context.
+ private final Context mContext;
+
+ // True if we have kernel support.
+ private final boolean mHaveKernelSupport;
+
+ // Mutex for all mutable shared state.
+ private final Object mLock = new Object();
+
+ // List of all ports, indexed by id.
+ // Ports may temporarily have different dispositions as they are added or removed
+ // but the class invariant is that this list will only contain ports with DISPOSITION_READY
+ // except while updatePortsLocked() is in progress.
+ private final ArrayMap<String, PortInfo> mPorts = new ArrayMap<String, PortInfo>();
+
+ // List of all simulated ports, indexed by id.
+ private final ArrayMap<String, SimulatedPortInfo> mSimulatedPorts =
+ new ArrayMap<String, SimulatedPortInfo>();
+
+ public UsbPortManager(Context context) {
+ mContext = context;
+ mHaveKernelSupport = new File(SYSFS_CLASS).exists();
+ }
+
+ public void systemReady() {
+ mUEventObserver.startObserving(UEVENT_FILTER);
+ scheduleUpdatePorts();
+ }
+
+ public UsbPort[] getPorts() {
+ synchronized (mLock) {
+ final int count = mPorts.size();
+ final UsbPort[] result = new UsbPort[count];
+ for (int i = 0; i < count; i++) {
+ result[i] = mPorts.valueAt(i).mUsbPort;
+ }
+ return result;
+ }
+ }
+
+ public UsbPortStatus getPortStatus(String portId) {
+ synchronized (mLock) {
+ final PortInfo portInfo = mPorts.get(portId);
+ return portInfo != null ? portInfo.mUsbPortStatus : null;
+ }
+ }
+
+ public void setPortRoles(String portId, int newPowerRole, int newDataRole,
+ IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ final PortInfo portInfo = mPorts.get(portId);
+ if (portInfo == null) {
+ if (pw != null) {
+ pw.println("No such USB port: " + portId);
+ }
+ return;
+ }
+
+ // Check whether the new role is actually supported.
+ if (!portInfo.mUsbPortStatus.isRoleCombinationSupported(newPowerRole, newDataRole)) {
+ logAndPrint(Log.ERROR, pw, "Attempted to set USB port into unsupported "
+ + "role combination: portId=" + portId
+ + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
+ + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole));
+ return;
+ }
+
+ // Check whether anything actually changed.
+ final int currentDataRole = portInfo.mUsbPortStatus.getCurrentDataRole();
+ final int currentPowerRole = portInfo.mUsbPortStatus.getCurrentPowerRole();
+ if (currentDataRole == newDataRole && currentPowerRole == newPowerRole) {
+ if (pw != null) {
+ pw.println("No change.");
+ }
+ return;
+ }
+
+ // Determine whether we need to change the mode in order to accomplish this goal.
+ // We prefer not to do this since it's more likely to fail.
+ //
+ // Note: Arguably it might be worth allowing the client to influence this policy
+ // decision so that we could show more powerful developer facing UI but let's
+ // see how far we can get without having to do that.
+ final boolean canChangeMode = portInfo.mCanChangeMode;
+ final boolean canChangePowerRole = portInfo.mCanChangePowerRole;
+ final boolean canChangeDataRole = portInfo.mCanChangeDataRole;
+ final int currentMode = portInfo.mUsbPortStatus.getCurrentMode();
+ final int newMode;
+ if ((!canChangePowerRole && currentPowerRole != newPowerRole)
+ || (!canChangeDataRole && currentDataRole != newDataRole)) {
+ if (canChangeMode && newPowerRole == UsbPort.POWER_ROLE_SOURCE
+ && newDataRole == UsbPort.DATA_ROLE_HOST) {
+ newMode = UsbPort.MODE_DFP;
+ } else if (canChangeMode && newPowerRole == UsbPort.POWER_ROLE_SINK
+ && newDataRole == UsbPort.DATA_ROLE_DEVICE) {
+ newMode = UsbPort.MODE_UFP;
+ } else {
+ logAndPrint(Log.ERROR, pw, "Found mismatch in supported USB role combinations "
+ + "while attempting to change role: " + portInfo
+ + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
+ + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole));
+ return;
+ }
+ } else {
+ newMode = currentMode;
+ }
+
+ // Make it happen.
+ logAndPrint(Log.INFO, pw, "Setting USB port mode and role: portId=" + portId
+ + ", currentMode=" + UsbPort.modeToString(currentMode)
+ + ", currentPowerRole=" + UsbPort.powerRoleToString(currentPowerRole)
+ + ", currentDataRole=" + UsbPort.dataRoleToString(currentDataRole)
+ + ", newMode=" + UsbPort.modeToString(newMode)
+ + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
+ + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole));
+
+ SimulatedPortInfo sim = mSimulatedPorts.get(portId);
+ if (sim != null) {
+ // Change simulated state.
+ sim.mCurrentMode = newMode;
+ sim.mCurrentPowerRole = newPowerRole;
+ sim.mCurrentDataRole = newDataRole;
+ } else if (mHaveKernelSupport) {
+ // Change actual state.
+ final File portDir = new File(SYSFS_CLASS, portId);
+ if (!portDir.exists()) {
+ logAndPrint(Log.ERROR, pw, "USB port not found: portId=" + portId);
+ return;
+ }
+
+ if (currentMode != newMode) {
+ // Changing the mode will have the side-effect of also changing
+ // the power and data roles but it might take some time to apply
+ // and the renegotiation might fail. Due to limitations of the USB
+ // hardware, we have no way of knowing whether it will work apriori
+ // which is why we would prefer to set the power and data roles
+ // directly instead.
+ if (!writeFile(portDir, SYSFS_PORT_MODE,
+ newMode == UsbPort.MODE_DFP ? PORT_MODE_DFP : PORT_MODE_UFP)) {
+ logAndPrint(Log.ERROR, pw, "Failed to set the USB port mode: "
+ + "portId=" + portId
+ + ", newMode=" + UsbPort.modeToString(newMode));
+ return;
+ }
+ } else {
+ // Change power and data role independently as needed.
+ if (currentPowerRole != newPowerRole) {
+ if (!writeFile(portDir, SYSFS_PORT_POWER_ROLE,
+ newPowerRole == UsbPort.POWER_ROLE_SOURCE
+ ? PORT_POWER_ROLE_SOURCE : PORT_POWER_ROLE_SINK)) {
+ logAndPrint(Log.ERROR, pw, "Failed to set the USB port power role: "
+ + "portId=" + portId
+ + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole));
+ return;
+ }
+ }
+ if (currentDataRole != newDataRole) {
+ if (!writeFile(portDir, SYSFS_PORT_DATA_ROLE,
+ newDataRole == UsbPort.DATA_ROLE_HOST
+ ? PORT_DATA_ROLE_HOST : PORT_DATA_ROLE_DEVICE)) {
+ logAndPrint(Log.ERROR, pw, "Failed to set the USB port data role: "
+ + "portId=" + portId
+ + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole));
+ return;
+ }
+ }
+ }
+ }
+ updatePortsLocked(pw);
+ }
+ }
+
+ public void addSimulatedPort(String portId, int supportedModes, IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ if (mSimulatedPorts.containsKey(portId)) {
+ pw.println("Port with same name already exists. Please remove it first.");
+ return;
+ }
+
+ pw.println("Adding simulated port: portId=" + portId
+ + ", supportedModes=" + UsbPort.modeToString(supportedModes));
+ mSimulatedPorts.put(portId,
+ new SimulatedPortInfo(portId, supportedModes));
+ updatePortsLocked(pw);
+ }
+ }
+
+ public void connectSimulatedPort(String portId, int mode, boolean canChangeMode,
+ int powerRole, boolean canChangePowerRole,
+ int dataRole, boolean canChangeDataRole, IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ final SimulatedPortInfo portInfo = mSimulatedPorts.get(portId);
+ if (portInfo == null) {
+ pw.println("Cannot connect simulated port which does not exist.");
+ return;
+ }
+
+ if (mode == 0 || powerRole == 0 || dataRole == 0) {
+ pw.println("Cannot connect simulated port in null mode, "
+ + "power role, or data role.");
+ return;
+ }
+
+ if ((portInfo.mSupportedModes & mode) == 0) {
+ pw.println("Simulated port does not support mode: " + UsbPort.modeToString(mode));
+ return;
+ }
+
+ pw.println("Connecting simulated port: portId=" + portId
+ + ", mode=" + UsbPort.modeToString(mode)
+ + ", canChangeMode=" + canChangeMode
+ + ", powerRole=" + UsbPort.powerRoleToString(powerRole)
+ + ", canChangePowerRole=" + canChangePowerRole
+ + ", dataRole=" + UsbPort.dataRoleToString(dataRole)
+ + ", canChangeDataRole=" + canChangeDataRole);
+ portInfo.mCurrentMode = mode;
+ portInfo.mCanChangeMode = canChangeMode;
+ portInfo.mCurrentPowerRole = powerRole;
+ portInfo.mCanChangePowerRole = canChangePowerRole;
+ portInfo.mCurrentDataRole = dataRole;
+ portInfo.mCanChangeDataRole = canChangeDataRole;
+ updatePortsLocked(pw);
+ }
+ }
+
+ public void disconnectSimulatedPort(String portId, IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ final SimulatedPortInfo portInfo = mSimulatedPorts.get(portId);
+ if (portInfo == null) {
+ pw.println("Cannot disconnect simulated port which does not exist.");
+ return;
+ }
+
+ pw.println("Disconnecting simulated port: portId=" + portId);
+ portInfo.mCurrentMode = 0;
+ portInfo.mCanChangeMode = false;
+ portInfo.mCurrentPowerRole = 0;
+ portInfo.mCanChangePowerRole = false;
+ portInfo.mCurrentDataRole = 0;
+ portInfo.mCanChangeDataRole = false;
+ updatePortsLocked(pw);
+ }
+ }
+
+ public void removeSimulatedPort(String portId, IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ final int index = mSimulatedPorts.indexOfKey(portId);
+ if (index < 0) {
+ pw.println("Cannot remove simulated port which does not exist.");
+ return;
+ }
+
+ pw.println("Disconnecting simulated port: portId=" + portId);
+ mSimulatedPorts.removeAt(index);
+ updatePortsLocked(pw);
+ }
+ }
+
+ public void resetSimulation(IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ pw.println("Removing all simulated ports and ending simulation.");
+ if (!mSimulatedPorts.isEmpty()) {
+ mSimulatedPorts.clear();
+ updatePortsLocked(pw);
+ }
+ }
+ }
+
+ public void dump(IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ pw.print("USB Port State:");
+ if (!mSimulatedPorts.isEmpty()) {
+ pw.print(" (simulation active; end with 'dumpsys usb reset')");
+ }
+ pw.println();
+
+ if (mPorts.isEmpty()) {
+ pw.println(" <no ports>");
+ } else {
+ for (PortInfo portInfo : mPorts.values()) {
+ pw.println(" " + portInfo.mUsbPort.getId() + ": " + portInfo);
+ }
+ }
+ }
+ }
+
+ private void updatePortsLocked(IndentingPrintWriter pw) {
+ // Assume all ports are gone unless informed otherwise.
+ // Kind of pessimistic but simple.
+ for (int i = mPorts.size(); i-- > 0; ) {
+ mPorts.valueAt(i).mDisposition = PortInfo.DISPOSITION_REMOVED;
+ }
+
+ // Enumerate all extant ports.
+ if (!mSimulatedPorts.isEmpty()) {
+ final int count = mSimulatedPorts.size();
+ for (int i = 0; i < count; i++) {
+ final SimulatedPortInfo portInfo = mSimulatedPorts.valueAt(i);
+ addOrUpdatePortLocked(portInfo.mPortId, portInfo.mSupportedModes,
+ portInfo.mCurrentMode, portInfo.mCanChangeMode,
+ portInfo.mCurrentPowerRole, portInfo.mCanChangePowerRole,
+ portInfo.mCurrentDataRole, portInfo.mCanChangeDataRole, pw);
+ }
+ } else if (mHaveKernelSupport) {
+ final File[] portDirs = new File(SYSFS_CLASS).listFiles();
+ if (portDirs != null) {
+ for (File portDir : portDirs) {
+ if (!portDir.isDirectory()) {
+ continue;
+ }
+
+ // Parse the sysfs file contents.
+ final String portId = portDir.getName();
+ final int supportedModes = readSupportedModes(portDir);
+ final int currentMode = readCurrentMode(portDir);
+ final boolean canChangeMode = canChangeMode(portDir);
+ final int currentPowerRole = readCurrentPowerRole(portDir);
+ final boolean canChangePowerRole = canChangePowerRole(portDir);
+ final int currentDataRole = readCurrentDataRole(portDir);
+ final boolean canChangeDataRole = canChangeDataRole(portDir);
+ addOrUpdatePortLocked(portId, supportedModes,
+ currentMode, canChangeMode,
+ currentPowerRole, canChangePowerRole,
+ currentDataRole, canChangeDataRole, pw);
+ }
+ }
+ }
+
+ // Process the updates.
+ // Once finished, the list of ports will only contain ports in DISPOSITION_READY.
+ for (int i = mPorts.size(); i-- > 0; ) {
+ final PortInfo portInfo = mPorts.valueAt(i);
+ switch (portInfo.mDisposition) {
+ case PortInfo.DISPOSITION_ADDED:
+ handlePortAddedLocked(portInfo, pw);
+ portInfo.mDisposition = PortInfo.DISPOSITION_READY;
+ break;
+ case PortInfo.DISPOSITION_CHANGED:
+ handlePortChangedLocked(portInfo, pw);
+ portInfo.mDisposition = PortInfo.DISPOSITION_READY;
+ break;
+ case PortInfo.DISPOSITION_REMOVED:
+ mPorts.removeAt(i);
+ portInfo.mUsbPortStatus = null; // must do this early
+ handlePortRemovedLocked(portInfo, pw);
+ break;
+ }
+ }
+ }
+
+ // Must only be called by updatePortsLocked.
+ private void addOrUpdatePortLocked(String portId, int supportedModes,
+ int currentMode, boolean canChangeMode,
+ int currentPowerRole, boolean canChangePowerRole,
+ int currentDataRole, boolean canChangeDataRole,
+ IndentingPrintWriter pw) {
+ // Only allow mode switch capability for dual role ports.
+ // Validate that the current mode matches the supported modes we expect.
+ if (supportedModes != UsbPort.MODE_DUAL) {
+ canChangeMode = false;
+ if (currentMode != 0 && currentMode != supportedModes) {
+ logAndPrint(Log.WARN, pw, "Ignoring inconsistent current mode from USB "
+ + "port driver: supportedModes=" + UsbPort.modeToString(supportedModes)
+ + ", currentMode=" + UsbPort.modeToString(currentMode));
+ currentMode = 0;
+ }
+ }
+
+ // Determine the supported role combinations.
+ // Note that the policy is designed to prefer setting the power and data
+ // role independently rather than changing the mode.
+ int supportedRoleCombinations = UsbPort.combineRolesAsBit(
+ currentPowerRole, currentDataRole);
+ if (currentMode != 0 && currentPowerRole != 0 && currentDataRole != 0) {
+ if (canChangePowerRole && canChangeDataRole) {
+ // Can change both power and data role independently.
+ // Assume all combinations are possible.
+ supportedRoleCombinations |=
+ COMBO_SOURCE_HOST | COMBO_SOURCE_DEVICE
+ | COMBO_SINK_HOST | COMBO_SINK_DEVICE;
+ } else if (canChangePowerRole) {
+ // Can only change power role.
+ // Assume data role must remain at its current value.
+ supportedRoleCombinations |= UsbPort.combineRolesAsBit(
+ UsbPort.POWER_ROLE_SOURCE, currentDataRole);
+ supportedRoleCombinations |= UsbPort.combineRolesAsBit(
+ UsbPort.POWER_ROLE_SINK, currentDataRole);
+ } else if (canChangeDataRole) {
+ // Can only change data role.
+ // Assume power role must remain at its current value.
+ supportedRoleCombinations |= UsbPort.combineRolesAsBit(
+ currentPowerRole, UsbPort.DATA_ROLE_HOST);
+ supportedRoleCombinations |= UsbPort.combineRolesAsBit(
+ currentPowerRole, UsbPort.DATA_ROLE_DEVICE);
+ } else if (canChangeMode) {
+ // Can only change the mode.
+ // Assume both standard UFP and DFP configurations will become available
+ // when this happens.
+ supportedRoleCombinations |= COMBO_SOURCE_HOST | COMBO_SINK_DEVICE;
+ }
+ }
+
+ // Update the port data structures.
+ PortInfo portInfo = mPorts.get(portId);
+ if (portInfo == null) {
+ portInfo = new PortInfo(portId, supportedModes);
+ portInfo.setStatus(currentMode, canChangeMode,
+ currentPowerRole, canChangePowerRole,
+ currentDataRole, canChangeDataRole,
+ supportedRoleCombinations);
+ mPorts.put(portId, portInfo);
+ } else {
+ // Sanity check that ports aren't changing definition out from under us.
+ if (supportedModes != portInfo.mUsbPort.getSupportedModes()) {
+ logAndPrint(Log.WARN, pw, "Ignoring inconsistent list of supported modes from "
+ + "USB port driver (should be immutable): "
+ + "previous=" + UsbPort.modeToString(
+ portInfo.mUsbPort.getSupportedModes())
+ + ", current=" + UsbPort.modeToString(supportedModes));
+ }
+
+ if (portInfo.setStatus(currentMode, canChangeMode,
+ currentPowerRole, canChangePowerRole,
+ currentDataRole, canChangeDataRole,
+ supportedRoleCombinations)) {
+ portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
+ } else {
+ portInfo.mDisposition = PortInfo.DISPOSITION_READY;
+ }
+ }
+ }
+
+ private void handlePortAddedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
+ logAndPrint(Log.INFO, pw, "USB port added: " + portInfo);
+ sendPortChangedBroadcastLocked(portInfo);
+ }
+
+ private void handlePortChangedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
+ logAndPrint(Log.INFO, pw, "USB port changed: " + portInfo);
+ sendPortChangedBroadcastLocked(portInfo);
+ }
+
+ private void handlePortRemovedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
+ logAndPrint(Log.INFO, pw, "USB port removed: " + portInfo);
+ sendPortChangedBroadcastLocked(portInfo);
+ }
+
+ private void sendPortChangedBroadcastLocked(PortInfo portInfo) {
+ final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(UsbManager.EXTRA_PORT, portInfo.mUsbPort);
+ intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);
+
+ // Guard against possible reentrance by posting the broadcast from the handler
+ // instead of from within the critical section.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+ });
+ }
+
+ private void scheduleUpdatePorts() {
+ if (!mHandler.hasMessages(MSG_UPDATE_PORTS)) {
+ mHandler.sendEmptyMessage(MSG_UPDATE_PORTS);
+ }
+ }
+
+ private static int readSupportedModes(File portDir) {
+ int modes = 0;
+ final String contents = readFile(portDir, SYSFS_PORT_SUPPORTED_MODES);
+ if (contents != null) {
+ if (contents.contains(PORT_MODE_DFP)) {
+ modes |= UsbPort.MODE_DFP;
+ }
+ if (contents.contains(PORT_MODE_UFP)) {
+ modes |= UsbPort.MODE_UFP;
+ }
+ }
+ return modes;
+ }
+
+ private static int readCurrentMode(File portDir) {
+ final String contents = readFile(portDir, SYSFS_PORT_MODE);
+ if (contents != null) {
+ if (contents.equals(PORT_MODE_DFP)) {
+ return UsbPort.MODE_DFP;
+ }
+ if (contents.equals(PORT_MODE_UFP)) {
+ return UsbPort.MODE_UFP;
+ }
+ }
+ return 0;
+ }
+
+ private static int readCurrentPowerRole(File portDir) {
+ final String contents = readFile(portDir, SYSFS_PORT_POWER_ROLE);
+ if (contents != null) {
+ if (contents.equals(PORT_POWER_ROLE_SOURCE)) {
+ return UsbPort.POWER_ROLE_SOURCE;
+ }
+ if (contents.equals(PORT_POWER_ROLE_SINK)) {
+ return UsbPort.POWER_ROLE_SINK;
+ }
+ }
+ return 0;
+ }
+
+ private static int readCurrentDataRole(File portDir) {
+ final String contents = readFile(portDir, SYSFS_PORT_DATA_ROLE);
+ if (contents != null) {
+ if (contents.equals(PORT_DATA_ROLE_HOST)) {
+ return UsbPort.DATA_ROLE_HOST;
+ }
+ if (contents.equals(PORT_DATA_ROLE_DEVICE)) {
+ return UsbPort.DATA_ROLE_DEVICE;
+ }
+ }
+ return 0;
+ }
+
+ private static boolean canChangeMode(File portDir) {
+ return new File(portDir, SYSFS_PORT_MODE).canWrite();
+ }
+
+ private static boolean canChangePowerRole(File portDir) {
+ return new File(portDir, SYSFS_PORT_POWER_ROLE).canWrite();
+ }
+
+ private static boolean canChangeDataRole(File portDir) {
+ return new File(portDir, SYSFS_PORT_DATA_ROLE).canWrite();
+ }
+
+ private static String readFile(File dir, String filename) {
+ final File file = new File(dir, filename);
+ try {
+ return IoUtils.readFileAsString(file.getAbsolutePath()).trim();
+ } catch (IOException ex) {
+ return null;
+ }
+ }
+
+ private static boolean writeFile(File dir, String filename, String contents) {
+ final File file = new File(dir, filename);
+ try {
+ try (FileWriter writer = new FileWriter(file)) {
+ writer.write(contents);
+ }
+ return true;
+ } catch (IOException ex) {
+ return false;
+ }
+ }
+
+ private static void logAndPrint(int priority, IndentingPrintWriter pw, String msg) {
+ Slog.println(priority, TAG, msg);
+ if (pw != null) {
+ pw.println(msg);
+ }
+ }
+
+ private final Handler mHandler = new Handler(FgThread.get().getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_PORTS: {
+ synchronized (mLock) {
+ updatePortsLocked(null);
+ }
+ break;
+ }
+ }
+ }
+ };
+
+ private final UEventObserver mUEventObserver = new UEventObserver() {
+ @Override
+ public void onUEvent(UEvent event) {
+ scheduleUpdatePorts();
+ }
+ };
+
+ /**
+ * Describes a USB port.
+ */
+ private static final class PortInfo {
+ public static final int DISPOSITION_ADDED = 0;
+ public static final int DISPOSITION_CHANGED = 1;
+ public static final int DISPOSITION_READY = 2;
+ public static final int DISPOSITION_REMOVED = 3;
+
+ public final UsbPort mUsbPort;
+ public UsbPortStatus mUsbPortStatus;
+ public boolean mCanChangeMode;
+ public boolean mCanChangePowerRole;
+ public boolean mCanChangeDataRole;
+ public int mDisposition; // default initialized to 0 which means added
+
+ public PortInfo(String portId, int supportedModes) {
+ mUsbPort = new UsbPort(portId, supportedModes);
+ }
+
+ public boolean setStatus(int currentMode, boolean canChangeMode,
+ int currentPowerRole, boolean canChangePowerRole,
+ int currentDataRole, boolean canChangeDataRole,
+ int supportedRoleCombinations) {
+ mCanChangeMode = canChangeMode;
+ mCanChangePowerRole = canChangePowerRole;
+ mCanChangeDataRole = canChangeDataRole;
+ if (mUsbPortStatus == null
+ || mUsbPortStatus.getCurrentMode() != currentMode
+ || mUsbPortStatus.getCurrentPowerRole() != currentPowerRole
+ || mUsbPortStatus.getCurrentDataRole() != currentDataRole
+ || mUsbPortStatus.getSupportedRoleCombinations()
+ != supportedRoleCombinations) {
+ mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
+ supportedRoleCombinations);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "port=" + mUsbPort + ", status=" + mUsbPortStatus
+ + ", canChangeMode=" + mCanChangeMode
+ + ", canChangePowerRole=" + mCanChangePowerRole
+ + ", canChangeDataRole=" + mCanChangeDataRole;
+ }
+ }
+
+ /**
+ * Describes a simulated USB port.
+ * Roughly mirrors the information we would ordinarily get from the kernel.
+ */
+ private static final class SimulatedPortInfo {
+ public final String mPortId;
+ public final int mSupportedModes;
+ public int mCurrentMode;
+ public boolean mCanChangeMode;
+ public int mCurrentPowerRole;
+ public boolean mCanChangePowerRole;
+ public int mCurrentDataRole;
+ public boolean mCanChangeDataRole;
+
+ public SimulatedPortInfo(String portId, int supportedModes) {
+ mPortId = portId;
+ mSupportedModes = supportedModes;
+ }
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index c8b4226..f93a2ef 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -27,6 +27,9 @@ import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
+import android.hardware.usb.UsbPort;
+import android.hardware.usb.UsbPortStatus;
+import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
@@ -36,6 +39,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
import java.io.File;
@@ -78,6 +82,7 @@ public class UsbService extends IUsbManager.Stub {
private UsbDeviceManager mDeviceManager;
private UsbHostManager mHostManager;
+ private UsbPortManager mPortManager;
private final UsbAlsaManager mAlsaManager;
private final Object mLock = new Object();
@@ -110,6 +115,9 @@ public class UsbService extends IUsbManager.Stub {
if (new File("/sys/class/android_usb").exists()) {
mDeviceManager = new UsbDeviceManager(context, mAlsaManager);
}
+ if (mHostManager != null || mDeviceManager != null) {
+ mPortManager = new UsbPortManager(context);
+ }
setCurrentUser(UserHandle.USER_OWNER);
@@ -160,6 +168,9 @@ public class UsbService extends IUsbManager.Stub {
if (mHostManager != null) {
mHostManager.systemReady();
}
+ if (mPortManager != null) {
+ mPortManager.systemReady();
+ }
}
public void bootCompleted() {
@@ -346,29 +357,258 @@ public class UsbService extends IUsbManager.Stub {
}
@Override
- public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
- final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ public UsbPort[] getPorts() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- pw.println("USB Manager State:");
- if (mDeviceManager != null) {
- mDeviceManager.dump(fd, pw);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return mPortManager != null ? mPortManager.getPorts() : null;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- if (mHostManager != null) {
- mHostManager.dump(fd, pw);
+ }
+
+ @Override
+ public UsbPortStatus getPortStatus(String portId) {
+ Preconditions.checkNotNull(portId, "portId must not be null");
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return mPortManager != null ? mPortManager.getPortStatus(portId) : null;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- mAlsaManager.dump(fd, pw);
+ }
- synchronized (mLock) {
- for (int i = 0; i < mSettingsByUser.size(); i++) {
- final int userId = mSettingsByUser.keyAt(i);
- final UsbSettingsManager settings = mSettingsByUser.valueAt(i);
+ @Override
+ public void setPortRoles(String portId, int powerRole, int dataRole) {
+ Preconditions.checkNotNull(portId, "portId must not be null");
+ UsbPort.checkRoles(powerRole, dataRole);
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mPortManager != null) {
+ mPortManager.setPortRoles(portId, powerRole, dataRole, null);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (args == null || args.length == 0 || "-a".equals(args[0])) {
+ pw.println("USB Manager State:");
pw.increaseIndent();
- pw.println("Settings for user " + userId + ":");
- settings.dump(fd, pw);
- pw.decreaseIndent();
+ if (mDeviceManager != null) {
+ mDeviceManager.dump(pw);
+ }
+ if (mHostManager != null) {
+ mHostManager.dump(pw);
+ }
+ if (mPortManager != null) {
+ mPortManager.dump(pw);
+ }
+ mAlsaManager.dump(pw);
+
+ synchronized (mLock) {
+ for (int i = 0; i < mSettingsByUser.size(); i++) {
+ final int userId = mSettingsByUser.keyAt(i);
+ final UsbSettingsManager settings = mSettingsByUser.valueAt(i);
+ pw.println("Settings for user " + userId + ":");
+ pw.increaseIndent();
+ settings.dump(pw);
+ pw.decreaseIndent();
+ }
+ }
+ } else if (args.length == 4 && "set-port-roles".equals(args[0])) {
+ final String portId = args[1];
+ final int powerRole;
+ switch (args[2]) {
+ case "source":
+ powerRole = UsbPort.POWER_ROLE_SOURCE;
+ break;
+ case "sink":
+ powerRole = UsbPort.POWER_ROLE_SINK;
+ break;
+ case "no-power":
+ powerRole = 0;
+ break;
+ default:
+ pw.println("Invalid power role: " + args[2]);
+ return;
+ }
+ final int dataRole;
+ switch (args[3]) {
+ case "host":
+ dataRole = UsbPort.DATA_ROLE_HOST;
+ break;
+ case "device":
+ dataRole = UsbPort.DATA_ROLE_DEVICE;
+ break;
+ case "no-data":
+ dataRole = 0;
+ break;
+ default:
+ pw.println("Invalid data role: " + args[3]);
+ return;
+ }
+ if (mPortManager != null) {
+ mPortManager.setPortRoles(portId, powerRole, dataRole, pw);
+ // Note: It might take some time for the side-effects of this operation
+ // to be fully applied by the kernel since the driver may need to
+ // renegotiate the USB port mode. If this proves to be an issue
+ // during debugging, it might be worth adding a sleep here before
+ // dumping the new state.
+ pw.println();
+ mPortManager.dump(pw);
+ }
+ } else if (args.length == 3 && "add-port".equals(args[0])) {
+ final String portId = args[1];
+ final int supportedModes;
+ switch (args[2]) {
+ case "ufp":
+ supportedModes = UsbPort.MODE_UFP;
+ break;
+ case "dfp":
+ supportedModes = UsbPort.MODE_DFP;
+ break;
+ case "dual":
+ supportedModes = UsbPort.MODE_DUAL;
+ break;
+ case "none":
+ supportedModes = 0;
+ break;
+ default:
+ pw.println("Invalid mode: " + args[2]);
+ return;
+ }
+ if (mPortManager != null) {
+ mPortManager.addSimulatedPort(portId, supportedModes, pw);
+ pw.println();
+ mPortManager.dump(pw);
+ }
+ } else if (args.length == 5 && "connect-port".equals(args[0])) {
+ final String portId = args[1];
+ final int mode;
+ final boolean canChangeMode = args[2].endsWith("?");
+ switch (canChangeMode ? removeLastChar(args[2]) : args[2]) {
+ case "ufp":
+ mode = UsbPort.MODE_UFP;
+ break;
+ case "dfp":
+ mode = UsbPort.MODE_DFP;
+ break;
+ default:
+ pw.println("Invalid mode: " + args[2]);
+ return;
+ }
+ final int powerRole;
+ final boolean canChangePowerRole = args[3].endsWith("?");
+ switch (canChangePowerRole ? removeLastChar(args[3]) : args[3]) {
+ case "source":
+ powerRole = UsbPort.POWER_ROLE_SOURCE;
+ break;
+ case "sink":
+ powerRole = UsbPort.POWER_ROLE_SINK;
+ break;
+ default:
+ pw.println("Invalid power role: " + args[3]);
+ return;
+ }
+ final int dataRole;
+ final boolean canChangeDataRole = args[4].endsWith("?");
+ switch (canChangeDataRole ? removeLastChar(args[4]) : args[4]) {
+ case "host":
+ dataRole = UsbPort.DATA_ROLE_HOST;
+ break;
+ case "device":
+ dataRole = UsbPort.DATA_ROLE_DEVICE;
+ break;
+ default:
+ pw.println("Invalid data role: " + args[4]);
+ return;
+ }
+ if (mPortManager != null) {
+ mPortManager.connectSimulatedPort(portId, mode, canChangeMode,
+ powerRole, canChangePowerRole, dataRole, canChangeDataRole, pw);
+ pw.println();
+ mPortManager.dump(pw);
+ }
+ } else if (args.length == 2 && "disconnect-port".equals(args[0])) {
+ final String portId = args[1];
+ if (mPortManager != null) {
+ mPortManager.disconnectSimulatedPort(portId, pw);
+ pw.println();
+ mPortManager.dump(pw);
+ }
+ } else if (args.length == 2 && "remove-port".equals(args[0])) {
+ final String portId = args[1];
+ if (mPortManager != null) {
+ mPortManager.removeSimulatedPort(portId, pw);
+ pw.println();
+ mPortManager.dump(pw);
+ }
+ } else if (args.length == 1 && "reset".equals(args[0])) {
+ if (mPortManager != null) {
+ mPortManager.resetSimulation(pw);
+ pw.println();
+ mPortManager.dump(pw);
+ }
+ } else if (args.length == 1 && "ports".equals(args[0])) {
+ if (mPortManager != null) {
+ mPortManager.dump(pw);
+ }
+ } else {
+ pw.println("Dump current USB state or issue command:");
+ pw.println(" ports");
+ pw.println(" set-port-roles <id> <source|sink|no-power> <host|device|no-data>");
+ pw.println(" add-port <id> <ufp|dfp|dual|none>");
+ pw.println(" connect-port <id> <ufp|dfp><?> <source|sink><?> <host|device><?>");
+ pw.println(" (add ? suffix if mode, power role, or data role can be changed)");
+ pw.println(" disconnect-port <id>");
+ pw.println(" remove-port <id>");
+ pw.println(" reset");
+ pw.println();
+ pw.println("Example USB type C port role switch:");
+ pw.println(" dumpsys usb set-port-roles \"default\" source device");
+ pw.println();
+ pw.println("Example USB type C port simulation with full capabilities:");
+ pw.println(" dumpsys usb add-port \"matrix\" dual");
+ pw.println(" dumpsys usb connect-port \"matrix\" ufp? sink? device?");
+ pw.println(" dumpsys usb ports");
+ pw.println(" dumpsys usb disconnect-port \"matrix\"");
+ pw.println(" dumpsys usb remove-port \"matrix\"");
+ pw.println(" dumpsys usb reset");
+ pw.println();
+ pw.println("Example USB type C port where only power role can be changed:");
+ pw.println(" dumpsys usb add-port \"matrix\" dual");
+ pw.println(" dumpsys usb connect-port \"matrix\" dfp source? host");
+ pw.println(" dumpsys usb reset");
+ pw.println();
+ pw.println("Example USB OTG port where id pin determines function:");
+ pw.println(" dumpsys usb add-port \"matrix\" dual");
+ pw.println(" dumpsys usb connect-port \"matrix\" dfp source host");
+ pw.println(" dumpsys usb reset");
+ pw.println();
+ pw.println("Example USB device-only port:");
+ pw.println(" dumpsys usb add-port \"matrix\" ufp");
+ pw.println(" dumpsys usb connect-port \"matrix\" ufp sink device");
+ pw.println(" dumpsys usb reset");
}
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- pw.decreaseIndent();
+ }
+
+ private static final String removeLastChar(String value) {
+ return value.substring(0, value.length() - 1);
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 2331a8b..2cf42f0 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -44,6 +44,7 @@ import android.util.Xml;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -1193,35 +1194,35 @@ class UsbSettingsManager {
}
}
- public void dump(FileDescriptor fd, PrintWriter pw) {
+ public void dump(IndentingPrintWriter pw) {
synchronized (mLock) {
- pw.println(" Device permissions:");
+ pw.println("Device permissions:");
for (String deviceName : mDevicePermissionMap.keySet()) {
- pw.print(" " + deviceName + ": ");
+ pw.print(" " + deviceName + ": ");
SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
int count = uidList.size();
for (int i = 0; i < count; i++) {
pw.print(Integer.toString(uidList.keyAt(i)) + " ");
}
- pw.println("");
+ pw.println();
}
- pw.println(" Accessory permissions:");
+ pw.println("Accessory permissions:");
for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) {
- pw.print(" " + accessory + ": ");
+ pw.print(" " + accessory + ": ");
SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
int count = uidList.size();
for (int i = 0; i < count; i++) {
pw.print(Integer.toString(uidList.keyAt(i)) + " ");
}
- pw.println("");
+ pw.println();
}
- pw.println(" Device preferences:");
+ pw.println("Device preferences:");
for (DeviceFilter filter : mDevicePreferenceMap.keySet()) {
- pw.println(" " + filter + ": " + mDevicePreferenceMap.get(filter));
+ pw.println(" " + filter + ": " + mDevicePreferenceMap.get(filter));
}
- pw.println(" Accessory preferences:");
+ pw.println("Accessory preferences:");
for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) {
- pw.println(" " + filter + ": " + mAccessoryPreferenceMap.get(filter));
+ pw.println(" " + filter + ": " + mAccessoryPreferenceMap.get(filter));
}
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 36478da..42f879c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -578,6 +578,44 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
+ @Override
+ public void setDisabledShowContext(int flags) {
+ synchronized (this) {
+ if (mImpl == null) {
+ Slog.w(TAG, "setDisabledShowContext without running voice interaction service");
+ return;
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mImpl.setDisabledShowContextLocked(callingPid, callingUid, flags);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+
+ }
+
+ @Override
+ public int getDisabledShowContext() {
+ synchronized (this) {
+ if (mImpl == null) {
+ Slog.w(TAG, "getDisabledShowContext without running voice interaction service");
+ return 0;
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mImpl.getDisabledShowContextLocked(callingPid, callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+
+ }
+
//----------------- Model management APIs --------------------------------//
@Override
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index e5faf4d..7409f99 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -65,6 +65,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
IVoiceInteractionService mService;
VoiceInteractionSessionConnection mActiveSession;
+ int mDisabledShowContext;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -146,7 +147,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName,
mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler);
}
- return mActiveSession.showLocked(args, flags, showCallback);
+ return mActiveSession.showLocked(args, flags, mDisabledShowContext, showCallback);
}
public boolean hideSessionLocked() {
@@ -222,6 +223,24 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession = null;
}
+ public void setDisabledShowContextLocked(int callingPid, int callingUid, int flags) {
+ int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
+ if (callingUid != activeUid) {
+ throw new SecurityException("Calling uid " + callingUid
+ + " does not match active uid " + activeUid);
+ }
+ mDisabledShowContext = flags;
+ }
+
+ public int getDisabledShowContextLocked(int callingPid, int callingUid) {
+ int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
+ if (callingUid != activeUid) {
+ throw new SecurityException("Calling uid " + callingUid
+ + " does not match active uid " + activeUid);
+ }
+ return mDisabledShowContext;
+ }
+
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!mValid) {
pw.print(" NOT VALID: ");
@@ -235,6 +254,10 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
pw.print(" mComponent="); pw.println(mComponent.flattenToShortString());
pw.print(" Session service="); pw.println(mInfo.getSessionService());
pw.print(" Settings activity="); pw.println(mInfo.getSettingsActivity());
+ if (mDisabledShowContext != 0) {
+ pw.print(" mDisabledShowContext=");
+ pw.println(Integer.toHexString(mDisabledShowContext));
+ }
pw.print(" mBound="); pw.print(mBound); pw.print(" mService="); pw.println(mService);
if (mActiveSession != null) {
pw.println(" Active session:");
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index bd043ac..dfdd639 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -183,7 +183,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
}
}
- public boolean showLocked(Bundle args, int flags,
+ public boolean showLocked(Bundle args, int flags, int disabledContext,
IVoiceInteractionSessionShowCallback showCallback) {
if (mBound) {
if (!mFullyBound) {
@@ -200,15 +200,17 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
}
boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0
- && isScreenCaptureAllowed;
+ && isScreenCaptureAllowed
+ && (disabledContext&VoiceInteractionSession.SHOW_WITH_ASSIST) == 0;
boolean screenshotEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1, mUser) != 0
- && isScreenCaptureAllowed;
+ && isScreenCaptureAllowed
+ && (disabledContext&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0;
mShowArgs = args;
mShowFlags = flags;
mHaveAssistData = false;
boolean needDisclosure = false;
- if ((flags& VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
+ if ((flags&VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
&& structureEnabled) {
@@ -226,7 +228,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mAssistData = null;
}
mHaveScreenshot = false;
- if ((flags& VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) {
+ if ((flags&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_SCREENSHOT, mCallingUid,
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
&& screenshotEnabled) {