summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java116
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java54
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java1
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java39
-rw-r--r--services/core/java/com/android/server/MountService.java68
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java74
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java201
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java14
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java4
-rw-r--r--services/core/java/com/android/server/am/ProviderMap.java27
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java66
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java25
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java16
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java12
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java5
-rw-r--r--services/core/java/com/android/server/notification/CalendarTracker.java4
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java4
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java133
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java55
-rw-r--r--services/core/java/com/android/server/pm/BasePermission.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java94
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java148
-rw-r--r--services/core/java/com/android/server/pm/PermissionsState.java415
-rw-r--r--services/core/java/com/android/server/pm/SettingBase.java6
-rw-r--r--services/core/java/com/android/server/pm/Settings.java173
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java269
-rw-r--r--services/core/java/com/android/server/policy/BarController.java22
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java21
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java93
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java14
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java6
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java13
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java10
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java5
35 files changed, 1433 insertions, 790 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8d1d124..1dc2d7e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -190,7 +190,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
/** Set of ifaces that are costly. */
private HashSet<String> mMeteredIfaces = Sets.newHashSet();
- private Context mContext;
+ final private Context mContext;
private int mNetworkPreference;
// 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0;
@@ -344,6 +344,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private static final int EVENT_PROMPT_UNVALIDATED = 29;
+ /**
+ * used internally to (re)configure mobile data always-on settings.
+ */
+ private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
+
/** Handler used for internal events. */
final private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -374,7 +379,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private PacManager mPacManager = null;
- private SettingsObserver mSettingsObserver;
+ final private SettingsObserver mSettingsObserver;
private UserManager mUserManager;
@@ -555,13 +560,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
if (DBG) log("ConnectivityService starting up");
- NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
- mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
- NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
- NetworkRequestInfo.REQUEST);
- mNetworkRequests.put(mDefaultRequest, nri);
+ mDefaultRequest = createInternetRequestForTransport(-1);
+ mNetworkRequests.put(mDefaultRequest, new NetworkRequestInfo(
+ null, mDefaultRequest, new Binder(), NetworkRequestInfo.REQUEST));
+
+ mDefaultMobileDataRequest = createInternetRequestForTransport(
+ NetworkCapabilities.TRANSPORT_CELLULAR);
HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
handlerThread.start();
@@ -696,8 +700,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
mInetLog = new ArrayList();
}
- mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
- mSettingsObserver.observe(mContext);
+ mSettingsObserver = new SettingsObserver(mContext, mHandler);
+ registerSettingsCallbacks();
mDataConnectionStats = new DataConnectionStats(mContext);
mDataConnectionStats.startMonitoring();
@@ -707,6 +711,44 @@ public class ConnectivityService extends IConnectivityManager.Stub
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
}
+ private NetworkRequest createInternetRequestForTransport(int transportType) {
+ NetworkCapabilities netCap = new NetworkCapabilities();
+ netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ if (transportType > -1) {
+ netCap.addTransportType(transportType);
+ }
+ return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
+ }
+
+ private void handleMobileDataAlwaysOn() {
+ final boolean enable = (Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1);
+ final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
+ if (enable == isEnabled) {
+ return; // Nothing to do.
+ }
+
+ if (enable) {
+ handleRegisterNetworkRequest(new NetworkRequestInfo(
+ null, mDefaultMobileDataRequest, new Binder(), NetworkRequestInfo.REQUEST));
+ } else {
+ handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID);
+ }
+ }
+
+ private void registerSettingsCallbacks() {
+ // Watch for global HTTP proxy changes.
+ mSettingsObserver.observe(
+ Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
+ EVENT_APPLY_GLOBAL_HTTP_PROXY);
+
+ // Watch for whether or not to keep mobile data always on.
+ mSettingsObserver.observe(
+ Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
+ EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
+ }
+
private synchronized int nextNetworkRequestId() {
return mNextNetworkRequestId++;
}
@@ -1491,6 +1533,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
mContext.registerReceiver(mUserPresentReceiver, filter);
}
+ // Configure whether mobile data is always on.
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON));
+
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
mPermissionMonitor.startMonitoring();
@@ -2107,12 +2152,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
+ nri.request + " because their intents matched.");
handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
}
- handleRegisterNetworkRequest(msg);
+ handleRegisterNetworkRequest(nri);
}
- private void handleRegisterNetworkRequest(Message msg) {
- final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
-
+ private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
mNetworkRequests.put(nri.request, nri);
// TODO: This logic may be better replaced with a call to rematchNetworkAndRequests
@@ -2423,7 +2466,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
case EVENT_REGISTER_NETWORK_REQUEST:
case EVENT_REGISTER_NETWORK_LISTENER: {
- handleRegisterNetworkRequest(msg);
+ handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
break;
}
case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: {
@@ -2446,6 +2489,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
handlePromptUnvalidated((Network) msg.obj);
break;
}
+ case EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON: {
+ handleMobileDataAlwaysOn();
+ break;
+ }
case EVENT_SYSTEM_READY: {
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
nai.networkMonitor.systemReady = true;
@@ -2837,23 +2884,36 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private static class SettingsObserver extends ContentObserver {
- private int mWhat;
- private Handler mHandler;
- SettingsObserver(Handler handler, int what) {
- super(handler);
+ final private HashMap<Uri, Integer> mUriEventMap;
+ final private Context mContext;
+ final private Handler mHandler;
+
+ SettingsObserver(Context context, Handler handler) {
+ super(null);
+ mUriEventMap = new HashMap<Uri, Integer>();
+ mContext = context;
mHandler = handler;
- mWhat = what;
}
- void observe(Context context) {
- ContentResolver resolver = context.getContentResolver();
- resolver.registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.HTTP_PROXY), false, this);
+ void observe(Uri uri, int what) {
+ mUriEventMap.put(uri, what);
+ final ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(uri, false, this);
}
@Override
public void onChange(boolean selfChange) {
- mHandler.obtainMessage(mWhat).sendToTarget();
+ Slog.wtf(TAG, "Should never be reached.");
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ final Integer what = mUriEventMap.get(uri);
+ if (what != null) {
+ mHandler.obtainMessage(what.intValue()).sendToTarget();
+ } else {
+ loge("No matching event to send for URI=" + uri);
+ }
}
}
@@ -3643,6 +3703,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
private final NetworkRequest mDefaultRequest;
+ // Request used to optionally keep mobile data active even when higher
+ // priority networks like Wi-Fi are active.
+ private final NetworkRequest mDefaultMobileDataRequest;
+
private NetworkAgentInfo getDefaultNetwork() {
return mNetworkForRequestId.get(mDefaultRequest.requestId);
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index b7bc0f0..76465d4 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -142,6 +142,7 @@ public class DeviceIdleController extends SystemService {
private PendingIntent mAlarmIntent;
private Intent mIdleIntent;
private Display mCurDisplay;
+ private boolean mIdleDisabled;
private boolean mScreenOn;
private boolean mCharging;
private boolean mSigMotionActive;
@@ -187,10 +188,16 @@ public class DeviceIdleController extends SystemService {
private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
/**
- * UIDs that have been white-listed to opt out of power save restrictions.
+ * App IDs that have been white-listed to opt out of power save restrictions.
*/
private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
+ /**
+ * Current app IDs that are in the complete power save white list. This array can
+ * be shared with others because it will not be modified once set.
+ */
+ private int[] mPowerSaveWhitelistAppIdArray = new int[0];
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
@@ -381,6 +388,8 @@ public class DeviceIdleController extends SystemService {
filter.addAction(ACTION_STEP_IDLE_STATE);
getContext().registerReceiver(mReceiver, filter);
+ mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);
+
mDisplayManager.registerDisplayListener(mDisplayListener, null);
updateDisplayLocked();
}
@@ -445,12 +454,7 @@ public class DeviceIdleController extends SystemService {
public int[] getAppIdWhitelistInternal() {
synchronized (this) {
- int size = mPowerSaveWhitelistAppIds.size();
- int[] appids = new int[size];
- for (int i = 0; i < size; i++) {
- appids[i] = mPowerSaveWhitelistAppIds.keyAt(i);
- }
- return appids;
+ return mPowerSaveWhitelistAppIdArray;
}
}
@@ -499,7 +503,7 @@ public class DeviceIdleController extends SystemService {
}
void becomeInactiveIfAppropriateLocked() {
- if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) {
+ if (!mScreenOn && !mCharging && !mIdleDisabled && mState == STATE_ACTIVE) {
// Screen has turned off; we are now going to become inactive and start
// waiting to see if we will ultimately go idle.
mState = STATE_INACTIVE;
@@ -625,6 +629,15 @@ public class DeviceIdleController extends SystemService {
for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true);
}
+ int size = mPowerSaveWhitelistAppIds.size();
+ int[] appids = new int[size];
+ for (int i = 0; i < size; i++) {
+ appids[i] = mPowerSaveWhitelistAppIds.keyAt(i);
+ }
+ mPowerSaveWhitelistAppIdArray = appids;
+ if (mLocalPowerManager != null) {
+ mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);
+ }
}
private void reportPowerSaveWhitelistChangedLocked() {
@@ -763,6 +776,10 @@ public class DeviceIdleController extends SystemService {
pw.println("Commands:");
pw.println(" step");
pw.println(" Immediately step to next state, without waiting for alarm.");
+ pw.println(" disable");
+ pw.println(" Completely disable device idle mode.");
+ pw.println(" enable");
+ pw.println(" Re-enable device idle mode after it had previously been disabled.");
pw.println(" whitelist");
pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
}
@@ -782,12 +799,32 @@ public class DeviceIdleController extends SystemService {
if ("-h".equals(arg)) {
dumpHelp(pw);
return;
+ } else if ("-a".equals(arg)) {
+ // Ignore, we always dump all.
} else if ("step".equals(arg)) {
synchronized (this) {
stepIdleStateLocked();
pw.print("Stepped to: "); pw.println(stateToString(mState));
}
return;
+ } else if ("disable".equals(arg)) {
+ synchronized (this) {
+ if (!mIdleDisabled) {
+ mIdleDisabled = true;
+ becomeActiveLocked("disabled");
+ pw.println("Idle mode disabled");
+ }
+ }
+ return;
+ } else if ("enable".equals(arg)) {
+ synchronized (this) {
+ if (mIdleDisabled) {
+ mIdleDisabled = false;
+ becomeInactiveIfAppropriateLocked();
+ pw.println("Idle mode enabled");
+ }
+ }
+ return;
} else if ("whitelist".equals(arg)) {
i++;
while (i < args.length) {
@@ -853,6 +890,7 @@ public class DeviceIdleController extends SystemService {
}
pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
pw.print(" mCurDisplay="); pw.println(mCurDisplay);
+ pw.print(" mIdleDisabled="); pw.println(mIdleDisabled);
pw.print(" mScreenOn="); pw.println(mScreenOn);
pw.print(" mCharging="); pw.println(mCharging);
pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 9511f54..e856a93 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1695,6 +1695,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
vis = 0;
}
mImeWindowVis = vis;
+ mInputShown = ((mImeWindowVis & InputMethodService.IME_VISIBLE) != 0);
mBackDisposition = backDisposition;
final boolean iconVisibility = ((vis & (InputMethodService.IME_ACTIVE)) != 0)
&& (mWindowManagerService.isHardKeyboardAvailable()
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 5df74c5..ed2de4a 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -356,28 +356,23 @@ public class LockSettingsService extends ILockSettings.Stub {
return mStorage.hasPattern(userId);
}
- private void maybeUpdateKeystore(String password, int userHandle) {
+ private void setKeystorePassword(String password, int userHandle) {
final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final KeyStore ks = KeyStore.getInstance();
final List<UserInfo> profiles = um.getProfiles(userHandle);
- boolean shouldReset = TextUtils.isEmpty(password);
-
- // For historical reasons, don't wipe a non-empty keystore if we have a single user with a
- // single profile.
- if (userHandle == UserHandle.USER_OWNER && profiles.size() == 1) {
- if (!ks.isEmpty()) {
- shouldReset = false;
- }
+ for (UserInfo pi : profiles) {
+ ks.onUserPasswordChanged(pi.id, password);
}
+ }
+
+ private void unlockKeystore(String password, int userHandle) {
+ final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+ final KeyStore ks = KeyStore.getInstance();
+ final List<UserInfo> profiles = um.getProfiles(userHandle);
for (UserInfo pi : profiles) {
- final int profileUid = UserHandle.getUid(pi.id, Process.SYSTEM_UID);
- if (shouldReset) {
- ks.resetUid(profileUid);
- } else {
- ks.passwordUid(password, profileUid);
- }
+ ks.unlock(pi.id, password);
}
}
@@ -423,7 +418,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (pattern == null) {
getGateKeeperService().clearSecureUserId(userId);
mStorage.writePatternHash(null, userId);
- maybeUpdateKeystore(null, userId);
+ setKeystorePassword(null, userId);
return;
}
@@ -451,7 +446,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (password == null) {
getGateKeeperService().clearSecureUserId(userId);
mStorage.writePasswordHash(null, userId);
- maybeUpdateKeystore(null, userId);
+ setKeystorePassword(null, userId);
return;
}
@@ -484,7 +479,7 @@ public class LockSettingsService extends ILockSettings.Stub {
toEnrollBytes);
if (hash != null) {
- maybeUpdateKeystore(toEnroll, userId);
+ setKeystorePassword(toEnroll, userId);
}
return hash;
@@ -530,7 +525,7 @@ public class LockSettingsService extends ILockSettings.Stub {
byte[] hash = mLockPatternUtils.patternToHash(
mLockPatternUtils.stringToPattern(pattern));
if (Arrays.equals(hash, storedHash.hash)) {
- maybeUpdateKeystore(pattern, userId);
+ unlockKeystore(pattern, userId);
// migrate password to GateKeeper
setLockPattern(pattern, null, userId);
if (!hasChallenge) {
@@ -556,7 +551,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
// pattern has matched
- maybeUpdateKeystore(pattern, userId);
+ unlockKeystore(pattern, userId);
return token;
}
@@ -599,7 +594,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (storedHash.version == CredentialHash.VERSION_LEGACY) {
byte[] hash = mLockPatternUtils.passwordToHash(password, userId);
if (Arrays.equals(hash, storedHash.hash)) {
- maybeUpdateKeystore(password, userId);
+ unlockKeystore(password, userId);
// migrate password to GateKeeper
setLockPassword(password, null, userId);
if (!hasChallenge) {
@@ -625,7 +620,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
// password has matched
- maybeUpdateKeystore(password, userId);
+ unlockKeystore(password, userId);
return token;
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 0925fa5..93ac51a 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -242,6 +242,7 @@ class MountService extends IMountService.Stub
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_PRIMARY = 2;
+ private static final int VERSION_FIX_PRIMARY = 3;
private static final String TAG_VOLUMES = "volumes";
private static final String ATTR_VERSION = "version";
@@ -1187,8 +1188,17 @@ class MountService extends IMountService.Stub
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}
+ private String getDefaultPrimaryStorageUuid() {
+ if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
+ return StorageManager.UUID_PRIMARY_PHYSICAL;
+ } else {
+ return StorageManager.UUID_PRIVATE_INTERNAL;
+ }
+ }
+
private void readSettingsLocked() {
mRecords.clear();
+ mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
FileInputStream fis = null;
try {
@@ -1202,16 +1212,13 @@ class MountService extends IMountService.Stub
final String tag = in.getName();
if (TAG_VOLUMES.equals(tag)) {
final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
- if (version >= VERSION_ADD_PRIMARY) {
+ final boolean primaryPhysical = SystemProperties.getBoolean(
+ StorageManager.PROP_PRIMARY_PHYSICAL, false);
+ final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
+ || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
+ if (validAttr) {
mPrimaryStorageUuid = readStringAttribute(in,
ATTR_PRIMARY_STORAGE_UUID);
- } else {
- if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL,
- false)) {
- mPrimaryStorageUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
- } else {
- mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL;
- }
}
} else if (TAG_VOLUME.equals(tag)) {
@@ -1240,7 +1247,7 @@ class MountService extends IMountService.Stub
out.setOutput(fos, "utf-8");
out.startDocument(null, true);
out.startTag(null, TAG_VOLUMES);
- writeIntAttribute(out, ATTR_VERSION, VERSION_ADD_PRIMARY);
+ writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
final int size = mRecords.size();
for (int i = 0; i < size; i++) {
@@ -1482,7 +1489,7 @@ class MountService extends IMountService.Stub
// If this had been primary storage, revert back to internal and
// reset vold so we bind into new volume into place.
if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
- mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL;
+ mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
resetIfReadyAndConnected();
}
@@ -1497,11 +1504,13 @@ class MountService extends IMountService.Stub
final String fsUuid = mRecords.keyAt(i);
mCallbacks.notifyVolumeForgotten(fsUuid);
}
-
mRecords.clear();
- writeSettingsLocked();
- mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL;
+ if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
+ mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
+ }
+
+ writeSettingsLocked();
resetIfReadyAndConnected();
}
}
@@ -1522,13 +1531,8 @@ class MountService extends IMountService.Stub
waitForReady();
synchronized (mLock) {
- final VolumeInfo from = Preconditions.checkNotNull(
- findStorageForUuid(mPrimaryStorageUuid));
- final VolumeInfo to = Preconditions.checkNotNull(
- findStorageForUuid(volumeUuid));
-
- if (Objects.equals(from, to)) {
- throw new IllegalArgumentException("Primary storage already at " + from);
+ if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
+ throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
}
if (mMoveCallback != null) {
@@ -1537,10 +1541,26 @@ class MountService extends IMountService.Stub
mMoveCallback = callback;
mMoveTargetUuid = volumeUuid;
- try {
- mConnector.execute("volume", "move_storage", from.id, to.id);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ // When moving to/from primary physical volume, we probably just nuked
+ // the current storage location, so we have nothing to move.
+ if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
+ || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
+ Slog.d(TAG, "Skipping move to/from primary physical");
+ onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
+ onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
+ resetIfReadyAndConnected();
+
+ } else {
+ final VolumeInfo from = Preconditions.checkNotNull(
+ findStorageForUuid(mPrimaryStorageUuid));
+ final VolumeInfo to = Preconditions.checkNotNull(
+ findStorageForUuid(volumeUuid));
+
+ try {
+ mConnector.execute("volume", "move_storage", from.id, to.id);
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3dece49..fa4d204 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import android.app.ActivityThread;
import android.os.Build;
@@ -119,14 +120,13 @@ public final class ActiveServices {
// at the same time.
final int mMaxStartingBackground;
- final SparseArray<ServiceMap> mServiceMap = new SparseArray<ServiceMap>();
+ final SparseArray<ServiceMap> mServiceMap = new SparseArray<>();
/**
* All currently bound service connections. Keys are the IBinder of
* the client's IServiceConnection.
*/
- final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
- = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
+ final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections = new ArrayMap<>();
/**
* List of services that we have been asked to start,
@@ -134,20 +134,20 @@ public final class ActiveServices {
* while waiting for their corresponding application thread to get
* going.
*/
- final ArrayList<ServiceRecord> mPendingServices
- = new ArrayList<ServiceRecord>();
+ final ArrayList<ServiceRecord> mPendingServices = new ArrayList<>();
/**
* List of services that are scheduled to restart following a crash.
*/
- final ArrayList<ServiceRecord> mRestartingServices
- = new ArrayList<ServiceRecord>();
+ final ArrayList<ServiceRecord> mRestartingServices = new ArrayList<>();
/**
* List of services that are in the process of being destroyed.
*/
- final ArrayList<ServiceRecord> mDestroyingServices
- = new ArrayList<ServiceRecord>();
+ final ArrayList<ServiceRecord> mDestroyingServices = new ArrayList<>();
+
+ /** Temporary list for holding the results of calls to {@link #collectPackageServicesLocked} */
+ private ArrayList<ServiceRecord> mTmpCollectionResults = null;
/** Amount of time to allow a last ANR message to exist before freeing the memory. */
static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
@@ -162,10 +162,6 @@ public final class ActiveServices {
}
};
- static final class DelayingProcess extends ArrayList<ServiceRecord> {
- long timeoout;
- }
-
/**
* Information about services for a single user.
*/
@@ -2076,14 +2072,16 @@ public final class ActiveServices {
}
}
- private boolean collectForceStopServicesLocked(String name, int userId,
- boolean evenPersistent, boolean doit,
- ArrayMap<ComponentName, ServiceRecord> services,
- ArrayList<ServiceRecord> result) {
+ private boolean collectPackageServicesLocked(String packageName, Set<String> filterByClasses,
+ boolean evenPersistent, boolean doit, ArrayMap<ComponentName, ServiceRecord> services) {
boolean didSomething = false;
- for (int i=0; i<services.size(); i++) {
+ for (int i = services.size() - 1; i >= 0; i--) {
ServiceRecord service = services.valueAt(i);
- if ((name == null || service.packageName.equals(name))
+ final boolean sameComponent = packageName == null
+ || (service.packageName.equals(packageName)
+ && (filterByClasses == null
+ || filterByClasses.contains(service.name.getClassName())));
+ if (sameComponent
&& (service.app == null || evenPersistent || !service.app.persistent)) {
if (!doit) {
return true;
@@ -2098,19 +2096,27 @@ public final class ActiveServices {
}
service.app = null;
service.isolatedProc = null;
- result.add(service);
+ if (mTmpCollectionResults == null) {
+ mTmpCollectionResults = new ArrayList<>();
+ }
+ mTmpCollectionResults.add(service);
}
}
return didSomething;
}
- boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
+ boolean bringDownDisabledPackageServicesLocked(String packageName, Set<String> filterByClasses,
+ int userId, boolean evenPersistent, boolean doit) {
boolean didSomething = false;
- ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+
+ if (mTmpCollectionResults != null) {
+ mTmpCollectionResults.clear();
+ }
+
if (userId == UserHandle.USER_ALL) {
- for (int i=0; i<mServiceMap.size(); i++) {
- didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
- doit, mServiceMap.valueAt(i).mServicesByName, services);
+ for (int i = mServiceMap.size() - 1; i >= 0; i--) {
+ didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
+ evenPersistent, doit, mServiceMap.valueAt(i).mServicesByName);
if (!doit && didSomething) {
return true;
}
@@ -2119,22 +2125,24 @@ public final class ActiveServices {
ServiceMap smap = mServiceMap.get(userId);
if (smap != null) {
ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
- didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
- doit, items, services);
+ didSomething = collectPackageServicesLocked(packageName, filterByClasses,
+ evenPersistent, doit, items);
}
}
- int N = services.size();
- for (int i=0; i<N; i++) {
- bringDownServiceLocked(services.get(i));
+ if (mTmpCollectionResults != null) {
+ for (int i = mTmpCollectionResults.size() - 1; i >= 0; i--) {
+ bringDownServiceLocked(mTmpCollectionResults.get(i));
+ }
+ mTmpCollectionResults.clear();
}
return didSomething;
}
void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
- ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+ ArrayList<ServiceRecord> services = new ArrayList<>();
ArrayMap<ComponentName, ServiceRecord> alls = getServices(tr.userId);
- for (int i=0; i<alls.size(); i++) {
+ for (int i = alls.size() - 1; i >= 0; i--) {
ServiceRecord sr = alls.valueAt(i);
if (sr.packageName.equals(component.getPackageName())) {
services.add(sr);
@@ -2142,7 +2150,7 @@ public final class ActiveServices {
}
// Take care of any running services associated with the app.
- for (int i=0; i<services.size(); i++) {
+ for (int i = services.size() - 1; i >= 0; i--) {
ServiceRecord sr = services.get(i);
if (sr.startRequested) {
if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 82dbfee..76ee3bc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -375,6 +375,10 @@ public final class ActivityManagerService extends ActivityManagerNative
// Delay in notifying task stack change listeners (in millis)
static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 1000;
+ // Necessary ApplicationInfo flags to mark an app as persistent
+ private static final int PERSISTENT_MASK =
+ ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
+
/** All system services */
SystemServiceManager mSystemServiceManager;
@@ -5363,39 +5367,117 @@ public final class ActivityManagerService extends ActivityManagerNative
return N > 0;
}
- private final boolean forceStopPackageLocked(String name, int appId,
+ private void cleanupDisabledPackageComponentsLocked(
+ String packageName, int userId, String[] changedClasses) {
+
+ Set<String> disabledClasses = null;
+ boolean packageDisabled = false;
+ IPackageManager pm = AppGlobals.getPackageManager();
+
+ if (changedClasses == null) {
+ // Nothing changed...
+ return;
+ }
+
+ // Determine enable/disable state of the package and its components.
+ int enabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ for (int i = changedClasses.length - 1; i >= 0; i--) {
+ final String changedClass = changedClasses[i];
+
+ if (changedClass.equals(packageName)) {
+ try {
+ // Entire package setting changed
+ enabled = pm.getApplicationEnabledSetting(packageName,
+ (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER);
+ } catch (RemoteException e) {
+ // Can't happen...
+ }
+ packageDisabled = enabled != PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ && enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ if (packageDisabled) {
+ // Entire package is disabled.
+ // No need to continue to check component states.
+ disabledClasses = null;
+ break;
+ }
+ } else {
+ try {
+ enabled = pm.getComponentEnabledSetting(
+ new ComponentName(packageName, changedClass),
+ (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER);
+ } catch (RemoteException e) {
+ // Can't happen...
+ }
+ if (enabled != PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ && enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ if (disabledClasses == null) {
+ disabledClasses = new ArraySet<>(changedClasses.length);
+ }
+ disabledClasses.add(changedClass);
+ }
+ }
+ }
+
+ if (!packageDisabled && disabledClasses == null) {
+ // Nothing to do here...
+ return;
+ }
+
+ // Clean-up disabled activities.
+ if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
+ packageName, disabledClasses, true, false, userId) && mBooted) {
+ mStackSupervisor.resumeTopActivitiesLocked();
+ mStackSupervisor.scheduleIdleLocked();
+ }
+
+ // Clean-up disabled tasks
+ cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId);
+
+ // Clean-up disabled services.
+ mServices.bringDownDisabledPackageServicesLocked(
+ packageName, disabledClasses, userId, false, true);
+
+ // Clean-up disabled providers.
+ ArrayList<ContentProviderRecord> providers = new ArrayList<>();
+ mProviderMap.collectPackageProvidersLocked(
+ packageName, disabledClasses, true, false, userId, providers);
+ for (int i = providers.size() - 1; i >= 0; i--) {
+ removeDyingProviderLocked(null, providers.get(i), true);
+ }
+ }
+
+ private final boolean forceStopPackageLocked(String packageName, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, boolean uninstalling, int userId, String reason) {
int i;
- int N;
- if (userId == UserHandle.USER_ALL && name == null) {
+ if (userId == UserHandle.USER_ALL && packageName == null) {
Slog.w(TAG, "Can't force stop all processes of all users, that is insane!");
}
- if (appId < 0 && name != null) {
+ if (appId < 0 && packageName != null) {
try {
appId = UserHandle.getAppId(
- AppGlobals.getPackageManager().getPackageUid(name, 0));
+ AppGlobals.getPackageManager().getPackageUid(packageName, 0));
} catch (RemoteException e) {
}
}
if (doit) {
- if (name != null) {
- Slog.i(TAG, "Force stopping " + name + " appid=" + appId
+ if (packageName != null) {
+ Slog.i(TAG, "Force stopping " + packageName + " appid=" + appId
+ " user=" + userId + ": " + reason);
} else {
Slog.i(TAG, "Force stopping u" + userId + ": " + reason);
}
final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
- for (int ip=pmap.size()-1; ip>=0; ip--) {
+ for (int ip = pmap.size() - 1; ip >= 0; ip--) {
SparseArray<Long> ba = pmap.valueAt(ip);
- for (i=ba.size()-1; i>=0; i--) {
+ for (i = ba.size() - 1; i >= 0; i--) {
boolean remove = false;
final int entUid = ba.keyAt(i);
- if (name != null) {
+ if (packageName != null) {
if (userId == UserHandle.USER_ALL) {
if (UserHandle.getAppId(entUid) == appId) {
remove = true;
@@ -5418,46 +5500,47 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- boolean didSomething = killPackageProcessesLocked(name, appId, userId,
+ boolean didSomething = killPackageProcessesLocked(packageName, appId, userId,
-100, callerWillRestart, true, doit, evenPersistent,
- name == null ? ("stop user " + userId) : ("stop " + name));
+ packageName == null ? ("stop user " + userId) : ("stop " + packageName));
- if (mStackSupervisor.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
+ if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
+ packageName, null, doit, evenPersistent, userId)) {
if (!doit) {
return true;
}
didSomething = true;
}
- if (mServices.forceStopLocked(name, userId, evenPersistent, doit)) {
+ if (mServices.bringDownDisabledPackageServicesLocked(
+ packageName, null, userId, evenPersistent, doit)) {
if (!doit) {
return true;
}
didSomething = true;
}
- if (name == null) {
+ if (packageName == null) {
// Remove all sticky broadcasts from this user.
mStickyBroadcasts.remove(userId);
}
- ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
- if (mProviderMap.collectForceStopProviders(name, appId, doit, evenPersistent,
+ ArrayList<ContentProviderRecord> providers = new ArrayList<>();
+ if (mProviderMap.collectPackageProvidersLocked(packageName, null, doit, evenPersistent,
userId, providers)) {
if (!doit) {
return true;
}
didSomething = true;
}
- N = providers.size();
- for (i=0; i<N; i++) {
+ for (i = providers.size() - 1; i >= 0; i--) {
removeDyingProviderLocked(null, providers.get(i), true);
}
// Remove transient permissions granted from/to this package/user
- removeUriPermissionsForPackageLocked(name, userId, false);
+ removeUriPermissionsForPackageLocked(packageName, userId, false);
- if (name == null || uninstalling) {
+ if (packageName == null || uninstalling) {
// Remove pending intents. For now we only do this when force
// stopping users, because we have some problems when doing this
// for packages -- app widgets are not currently cleaned up for
@@ -5476,7 +5559,7 @@ public final class ActivityManagerService extends ActivityManagerNative
it.remove();
continue;
}
- if (name == null) {
+ if (packageName == null) {
// Stopping user, remove all objects for the user.
if (pir.key.userId != userId) {
// Not the same user, skip it.
@@ -5491,7 +5574,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Different user, skip it.
continue;
}
- if (!pir.key.packageName.equals(name)) {
+ if (!pir.key.packageName.equals(packageName)) {
// Different package, skip it.
continue;
}
@@ -5510,10 +5593,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (doit) {
- if (purgeCache && name != null) {
+ if (purgeCache && packageName != null) {
AttributeCache ac = AttributeCache.instance();
if (ac != null) {
- ac.removePackage(name);
+ ac.removePackage(packageName);
}
}
if (mBooted) {
@@ -8331,29 +8414,20 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- private void removeTasksByRemovedPackageComponentsLocked(String packageName, int userId) {
- final IPackageManager pm = AppGlobals.getPackageManager();
- final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
+ private void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
+ int userId) {
for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
TaskRecord tr = mRecentTasks.get(i);
- if (tr.userId != userId) continue;
+ if (userId != UserHandle.USER_ALL && tr.userId != userId) {
+ continue;
+ }
ComponentName cn = tr.intent.getComponent();
- if (cn != null && cn.getPackageName().equals(packageName)) {
- // Skip if component still exists in the package.
- if (componentsKnownToExist.contains(cn)) continue;
-
- try {
- ActivityInfo info = pm.getActivityInfo(cn, 0, userId);
- if (info != null) {
- componentsKnownToExist.add(cn);
- } else {
- removeTaskByIdLocked(tr.taskId, false);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Activity info query failed. component=" + cn, e);
- }
+ final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
+ && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
+ if (sameComponent) {
+ removeTaskByIdLocked(tr.taskId, false);
}
}
}
@@ -9773,10 +9847,10 @@ public final class ActivityManagerService extends ActivityManagerNative
String proc = customProcess != null ? customProcess : info.processName;
BatteryStatsImpl.Uid.Proc ps = null;
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+ final int userId = UserHandle.getUserId(info.uid);
int uid = info.uid;
if (isolated) {
if (isolatedUid == 0) {
- int userId = UserHandle.getUserId(uid);
int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
while (true) {
if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID
@@ -9800,7 +9874,13 @@ public final class ActivityManagerService extends ActivityManagerNative
uid = isolatedUid;
}
}
- return new ProcessRecord(stats, info, proc, uid);
+ final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
+ if (!mBooted && !mBooting
+ && userId == UserHandle.USER_OWNER
+ && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+ r.persistent = true;
+ }
+ return r;
}
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
@@ -9832,8 +9912,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ info.packageName + ": " + e);
}
- if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
- == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
+ if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
@@ -14121,6 +14200,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean dumpDetails = false;
boolean dumpFullDetails = false;
boolean dumpDalvik = false;
+ boolean dumpSummaryOnly = false;
boolean oomOnly = false;
boolean isCompact = false;
boolean localOnly = false;
@@ -14141,6 +14221,9 @@ public final class ActivityManagerService extends ActivityManagerNative
dumpDalvik = true;
} else if ("-c".equals(opt)) {
isCompact = true;
+ } else if ("-s".equals(opt)) {
+ dumpDetails = true;
+ dumpSummaryOnly = true;
} else if ("--oom".equals(opt)) {
oomOnly = true;
} else if ("--local".equals(opt)) {
@@ -14148,10 +14231,11 @@ public final class ActivityManagerService extends ActivityManagerNative
} else if ("--package".equals(opt)) {
packages = true;
} else if ("-h".equals(opt)) {
- pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]");
+ pw.println("meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]");
pw.println(" -a: include all available information for each process.");
pw.println(" -d: include dalvik details.");
pw.println(" -c: dump in a compact machine-parseable representation.");
+ pw.println(" -s: dump only summary of application memory usage.");
pw.println(" --oom: only show processes organized by oom adj.");
pw.println(" --local: only collect details locally, don't call process.");
pw.println(" --package: interpret process arg as package, dumping all");
@@ -14212,7 +14296,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mi.dalvikPrivateDirty = (int)tmpLong[0];
}
ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
- dumpDalvik, pid, r.baseName, 0, 0, 0, 0, 0, 0);
+ dumpDalvik, dumpSummaryOnly, pid, r.baseName, 0, 0, 0, 0, 0, 0);
if (isCheckinRequest) {
pw.println();
}
@@ -14278,7 +14362,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (dumpDetails) {
if (localOnly) {
ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
- dumpDalvik, pid, r.processName, 0, 0, 0, 0, 0, 0);
+ dumpDalvik, dumpSummaryOnly, pid, r.processName, 0, 0, 0, 0, 0, 0);
if (isCheckinRequest) {
pw.println();
}
@@ -14286,7 +14370,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
pw.flush();
thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
- dumpDalvik, innerArgs);
+ dumpDalvik, dumpSummaryOnly, innerArgs);
} catch (RemoteException e) {
if (!isCheckinRequest) {
pw.println("Got RemoteException!");
@@ -16071,7 +16155,9 @@ public final class ActivityManagerService extends ActivityManagerNative
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
- removeTasksByRemovedPackageComponentsLocked(ssp, userId);
+ cleanupDisabledPackageComponentsLocked(ssp, userId,
+ intent.getStringArrayExtra(
+ Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
if (userId == UserHandle.USER_OWNER) {
mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
}
@@ -16089,9 +16175,6 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
- if (replacing) {
- removeTasksByRemovedPackageComponentsLocked(ssp, userId);
- }
if (userId == UserHandle.USER_OWNER) {
mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
}
@@ -19868,6 +19951,14 @@ public final class ActivityManagerService extends ActivityManagerNative
return token;
}
}
+
+ @Override
+ public ComponentName getHomeActivityForUser(int userId) {
+ synchronized (ActivityManagerService.this) {
+ ActivityRecord homeActivity = mStackSupervisor.getHomeActivityForUser(userId);
+ return homeActivity == null ? null : homeActivity.realActivity;
+ }
+ }
}
private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 62d70d2..a86df2d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -81,6 +81,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* State and management of a single stack of activities.
@@ -4000,7 +4001,8 @@ final class ActivityStack {
}
}
- boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
+ boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
+ boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
TaskRecord lastTask = null;
ComponentName homeActivity = null;
@@ -4009,10 +4011,12 @@ final class ActivityStack {
int numActivities = activities.size();
for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
ActivityRecord r = activities.get(activityNdx);
- final boolean samePackage = r.packageName.equals(name)
- || (name == null && r.userId == userId);
+ final boolean sameComponent =
+ (r.packageName.equals(packageName) && (filterByClasses == null
+ || filterByClasses.contains(r.realActivity.getClassName())))
+ || (packageName == null && r.userId == userId);
if ((userId == UserHandle.USER_ALL || r.userId == userId)
- && (samePackage || r.task == lastTask)
+ && (sameComponent || r.task == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (!doit) {
if (r.finishing) {
@@ -4032,7 +4036,7 @@ final class ActivityStack {
}
didSomething = true;
Slog.i(TAG, " Force finishing activity " + r);
- if (samePackage) {
+ if (sameComponent) {
if (r.app != null) {
r.app.removed = true;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8c98f9f..cb5ba8e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -118,6 +118,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
public final class ActivityStackSupervisor implements DisplayListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
@@ -2507,14 +2508,16 @@ public final class ActivityStackSupervisor implements DisplayListener {
/**
* @return true if some activity was finished (or would have finished if doit were true).
*/
- boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
+ boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
+ boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
+ if (stack.finishDisabledPackageActivitiesLocked(
+ packageName, filterByClasses, doit, evenPersistent, userId)) {
didSomething = true;
}
}
@@ -2653,6 +2656,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
ActivityRecord getHomeActivity() {
+ return getHomeActivityForUser(UserHandle.USER_ALL);
+ }
+
+ ActivityRecord getHomeActivityForUser(int userId) {
final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = tasks.get(taskNdx);
@@ -2660,7 +2667,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
- if (r.isHomeActivity()) {
+ if (r.isHomeActivity()
+ && ((userId == UserHandle.USER_ALL) || (r.userId == userId))) {
return r;
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index e5c5dff..e89ef57 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -85,7 +85,7 @@ public final class BroadcastQueue {
* a bunch of processes to execute IntentReceiver components. Background-
* and foreground-priority broadcasts are queued separately.
*/
- final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();
+ final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
/**
* List of all active broadcasts that are to be executed one at a time.
@@ -94,7 +94,7 @@ public final class BroadcastQueue {
* broadcasts, separate background- and foreground-priority queues are
* maintained.
*/
- final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>();
+ final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
/**
* Historical data of past broadcasts, for debugging. This is a ring buffer
diff --git a/services/core/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java
index 7da8c48..a1dc3e3 100644
--- a/services/core/java/com/android/server/am/ProviderMap.java
+++ b/services/core/java/com/android/server/am/ProviderMap.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
/**
* Keeps track of content providers by authority (name) and class. It separates the mapping by
@@ -184,13 +185,17 @@ public final class ProviderMap {
}
}
- private boolean collectForceStopProvidersLocked(String name, int appId,
- boolean doit, boolean evenPersistent, int userId,
+ private boolean collectPackageProvidersLocked(String packageName,
+ Set<String> filterByClasses, boolean doit, boolean evenPersistent,
HashMap<ComponentName, ContentProviderRecord> providers,
ArrayList<ContentProviderRecord> result) {
boolean didSomething = false;
for (ContentProviderRecord provider : providers.values()) {
- if ((name == null || provider.info.packageName.equals(name))
+ final boolean sameComponent = packageName == null
+ || (provider.info.packageName.equals(packageName)
+ && (filterByClasses == null
+ || filterByClasses.contains(provider.name.getClassName())));
+ if (sameComponent
&& (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
if (!doit) {
return true;
@@ -202,18 +207,18 @@ public final class ProviderMap {
return didSomething;
}
- boolean collectForceStopProviders(String name, int appId,
+ boolean collectPackageProvidersLocked(String packageName, Set<String> filterByClasses,
boolean doit, boolean evenPersistent, int userId,
ArrayList<ContentProviderRecord> result) {
- boolean didSomething = collectForceStopProvidersLocked(name, appId, doit,
- evenPersistent, userId, mSingletonByClass, result);
+ boolean didSomething = collectPackageProvidersLocked(packageName, filterByClasses,
+ doit, evenPersistent, mSingletonByClass, result);
if (!doit && didSomething) {
return true;
}
if (userId == UserHandle.USER_ALL) {
- for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
- if (collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
- userId, mProvidersByClassPerUser.valueAt(i), result)) {
+ for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
+ if (collectPackageProvidersLocked(packageName, filterByClasses,
+ doit, evenPersistent, mProvidersByClassPerUser.valueAt(i), result)) {
if (!doit) {
return true;
}
@@ -224,8 +229,8 @@ public final class ProviderMap {
HashMap<ComponentName, ContentProviderRecord> items
= getProvidersByClass(userId);
if (items != null) {
- didSomething |= collectForceStopProvidersLocked(name, appId, doit,
- evenPersistent, userId, items, result);
+ didSomething |= collectPackageProvidersLocked(packageName, filterByClasses,
+ doit, evenPersistent, items, result);
}
}
return didSomething;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 06fba34..2149b7a 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -20,9 +20,13 @@ import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
+import static android.os.Process.FIRST_APPLICATION_UID;
+import android.Manifest;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.KeyguardManager;
import android.bluetooth.BluetoothA2dp;
@@ -37,7 +41,10 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -82,11 +89,13 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.System;
import android.telecom.TelecomManager;
import android.text.TextUtils;
+import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -102,6 +111,7 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.util.XmlUtils;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerService;
import org.xmlpull.v1.XmlPullParserException;
@@ -645,6 +655,8 @@ public class AudioService extends IAudioService.Stub {
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
+ intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -668,7 +680,7 @@ public class AudioService extends IAudioService.Stub {
setRotationForAudioSystem();
}
- context.registerReceiver(mReceiver, intentFilter);
+ context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
}
@@ -4975,10 +4987,62 @@ public class AudioService extends IAudioService.Stub {
0,
0,
mStreamStates[AudioSystem.STREAM_MUSIC], 0);
+ } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
+ // Disable audio recording for the background user/profile
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ if (userId >= 0) {
+ // TODO Kill recording streams instead of killing processes holding permission
+ UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
+ killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
+ }
+ UserManagerService.getInstance().setSystemControlledUserRestriction(
+ UserManager.DISALLOW_RECORD_AUDIO, true, userId);
+ } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
+ // Enable audio recording for foreground user/profile
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ UserManagerService.getInstance().setSystemControlledUserRestriction(
+ UserManager.DISALLOW_RECORD_AUDIO, false, userId);
}
}
} // end class AudioServiceBroadcastReceiver
+ private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
+ PackageManager pm = mContext.getPackageManager();
+ // Find the home activity of the user. It should not be killed to avoid expensive restart,
+ // when the user switches back. For managed profiles, we should kill all recording apps
+ ComponentName homeActivityName = null;
+ if (!oldUser.isManagedProfile()) {
+ homeActivityName = LocalServices.getService(ActivityManagerInternal.class)
+ .getHomeActivityForUser(oldUser.id);
+ }
+ final String[] permissions = { Manifest.permission.RECORD_AUDIO };
+ List<PackageInfo> packages;
+ try {
+ packages = AppGlobals.getPackageManager()
+ .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
+ } catch (RemoteException e) {
+ throw new AndroidRuntimeException(e);
+ }
+ for (int j = packages.size() - 1; j >= 0; j--) {
+ PackageInfo pkg = packages.get(j);
+ // Skip system processes
+ if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
+ continue;
+ }
+ if (homeActivityName != null
+ && pkg.packageName.equals(homeActivityName.getPackageName())
+ && pkg.applicationInfo.isSystemApp()) {
+ continue;
+ }
+ try {
+ ActivityManagerNative.getDefault().killUid(pkg.applicationInfo.uid,
+ "killBackgroundUserProcessesWithAudioRecordPermission");
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling killUid", e);
+ }
+ }
+ }
+
//==========================================================================================
// RemoteControlDisplay / RemoteControlClient / Remote info
//==========================================================================================
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index ac55292..aeecdf3 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -217,14 +217,21 @@ public class Vpn {
* @return true if the operation is succeeded.
*/
public synchronized boolean prepare(String oldPackage, String newPackage) {
- if (oldPackage != null && getAppUid(oldPackage, mUserHandle) != mOwnerUID) {
- // The package doesn't match. We return false (to obtain user consent) unless the user
- // has already consented to that VPN package.
- if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) {
- prepareInternal(oldPackage);
- return true;
+ if (oldPackage != null) {
+ if (getAppUid(oldPackage, mUserHandle) != mOwnerUID) {
+ // The package doesn't match. We return false (to obtain user consent) unless the
+ // user has already consented to that VPN package.
+ if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) {
+ prepareInternal(oldPackage);
+ return true;
+ }
+ return false;
+ } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN)
+ && !isVpnUserPreConsented(oldPackage)) {
+ // Currently prepared VPN is revoked, so unprepare it and return false.
+ prepareInternal(VpnConfig.LEGACY_VPN);
+ return false;
}
- return false;
}
// Return true if we do not need to revoke.
@@ -481,6 +488,10 @@ public class Vpn {
if (Binder.getCallingUid() != mOwnerUID) {
return null;
}
+ // Check to ensure consent hasn't been revoked since we were prepared.
+ if (!isVpnUserPreConsented(mPackage)) {
+ return null;
+ }
// Check if the service is properly declared.
Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
intent.setClassName(mPackage, config.user);
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 6f59b54..7f961ae 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -82,7 +82,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
appToken.linkToDeath(device, 0);
} catch (RemoteException ex) {
mVirtualDisplayDevices.remove(appToken);
- device.destroyLocked();
+ device.destroyLocked(false);
return null;
}
@@ -110,7 +110,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
if (device != null) {
- device.destroyLocked();
+ device.destroyLocked(true);
appToken.unlinkToDeath(device, 0);
}
@@ -147,7 +147,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
if (device != null) {
Slog.i(TAG, "Virtual display device released because application token died: "
+ device.mOwnerPackageName);
- device.destroyLocked();
+ device.destroyLocked(false);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
}
}
@@ -205,19 +205,19 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
@Override
public void binderDied() {
synchronized (getSyncRoot()) {
- if (mSurface != null) {
- handleBinderDiedLocked(mAppToken);
- }
+ handleBinderDiedLocked(mAppToken);
}
}
- public void destroyLocked() {
+ public void destroyLocked(boolean binderAlive) {
if (mSurface != null) {
mSurface.release();
mSurface = null;
}
SurfaceControl.destroyDisplay(getDisplayTokenLocked());
- mCallback.dispatchDisplayStopped();
+ if (binderAlive) {
+ mCallback.dispatchDisplayStopped();
+ }
}
@Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index e650456..51ba32d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -906,14 +906,22 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
private void updateArcFeatureStatus(int portId, boolean isConnected) {
assertRunOnServiceThread();
+ HdmiPortInfo portInfo = mService.getPortInfo(portId);
+ if (!portInfo.isArcSupported()) {
+ return;
+ }
HdmiDeviceInfo avr = getAvrDeviceInfo();
if (avr == null) {
+ if (isConnected) {
+ // Update the status (since TV may not have seen AVR yet) so
+ // that ARC can be initiated after discovery.
+ mArcFeatureEnabled.put(portId, isConnected);
+ }
return;
}
// HEAC 2.4, HEACT 5-15
// Should not activate ARC if +5V status is false.
- HdmiPortInfo portInfo = mService.getPortInfo(portId);
- if (avr.getPortId() == portId && portInfo.isArcSupported()) {
+ if (avr.getPortId() == portId) {
changeArcFeatureEnabled(portId, isConnected);
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 65949bf..8086461 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -765,8 +765,9 @@ public class MediaSessionService extends SystemService implements Monitor {
// If we don't have a media button receiver to fall back on
// include non-playing sessions for dispatching
UserRecord ur = mUserRecords.get(ActivityManager.getCurrentUser());
- boolean useNotPlayingSessions = ur.mLastMediaButtonReceiver == null
- && ur.mRestoredMediaButtonReceiver == null;
+ boolean useNotPlayingSessions = (ur == null) ||
+ (ur.mLastMediaButtonReceiver == null
+ && ur.mRestoredMediaButtonReceiver == null);
MediaSessionRecord session = mPriorityStack
.getDefaultMediaButtonSession(mCurrentUserId, useNotPlayingSessions);
if (isVoiceKey(keyEvent.getKeyCode())) {
diff --git a/services/core/java/com/android/server/notification/CalendarTracker.java b/services/core/java/com/android/server/notification/CalendarTracker.java
index 28da73c..71d7f19 100644
--- a/services/core/java/com/android/server/notification/CalendarTracker.java
+++ b/services/core/java/com/android/server/notification/CalendarTracker.java
@@ -16,6 +16,8 @@
package com.android.server.notification;
+import static android.service.notification.ZenModeConfig.EventInfo.ANY_CALENDAR;
+
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
@@ -150,7 +152,7 @@ public class CalendarTracker {
eventId, owner, calendarId));
final boolean meetsTime = time >= begin && time < end;
final boolean meetsCalendar = visible
- && (filter.calendar == 0 || filter.calendar == calendarId)
+ && (filter.calendar == ANY_CALENDAR || filter.calendar == calendarId)
&& availability != Instances.AVAILABILITY_FREE;
if (meetsCalendar) {
if (DEBUG) Log.d(TAG, " MEETS CALENDAR");
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index b92c734..6f8e3ca 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -189,6 +189,10 @@ abstract public class ManagedServices {
}
}
+ public boolean isComponentEnabledForPackage(String pkg) {
+ return mEnabledServicesPackageNames.contains(pkg);
+ }
+
public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
+ " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 25998da..791c1de 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -37,7 +37,6 @@ import android.app.NotificationManager.Policy;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.usage.UsageEvents;
-import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -233,7 +232,7 @@ public class NotificationManagerService extends SystemService {
new ArrayMap<String, NotificationRecord>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
- private final ArrayMap<String, Policy.Token> mPolicyTokens = new ArrayMap<>();
+ private final ArrayMap<String, Boolean> mPolicyAccess = new ArrayMap<>();
// The last key in this list owns the hardware.
@@ -899,6 +898,7 @@ public class NotificationManagerService extends SystemService {
@Override
void onZenModeChanged() {
+ sendRegisteredOnlyBroadcast(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
synchronized(mNotificationList) {
updateInterruptionFilterLocked();
}
@@ -906,9 +906,12 @@ public class NotificationManagerService extends SystemService {
@Override
void onPolicyChanged() {
- getContext().sendBroadcast(
- new Intent(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED)
- .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
+ sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
+ }
+
+ private void sendRegisteredOnlyBroadcast(String action) {
+ getContext().sendBroadcast(new Intent(action)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
}
});
final File systemDir = new File(Environment.getDataDirectory(), "system");
@@ -1607,6 +1610,19 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ public void setInterruptionFilter(String pkg, int filter) throws RemoteException {
+ enforcePolicyAccess(pkg, "setInterruptionFilter");
+ final int zen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
+ if (zen == -1) throw new IllegalArgumentException("Invalid filter: " + filter);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mZenModeHelper.setManualZenMode(zen, null, "setInterruptionFilter");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void notifyConditions(String pkg, IConditionProvider provider,
Condition[] conditions) {
final ManagedServiceInfo info = mConditionProviders.checkServiceToken(provider);
@@ -1641,16 +1657,19 @@ public class NotificationManagerService extends SystemService {
message);
}
- private void enforcePolicyToken(Policy.Token token, String method) {
- if (!checkPolicyToken(token)) {
- Slog.w(TAG, "Invalid notification policy token calling " + method);
- throw new SecurityException("Invalid notification policy token");
+ private void enforcePolicyAccess(String pkg, String method) {
+ if (!checkPolicyAccess(pkg)) {
+ Slog.w(TAG, "Notification policy access denied calling " + method);
+ throw new SecurityException("Notification policy access denied");
}
}
- private boolean checkPolicyToken(Policy.Token token) {
- return mPolicyTokens.containsValue(token)
- || mListeners.mPolicyTokens.containsValue(token);
+ private boolean checkPackagePolicyAccess(String pkg) {
+ return Boolean.TRUE.equals(mPolicyAccess.get(pkg));
+ }
+
+ private boolean checkPolicyAccess(String pkg) {
+ return checkPackagePolicyAccess(pkg) || mListeners.isComponentEnabledForPackage(pkg);
}
@Override
@@ -1702,52 +1721,76 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public Policy.Token getPolicyTokenFromListener(INotificationListener listener) {
+ public void requestNotificationPolicyAccess(String pkg,
+ INotificationManagerCallback callback) throws RemoteException {
+ if (callback == null) {
+ Slog.w(TAG, "requestNotificationPolicyAccess: no callback specified");
+ return;
+ }
+ if (pkg == null) {
+ Slog.w(TAG, "requestNotificationPolicyAccess denied: no package specified");
+ callback.onPolicyRequestResult(false);
+ return;
+ }
final long identity = Binder.clearCallingIdentity();
try {
- return mListeners.getPolicyToken(listener);
+ synchronized (mNotificationList) {
+ // immediately grant for now
+ mPolicyAccess.put(pkg, true);
+ if (DBG) Slog.w(TAG, "requestNotificationPolicyAccess granted for " + pkg);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
+ callback.onPolicyRequestResult(true);
}
@Override
- public void requestNotificationPolicyToken(String pkg,
- INotificationManagerCallback callback) throws RemoteException {
- if (callback == null) {
- Slog.w(TAG, "requestNotificationPolicyToken: no callback specified");
- return;
- }
- if (pkg == null) {
- Slog.w(TAG, "requestNotificationPolicyToken denied: no package specified");
- callback.onPolicyToken(null);
- return;
- }
- Policy.Token token = null;
+ public boolean isNotificationPolicyAccessGranted(String pkg) {
+ return checkPolicyAccess(pkg);
+ }
+
+ @Override
+ public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
+ enforceSystemOrSystemUI("request policy access status for another package");
+ return checkPackagePolicyAccess(pkg);
+ }
+
+ @Override
+ public String[] getPackagesRequestingNotificationPolicyAccess()
+ throws RemoteException {
+ enforceSystemOrSystemUI("request policy access packages");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mNotificationList) {
- token = mPolicyTokens.get(pkg);
- if (token == null) {
- token = new Policy.Token(new Binder());
- mPolicyTokens.put(pkg, token);
+ final String[] rt = new String[mPolicyAccess.size()];
+ for (int i = 0; i < mPolicyAccess.size(); i++) {
+ rt[i] = mPolicyAccess.keyAt(i);
}
- if (DBG) Slog.w(TAG, "requestNotificationPolicyToken granted for " + pkg);
+ return rt;
}
} finally {
Binder.restoreCallingIdentity(identity);
}
- callback.onPolicyToken(token);
}
@Override
- public boolean isNotificationPolicyTokenValid(String pkg, Policy.Token token) {
- return checkPolicyToken(token);
+ public void setNotificationPolicyAccessGranted(String pkg, boolean granted)
+ throws RemoteException {
+ enforceSystemOrSystemUI("grant notification policy access");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mNotificationList) {
+ mPolicyAccess.put(pkg, granted);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
- public Policy getNotificationPolicy(Policy.Token token) {
- enforcePolicyToken(token, "getNotificationPolicy");
+ public Policy getNotificationPolicy(String pkg) {
+ enforcePolicyAccess(pkg, "getNotificationPolicy");
final long identity = Binder.clearCallingIdentity();
try {
return mZenModeHelper.getNotificationPolicy();
@@ -1757,8 +1800,8 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public void setNotificationPolicy(Policy.Token token, Policy policy) {
- enforcePolicyToken(token, "setNotificationPolicy");
+ public void setNotificationPolicy(String pkg, Policy policy) {
+ enforcePolicyAccess(pkg, "setNotificationPolicy");
final long identity = Binder.clearCallingIdentity();
try {
mZenModeHelper.setNotificationPolicy(policy);
@@ -1881,11 +1924,9 @@ public class NotificationManagerService extends SystemService {
pw.print(listener.component);
}
pw.println(')');
- pw.print(" mPolicyTokens.keys: ");
- pw.println(TextUtils.join(",", mPolicyTokens.keySet()));
- pw.print(" mListeners.mPolicyTokens.keys: ");
- pw.println(TextUtils.join(",", mListeners.mPolicyTokens.keySet()));
}
+ pw.println("\n Policy access:");
+ pw.print(" mPolicyAccess: "); pw.println(mPolicyAccess);
pw.println("\n Condition providers:");
mConditionProviders.dump(pw, filter);
@@ -3138,18 +3179,12 @@ public class NotificationManagerService extends SystemService {
public class NotificationListeners extends ManagedServices {
private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
- private final ArrayMap<ComponentName, Policy.Token> mPolicyTokens = new ArrayMap<>();
private boolean mNotificationGroupsDesired;
public NotificationListeners() {
super(getContext(), mHandler, mNotificationList, mUserProfiles);
}
- public Policy.Token getPolicyToken(INotificationListener listener) {
- final ManagedServiceInfo info = checkServiceTokenLocked(listener);
- return info == null ? null : mPolicyTokens.get(info.component);
- }
-
@Override
protected Config getConfig() {
Config c = new Config();
@@ -3174,7 +3209,6 @@ public class NotificationManagerService extends SystemService {
synchronized (mNotificationList) {
updateNotificationGroupsDesiredLocked();
update = makeRankingUpdateLocked(info);
- mPolicyTokens.put(info.component, new Policy.Token(new Binder()));
}
try {
listener.onListenerConnected(update);
@@ -3191,7 +3225,6 @@ public class NotificationManagerService extends SystemService {
}
mLightTrimListeners.remove(removed);
updateNotificationGroupsDesiredLocked();
- mPolicyTokens.remove(removed.component);
}
public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index e97def8..aeb6b78 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -22,6 +22,7 @@ import static android.media.AudioAttributes.USAGE_NOTIFICATION;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
import android.app.AppOpsManager;
+import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -42,6 +43,7 @@ import android.provider.Settings.Global;
import android.service.notification.IConditionListener;
import android.service.notification.NotificationListenerService;
import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.EventInfo;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenModeConfig.ZenRule;
import android.util.ArraySet;
@@ -90,6 +92,7 @@ public class ZenModeHelper {
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mDefaultConfig = readDefaultConfig(context.getResources());
appendDefaultScheduleRules(mDefaultConfig);
+ appendDefaultEventRules(mDefaultConfig);
mConfig = mDefaultConfig;
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
@@ -142,11 +145,11 @@ public class ZenModeHelper {
}
public int getZenModeListenerInterruptionFilter() {
- return getZenModeListenerInterruptionFilter(mZenMode);
+ return NotificationManager.zenModeToInterruptionFilter(mZenMode);
}
- public void requestFromListener(ComponentName name, int interruptionFilter) {
- final int newZen = zenModeFromListenerInterruptionFilter(interruptionFilter, -1);
+ public void requestFromListener(ComponentName name, int filter) {
+ final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
if (newZen != -1) {
setManualZenMode(newZen, null,
"listener:" + (name != null ? name.flattenToShortString() : null));
@@ -393,37 +396,6 @@ public class ZenModeHelper {
}
}
- private static int getZenModeListenerInterruptionFilter(int zen) {
- switch (zen) {
- case Global.ZEN_MODE_OFF:
- return NotificationListenerService.INTERRUPTION_FILTER_ALL;
- case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
- return NotificationListenerService.INTERRUPTION_FILTER_PRIORITY;
- case Global.ZEN_MODE_ALARMS:
- return NotificationListenerService.INTERRUPTION_FILTER_ALARMS;
- case Global.ZEN_MODE_NO_INTERRUPTIONS:
- return NotificationListenerService.INTERRUPTION_FILTER_NONE;
- default:
- return 0;
- }
- }
-
- private static int zenModeFromListenerInterruptionFilter(int listenerInterruptionFilter,
- int defValue) {
- switch (listenerInterruptionFilter) {
- case NotificationListenerService.INTERRUPTION_FILTER_ALL:
- return Global.ZEN_MODE_OFF;
- case NotificationListenerService.INTERRUPTION_FILTER_PRIORITY:
- return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
- case NotificationListenerService.INTERRUPTION_FILTER_ALARMS:
- return Global.ZEN_MODE_ALARMS;
- case NotificationListenerService.INTERRUPTION_FILTER_NONE:
- return Global.ZEN_MODE_NO_INTERRUPTIONS;
- default:
- return defValue;
- }
- }
-
private ZenModeConfig readDefaultConfig(Resources resources) {
XmlResourceParser parser = null;
try {
@@ -469,6 +441,20 @@ public class ZenModeHelper {
config.automaticRules.put(config.newRuleId(), rule2);
}
+ private void appendDefaultEventRules(ZenModeConfig config) {
+ if (config == null) return;
+
+ final EventInfo events = new EventInfo();
+ events.calendar = EventInfo.ANY_CALENDAR;
+ events.reply = EventInfo.REPLY_YES_OR_MAYBE;
+ final ZenRule rule = new ZenRule();
+ rule.enabled = false;
+ rule.name = mContext.getResources().getString(R.string.zen_mode_default_events_name);
+ rule.conditionId = ZenModeConfig.toEventConditionId(events);
+ rule.zenMode = Global.ZEN_MODE_ALARMS;
+ config.automaticRules.put(config.newRuleId(), rule);
+ }
+
private static int zenSeverity(int zen) {
switch (zen) {
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
@@ -511,6 +497,7 @@ public class ZenModeHelper {
Log.i(TAG, "No existing V1 downtime found, generating default schedules");
appendDefaultScheduleRules(rt);
}
+ appendDefaultEventRules(rt);
return rt;
}
};
diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java
index 30f8b37..18407c9 100644
--- a/services/core/java/com/android/server/pm/BasePermission.java
+++ b/services/core/java/com/android/server/pm/BasePermission.java
@@ -20,8 +20,6 @@ import android.content.pm.PackageParser;
import android.content.pm.PermissionInfo;
import android.os.UserHandle;
-import com.android.internal.util.ArrayUtils;
-
final class BasePermission {
final static int TYPE_NORMAL = 0;
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index a42e4e7..b505f7e 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -31,7 +31,6 @@ import java.util.ArrayList;
import java.util.List;
import dalvik.system.DexFile;
-import dalvik.system.StaleDexCacheError;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
@@ -112,61 +111,60 @@ final class PackageDexOptimizer {
}
for (String path : paths) {
- try {
- final int dexoptNeeded;
- if (forceDex) {
- dexoptNeeded = DexFile.DEX2OAT_NEEDED;
- } else {
- dexoptNeeded = DexFile.getDexOptNeeded(path,
- pkg.packageName, dexCodeInstructionSet, defer);
+ final int dexoptNeeded;
+ if (forceDex) {
+ dexoptNeeded = DexFile.DEX2OAT_NEEDED;
+ } else {
+ try {
+ dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
+ dexCodeInstructionSet, defer);
+ } catch (IOException ioe) {
+ Slog.w(TAG, "IOException reading apk: " + path, ioe);
+ return DEX_OPT_FAILED;
}
+ }
- if (!forceDex && defer && dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- // We're deciding to defer a needed dexopt. Don't bother dexopting for other
- // paths and instruction sets. We'll deal with them all together when we process
- // our list of deferred dexopts.
- addPackageForDeferredDexopt(pkg);
- return DEX_OPT_DEFERRED;
- }
+ if (!forceDex && defer && dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+ // We're deciding to defer a needed dexopt. Don't bother dexopting for other
+ // paths and instruction sets. We'll deal with them all together when we process
+ // our list of deferred dexopts.
+ addPackageForDeferredDexopt(pkg);
+ return DEX_OPT_DEFERRED;
+ }
- if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- final String dexoptType;
- String oatDir = null;
- if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
- dexoptType = "dex2oat";
+ if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+ final String dexoptType;
+ String oatDir = null;
+ if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
+ dexoptType = "dex2oat";
+ try {
oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
- } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
- dexoptType = "patchoat";
- } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
- dexoptType = "self patchoat";
- } else {
- throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
- }
- Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
- + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
- + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
- + " oatDir = " + oatDir);
- final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
- final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
- !pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet,
- dexoptNeeded, vmSafeMode, debuggable, oatDir);
- if (ret < 0) {
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Unable to create oatDir for package: " + pkg.packageName);
return DEX_OPT_FAILED;
}
+ } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
+ dexoptType = "patchoat";
+ } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
+ dexoptType = "self patchoat";
+ } else {
+ throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
+ }
+
+ Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
+ + " oatDir = " + oatDir);
+ final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
+ !pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet,
+ dexoptNeeded, vmSafeMode, debuggable, oatDir);
+
+ // Dex2oat might fail due to compiler / verifier errors. We soldier on
+ // regardless, and attempt to interpret the app as a safety net.
+ if (ret == 0) {
performedDexOpt = true;
}
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Apk not found for dexopt: " + path);
- return DEX_OPT_FAILED;
- } catch (IOException e) {
- Slog.w(TAG, "IOException reading apk: " + path, e);
- return DEX_OPT_FAILED;
- } catch (StaleDexCacheError e) {
- Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
- return DEX_OPT_FAILED;
- } catch (Exception e) {
- Slog.w(TAG, "Exception when doing dexopt : ", e);
- return DEX_OPT_FAILED;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dd5f7d4..477af72 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -206,6 +206,7 @@ import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.pm.Settings.DatabaseVersion;
+import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.storage.DeviceStorageMonitorInternal;
import org.xmlpull.v1.XmlPullParser;
@@ -304,6 +305,8 @@ public class PackageManagerService extends IPackageManager.Stub {
static final int REMOVE_CHATTY = 1<<16;
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
+
/**
* Timeout (in milliseconds) after which the watchdog should declare that
* our handler thread is wedged. The usual default for such things is one
@@ -3139,18 +3142,26 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ private static void enforceOnlySystemUpdatesPermissionPolicyFlags(int flagMask, int flagValues) {
+ if (((flagMask & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0
+ || (flagValues & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0)
+ && getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Only the system can modify policy flags");
+ }
+ }
+
@Override
- public void grantPermission(String packageName, String name, int userId) {
+ public void grantRuntimePermission(String packageName, String name, int userId) {
if (!sUserManager.exists(userId)) {
return;
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
- "grantPermission");
+ "grantRuntimePermission");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
- "grantPermission");
+ "grantRuntimePermission");
boolean gidsChanged = false;
final SettingBase sb;
@@ -3197,17 +3208,17 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- public void revokePermission(String packageName, String name, int userId) {
+ public void revokeRuntimePermission(String packageName, String name, int userId) {
if (!sUserManager.exists(userId)) {
return;
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
- "revokePermission");
+ "revokeRuntimePermission");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
- "revokePermission");
+ "revokeRuntimePermission");
final SettingBase sb;
@@ -3236,7 +3247,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
- // Critical, after this call all should never have the permission.
+ // Critical, after this call app should never have the permission.
mSettings.writeRuntimePermissionsForUserLPr(userId, true);
}
@@ -3244,6 +3255,86 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public int getPermissionFlags(String name, String packageName, int userId) {
+ if (!sUserManager.exists(userId)) {
+ return 0;
+ }
+
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
+ "getPermissionFlags");
+
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ "getPermissionFlags");
+
+ synchronized (mPackages) {
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+
+ final BasePermission bp = mSettings.mPermissions.get(name);
+ if (bp == null) {
+ throw new IllegalArgumentException("Unknown permission: " + name);
+ }
+
+ SettingBase sb = (SettingBase) pkg.mExtras;
+ if (sb == null) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+
+ PermissionsState permissionsState = sb.getPermissionsState();
+ return permissionsState.getPermissionFlags(name, userId);
+ }
+ }
+
+ @Override
+ public void updatePermissionFlags(String name, String packageName, int flagMask,
+ int flagValues, int userId) {
+ if (!sUserManager.exists(userId)) {
+ return;
+ }
+
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
+ "updatePermissionFlags");
+
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ "updatePermissionFlags");
+
+ enforceOnlySystemUpdatesPermissionPolicyFlags(flagMask, flagValues);
+
+ synchronized (mPackages) {
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+
+ final BasePermission bp = mSettings.mPermissions.get(name);
+ if (bp == null) {
+ throw new IllegalArgumentException("Unknown permission: " + name);
+ }
+
+ SettingBase sb = (SettingBase) pkg.mExtras;
+ if (sb == null) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+
+ PermissionsState permissionsState = sb.getPermissionsState();
+
+ if (permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues)) {
+ // Install and runtime permissions are stored in different places,
+ // so figure out what permission changed and persist the change.
+ if (permissionsState.getInstallPermissionState(name) != null) {
+ scheduleWriteSettingsLocked();
+ } else if (permissionsState.getRuntimePermissionState(name, userId) != null) {
+ mSettings.writeRuntimePermissionsForUserLPr(userId, false);
+ }
+ }
+ }
+ }
+
+ @Override
public boolean isProtectedBroadcast(String actionName) {
synchronized (mPackages) {
return mProtectedBroadcasts.contains(actionName);
@@ -7530,8 +7621,8 @@ public class PackageManagerService extends IPackageManager.Stub {
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
- int[] upgradeUserIds = PermissionsState.USERS_NONE;
- int[] changedRuntimePermissionUserIds = PermissionsState.USERS_NONE;
+ int[] upgradeUserIds = EMPTY_INT_ARRAY;
+ int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY;
boolean changedInstallPermission = false;
@@ -7657,11 +7748,18 @@ public class PackageManagerService extends IPackageManager.Stub {
// Grant previously granted runtime permissions.
for (int userId : UserManagerService.getInstance().getUserIds()) {
if (origPermissions.hasRuntimePermission(bp.name, userId)) {
+ PermissionState permissionState = origPermissions
+ .getRuntimePermissionState(bp.name, userId);
+ final int flags = permissionState.getFlags();
if (permissionsState.grantRuntimePermission(bp, userId) ==
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// If we cannot put the permission as it was, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
+ } else {
+ // Propagate the permission flags.
+ permissionsState.updatePermissionFlags(bp, userId,
+ flags, flags);
}
}
}
@@ -7669,13 +7767,28 @@ public class PackageManagerService extends IPackageManager.Stub {
case GRANT_UPGRADE: {
// Grant runtime permissions for a previously held install permission.
- permissionsState.revokeInstallPermission(bp);
- for (int userId : upgradeUserIds) {
- if (permissionsState.grantRuntimePermission(bp, userId) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // If we granted the permission, we have to write.
- changedRuntimePermissionUserIds = ArrayUtils.appendInt(
- changedRuntimePermissionUserIds, userId);
+ PermissionState permissionState = origPermissions
+ .getInstallPermissionState(bp.name);
+ final int flags = permissionState != null ? permissionState.getFlags() : 0;
+
+ origPermissions.revokeInstallPermission(bp);
+ // We will be transferring the permission flags, so clear them.
+ origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+
+ // If the permission is not to be promoted to runtime we ignore it and
+ // also its other flags as they are not applicable to install permissions.
+ if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
+ for (int userId : upgradeUserIds) {
+ if (permissionsState.grantRuntimePermission(bp, userId) !=
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // Transfer the permission flags.
+ permissionsState.updatePermissionFlags(bp, userId,
+ flags, flags);
+ // If we granted the permission, we have to write.
+ changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+ changedRuntimePermissionUserIds, userId);
+ }
}
}
} break;
@@ -7692,6 +7805,9 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
if (permissionsState.revokeInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // Also drop the permission flags.
+ permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
changedInstallPermission = true;
Slog.i(TAG, "Un-granting permission " + perm
+ " from package " + pkg.packageName
diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java
index 3749957..171a50d 100644
--- a/services/core/java/com/android/server/pm/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/PermissionsState.java
@@ -20,10 +20,13 @@ import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.SparseArray;
import com.android.internal.util.ArrayUtils;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Set;
/**
@@ -55,15 +58,8 @@ public final class PermissionsState {
/** The permission operation failed. */
public static final int PERMISSION_OPERATION_FAILURE = 3;
- public static final int[] USERS_ALL = {UserHandle.USER_ALL};
-
- public static final int[] USERS_NONE = {};
-
private static final int[] NO_GIDS = {};
- private static final int FLAG_INSTALL_PERMISSIONS = 1 << 0;
- private static final int FLAG_RUNTIME_PERMISSIONS = 1 << 1;
-
private ArrayMap<String, PermissionData> mPermissions;
private int[] mGlobalGids = NO_GIDS;
@@ -147,14 +143,16 @@ public final class PermissionsState {
}
/**
- * Grant a runtime permission.
+ * Grant a runtime permission for a given device user.
*
* @param permission The permission to grant.
+ * @param userId The device user id.
* @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
* or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
* #PERMISSION_OPERATION_FAILURE}.
*/
public int grantRuntimePermission(BasePermission permission, int userId) {
+ enforceValidUserId(userId);
if (userId == UserHandle.USER_ALL) {
return PERMISSION_OPERATION_FAILURE;
}
@@ -162,15 +160,18 @@ public final class PermissionsState {
}
/**
- * Revoke a runtime permission for a given device user.
+ * Revoke a runtime permission for a given device user.
*
* @param permission The permission to revoke.
* @param userId The device user id.
* @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
* or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
* #PERMISSION_OPERATION_FAILURE}.
+ *
+ * @see android.content.pm.PackageManager.PermissionFlags
*/
public int revokeRuntimePermission(BasePermission permission, int userId) {
+ enforceValidUserId(userId);
if (userId == UserHandle.USER_ALL) {
return PERMISSION_OPERATION_FAILURE;
}
@@ -178,17 +179,6 @@ public final class PermissionsState {
}
/**
- * Gets whether this state has a given permission, regardless if
- * it is install time or runtime one.
- *
- * @param name The permission name.
- * @return Whether this state has the permission.
- */
- public boolean hasPermission(String name) {
- return mPermissions != null && mPermissions.get(name) != null;
- }
-
- /**
* Gets whether this state has a given runtime permission for a
* given device user id.
*
@@ -197,6 +187,7 @@ public final class PermissionsState {
* @return Whether this state has the permission.
*/
public boolean hasRuntimePermission(String name, int userId) {
+ enforceValidUserId(userId);
return !hasInstallPermission(name) && hasPermission(name, userId);
}
@@ -211,36 +202,6 @@ public final class PermissionsState {
}
/**
- * Revokes a permission for all users regardless if it is an install or
- * a runtime permission.
- *
- * @param permission The permission to revoke.
- * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
- * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
- * #PERMISSION_OPERATION_FAILURE}.
- */
- public int revokePermission(BasePermission permission) {
- if (!hasPermission(permission.name)) {
- return PERMISSION_OPERATION_FAILURE;
- }
-
- int result = PERMISSION_OPERATION_SUCCESS;
-
- PermissionData permissionData = mPermissions.get(permission.name);
- for (int userId : permissionData.getUserIds()) {
- if (revokePermission(permission, userId)
- == PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
- result = PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
- break;
- }
- }
-
- mPermissions.remove(permission.name);
-
- return result;
- }
-
- /**
* Gets whether the state has a given permission for the specified
* user, regardless if this is an install or a runtime permission.
*
@@ -256,49 +217,133 @@ public final class PermissionsState {
}
PermissionData permissionData = mPermissions.get(name);
- return permissionData != null && permissionData.hasUserId(userId);
+ return permissionData != null && permissionData.isGranted(userId);
}
/**
- * Gets all permissions regardless if they are install or runtime.
+ * Gets all permissions for a given device user id regardless if they
+ * are install time or runtime permissions.
*
+ * @param userId The device user id.
* @return The permissions or an empty set.
*/
- public Set<String> getPermissions() {
- if (mPermissions != null) {
- return mPermissions.keySet();
+ public Set<String> getPermissions(int userId) {
+ enforceValidUserId(userId);
+
+ if (mPermissions == null) {
+ return Collections.emptySet();
}
- return Collections.emptySet();
+ Set<String> permissions = new ArraySet<>();
+
+ final int permissionCount = mPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ String permission = mPermissions.keyAt(i);
+
+ if (hasInstallPermission(permission)) {
+ permissions.add(permission);
+ }
+
+ if (userId != UserHandle.USER_ALL) {
+ if (hasRuntimePermission(permission, userId)) {
+ permissions.add(permission);
+ }
+ }
+ }
+
+ return permissions;
}
/**
- * Gets all permissions for a given device user id regardless if they
- * are install time or runtime permissions.
+ * Gets the state for an install permission or null if no such.
*
+ * @param name The permission name.
+ * @return The permission state.
+ */
+ public PermissionState getInstallPermissionState(String name) {
+ return getPermissionState(name, UserHandle.USER_ALL);
+ }
+
+ /**
+ * Gets the state for a runtime permission or null if no such.
+ *
+ * @param name The permission name.
* @param userId The device user id.
- * @return The permissions or an empty set.
+ * @return The permission state.
*/
- public Set<String> getPermissions(int userId) {
- return getPermissionsInternal(FLAG_INSTALL_PERMISSIONS | FLAG_RUNTIME_PERMISSIONS, userId);
+ public PermissionState getRuntimePermissionState(String name, int userId) {
+ enforceValidUserId(userId);
+ return getPermissionState(name, userId);
}
/**
- * Gets all runtime permissions.
+ * Gets all install permission states.
*
- * @return The permissions or an empty set.
+ * @return The permission states or an empty set.
*/
- public Set<String> getRuntimePermissions(int userId) {
- return getPermissionsInternal(FLAG_RUNTIME_PERMISSIONS, userId);
+ public List<PermissionState> getInstallPermissionStates() {
+ return getPermissionStatesInternal(UserHandle.USER_ALL);
}
/**
- * Gets all install permissions.
+ * Gets all runtime permission states.
*
- * @return The permissions or an empty set.
+ * @return The permission states or an empty set.
+ */
+ public List<PermissionState> getRuntimePermissionStates(int userId) {
+ enforceValidUserId(userId);
+ return getPermissionStatesInternal(userId);
+ }
+
+ /**
+ * Gets the flags for a permission regardless if it is install or
+ * runtime permission.
+ *
+ * @param name The permission name.
+ * @return The permission state or null if no such.
*/
- public Set<String> getInstallPermissions() {
- return getPermissionsInternal(FLAG_INSTALL_PERMISSIONS, UserHandle.USER_ALL);
+ public int getPermissionFlags(String name, int userId) {
+ PermissionState installPermState = getInstallPermissionState(name);
+ if (installPermState != null) {
+ return installPermState.getFlags();
+ }
+ PermissionState runtimePermState = getRuntimePermissionState(name, userId);
+ if (runtimePermState != null) {
+ return runtimePermState.getFlags();
+ }
+ return 0;
+ }
+
+ /**
+ * Update the flags associated with a given permission.
+ * @param permission The permission whose flags to update.
+ * @param userId The user for which to update.
+ * @param flagMask Mask for which flags to change.
+ * @param flagValues New values for the mask flags.
+ * @return Whether the permission flags changed.
+ */
+ public boolean updatePermissionFlags(BasePermission permission, int userId,
+ int flagMask, int flagValues) {
+ enforceValidUserId(userId);
+
+ final boolean mayChangeFlags = flagValues != 0 || flagMask != 0;
+
+ if (mPermissions == null) {
+ if (!mayChangeFlags) {
+ return false;
+ }
+ ensurePermissionData(permission);
+ }
+
+ PermissionData permissionData = mPermissions.get(permission.name);
+ if (permissionData == null) {
+ if (!mayChangeFlags) {
+ return false;
+ }
+ permissionData = ensurePermissionData(permission);
+ }
+
+ return permissionData.updateFlags(userId, flagMask, flagValues);
}
/**
@@ -357,36 +402,37 @@ public final class PermissionsState {
mPermissions = null;
}
- private Set<String> getPermissionsInternal(int flags, int userId) {
- enforceValidUserId(userId);
-
+ private PermissionState getPermissionState(String name, int userId) {
if (mPermissions == null) {
- return Collections.emptySet();
+ return null;
}
+ PermissionData permissionData = mPermissions.get(name);
+ if (permissionData == null) {
+ return null;
+ }
+ return permissionData.getPermissionState(userId);
+ }
- if (userId == UserHandle.USER_ALL) {
- flags = FLAG_INSTALL_PERMISSIONS;
+ private List<PermissionState> getPermissionStatesInternal(int userId) {
+ enforceValidUserId(userId);
+
+ if (mPermissions == null) {
+ return Collections.emptyList();
}
- Set<String> permissions = new ArraySet<>();
+ List<PermissionState> permissionStates = new ArrayList<>();
final int permissionCount = mPermissions.size();
for (int i = 0; i < permissionCount; i++) {
- String permission = mPermissions.keyAt(i);
+ PermissionData permissionData = mPermissions.valueAt(i);
- if ((flags & FLAG_INSTALL_PERMISSIONS) != 0) {
- if (hasInstallPermission(permission)) {
- permissions.add(permission);
- }
- }
- if ((flags & FLAG_RUNTIME_PERMISSIONS) != 0) {
- if (hasRuntimePermission(permission, userId)) {
- permissions.add(permission);
- }
+ PermissionState permissionState = permissionData.getPermissionState(userId);
+ if (permissionState != null) {
+ permissionStates.add(permissionState);
}
}
- return permissions;
+ return permissionStates;
}
private int grantPermission(BasePermission permission, int userId) {
@@ -397,17 +443,9 @@ public final class PermissionsState {
final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
- if (mPermissions == null) {
- mPermissions = new ArrayMap<>();
- }
-
- PermissionData permissionData = mPermissions.get(permission.name);
- if (permissionData == null) {
- permissionData = new PermissionData(permission);
- mPermissions.put(permission.name, permissionData);
- }
+ PermissionData permissionData = ensurePermissionData(permission);
- if (!permissionData.addUserId(userId)) {
+ if (!permissionData.grant(userId)) {
return PERMISSION_OPERATION_FAILURE;
}
@@ -431,16 +469,12 @@ public final class PermissionsState {
PermissionData permissionData = mPermissions.get(permission.name);
- if (!permissionData.removeUserId(userId)) {
+ if (!permissionData.revoke(userId)) {
return PERMISSION_OPERATION_FAILURE;
}
- if (permissionData.getUserIds() == USERS_NONE) {
- mPermissions.remove(permission.name);
- }
-
- if (mPermissions.isEmpty()) {
- mPermissions = null;
+ if (permissionData.isDefault()) {
+ ensureNoPermissionData(permission.name);
}
if (hasGids) {
@@ -468,9 +502,31 @@ public final class PermissionsState {
}
}
+ private PermissionData ensurePermissionData(BasePermission permission) {
+ if (mPermissions == null) {
+ mPermissions = new ArrayMap<>();
+ }
+ PermissionData permissionData = mPermissions.get(permission.name);
+ if (permissionData == null) {
+ permissionData = new PermissionData(permission);
+ mPermissions.put(permission.name, permissionData);
+ }
+ return permissionData;
+ }
+
+ private void ensureNoPermissionData(String name) {
+ if (mPermissions == null) {
+ return;
+ }
+ mPermissions.remove(name);
+ if (mPermissions.isEmpty()) {
+ mPermissions = null;
+ }
+ }
+
private static final class PermissionData {
private final BasePermission mPerm;
- private int[] mUserIds = USERS_NONE;
+ private SparseArray<PermissionState> mUserStates = new SparseArray<>();
public PermissionData(BasePermission perm) {
mPerm = perm;
@@ -478,11 +534,11 @@ public final class PermissionsState {
public PermissionData(PermissionData other) {
this(other.mPerm);
-
- if (other.mUserIds == USERS_ALL || other.mUserIds == USERS_NONE) {
- mUserIds = other.mUserIds;
- } else {
- mUserIds = Arrays.copyOf(other.mUserIds, other.mUserIds.length);
+ final int otherStateCount = other.mUserStates.size();
+ for (int i = 0; i < otherStateCount; i++) {
+ final int otherUserId = other.mUserStates.keyAt(i);
+ PermissionState otherState = other.mUserStates.valueAt(i);
+ mUserStates.put(otherUserId, new PermissionState(otherState));
}
}
@@ -490,53 +546,146 @@ public final class PermissionsState {
return mPerm.computeGids(userId);
}
- public int[] getUserIds() {
- return mUserIds;
- }
-
- public boolean hasUserId(int userId) {
- if (mUserIds == USERS_ALL) {
- return true;
+ public boolean isGranted(int userId) {
+ if (isInstallPermission()) {
+ userId = UserHandle.USER_ALL;
}
- if (userId != UserHandle.USER_ALL) {
- return ArrayUtils.contains(mUserIds, userId);
+ PermissionState userState = mUserStates.get(userId);
+ if (userState == null) {
+ return false;
}
- return false;
+ return userState.mGranted;
}
- public boolean addUserId(int userId) {
- if (hasUserId(userId)) {
+ public boolean grant(int userId) {
+ if (!isCompatibleUserId(userId)) {
return false;
}
- if (userId == UserHandle.USER_ALL) {
- mUserIds = USERS_ALL;
- return true;
+ if (isGranted(userId)) {
+ return false;
}
- mUserIds = ArrayUtils.appendInt(mUserIds, userId);
+ PermissionState userState = mUserStates.get(userId);
+ if (userState == null) {
+ userState = new PermissionState(mPerm.name);
+ mUserStates.put(userId, userState);
+ }
+
+ userState.mGranted = true;
return true;
}
- public boolean removeUserId(int userId) {
- if (!hasUserId(userId)) {
+ public boolean revoke(int userId) {
+ if (!isCompatibleUserId(userId)) {
return false;
}
- if (mUserIds == USERS_ALL) {
- mUserIds = UserManagerService.getInstance().getUserIds();
+ if (!isGranted(userId)) {
+ return false;
}
- mUserIds = ArrayUtils.removeInt(mUserIds, userId);
+ PermissionState userState = mUserStates.get(userId);
+ userState.mGranted = false;
- if (mUserIds.length == 0) {
- mUserIds = USERS_NONE;
+ if (userState.isDefault()) {
+ mUserStates.remove(userId);
}
return true;
}
+
+ public PermissionState getPermissionState(int userId) {
+ return mUserStates.get(userId);
+ }
+
+ public int getFlags(int userId) {
+ PermissionState userState = mUserStates.get(userId);
+ if (userState != null) {
+ return userState.mFlags;
+ }
+ return 0;
+ }
+
+ public boolean isDefault() {
+ return mUserStates.size() <= 0;
+ }
+
+ public static boolean isInstallPermissionKey(int userId) {
+ return userId == UserHandle.USER_ALL;
+ }
+
+ public boolean updateFlags(int userId, int flagMask, int flagValues) {
+ if (isInstallPermission()) {
+ userId = UserHandle.USER_ALL;
+ }
+
+ if (!isCompatibleUserId(userId)) {
+ return false;
+ }
+
+ final int newFlags = flagValues & flagMask;
+
+ PermissionState userState = mUserStates.get(userId);
+ if (userState != null) {
+ final int oldFlags = userState.mFlags;
+ userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
+ if (userState.isDefault()) {
+ mUserStates.remove(userId);
+ }
+ return userState.mFlags != oldFlags;
+ } else if (newFlags != 0) {
+ userState = new PermissionState(mPerm.name);
+ userState.mFlags = newFlags;
+ mUserStates.put(userId, userState);
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isCompatibleUserId(int userId) {
+ return isDefault() || !(isInstallPermission() ^ isInstallPermissionKey(userId));
+ }
+
+ private boolean isInstallPermission() {
+ return mUserStates.size() == 1
+ && mUserStates.get(UserHandle.USER_ALL) != null;
+ }
+ }
+
+ public static final class PermissionState {
+ private final String mName;
+ private boolean mGranted;
+ private int mFlags;
+
+ public PermissionState(String name) {
+ mName = name;
+ }
+
+ public PermissionState(PermissionState other) {
+ mName = other.mName;
+ mGranted = other.mGranted;
+ mFlags = other.mFlags;
+ }
+
+ public boolean isDefault() {
+ return !mGranted && mFlags == 0;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public boolean isGranted() {
+ return mGranted;
+ }
+
+ public int getFlags() {
+ return mFlags;
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 0c7f79d..c35258a 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -21,11 +21,13 @@ import android.content.pm.ApplicationInfo;
import java.util.Arrays;
abstract class SettingBase {
+ private static final int[] USERS_NONE = new int[0];
+
int pkgFlags;
int pkgPrivateFlags;
protected final PermissionsState mPermissionsState;
- private int[] mPermissionsUpdatedForUserIds = PermissionsState.USERS_NONE;
+ private int[] mPermissionsUpdatedForUserIds = USERS_NONE;
SettingBase(int pkgFlags, int pkgPrivateFlags) {
setFlags(pkgFlags);
@@ -53,7 +55,7 @@ abstract class SettingBase {
return;
}
- if (userIds == PermissionsState.USERS_NONE || userIds == PermissionsState.USERS_ALL) {
+ if (userIds == USERS_NONE) {
mPermissionsUpdatedForUserIds = userIds;
} else {
mPermissionsUpdatedForUserIds = Arrays.copyOf(userIds, userIds.length);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index fd70ce1..2e9656a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -60,6 +60,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.backup.PreferredActivityBackupHelper;
import com.android.server.pm.PackageManagerService.DumpState;
+import com.android.server.pm.PermissionsState.PermissionState;
import java.io.FileNotFoundException;
import java.util.Collection;
@@ -178,6 +179,8 @@ final class Settings {
private static final String ATTR_CODE = "code";
private static final String ATTR_NOT_LAUNCHED = "nl";
private static final String ATTR_ENABLED = "enabled";
+ private static final String ATTR_GRANTED = "granted";
+ private static final String ATTR_FLAGS = "flags";
private static final String ATTR_ENABLED_CALLER = "enabledCaller";
private static final String ATTR_STOPPED = "stopped";
// Legacy, here for reading older versions of the package-restrictions.
@@ -820,14 +823,20 @@ final class Settings {
}
if (!used) {
+ PermissionsState permissionsState = sus.getPermissionsState();
+
// Try to revoke as an install permission which is for all users.
- if (sus.getPermissionsState().revokeInstallPermission(bp) ==
+ // The package is gone - no need to keep flags for applying policy.
+ permissionsState.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+
+ if (permissionsState.revokeInstallPermission(bp) ==
PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
return UserHandle.USER_ALL;
}
// Try to revoke as an install permission which is per user.
- if (sus.getPermissionsState().revokeRuntimePermission(bp, userId) ==
+ if (permissionsState.revokeRuntimePermission(bp, userId) ==
PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
return userId;
}
@@ -1724,10 +1733,32 @@ final class Settings {
continue;
}
- if (permissionsState.grantInstallPermission(bp) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- Slog.w(PackageManagerService.TAG, "Permission already added: " + name);
- XmlUtils.skipCurrentTag(parser);
+ String grantedStr = parser.getAttributeValue(null, ATTR_GRANTED);
+ final boolean granted = grantedStr == null
+ || Boolean.parseBoolean(grantedStr);
+
+ String flagsStr = parser.getAttributeValue(null, ATTR_FLAGS);
+ final int flags = (flagsStr != null)
+ ? Integer.parseInt(flagsStr, 16) : 0;
+
+ if (granted) {
+ if (permissionsState.grantInstallPermission(bp) ==
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ Slog.w(PackageManagerService.TAG, "Permission already added: " + name);
+ XmlUtils.skipCurrentTag(parser);
+ } else {
+ permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, flags);
+ }
+ } else {
+ if (permissionsState.revokeInstallPermission(bp) ==
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ Slog.w(PackageManagerService.TAG, "Permission already added: " + name);
+ XmlUtils.skipCurrentTag(parser);
+ } else {
+ permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, flags);
+ }
}
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <permissions>: "
@@ -1737,17 +1768,19 @@ final class Settings {
}
}
- void writePermissionsLPr(XmlSerializer serializer, Set<String> permissions)
+ void writePermissionsLPr(XmlSerializer serializer, List<PermissionState> permissionStates)
throws IOException {
- if (permissions.isEmpty()) {
+ if (permissionStates.isEmpty()) {
return;
}
serializer.startTag(null, TAG_PERMISSIONS);
- for (String permission : permissions) {
+ for (PermissionState permissionState : permissionStates) {
serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME, permission);
+ serializer.attribute(null, ATTR_NAME, permissionState.getName());
+ serializer.attribute(null, ATTR_GRANTED, String.valueOf(permissionState.isGranted()));
+ serializer.attribute(null, ATTR_FLAGS, Integer.toHexString(permissionState.getFlags()));
serializer.endTag(null, TAG_ITEM);
}
@@ -1945,7 +1978,8 @@ final class Settings {
serializer.attribute(null, "userId",
Integer.toString(usr.userId));
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
- writePermissionsLPr(serializer, usr.getPermissionsState().getInstallPermissions());
+ writePermissionsLPr(serializer, usr.getPermissionsState()
+ .getInstallPermissionStates());
serializer.endTag(null, "shared-user");
}
@@ -2120,7 +2154,8 @@ final class Settings {
// If this is a shared user, the permissions will be written there.
if (pkg.sharedUser == null) {
- writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissions());
+ writePermissionsLPr(serializer, pkg.getPermissionsState()
+ .getInstallPermissionStates());
}
serializer.endTag(null, "updated-package");
@@ -2175,9 +2210,9 @@ final class Settings {
serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
}
pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
- if ((pkg.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissions());
- }
+
+ writePermissionsLPr(serializer, pkg.getPermissionsState()
+ .getInstallPermissionStates());
writeSigningKeySetLPr(serializer, pkg.keySetData);
writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
@@ -3922,7 +3957,7 @@ final class Settings {
PermissionsState permissionsState = ps.getPermissionsState();
dumpGidsLPr(pw, prefix + " ", permissionsState.computeGids(user.id));
dumpRuntimePermissionsLPr(pw, prefix + " ", permissionsState
- .getRuntimePermissions(user.id));
+ .getRuntimePermissionStates(user.id));
}
ArraySet<String> cmp = ps.getDisabledComponents(user.id);
@@ -4071,7 +4106,8 @@ final class Settings {
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int[] gids = permissionsState.computeGids(userId);
- Set<String> permissions = permissionsState.getRuntimePermissions(userId);
+ List<PermissionState> permissions = permissionsState
+ .getRuntimePermissionStates(userId);
if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) {
pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": ");
dumpGidsLPr(pw, prefix + " ", gids);
@@ -4120,22 +4156,29 @@ final class Settings {
}
}
- void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, Set<String> permissions) {
- if (!permissions.isEmpty()) {
+ void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix,
+ List<PermissionState> permissionStates) {
+ if (!permissionStates.isEmpty()) {
pw.print(prefix); pw.println("runtime permissions:");
- for (String permission : permissions) {
- pw.print(prefix); pw.print(" "); pw.println(permission);
+ for (PermissionState permissionState : permissionStates) {
+ pw.print(prefix); pw.print(" "); pw.print(permissionState.getName());
+ pw.print(", granted="); pw.print(permissionState.isGranted());
+ pw.print(", flags=0x"); pw.println(Integer.toHexString(
+ permissionState.getFlags()));
}
}
}
void dumpInstallPermissionsLPr(PrintWriter pw, String prefix,
PermissionsState permissionsState) {
- Set<String> permissions = permissionsState.getInstallPermissions();
- if (!permissions.isEmpty()) {
+ List<PermissionState> permissionStates = permissionsState.getInstallPermissionStates();
+ if (!permissionStates.isEmpty()) {
pw.print(prefix); pw.println("install permissions:");
- for (String permission : permissions) {
- pw.print(prefix); pw.print(" "); pw.println(permission);
+ for (PermissionState permissionState : permissionStates) {
+ pw.print(prefix); pw.print(" "); pw.print(permissionState.getName());
+ pw.print(", granted="); pw.print(permissionState.isGranted());
+ pw.print(", flags=0x"); pw.println(Integer.toHexString(
+ permissionState.getFlags()));
}
}
}
@@ -4207,8 +4250,8 @@ final class Settings {
private void writePermissionsSync(int userId) {
AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId));
- ArrayMap<String, Set<String>> permissionsForPackage = new ArrayMap<>();
- ArrayMap<String, Set<String>> permissionsForSharedUser = new ArrayMap<>();
+ ArrayMap<String, List<PermissionState>> permissionsForPackage = new ArrayMap<>();
+ ArrayMap<String, List<PermissionState>> permissionsForSharedUser = new ArrayMap<>();
synchronized (mLock) {
mWriteScheduled.delete(userId);
@@ -4219,9 +4262,10 @@ final class Settings {
PackageSetting packageSetting = mPackages.valueAt(i);
if (packageSetting.sharedUser == null) {
PermissionsState permissionsState = packageSetting.getPermissionsState();
- Set<String> permissions = permissionsState.getRuntimePermissions(userId);
- if (!permissions.isEmpty()) {
- permissionsForPackage.put(packageName, permissions);
+ List<PermissionState> permissionsStates = permissionsState
+ .getRuntimePermissionStates(userId);
+ if (!permissionsStates.isEmpty()) {
+ permissionsForPackage.put(packageName, permissionsStates);
}
}
}
@@ -4231,9 +4275,10 @@ final class Settings {
String sharedUserName = mSharedUsers.keyAt(i);
SharedUserSetting sharedUser = mSharedUsers.valueAt(i);
PermissionsState permissionsState = sharedUser.getPermissionsState();
- Set<String> permissions = permissionsState.getRuntimePermissions(userId);
- if (!permissions.isEmpty()) {
- permissionsForSharedUser.put(sharedUserName, permissions);
+ List<PermissionState> permissionsStates = permissionsState
+ .getRuntimePermissionStates(userId);
+ if (!permissionsStates.isEmpty()) {
+ permissionsForSharedUser.put(sharedUserName, permissionsStates);
}
}
}
@@ -4252,20 +4297,20 @@ final class Settings {
final int packageCount = permissionsForPackage.size();
for (int i = 0; i < packageCount; i++) {
String packageName = permissionsForPackage.keyAt(i);
- Set<String> permissions = permissionsForPackage.valueAt(i);
+ List<PermissionState> permissionStates = permissionsForPackage.valueAt(i);
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, packageName);
- writePermissions(serializer, permissions);
+ writePermissions(serializer, permissionStates);
serializer.endTag(null, TAG_PACKAGE);
}
final int sharedUserCount = permissionsForSharedUser.size();
for (int i = 0; i < sharedUserCount; i++) {
String packageName = permissionsForSharedUser.keyAt(i);
- Set<String> permissions = permissionsForSharedUser.valueAt(i);
+ List<PermissionState> permissionStates = permissionsForSharedUser.valueAt(i);
serializer.startTag(null, TAG_SHARED_USER);
serializer.attribute(null, ATTR_NAME, packageName);
- writePermissions(serializer, permissions);
+ writePermissions(serializer, permissionStates);
serializer.endTag(null, TAG_SHARED_USER);
}
@@ -4290,20 +4335,23 @@ final class Settings {
mHandler.removeMessages(userId);
for (SettingBase sb : mPackages.values()) {
- revokeRuntimePermissions(sb, userId);
+ revokeRuntimePermissionsAndClearFlags(sb, userId);
}
for (SettingBase sb : mSharedUsers.values()) {
- revokeRuntimePermissions(sb, userId);
+ revokeRuntimePermissionsAndClearFlags(sb, userId);
}
}
- private void revokeRuntimePermissions(SettingBase sb, int userId) {
+ private void revokeRuntimePermissionsAndClearFlags(SettingBase sb, int userId) {
PermissionsState permissionsState = sb.getPermissionsState();
- for (String permission : permissionsState.getRuntimePermissions(userId)) {
- BasePermission bp = mPermissions.get(permission);
+ for (PermissionState permissionState
+ : permissionsState.getRuntimePermissionStates(userId)) {
+ BasePermission bp = mPermissions.get(permissionState.getName());
if (bp != null) {
permissionsState.revokeRuntimePermission(bp, userId);
+ permissionsState.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
}
}
}
@@ -4391,20 +4439,47 @@ final class Settings {
continue;
}
- if (permissionsState.grantRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
+ String grantedStr = parser.getAttributeValue(null, ATTR_GRANTED);
+ final boolean granted = grantedStr == null
+ || Boolean.parseBoolean(grantedStr);
+
+ String flagsStr = parser.getAttributeValue(null, ATTR_FLAGS);
+ final int flags = (flagsStr != null)
+ ? Integer.parseInt(flagsStr, 16) : 0;
+
+ if (granted) {
+ if (permissionsState.grantRuntimePermission(bp, userId) ==
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
+ } else {
+ permissionsState.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS, flags);
+
+ }
+ } else {
+ if (permissionsState.revokeRuntimePermission(bp, userId) ==
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
+ } else {
+ permissionsState.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS, flags);
+ }
}
+
} break;
}
}
}
- private void writePermissions(XmlSerializer serializer, Set<String> permissions)
- throws IOException {
- for (String permission : permissions) {
+ private void writePermissions(XmlSerializer serializer,
+ List<PermissionState> permissionStates) throws IOException {
+ for (PermissionState permissionState : permissionStates) {
serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME, permission);
+ serializer.attribute(null, ATTR_NAME,permissionState.getName());
+ serializer.attribute(null, ATTR_GRANTED,
+ String.valueOf(permissionState.isGranted()));
+ serializer.attribute(null, ATTR_FLAGS,
+ Integer.toHexString(permissionState.getFlags()));
serializer.endTag(null, TAG_ITEM);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e79a206..8dccfdf 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -50,6 +50,8 @@ import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.Xml;
+import com.google.android.collect.Sets;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.ArrayUtils;
@@ -68,11 +70,9 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import libcore.io.IoUtils;
@@ -88,10 +88,6 @@ public class UserManagerService extends IUserManager.Stub {
private static final String ATTR_ID = "id";
private static final String ATTR_CREATION_TIME = "created";
private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
- private static final String ATTR_SALT = "salt";
- private static final String ATTR_PIN_HASH = "pinHash";
- private static final String ATTR_FAILED_ATTEMPTS = "failedAttempts";
- private static final String ATTR_LAST_RETRY_MS = "lastAttemptMs";
private static final String ATTR_SERIAL_NO = "serialNumber";
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
private static final String ATTR_PARTIAL = "partial";
@@ -129,16 +125,13 @@ public class UserManagerService extends IUserManager.Stub {
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
- // Number of attempts before jumping to the next BACKOFF_TIMES slot
- private static final int BACKOFF_INC_INTERVAL = 5;
-
// Maximum number of managed profiles permitted is 1. This cannot be increased
// without first making sure that the rest of the framework is prepared for it.
private static final int MAX_MANAGED_PROFILES = 1;
- // Amount of time to force the user to wait before entering the PIN again, after failing
- // BACKOFF_INC_INTERVAL times.
- private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 };
+ // Set of user restrictions, which can only be enforced by the system
+ private static final Set<String> SYSTEM_CONTROLLED_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_RECORD_AUDIO);
static final int WRITE_USER_MSG = 1;
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
@@ -158,16 +151,6 @@ public class UserManagerService extends IUserManager.Stub {
private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>();
private final Bundle mGuestRestrictions = new Bundle();
- class RestrictionsPinState {
- long salt;
- String pinHash;
- int failedAttempts;
- long lastAttemptTime;
- }
-
- private final SparseArray<RestrictionsPinState> mRestrictionsPinStates =
- new SparseArray<RestrictionsPinState>();
-
/**
* Set of user IDs being actively removed. Removed IDs linger in this set
* for several seconds to work around a VFS caching issue.
@@ -234,6 +217,14 @@ public class UserManagerService extends IUserManager.Stub {
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
initDefaultGuestRestrictions();
readUserListLocked();
+ sInstance = this;
+ }
+ }
+ }
+
+ void systemReady() {
+ synchronized (mInstallLock) {
+ synchronized (mPackagesLock) {
// Prune out any partially created/partially removed users.
ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
for (int i = 0; i < mUsers.size(); i++) {
@@ -248,12 +239,8 @@ public class UserManagerService extends IUserManager.Stub {
+ " (name=" + ui.name + ")");
removeUserStateLocked(ui.id);
}
- sInstance = this;
}
}
- }
-
- void systemReady() {
userForeground(UserHandle.USER_OWNER);
mAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
@@ -520,7 +507,7 @@ public class UserManagerService extends IUserManager.Stub {
public boolean hasUserRestriction(String restrictionKey, int userId) {
synchronized (mPackagesLock) {
Bundle restrictions = mUserRestrictions.get(userId);
- return restrictions != null ? restrictions.getBoolean(restrictionKey) : false;
+ return restrictions != null && restrictions.getBoolean(restrictionKey);
}
}
@@ -535,23 +522,57 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
+ public void setUserRestriction(String key, boolean value, int userId) {
+ synchronized (mPackagesLock) {
+ if (!SYSTEM_CONTROLLED_RESTRICTIONS.contains(key)) {
+ Bundle restrictions = getUserRestrictions(userId);
+ restrictions.putBoolean(key, value);
+ setUserRestrictionsInternalLocked(restrictions, userId);
+ }
+ }
+ }
+
+ @Override
+ public void setSystemControlledUserRestriction(String key, boolean value, int userId) {
+ checkSystemOrRoot("setSystemControlledUserRestriction");
+ synchronized (mPackagesLock) {
+ Bundle restrictions = getUserRestrictions(userId);
+ restrictions.putBoolean(key, value);
+ setUserRestrictionsInternalLocked(restrictions, userId);
+ }
+ }
+
+ @Override
public void setUserRestrictions(Bundle restrictions, int userId) {
checkManageUsersPermission("setUserRestrictions");
if (restrictions == null) return;
synchronized (mPackagesLock) {
- mUserRestrictions.get(userId).clear();
- mUserRestrictions.get(userId).putAll(restrictions);
- long token = Binder.clearCallingIdentity();
- try {
- mAppOpsService.setUserRestrictions(mUserRestrictions.get(userId), userId);
- } catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
- } finally {
- Binder.restoreCallingIdentity(token);
+ final Bundle oldUserRestrictions = mUserRestrictions.get(userId);
+ // Restore the original state of system controlled restrictions from oldUserRestrictions
+ for (String key : SYSTEM_CONTROLLED_RESTRICTIONS) {
+ restrictions.remove(key);
+ if (oldUserRestrictions.containsKey(key)) {
+ restrictions.putBoolean(key, oldUserRestrictions.getBoolean(key));
+ }
}
- scheduleWriteUserLocked(mUsers.get(userId));
+ setUserRestrictionsInternalLocked(restrictions, userId);
+ }
+ }
+
+ private void setUserRestrictionsInternalLocked(Bundle restrictions, int userId) {
+ final Bundle userRestrictions = mUserRestrictions.get(userId);
+ userRestrictions.clear();
+ userRestrictions.putAll(restrictions);
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppOpsService.setUserRestrictions(userRestrictions, userId);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
+ scheduleWriteUserLocked(mUsers.get(userId));
}
/**
@@ -589,6 +610,13 @@ public class UserManagerService extends IUserManager.Stub {
}
}
+ private static void checkSystemOrRoot(String message) {
+ final int uid = Binder.getCallingUid();
+ if (uid != Process.SYSTEM_UID && uid != 0) {
+ throw new SecurityException("Only system may call: " + message);
+ }
+ }
+
private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
@@ -806,21 +834,6 @@ public class UserManagerService extends IUserManager.Stub {
serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
Long.toString(userInfo.lastLoggedInTime));
- RestrictionsPinState pinState = mRestrictionsPinStates.get(userInfo.id);
- if (pinState != null) {
- if (pinState.salt != 0) {
- serializer.attribute(null, ATTR_SALT, Long.toString(pinState.salt));
- }
- if (pinState.pinHash != null) {
- serializer.attribute(null, ATTR_PIN_HASH, pinState.pinHash);
- }
- if (pinState.failedAttempts != 0) {
- serializer.attribute(null, ATTR_FAILED_ATTEMPTS,
- Integer.toString(pinState.failedAttempts));
- serializer.attribute(null, ATTR_LAST_RETRY_MS,
- Long.toString(pinState.lastAttemptTime));
- }
- }
if (userInfo.iconPath != null) {
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
}
@@ -940,11 +953,7 @@ public class UserManagerService extends IUserManager.Stub {
String iconPath = null;
long creationTime = 0L;
long lastLoggedInTime = 0L;
- long salt = 0L;
- String pinHash = null;
- int failedAttempts = 0;
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
- long lastAttemptTime = 0L;
boolean partial = false;
boolean guestToRemove = false;
Bundle restrictions = new Bundle();
@@ -978,10 +987,6 @@ public class UserManagerService extends IUserManager.Stub {
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
- salt = readLongAttribute(parser, ATTR_SALT, 0L);
- pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
- failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
- lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
UserInfo.NO_PROFILE_GROUP_ID);
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
@@ -1019,17 +1024,6 @@ public class UserManagerService extends IUserManager.Stub {
userInfo.guestToRemove = guestToRemove;
userInfo.profileGroupId = profileGroupId;
mUserRestrictions.append(id, restrictions);
- if (salt != 0L) {
- RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
- if (pinState == null) {
- pinState = new RestrictionsPinState();
- mRestrictionsPinStates.put(id, pinState);
- }
- pinState.salt = salt;
- pinState.pinHash = pinHash;
- pinState.failedAttempts = failedAttempts;
- pinState.lastAttemptTime = lastAttemptTime;
- }
return userInfo;
} catch (IOException ioe) {
@@ -1431,8 +1425,6 @@ public class UserManagerService extends IUserManager.Stub {
// Remove this user from the list
mUsers.remove(userHandle);
-
- mRestrictionsPinStates.remove(userHandle);
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
userFile.delete();
@@ -1504,92 +1496,6 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public boolean setRestrictionsChallenge(String newPin) {
- checkManageUsersPermission("Only system can modify the restrictions pin");
- int userId = UserHandle.getCallingUserId();
- synchronized (mPackagesLock) {
- RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
- if (pinState == null) {
- pinState = new RestrictionsPinState();
- }
- if (newPin == null) {
- pinState.salt = 0;
- pinState.pinHash = null;
- } else {
- try {
- pinState.salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
- } catch (NoSuchAlgorithmException e) {
- pinState.salt = (long) (Math.random() * Long.MAX_VALUE);
- }
- pinState.pinHash = passwordToHash(newPin, pinState.salt);
- pinState.failedAttempts = 0;
- }
- mRestrictionsPinStates.put(userId, pinState);
- writeUserLocked(mUsers.get(userId));
- }
- return true;
- }
-
- @Override
- public int checkRestrictionsChallenge(String pin) {
- checkManageUsersPermission("Only system can verify the restrictions pin");
- int userId = UserHandle.getCallingUserId();
- synchronized (mPackagesLock) {
- RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
- // If there's no pin set, return error code
- if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
- return UserManager.PIN_VERIFICATION_FAILED_NOT_SET;
- } else if (pin == null) {
- // If just checking if user can be prompted, return remaining time
- int waitTime = getRemainingTimeForPinAttempt(pinState);
- Slog.d(LOG_TAG, "Remaining waittime peek=" + waitTime);
- return waitTime;
- } else {
- int waitTime = getRemainingTimeForPinAttempt(pinState);
- Slog.d(LOG_TAG, "Remaining waittime=" + waitTime);
- if (waitTime > 0) {
- return waitTime;
- }
- if (passwordToHash(pin, pinState.salt).equals(pinState.pinHash)) {
- pinState.failedAttempts = 0;
- scheduleWriteUserLocked(mUsers.get(userId));
- return UserManager.PIN_VERIFICATION_SUCCESS;
- } else {
- pinState.failedAttempts++;
- pinState.lastAttemptTime = System.currentTimeMillis();
- scheduleWriteUserLocked(mUsers.get(userId));
- return waitTime;
- }
- }
- }
- }
-
- private int getRemainingTimeForPinAttempt(RestrictionsPinState pinState) {
- int backoffIndex = Math.min(pinState.failedAttempts / BACKOFF_INC_INTERVAL,
- BACKOFF_TIMES.length - 1);
- int backoffTime = (pinState.failedAttempts % BACKOFF_INC_INTERVAL) == 0 ?
- BACKOFF_TIMES[backoffIndex] : 0;
- return (int) Math.max(backoffTime + pinState.lastAttemptTime - System.currentTimeMillis(),
- 0);
- }
-
- @Override
- public boolean hasRestrictionsChallenge() {
- int userId = UserHandle.getCallingUserId();
- synchronized (mPackagesLock) {
- return hasRestrictionsPinLocked(userId);
- }
- }
-
- private boolean hasRestrictionsPinLocked(int userId) {
- RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
- if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
- return false;
- }
- return true;
- }
-
- @Override
public void removeRestrictions() {
checkManageUsersPermission("Only system can remove restrictions");
final int userHandle = UserHandle.getCallingUserId();
@@ -1600,8 +1506,6 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mPackagesLock) {
// Remove all user restrictions
setUserRestrictions(new Bundle(), userHandle);
- // Remove restrictions pin
- setRestrictionsChallenge(null);
// Remove any app restrictions
cleanAppRestrictions(userHandle);
}
@@ -1633,42 +1537,6 @@ public class UserManagerService extends IUserManager.Stub {
}
});
}
-
- /*
- * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
- * Not the most secure, but it is at least a second level of protection. First level is that
- * the file is in a location only readable by the system process.
- * @param password the password.
- * @param salt the randomly generated salt
- * @return the hash of the pattern in a String.
- */
- private String passwordToHash(String password, long salt) {
- if (password == null) {
- return null;
- }
- String algo = null;
- String hashed = salt + password;
- try {
- byte[] saltedPassword = (password + salt).getBytes();
- byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
- byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
- hashed = toHex(sha1) + toHex(md5);
- } catch (NoSuchAlgorithmException e) {
- Log.w(LOG_TAG, "Failed to encode string because of missing algorithm: " + algo);
- }
- return hashed;
- }
-
- private static String toHex(byte[] ary) {
- final String hex = "0123456789ABCDEF";
- String ret = "";
- for (int i = 0; i < ary.length; i++) {
- ret += hex.charAt((ary[i] >> 4) & 0xf);
- ret += hex.charAt(ary[i] & 0xf);
- }
- return ret;
- }
-
private int getUidForPackage(String packageName) {
long ident = Binder.clearCallingIdentity();
try {
@@ -1954,11 +1822,6 @@ public class UserManagerService extends IUserManager.Stub {
return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
}
- private String restrictionsFileNameToPackage(String fileName) {
- return fileName.substring(RESTRICTIONS_FILE_PREFIX.length(),
- (int) (fileName.length() - XML_SUFFIX.length()));
- }
-
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index e972ec7..5877b3e 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -58,6 +58,9 @@ public class BarController {
private int mTransientBarState;
private boolean mPendingShow;
private long mLastTranslucent;
+ private boolean mShowTransparent;
+ private boolean mSetUnHideFlagWhenNextTransparent;
+ private boolean mNoAnimationOnNextShow;
public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
int statusBarManagerId, int translucentWmFlag) {
@@ -74,6 +77,14 @@ public class BarController {
mWin = win;
}
+ public void setShowTransparent(boolean transparent) {
+ if (transparent != mShowTransparent) {
+ mShowTransparent = transparent;
+ mSetUnHideFlagWhenNextTransparent = transparent;
+ mNoAnimationOnNextShow = true;
+ }
+ }
+
public void showTransient() {
if (mWin != null) {
setTransientBarState(TRANSIENT_BAR_SHOW_REQUESTED);
@@ -135,7 +146,9 @@ public class BarController {
}
final boolean wasVis = mWin.isVisibleLw();
final boolean wasAnim = mWin.isAnimatingLw();
- final boolean change = show ? mWin.showLw(true) : mWin.hideLw(true);
+ final boolean change = show ? mWin.showLw(!mNoAnimationOnNextShow)
+ : mWin.hideLw(!mNoAnimationOnNextShow);
+ mNoAnimationOnNextShow = false;
final int state = computeStateLw(wasVis, wasAnim, mWin, change);
final boolean stateChanged = updateStateLw(state);
return change || stateChanged;
@@ -233,6 +246,13 @@ public class BarController {
setTransientBarState(TRANSIENT_BAR_NONE); // request denied
}
}
+ if (mShowTransparent) {
+ vis |= View.SYSTEM_UI_TRANSPARENT;
+ if (mSetUnHideFlagWhenNextTransparent) {
+ vis |= mUnhideFlag;
+ mSetUnHideFlagWhenNextTransparent = false;
+ }
+ }
if (mTransientBarState != TRANSIENT_BAR_NONE) {
vis |= mTransientFlag; // ignore clear requests until transition completes
vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index dbd3676..185ef03 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -476,6 +476,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mTopIsFullscreen;
boolean mForceStatusBar;
boolean mForceStatusBarFromKeyguard;
+ private boolean mForceStatusBarTransparent;
boolean mHideLockScreen;
boolean mForcingShowNavBar;
int mForcingShowNavBarLayer;
@@ -4129,6 +4130,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAppsThatDismissKeyguard.clear();
mForceStatusBar = false;
mForceStatusBarFromKeyguard = false;
+ mForceStatusBarTransparent = false;
mForcingShowNavBar = false;
mForcingShowNavBarLayer = -1;
@@ -4154,8 +4156,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mForcingShowNavBar = true;
mForcingShowNavBarLayer = win.getSurfaceLayer();
}
- if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- mForceStatusBarFromKeyguard = true;
+ if (attrs.type == TYPE_STATUS_BAR) {
+ if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ mForceStatusBarFromKeyguard = true;
+ }
+ if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
+ mForceStatusBarTransparent = true;
+ }
}
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
@@ -4302,7 +4309,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
+ " forcefkg=" + mForceStatusBarFromKeyguard
+ " top=" + mTopFullscreenOpaqueWindowState);
- if (mForceStatusBar || mForceStatusBarFromKeyguard) {
+ boolean shouldBeTransparent = mForceStatusBarTransparent
+ && !mForceStatusBar
+ && !mForceStatusBarFromKeyguard;
+ if (!shouldBeTransparent) {
+ mStatusBarController.setShowTransparent(false /* transparent */);
+ } else if (!mStatusBar.isVisibleLw()) {
+ mStatusBarController.setShowTransparent(true /* transparent */);
+ }
+ if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
if (mStatusBarController.setBarShowingLw(true)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f790f75..decca16 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -69,6 +69,7 @@ import android.view.WindowManagerPolicy;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import libcore.util.Objects;
@@ -423,6 +424,9 @@ public final class PowerManagerService extends SystemService
// True if we are currently in device idle mode.
private boolean mDeviceIdleMode;
+ // Set of app ids that we will always respect the wake locks for.
+ int[] mDeviceIdleWhitelist = new int[0];
+
// True if theater mode is enabled
private boolean mTheaterModeEnabled;
@@ -758,6 +762,7 @@ public final class PowerManagerService extends SystemService
throw new IllegalArgumentException("Wake lock is already dead.");
}
mWakeLocks.add(wakeLock);
+ setWakeLockDisabledStateLocked(wakeLock);
notifyAcquire = true;
}
@@ -894,7 +899,7 @@ public final class PowerManagerService extends SystemService
}
private void notifyWakeLockAcquiredLocked(WakeLock wakeLock) {
- if (mSystemReady) {
+ if (mSystemReady && !wakeLock.mDisabled) {
wakeLock.mNotifiedAcquired = true;
mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
@@ -1388,7 +1393,10 @@ public final class PowerManagerService extends SystemService
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.PARTIAL_WAKE_LOCK:
- mWakeLockSummary |= WAKE_LOCK_CPU;
+ if (!wakeLock.mDisabled) {
+ // We only respect this if the wake lock is not disabled.
+ mWakeLockSummary |= WAKE_LOCK_CPU;
+ }
break;
case PowerManager.FULL_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
@@ -2248,12 +2256,12 @@ public final class PowerManagerService extends SystemService
}
}
- private void setStayOnSettingInternal(int val) {
+ void setStayOnSettingInternal(int val) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
}
- private void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) {
+ void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) {
synchronized (mLock) {
mMaximumScreenOffTimeoutFromDeviceAdmin = timeMs;
mDirty |= DIRTY_SETTINGS;
@@ -2261,6 +2269,69 @@ public final class PowerManagerService extends SystemService
}
}
+ void setDeviceIdleModeInternal(boolean enabled) {
+ synchronized (mLock) {
+ if (mDeviceIdleMode != enabled) {
+ mDeviceIdleMode = enabled;
+ updateWakeLockDisabledStatesLocked();
+ }
+ }
+ }
+
+ void setDeviceIdleWhitelistInternal(int[] appids) {
+ synchronized (mLock) {
+ mDeviceIdleWhitelist = appids;
+ if (mDeviceIdleMode) {
+ updateWakeLockDisabledStatesLocked();
+ }
+ }
+ }
+
+ private void updateWakeLockDisabledStatesLocked() {
+ boolean changed = false;
+ final int numWakeLocks = mWakeLocks.size();
+ for (int i = 0; i < numWakeLocks; i++) {
+ final WakeLock wakeLock = mWakeLocks.get(i);
+ if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+ == PowerManager.PARTIAL_WAKE_LOCK) {
+ if (setWakeLockDisabledStateLocked(wakeLock)) {
+ changed = true;
+ if (wakeLock.mDisabled) {
+ // This wake lock is no longer being respected.
+ notifyWakeLockReleasedLocked(wakeLock);
+ } else {
+ notifyWakeLockAcquiredLocked(wakeLock);
+ }
+ }
+ }
+ }
+ if (changed) {
+ mDirty |= DIRTY_WAKE_LOCKS;
+ updatePowerStateLocked();
+ }
+ }
+
+ private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) {
+ if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+ == PowerManager.PARTIAL_WAKE_LOCK) {
+ boolean disabled = false;
+ if (mDeviceIdleMode) {
+ final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
+ // If we are in idle mode, we will ignore all partial wake locks that are
+ // for application uids that are not whitelisted.
+ if (appid >= Process.FIRST_APPLICATION_UID &&
+ Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0) {
+ disabled = true;
+ }
+ }
+ if (wakeLock.mDisabled != disabled) {
+ wakeLock.mDisabled = disabled;
+ return true;
+ }
+ }
+ return false;
+ }
+
private boolean isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() {
return mMaximumScreenOffTimeoutFromDeviceAdmin >= 0
&& mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE;
@@ -2459,6 +2530,8 @@ public final class PowerManagerService extends SystemService
pw.println(" mSandmanSummoned=" + mSandmanSummoned);
pw.println(" mLowPowerModeEnabled=" + mLowPowerModeEnabled);
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
+ pw.println(" mDeviceIdleMode=" + mDeviceIdleMode);
+ pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
@@ -2671,6 +2744,7 @@ public final class PowerManagerService extends SystemService
public final int mOwnerUid;
public final int mOwnerPid;
public boolean mNotifiedAcquired;
+ public boolean mDisabled;
public WakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource workSource, String historyTag, int ownerUid, int ownerPid) {
@@ -2729,7 +2803,7 @@ public final class PowerManagerService extends SystemService
@Override
public String toString() {
return getLockLevelString()
- + " '" + mTag + "'" + getLockFlagsString()
+ + " '" + mTag + "'" + getLockFlagsString() + (mDisabled ? " DISABLED" : "")
+ " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")";
}
@@ -3340,9 +3414,12 @@ public final class PowerManagerService extends SystemService
@Override
public void setDeviceIdleMode(boolean enabled) {
- synchronized (mLock) {
- mDeviceIdleMode = enabled;
- }
+ setDeviceIdleModeInternal(enabled);
+ }
+
+ @Override
+ public void setDeviceIdleWhitelist(int[] appids) {
+ setDeviceIdleWhitelistInternal(appids);
}
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6f01ca0..c6816b0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2897,7 +2897,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean callerIsDeviceOwnerAdmin = isCallerDeviceOwnerOrInitializer(callingUid);
boolean doNotAskCredentialsOnBoot =
- (flags & DevicePolicyManager.DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0;
+ (flags & DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0;
if (callerIsDeviceOwnerAdmin && doNotAskCredentialsOnBoot) {
setDoNotAskCredentialsOnBoot();
}
@@ -6344,10 +6344,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long ident = Binder.clearCallingIdentity();
try {
+ PackageManager packageManager = mContext.getPackageManager();
if (granted) {
- mContext.getPackageManager().grantPermission(packageName, permission, user);
+ packageManager.grantRuntimePermission(packageName, permission, user);
+ packageManager.updatePermissionFlags(permission, packageName,
+ PackageManager.FLAG_PERMISSION_POLICY_FIXED,
+ PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
} else {
- mContext.getPackageManager().revokePermission(packageName, permission, user);
+ packageManager.revokeRuntimePermission(packageName,
+ permission, user);
+ packageManager.updatePermissionFlags(permission, packageName,
+ PackageManager.FLAG_PERMISSION_POLICY_FIXED,
+ PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
}
return true;
} catch (SecurityException se) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 117cbe4..48b127a 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -718,10 +718,10 @@ public class UsageStatsService extends SystemService implements
}
@Override
- public boolean isAppIdle(String packageName, int userId) {
+ public boolean isAppInactive(String packageName, int userId) {
try {
userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, false, true, "isAppIdle", null);
+ Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
} catch (RemoteException re) {
return false;
}
@@ -734,7 +734,7 @@ public class UsageStatsService extends SystemService implements
}
@Override
- public void setAppIdle(String packageName, boolean idle, int userId) {
+ public void setAppInactive(String packageName, boolean idle, int userId) {
final int callingUid = Binder.getCallingUid();
try {
userId = ActivityManagerNative.getDefault().handleIncomingUser(
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 6adb8be..f84beb6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -78,8 +78,6 @@ public class UsbDeviceManager {
"/sys/class/android_usb/android0/functions";
private static final String STATE_PATH =
"/sys/class/android_usb/android0/state";
- private static final String MASS_STORAGE_FILE_PATH =
- "/sys/class/android_usb/android0/f_mass_storage/lun/file";
private static final String RNDIS_ETH_ADDR_PATH =
"/sys/class/android_usb/android0/f_rndis/ethaddr";
private static final String AUDIO_SOURCE_PCM_PATH =
@@ -832,8 +830,6 @@ public class UsbDeviceManager {
+ FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
pw.println(" Kernel function list: "
+ FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
- pw.println(" Mass storage backing file: "
- + FileUtils.readTextFile(new File(MASS_STORAGE_FILE_PATH), 0, null).trim());
} catch (IOException e) {
pw.println("IOException: " + e);
}
@@ -866,15 +862,6 @@ public class UsbDeviceManager {
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, makeDefault);
}
- public void setMassStorageBackingFile(String path) {
- if (path == null) path = "";
- try {
- FileUtils.stringToFile(MASS_STORAGE_FILE_PATH, path);
- } catch (IOException e) {
- Slog.e(TAG, "failed to write to " + MASS_STORAGE_FILE_PATH);
- }
- }
-
private void readOemUsbOverrideConfig() {
String[] configList = mContext.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index fda8076..e03884f 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -271,16 +271,6 @@ public class UsbService extends IUsbManager.Stub {
}
@Override
- public void setMassStorageBackingFile(String path) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- if (mDeviceManager != null) {
- mDeviceManager.setMassStorageBackingFile(path);
- } else {
- throw new IllegalStateException("USB device mode not supported");
- }
- }
-
- @Override
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 2897c61..fcdb6d6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -754,7 +754,7 @@ public class VoiceInteractionManagerService extends SystemService {
public boolean activeServiceSupportsAssist() {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
synchronized (this) {
- return mImpl != null && mImpl.mInfo.getSupportsAssist();
+ return mImpl != null && mImpl.mInfo != null && mImpl.mInfo.getSupportsAssist();
}
}
@@ -762,7 +762,8 @@ public class VoiceInteractionManagerService extends SystemService {
public boolean activeServiceSupportsLaunchFromKeyguard() throws RemoteException {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
synchronized (this) {
- return mImpl != null && mImpl.mInfo.getSupportsLaunchFromKeyguard();
+ return mImpl != null && mImpl.mInfo != null
+ && mImpl.mInfo.getSupportsLaunchFromKeyguard();
}
}