summaryrefslogtreecommitdiffstats
path: root/services/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/core/java')
-rw-r--r--services/core/java/com/android/server/AppOpsService.java45
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java49
-rw-r--r--services/core/java/com/android/server/BluetoothService.java51
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java172
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags12
-rw-r--r--services/core/java/com/android/server/MountService.java124
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java279
-rw-r--r--services/core/java/com/android/server/accounts/TokenCache.java163
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java32
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java37
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java135
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java113
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java3
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkMonitor.java55
-rw-r--r--services/core/java/com/android/server/content/ContentService.java14
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java8
-rw-r--r--services/core/java/com/android/server/notification/NotificationDelegate.java2
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java4
-rw-r--r--services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java147
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java88
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java38
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java5
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java4
-rw-r--r--services/core/java/com/android/server/telecom/TelecomLoaderService.java95
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java39
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java8
-rw-r--r--services/core/java/com/android/server/wm/Session.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java9
29 files changed, 1245 insertions, 496 deletions
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 79c66b9..f0fc399 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -116,6 +116,8 @@ public class AppOpsService extends IAppOpsService.Stub {
public final static class Op {
public final int uid;
public final String packageName;
+ public int proxyUid = -1;
+ public String proxyPackageName;
public final int op;
public int mode;
public int duration;
@@ -289,7 +291,8 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int j=0; j<pkgOps.size(); j++) {
Op curOp = pkgOps.valueAt(j);
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
- curOp.rejectTime, curOp.duration));
+ curOp.rejectTime, curOp.duration, curOp.proxyUid,
+ curOp.proxyPackageName));
}
} else {
for (int j=0; j<ops.length; j++) {
@@ -299,7 +302,8 @@ public class AppOpsService extends IAppOpsService.Stub {
resOps = new ArrayList<AppOpsManager.OpEntry>();
}
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
- curOp.rejectTime, curOp.duration));
+ curOp.rejectTime, curOp.duration, curOp.proxyUid,
+ curOp.proxyPackageName));
}
}
}
@@ -659,9 +663,28 @@ public class AppOpsService extends IAppOpsService.Stub {
}
@Override
+ public int noteProxyOperation(int code, String proxyPackageName,
+ int proxiedUid, String proxiedPackageName) {
+ verifyIncomingOp(code);
+ final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(),
+ proxyPackageName, -1, null);
+ if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
+ return proxyMode;
+ }
+ return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
+ Binder.getCallingUid(), proxyPackageName);
+
+ }
+
+ @Override
public int noteOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
+ return noteOperationUnchecked(code, uid, packageName, 0, null);
+ }
+
+ private int noteOperationUnchecked(int code, int uid, String packageName,
+ int proxyUid, String proxyPackageName) {
synchronized (this) {
Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
@@ -690,6 +713,8 @@ public class AppOpsService extends IAppOpsService.Stub {
+ " package " + packageName);
op.time = System.currentTimeMillis();
op.rejectTime = 0;
+ op.proxyUid = proxyUid;
+ op.proxyPackageName = proxyPackageName;
return AppOpsManager.MODE_ALLOWED;
}
}
@@ -1051,6 +1076,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (dur != null) {
op.duration = Integer.parseInt(dur);
}
+ String proxyUid = parser.getAttributeValue(null, "pu");
+ if (proxyUid != null) {
+ op.proxyUid = Integer.parseInt(proxyUid);
+ }
+ String proxyPackageName = parser.getAttributeValue(null, "pp");
+ if (proxyPackageName != null) {
+ op.proxyPackageName = proxyPackageName;
+ }
HashMap<String, Ops> pkgOps = mUidOps.get(uid);
if (pkgOps == null) {
pkgOps = new HashMap<String, Ops>();
@@ -1132,6 +1165,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (dur != 0) {
out.attribute(null, "d", Integer.toString(dur));
}
+ int proxyUid = op.getProxyUid();
+ if (proxyUid != -1) {
+ out.attribute(null, "pu", Integer.toString(proxyUid));
+ }
+ String proxyPackageName = op.getProxyPackageName();
+ if (proxyPackageName != null) {
+ out.attribute(null, "pp", proxyPackageName);
+ }
out.endTag(null, "op");
}
out.endTag(null, "uid");
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 25f8872..b9f62e6 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -60,6 +60,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
+
class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String TAG = "BluetoothManagerService";
private static final boolean DBG = false;
@@ -234,25 +235,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
sendEnableMsg(mQuietEnableExternal);
}
}
- } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- if (DBG) Log.d(TAG, "Bluetooth user switched");
- mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED,
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
- } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- if (DBG) Log.d(TAG, "Bluetooth boot completed");
- synchronized(mReceiver) {
- if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
- //Enable
- if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
- sendEnableMsg(mQuietEnableExternal);
- }
- if (!isNameAndAddressSet()) {
- // Sync the Bluetooth name and address from the
- // Bluetooth Adapter
- if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address...");
- getNameAndAddress();
- }
- }
}
}
};
@@ -277,9 +259,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
registerForBleScanModeChange();
mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
- IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
- filter.addAction(Intent.ACTION_USER_SWITCHED);
+ IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
registerForAirplaneMode(filter);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mReceiver, filter);
@@ -790,6 +770,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
/**
+ * Send enable message and set adapter name and address. Called when the boot phase becomes
+ * PHASE_SYSTEM_SERVICES_READY.
+ */
+ public void handleOnBootPhase() {
+ if (DBG) Log.d(TAG, "Bluetooth boot completed");
+ if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
+ if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
+ sendEnableMsg(mQuietEnableExternal);
+ }
+ if (!isNameAndAddressSet()) {
+ // Sync the Bluetooth name and address from the Bluetooth Adapter
+ if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address...");
+ getNameAndAddress();
+ }
+ }
+
+ /**
+ * Called when switching to a different foreground user.
+ */
+ public void handleOnSwitchUser(int userHandle) {
+ if (DBG) Log.d(TAG, "Bluetooth user switched");
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0));
+ }
+
+ /**
* This class manages the clients connected to a given ProfileService
* and maintains the connection with that service.
*/
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
new file mode 100644
index 0000000..73e8c52
--- /dev/null
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.util.Log;
+
+class BluetoothService extends SystemService {
+ private static final String TAG = "BluetoothService";
+ private BluetoothManagerService mBluetoothManagerService;
+
+ public BluetoothService(Context context) {
+ super(context);
+ mBluetoothManagerService = new BluetoothManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ Log.d(TAG, "onStart: publishing BluetoothManagerService");
+ publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, mBluetoothManagerService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
+ mBluetoothManagerService.handleOnBootPhase();
+ }
+ }
+
+ @Override
+ public void onSwitchUser(int userHandle) {
+ Log.d(TAG, "onSwitchUser: switching to user " + userHandle);
+ mBluetoothManagerService.handleOnSwitchUser(userHandle);
+ }
+}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index dc203ff..c8dc565 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -158,15 +158,20 @@ public class DeviceIdleController extends SystemService
private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
/**
+ * App IDs of built-in system apps that have been white-listed.
+ */
+ private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
+
+ /**
* App IDs that have been white-listed to opt out of power save restrictions.
*/
- private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
+ private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = 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 int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
/**
* List of end times for UIDs that are temporarily marked as being allowed to access
@@ -478,6 +483,7 @@ public class DeviceIdleController extends SystemService
handleWriteConfigFile();
} break;
case MSG_REPORT_IDLE_ON: {
+ EventLogTags.writeDeviceIdleOnStart();
mLocalPowerManager.setDeviceIdleMode(true);
try {
mNetworkPolicyManager.setDeviceIdleMode(true);
@@ -485,8 +491,10 @@ public class DeviceIdleController extends SystemService
} catch (RemoteException e) {
}
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ EventLogTags.writeDeviceIdleOnComplete();
} break;
case MSG_REPORT_IDLE_OFF: {
+ EventLogTags.writeDeviceIdleOffStart("unknown");
mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
@@ -494,11 +502,14 @@ public class DeviceIdleController extends SystemService
} catch (RemoteException e) {
}
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_REPORT_ACTIVE: {
String activeReason = (String)msg.obj;
int activeUid = msg.arg1;
boolean needBroadcast = msg.arg2 != 0;
+ EventLogTags.writeDeviceIdleOffStart(
+ activeReason != null ? activeReason : "unknown");
mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
@@ -508,6 +519,7 @@ public class DeviceIdleController extends SystemService
if (needBroadcast) {
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
}
+ EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
int uid = msg.arg1;
@@ -557,17 +569,18 @@ public class DeviceIdleController extends SystemService
getContext().enforceCallingPermission(
Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
"No permission to change device idle whitelist");
+ final int callingUid = Binder.getCallingUid();
userId = ActivityManagerNative.getDefault().handleIncomingUser(
Binder.getCallingPid(),
- Binder.getCallingUid(),
+ callingUid,
userId,
/*allowAll=*/ false,
/*requireFull=*/ false,
"addPowerSaveTempWhitelistApp", null);
final long token = Binder.clearCallingIdentity();
try {
- DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(packageName,
- duration, userId);
+ DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid,
+ packageName, duration, userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -586,7 +599,7 @@ public class DeviceIdleController extends SystemService
public final class LocalService {
public void addPowerSaveTempWhitelistAppDirect(int appId, long duration) {
- DeviceIdleController.this.addPowerSaveTempWhitelistAppDirectInternal(appId, duration);
+ addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration);
}
}
@@ -614,8 +627,9 @@ public class DeviceIdleController extends SystemService
try {
ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
- mPowerSaveWhitelistApps.put(ai.packageName,
- UserHandle.getAppId(ai.uid));
+ int appid = UserHandle.getAppId(ai.uid);
+ mPowerSaveWhitelistApps.put(ai.packageName, appid);
+ mPowerSaveWhitelistSystemAppIds.put(appid, true);
}
} catch (PackageManager.NameNotFoundException e) {
}
@@ -667,14 +681,15 @@ public class DeviceIdleController extends SystemService
mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
- mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ACTION_STEP_IDLE_STATE);
getContext().registerReceiver(mReceiver, filter);
- mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);
+ mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
mDisplayManager.registerDisplayListener(mDisplayListener, null);
updateDisplayLocked();
@@ -747,7 +762,7 @@ public class DeviceIdleController extends SystemService
public int[] getAppIdWhitelistInternal() {
synchronized (this) {
- return mPowerSaveWhitelistAppIdArray;
+ return mPowerSaveWhitelistAllAppIdArray;
}
}
@@ -761,12 +776,12 @@ public class DeviceIdleController extends SystemService
* Adds an app to the temporary whitelist and resets the endTime for granting the
* app an exemption to access network and acquire wakelocks.
*/
- public void addPowerSaveTempWhitelistAppInternal(String packageName, long duration,
- int userId) {
+ public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
+ long duration, int userId) {
try {
int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
int appId = UserHandle.getAppId(uid);
- addPowerSaveTempWhitelistAppDirectInternal(appId, duration);
+ addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration);
} catch (NameNotFoundException e) {
}
}
@@ -775,9 +790,17 @@ public class DeviceIdleController extends SystemService
* Adds an app to the temporary whitelist and resets the endTime for granting the
* app an exemption to access network and acquire wakelocks.
*/
- public void addPowerSaveTempWhitelistAppDirectInternal(int appId, long duration) {
+ public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
+ long duration) {
final long timeNow = SystemClock.elapsedRealtime();
synchronized (this) {
+ int callingAppId = UserHandle.getAppId(callingUid);
+ if (callingAppId >= Process.FIRST_APPLICATION_UID) {
+ if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
+ throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
+ + " is not on whitelist");
+ }
+ }
duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId);
// Set the new end time
@@ -1026,25 +1049,25 @@ public class DeviceIdleController extends SystemService
}
private void updateWhitelistAppIdsLocked() {
- mPowerSaveWhitelistAppIds.clear();
+ mPowerSaveWhitelistAllAppIds.clear();
for (int i=0; i<mPowerSaveWhitelistApps.size(); i++) {
- mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true);
+ mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true);
}
for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
- mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true);
+ mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true);
}
- int size = mPowerSaveWhitelistAppIds.size();
+ int size = mPowerSaveWhitelistAllAppIds.size();
int[] appids = new int[size];
for (int i = 0; i < size; i++) {
- appids[i] = mPowerSaveWhitelistAppIds.keyAt(i);
+ appids[i] = mPowerSaveWhitelistAllAppIds.keyAt(i);
}
- mPowerSaveWhitelistAppIdArray = appids;
+ mPowerSaveWhitelistAllAppIdArray = appids;
if (mLocalPowerManager != null) {
if (DEBUG) {
Slog.d(TAG, "Setting wakelock whitelist to "
- + Arrays.toString(mPowerSaveWhitelistAppIdArray));
+ + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
}
- mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);
+ mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
}
}
@@ -1245,25 +1268,40 @@ public class DeviceIdleController extends SystemService
// Ignore, we always dump all.
} else if ("step".equals(arg)) {
synchronized (this) {
- stepIdleStateLocked();
- pw.print("Stepped to: "); pw.println(stateToString(mState));
+ long token = Binder.clearCallingIdentity();
+ try {
+ stepIdleStateLocked();
+ pw.print("Stepped to: "); pw.println(stateToString(mState));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
return;
} else if ("disable".equals(arg)) {
synchronized (this) {
- if (mEnabled) {
- mEnabled = false;
- becomeActiveLocked("disabled", Process.myUid());
- pw.println("Idle mode disabled");
+ long token = Binder.clearCallingIdentity();
+ try {
+ if (mEnabled) {
+ mEnabled = false;
+ becomeActiveLocked("disabled", Process.myUid());
+ pw.println("Idle mode disabled");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
return;
} else if ("enable".equals(arg)) {
synchronized (this) {
- if (!mEnabled) {
- mEnabled = true;
- becomeInactiveIfAppropriateLocked();
- pw.println("Idle mode enabled");
+ long token = Binder.clearCallingIdentity();
+ try {
+ if (!mEnabled) {
+ mEnabled = true;
+ becomeInactiveIfAppropriateLocked();
+ pw.println("Idle mode enabled");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
return;
@@ -1273,40 +1311,50 @@ public class DeviceIdleController extends SystemService
}
return;
} else if ("whitelist".equals(arg)) {
- i++;
- while (i < args.length) {
- arg = args[i];
+ long token = Binder.clearCallingIdentity();
+ try {
i++;
- if (arg.length() < 1 || (arg.charAt(0) != '-'
- && arg.charAt(0) != '+')) {
- pw.println("Package must be prefixed with + or -: " + arg);
- return;
- }
- char op = arg.charAt(0);
- String pkg = arg.substring(1);
- if (op == '+') {
- if (addPowerSaveWhitelistAppInternal(pkg)) {
- pw.println("Added: " + pkg);
- } else {
- pw.println("Unknown package: " + pkg);
+ while (i < args.length) {
+ arg = args[i];
+ i++;
+ if (arg.length() < 1 || (arg.charAt(0) != '-'
+ && arg.charAt(0) != '+')) {
+ pw.println("Package must be prefixed with + or -: " + arg);
+ return;
}
- } else {
- if (removePowerSaveWhitelistAppInternal(pkg)) {
- pw.println("Removed: " + pkg);
+ char op = arg.charAt(0);
+ String pkg = arg.substring(1);
+ if (op == '+') {
+ if (addPowerSaveWhitelistAppInternal(pkg)) {
+ pw.println("Added: " + pkg);
+ } else {
+ pw.println("Unknown package: " + pkg);
+ }
+ } else {
+ if (removePowerSaveWhitelistAppInternal(pkg)) {
+ pw.println("Removed: " + pkg);
+ }
}
}
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
return;
} else if ("tempwhitelist".equals(arg)) {
- i++;
- if (i >= args.length) {
- pw.println("At least one package name must be specified");
- return;
- }
- while (i < args.length) {
- arg = args[i];
+ long token = Binder.clearCallingIdentity();
+ try {
i++;
- addPowerSaveTempWhitelistAppInternal(arg, 10000L, userId);
+ if (i >= args.length) {
+ pw.println("At least one package name must be specified");
+ return;
+ }
+ while (i < args.length) {
+ arg = args[i];
+ i++;
+ addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
pw.println("Unknown option: " + arg);
@@ -1337,12 +1385,12 @@ public class DeviceIdleController extends SystemService
pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
}
}
- size = mPowerSaveWhitelistAppIds.size();
+ size = mPowerSaveWhitelistAllAppIds.size();
if (size > 0) {
- pw.println(" Whitelist app ids:");
+ pw.println(" Whitelist all app ids:");
for (int i = 0; i < size; i++) {
pw.print(" ");
- pw.print(mPowerSaveWhitelistAppIds.keyAt(i));
+ pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
pw.println();
}
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 43b640b..7aebc1a 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -60,7 +60,7 @@ option java_package com.android.server
2752 notification_cancel_all (uid|1|5),(pid|1|5),(pkg|3),(userid|1|5),(required_flags|1),(forbidden_flags|1),(reason|1|5),(listener|3)
# when the notification panel is shown
# Note: New tag range starts here since 2753+ have been used below.
-27500 notification_panel_revealed
+27500 notification_panel_revealed (items|1)
# when the notification panel is hidden
27501 notification_panel_hidden
# when notifications are newly displayed on screen, or disappear from screen
@@ -183,6 +183,12 @@ option java_package com.android.server
34000 device_idle (state|1|5), (reason|3)
34001 device_idle_step
34002 device_idle_wake_from_idle (is_idle|1|5), (reason|3)
+34003 device_idle_on_start
+34004 device_idle_on_phase (what|3)
+34005 device_idle_on_complete
+34006 device_idle_off_start (reason|3)
+34007 device_idle_off_phase (what|3)
+34008 device_idle_off_complete
# ---------------------------
# DisplayManagerService.java
@@ -224,8 +230,8 @@ option java_package com.android.server
# ---------------------------
# IdleMaintenanceService.java
# ---------------------------
-2753 idle_maintenance_window_start (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5)
-2754 idle_maintenance_window_finish (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5)
+51500 idle_maintenance_window_start (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5)
+51501 idle_maintenance_window_finish (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5)
# ---------------------------
# MountService.java
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b4fa46d..c82ba24 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -18,9 +18,11 @@ package com.android.server;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
+import static com.android.internal.util.XmlUtils.readLongAttribute;
import static com.android.internal.util.XmlUtils.readStringAttribute;
import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
+import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -56,7 +58,6 @@ import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -71,12 +72,14 @@ import android.os.storage.StorageResultCode;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
+import android.util.TimeUtils;
import android.util.Xml;
import libcore.io.IoUtils;
@@ -111,9 +114,7 @@ import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -182,7 +183,9 @@ class MountService extends IMountService.Stub
private static final boolean WATCHDOG_ENABLE = false;
private static final String TAG = "MountService";
+
private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
+ private static final String TAG_STORAGE_TRIM = "storage_trim";
private static final String VOLD_TAG = "VoldConnector";
private static final String CRYPTD_TAG = "CryptdConnector";
@@ -231,6 +234,7 @@ class MountService extends IMountService.Stub
public static final int DISK_SIZE_CHANGED = 641;
public static final int DISK_LABEL_CHANGED = 642;
public static final int DISK_SCANNED = 643;
+ public static final int DISK_SYS_PATH_CHANGED = 644;
public static final int DISK_DESTROYED = 649;
public static final int VOLUME_CREATED = 650;
@@ -244,11 +248,7 @@ class MountService extends IMountService.Stub
public static final int MOVE_STATUS = 660;
public static final int BENCHMARK_RESULT = 661;
-
- /*
- * 700 series - fstrim
- */
- public static final int FstrimCompleted = 700;
+ public static final int TRIM_RESULT = 662;
}
private static final int VERSION_INIT = 1;
@@ -265,6 +265,9 @@ class MountService extends IMountService.Stub
private static final String ATTR_PART_GUID = "partGuid";
private static final String ATTR_NICKNAME = "nickname";
private static final String ATTR_USER_FLAGS = "userFlags";
+ private static final String ATTR_CREATED_MILLIS = "createdMillis";
+ private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
+ private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
private final AtomicFile mSettingsFile;
@@ -321,7 +324,6 @@ class MountService extends IMountService.Stub
throw new IllegalArgumentException("No volume found for ID " + id);
}
- @Deprecated
private String findVolumeIdForPath(String path) {
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
@@ -334,6 +336,31 @@ class MountService extends IMountService.Stub
throw new IllegalArgumentException("No volume found for path " + path);
}
+ private VolumeRecord findRecordForPath(String path) {
+ synchronized (mLock) {
+ for (int i = 0; i < mVolumes.size(); i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ if (vol.path != null && path.startsWith(vol.path)) {
+ return mRecords.get(vol.fsUuid);
+ }
+ }
+ }
+ return null;
+ }
+
+ private String scrubPath(String path) {
+ if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
+ return "internal";
+ }
+ final VolumeRecord rec = findRecordForPath(path);
+ if (rec == null || rec.createdMillis == 0) {
+ return "unknown";
+ } else {
+ return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
+ / DateUtils.WEEK_IN_MILLIS) + "w";
+ }
+ }
+
private VolumeInfo findStorageForUuid(String volumeUuid) {
final StorageManager storage = mContext.getSystemService(StorageManager.class);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
@@ -345,6 +372,24 @@ class MountService extends IMountService.Stub
}
}
+ private boolean shouldBenchmark() {
+ final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
+ Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
+ synchronized (mLock) {
+ for (int i = 0; i < mVolumes.size(); i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ final VolumeRecord rec = mRecords.get(vol.fsUuid);
+ if (vol.isMountedReadable() && rec != null) {
+ final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
+ if (benchAge >= benchInterval) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
synchronized (mLock) {
CountDownLatch latch = mDiskScanLatches.get(diskId);
@@ -563,16 +608,17 @@ class MountService extends IMountService.Stub
Slog.e(TAG, "Unable to record last fstrim!");
}
+ final boolean shouldBenchmark = shouldBenchmark();
try {
// This method must be run on the main (handler) thread,
// so it is safe to directly call into vold.
- mConnector.execute("fstrim", "dotrim");
- EventLogTags.writeFstrimStart(SystemClock.elapsedRealtime());
+ mConnector.execute("fstrim", shouldBenchmark ? "dotrimbench" : "dotrim");
} catch (NativeDaemonConnectorException ndce) {
Slog.e(TAG, "Failed to run fstrim!");
}
// invoke the completion callback, if any
+ // TODO: fstrim is non-blocking, so remove this useless callback
Runnable callback = (Runnable) msg.obj;
if (callback != null) {
callback.run();
@@ -896,6 +942,14 @@ class MountService extends IMountService.Stub
}
break;
}
+ case VoldResponseCode.DISK_SYS_PATH_CHANGED: {
+ if (cooked.length != 3) break;
+ final DiskInfo disk = mDisks.get(cooked[1]);
+ if (disk != null) {
+ disk.sysPath = cooked[2];
+ }
+ break;
+ }
case VoldResponseCode.DISK_DESTROYED: {
if (cooked.length != 2) break;
final DiskInfo disk = mDisks.remove(cooked[1]);
@@ -984,17 +1038,46 @@ class MountService extends IMountService.Stub
onMoveStatusLocked(status);
break;
}
-
case VoldResponseCode.BENCHMARK_RESULT: {
+ if (cooked.length != 7) break;
+ final String path = cooked[1];
+ final String ident = cooked[2];
+ final long create = Long.parseLong(cooked[3]);
+ final long drop = Long.parseLong(cooked[4]);
+ final long run = Long.parseLong(cooked[5]);
+ final long destroy = Long.parseLong(cooked[6]);
+
final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
- dropBox.addText(TAG_STORAGE_BENCHMARK, raw);
+ dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
+ + " " + ident + " " + create + " " + run + " " + destroy);
+
+ final VolumeRecord rec = findRecordForPath(path);
+ if (rec != null) {
+ rec.lastBenchMillis = System.currentTimeMillis();
+ writeSettingsLocked();
+ }
+
break;
}
+ case VoldResponseCode.TRIM_RESULT: {
+ if (cooked.length != 4) break;
+ final String path = cooked[1];
+ final long bytes = Long.parseLong(cooked[2]);
+ final long time = Long.parseLong(cooked[3]);
+
+ final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
+ dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path)
+ + " " + bytes + " " + time);
+
+ final VolumeRecord rec = findRecordForPath(path);
+ if (rec != null) {
+ rec.lastTrimMillis = System.currentTimeMillis();
+ writeSettingsLocked();
+ }
- case VoldResponseCode.FstrimCompleted: {
- EventLogTags.writeFstrimFinish(SystemClock.elapsedRealtime());
break;
}
+
default: {
Slog.d(TAG, "Unhandled vold event " + code);
}
@@ -1106,6 +1189,7 @@ class MountService extends IMountService.Stub
if (rec == null) {
rec = new VolumeRecord(vol.type, vol.fsUuid);
rec.partGuid = vol.partGuid;
+ rec.createdMillis = System.currentTimeMillis();
if (vol.type == VolumeInfo.TYPE_PRIVATE) {
rec.nickname = vol.disk.getDescription();
}
@@ -1385,6 +1469,9 @@ class MountService extends IMountService.Stub
meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
+ meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
+ meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
+ meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
return meta;
}
@@ -1395,6 +1482,9 @@ class MountService extends IMountService.Stub
writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
+ writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
+ writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
+ writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
out.endTag(null, TAG_VOLUME);
}
@@ -3232,11 +3322,9 @@ class MountService extends IMountService.Stub
mConnector.dump(fd, pw, args);
pw.decreaseIndent();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
pw.println();
pw.print("Last maintenance: ");
- pw.println(sdf.format(new Date(mLastMaintenance)));
+ pw.println(TimeUtils.formatForLogging(mLastMaintenance));
}
/** {@inheritDoc} */
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 50d311f..a270974 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -86,7 +86,6 @@ import com.google.android.collect.Sets;
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
@@ -115,7 +114,6 @@ public class AccountManagerService
implements RegisteredServicesCacheListener<AuthenticatorDescription> {
private static final String TAG = "AccountManagerService";
- private static final int TIMEOUT_DELAY_MS = 1000 * 60;
private static final String DATABASE_NAME = "accounts.db";
private static final int DATABASE_VERSION = 8;
@@ -216,7 +214,7 @@ public class AccountManagerService
new HashMap<Account, HashMap<String, String>>();
/** protected by the {@link #cacheLock} */
- private final HashMap<Account, WeakReference<TokenCache>> accountTokenCaches = new HashMap<>();
+ private final TokenCache accountTokenCaches = new TokenCache();
/**
* protected by the {@link #cacheLock}
@@ -529,7 +527,7 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot get secrets for accounts of type: %s",
callingUid,
@@ -627,7 +625,7 @@ public class AccountManagerService
}
if (account == null) throw new IllegalArgumentException("account is null");
if (key == null) throw new IllegalArgumentException("key is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot get user data for accounts of type: %s",
callingUid,
@@ -645,15 +643,22 @@ public class AccountManagerService
@Override
public AuthenticatorDescription[] getAuthenticatorTypes(int userId) {
+ int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthenticatorTypes: "
+ "for user id " + userId
- + "caller's uid " + Binder.getCallingUid()
+ + "caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
// Only allow the system process to read accounts of other users
- enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
- + " trying get authenticator types for " + userId);
+ if (isCrossUser(callingUid, userId)) {
+ throw new SecurityException(
+ String.format(
+ "User %s tying to get authenticator types for %s" ,
+ UserHandle.getCallingUserId(),
+ userId));
+ }
+
final long identityToken = clearCallingIdentity();
try {
Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
@@ -672,14 +677,12 @@ public class AccountManagerService
}
}
- private void enforceCrossUserPermission(int userId, String errorMessage) {
- if (userId != UserHandle.getCallingUserId()
- && Binder.getCallingUid() != Process.myUid()
+ private boolean isCrossUser(int callingUid, int userId) {
+ return (userId != UserHandle.getCallingUserId()
+ && callingUid != Process.myUid()
&& mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(errorMessage);
- }
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ != PackageManager.PERMISSION_GRANTED);
}
@Override
@@ -691,7 +694,7 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot explicitly add accounts of type: %s",
callingUid,
@@ -720,8 +723,11 @@ public class AccountManagerService
@Override
public void copyAccountToUser(final IAccountManagerResponse response, final Account account,
int userFrom, int userTo) {
- enforceCrossUserPermission(UserHandle.USER_ALL, "Calling copyAccountToUser requires "
+ int callingUid = Binder.getCallingUid();
+ if (isCrossUser(callingUid, UserHandle.USER_ALL)) {
+ throw new SecurityException("Calling copyAccountToUser requires "
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ }
final UserAccounts fromAccounts = getUserAccounts(userFrom);
final UserAccounts toAccounts = getUserAccounts(userTo);
if (fromAccounts == null || toAccounts == null) {
@@ -784,7 +790,7 @@ public class AccountManagerService
if (account == null) {
throw new IllegalArgumentException("account is null");
}
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot notify authentication for accounts of type: %s",
callingUid,
@@ -957,17 +963,18 @@ public class AccountManagerService
@Override
public void hasFeatures(IAccountManagerResponse response,
Account account, String[] features) {
+ int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "hasFeatures: " + account
+ ", response " + response
+ ", features " + stringArrayToString(features)
- + ", caller's uid " + Binder.getCallingUid()
+ + ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
if (response == null) throw new IllegalArgumentException("response is null");
if (account == null) throw new IllegalArgumentException("account is null");
if (features == null) throw new IllegalArgumentException("features is null");
- checkReadAccountsPermission();
+ checkReadAccountsPermitted(callingUid, account.type);
UserAccounts accounts = getUserAccountsForCaller();
long identityToken = clearCallingIdentity();
try {
@@ -1043,7 +1050,7 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (accountToRename == null) throw new IllegalArgumentException("account is null");
- if (!isAccountOwnedByCallingUid(accountToRename.type, callingUid)) {
+ if (!isAccountManagedByCaller(accountToRename.type, callingUid)) {
String msg = String.format(
"uid %s cannot rename accounts of type: %s",
callingUid,
@@ -1053,8 +1060,7 @@ public class AccountManagerService
UserAccounts accounts = getUserAccountsForCaller();
long identityToken = clearCallingIdentity();
try {
- Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName,
- callingUid);
+ Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName);
Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type);
@@ -1069,7 +1075,7 @@ public class AccountManagerService
}
private Account renameAccountInternal(
- UserAccounts accounts, Account accountToRename, String newName, int callingUid) {
+ UserAccounts accounts, Account accountToRename, String newName) {
Account resultAccount = null;
/*
* Cancel existing notifications. Let authenticators
@@ -1179,16 +1185,20 @@ public class AccountManagerService
}
if (response == null) throw new IllegalArgumentException("response is null");
if (account == null) throw new IllegalArgumentException("account is null");
-
// Only allow the system process to modify accounts of other users
- enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
- + " trying to remove account for " + userId);
+ if (isCrossUser(callingUid, userId)) {
+ throw new SecurityException(
+ String.format(
+ "User %s tying remove account for %s" ,
+ UserHandle.getCallingUserId(),
+ userId));
+ }
/*
* Only the system or authenticator should be allowed to remove accounts for that
* authenticator. This will let users remove accounts (via Settings in the system) but not
* arbitrary applications (like competing authenticators).
*/
- if (!isAccountOwnedByCallingUid(account.type, callingUid) && !isSystemUid(callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid) && !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot remove accounts of type: %s",
callingUid,
@@ -1252,7 +1262,7 @@ public class AccountManagerService
*/
Log.e(TAG, "account is null");
return false;
- } else if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ } else if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot explicitly add accounts of type: %s",
callingUid,
@@ -1398,16 +1408,7 @@ public class AccountManagerService
return;
}
// Also wipe out cached token in memory.
- for (Account a : accounts.accountTokenCaches.keySet()) {
- if (a.type.equals(accountType)) {
- WeakReference<TokenCache> tokenCacheRef =
- accounts.accountTokenCaches.get(a);
- TokenCache cache = null;
- if (tokenCacheRef != null && (cache = tokenCacheRef.get()) != null) {
- cache.remove(authToken);
- }
- }
- }
+ accounts.accountTokenCaches.remove(accountType, authToken);
}
private void invalidateAuthTokenLocked(UserAccounts accounts, SQLiteDatabase db,
@@ -1459,11 +1460,8 @@ public class AccountManagerService
cancelNotification(getSigninRequiredNotificationId(accounts, account),
new UserHandle(accounts.userId));
synchronized (accounts.cacheLock) {
- TokenCache cache = getTokenCacheForAccountLocked(accounts, account);
- if (cache != null) {
- cache.put(token, tokenType, callerPkg, callerSigDigest, expiryMillis);
- }
- return;
+ accounts.accountTokenCaches.put(
+ account, token, tokenType, callerPkg, callerSigDigest, expiryMillis);
}
}
@@ -1512,7 +1510,7 @@ public class AccountManagerService
}
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot peek the authtokens associated with accounts of type: %s",
callingUid,
@@ -1539,7 +1537,7 @@ public class AccountManagerService
}
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot set auth tokens associated with accounts of type: %s",
callingUid,
@@ -1564,7 +1562,7 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot set secrets for accounts of type: %s",
callingUid,
@@ -1627,7 +1625,7 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot clear passwords for accounts of type: %s",
callingUid,
@@ -1654,7 +1652,7 @@ public class AccountManagerService
}
if (key == null) throw new IllegalArgumentException("key is null");
if (account == null) throw new IllegalArgumentException("account is null");
- if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot set user data for accounts of type: %s",
callingUid,
@@ -1780,7 +1778,6 @@ public class AccountManagerService
final boolean notifyOnAuthFailure,
final boolean expectActivityLaunch,
final Bundle loginOptions) {
-
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: " + account
+ ", response " + response
@@ -1877,6 +1874,9 @@ public class AccountManagerService
callerPkg,
callerPkgSigDigest);
if (token != null) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "getAuthToken: cache hit ofr custom token authenticator.");
+ }
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTHTOKEN, token);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
@@ -1914,10 +1914,11 @@ public class AccountManagerService
public void onResult(Bundle result) {
if (result != null) {
if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
- Intent intent = newGrantCredentialsPermissionIntent(account, callerUid,
+ Intent intent = newGrantCredentialsPermissionIntent(
+ account,
+ callerUid,
new AccountAuthenticatorResponse(this),
- authTokenType,
- result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL));
+ authTokenType);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
onResult(bundle);
@@ -1995,9 +1996,6 @@ public class AccountManagerService
GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
String authTokenType = intent.getStringExtra(
GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE);
- String authTokenLabel = intent.getStringExtra(
- GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL);
-
final String titleAndSubtitle =
mContext.getString(R.string.permission_request_notification_with_subtitle,
account.name);
@@ -2025,7 +2023,7 @@ public class AccountManagerService
}
private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
- AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
+ AccountAuthenticatorResponse response, String authTokenType) {
Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
// See FLAG_ACTIVITY_NEW_TASK docs for limitations and benefits of the flag.
@@ -2149,6 +2147,7 @@ public class AccountManagerService
public void addAccountAsUser(final IAccountManagerResponse response, final String accountType,
final String authTokenType, final String[] requiredFeatures,
final boolean expectActivityLaunch, final Bundle optionsIn, int userId) {
+ int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccount: accountType " + accountType
+ ", response " + response
@@ -2161,10 +2160,14 @@ public class AccountManagerService
}
if (response == null) throw new IllegalArgumentException("response is null");
if (accountType == null) throw new IllegalArgumentException("accountType is null");
-
// Only allow the system process to add accounts of other users
- enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
- + " trying to add account for " + userId);
+ if (isCrossUser(callingUid, userId)) {
+ throw new SecurityException(
+ String.format(
+ "User %s trying to add account for %s" ,
+ UserHandle.getCallingUserId(),
+ userId));
+ }
// Is user disallowed from modifying accounts?
if (!canUserModifyAccounts(userId)) {
@@ -2235,20 +2238,28 @@ public class AccountManagerService
}
@Override
- public void confirmCredentialsAsUser(IAccountManagerResponse response,
- final Account account, final Bundle options, final boolean expectActivityLaunch,
+ public void confirmCredentialsAsUser(
+ IAccountManagerResponse response,
+ final Account account,
+ final Bundle options,
+ final boolean expectActivityLaunch,
int userId) {
- // Only allow the system process to read accounts of other users
- enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
- + " trying to confirm account credentials for " + userId);
-
+ int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "confirmCredentials: " + account
+ ", response " + response
+ ", expectActivityLaunch " + expectActivityLaunch
- + ", caller's uid " + Binder.getCallingUid()
+ + ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
+ // Only allow the system process to read accounts of other users
+ if (isCrossUser(callingUid, userId)) {
+ throw new SecurityException(
+ String.format(
+ "User %s trying to confirm account credentials for %s" ,
+ UserHandle.getCallingUserId(),
+ userId));
+ }
if (response == null) throw new IllegalArgumentException("response is null");
if (account == null) throw new IllegalArgumentException("account is null");
UserAccounts accounts = getUserAccounts(userId);
@@ -2324,7 +2335,7 @@ public class AccountManagerService
}
if (response == null) throw new IllegalArgumentException("response is null");
if (accountType == null) throw new IllegalArgumentException("accountType is null");
- if (!isAccountOwnedByCallingUid(accountType, callingUid) && !isSystemUid(callingUid)) {
+ if (!isAccountManagedByCaller(accountType, callingUid) && !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot edit authenticator properites for account type: %s",
callingUid,
@@ -2457,9 +2468,11 @@ public class AccountManagerService
* @hide
*/
public Account[] getAccounts(int userId) {
- checkReadAccountsPermission();
UserAccounts accounts = getUserAccounts(userId);
int callingUid = Binder.getCallingUid();
+ if (!isReadAccountsPermitted(callingUid, null)) {
+ return new Account[0];
+ }
long identityToken = clearCallingIdentity();
try {
synchronized (accounts.cacheLock) {
@@ -2519,7 +2532,10 @@ public class AccountManagerService
return getAccountsAsUser(type, userId, null, -1);
}
- private Account[] getAccountsAsUser(String type, int userId, String callingPackage,
+ private Account[] getAccountsAsUser(
+ String type,
+ int userId,
+ String callingPackage,
int packageUid) {
int callingUid = Binder.getCallingUid();
// Only allow the system process to read accounts of other users
@@ -2542,7 +2558,12 @@ public class AccountManagerService
if (packageUid != -1 && UserHandle.isSameApp(callingUid, Process.myUid())) {
callingUid = packageUid;
}
- checkReadAccountsPermission();
+
+ // Authenticators should be able to see their own accounts regardless of permissions.
+ if (TextUtils.isEmpty(type) && !isReadAccountsPermitted(callingUid, type)) {
+ return new Account[0];
+ }
+
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -2593,7 +2614,7 @@ public class AccountManagerService
logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_SHARED_ACCOUNTS,
sharedTableAccountId, accounts, callingUid);
// Recursively rename the account.
- renameAccountInternal(accounts, account, newName, callingUid);
+ renameAccountInternal(accounts, account, newName);
}
return r > 0;
}
@@ -2663,7 +2684,6 @@ public class AccountManagerService
@Override
public Account[] getAccountsByTypeForPackage(String type, String packageName) {
- checkBinderPermission(android.Manifest.permission.INTERACT_ACROSS_USERS);
int packageUid = -1;
try {
packageUid = AppGlobals.getPackageManager().getPackageUid(
@@ -2676,20 +2696,31 @@ public class AccountManagerService
}
@Override
- public void getAccountsByFeatures(IAccountManagerResponse response,
- String type, String[] features) {
+ public void getAccountsByFeatures(
+ IAccountManagerResponse response,
+ String type,
+ String[] features) {
+ int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAccounts: accountType " + type
+ ", response " + response
+ ", features " + stringArrayToString(features)
- + ", caller's uid " + Binder.getCallingUid()
+ + ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
if (response == null) throw new IllegalArgumentException("response is null");
if (type == null) throw new IllegalArgumentException("accountType is null");
- checkReadAccountsPermission();
+ if (!isReadAccountsPermitted(callingUid, type)) {
+ Bundle result = new Bundle();
+ result.putParcelableArray(AccountManager.KEY_ACCOUNTS, new Account[0]);
+ try {
+ response.onResult(result);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot respond to caller do to exception." , e);
+ }
+ return;
+ }
UserAccounts userAccounts = getUserAccountsForCaller();
- int callingUid = Binder.getCallingUid();
long identityToken = clearCallingIdentity();
try {
if (features == null || features.length == 0) {
@@ -2872,11 +2903,6 @@ public class AccountManagerService
}
}
- public void scheduleTimeout() {
- mMessageHandler.sendMessageDelayed(
- mMessageHandler.obtainMessage(MESSAGE_TIMED_OUT, this), TIMEOUT_DELAY_MS);
- }
-
public void cancelTimeout() {
mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this);
}
@@ -3181,12 +3207,9 @@ public class AccountManagerService
// who called.
private static String ACTION_CALLED_ACCOUNT_ADD = "action_called_account_add";
private static String ACTION_CALLED_ACCOUNT_REMOVE = "action_called_account_remove";
- private static String ACTION_CALLED_ACCOUNT_RENAME = "action_called_account_rename";
private static SimpleDateFormat dateFromat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- private static String UPDATE_WHERE_CLAUSE = KEY + "=?";
-
private static void createDebugTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_DEBUG + " ( "
+ ACCOUNTS_ID + " INTEGER,"
@@ -3421,7 +3444,7 @@ public class AccountManagerService
}
}
- public IBinder onBind(Intent intent) {
+ public IBinder onBind(@SuppressWarnings("unused") Intent intent) {
return asBinder();
}
@@ -3576,21 +3599,29 @@ public class AccountManagerService
}
}
- /** Succeeds if any of the specified permissions are granted. */
- private void checkBinderPermission(String... permissions) {
- final int uid = Binder.getCallingUid();
-
+ private boolean isPermitted(int callingUid, String... permissions) {
for (String perm : permissions) {
if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, " caller uid " + uid + " has " + perm);
+ Log.v(TAG, " caller uid " + callingUid + " has " + perm);
}
- return;
+ return true;
}
}
- String msg = "caller uid " + uid + " lacks any of " + TextUtils.join(",", permissions);
- Log.w(TAG, " " + msg);
- throw new SecurityException(msg);
+ return false;
+ }
+
+ /** Succeeds if any of the specified permissions are granted. */
+ private void checkBinderPermission(String... permissions) {
+ final int callingUid = Binder.getCallingUid();
+ if (isPermitted(callingUid, permissions)) {
+ String msg = String.format(
+ "caller uid %s lacks any of %s",
+ callingUid,
+ TextUtils.join(",", permissions));
+ Log.w(TAG, " " + msg);
+ throw new SecurityException(msg);
+ }
}
private int handleIncomingUser(int userId) {
@@ -3646,6 +3677,9 @@ public class AccountManagerService
}
private boolean isAccountManagedByCaller(String accountType, int callingUid) {
+ if (accountType == null) {
+ return false;
+ }
final int callingUserId = UserHandle.getUserId(callingUid);
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
mAuthenticatorCache.getAllServices(callingUserId)) {
@@ -3723,20 +3757,34 @@ public class AccountManagerService
return false;
}
- private boolean isAccountOwnedByCallingUid(String accountType, int callingUid) {
- if (!isAccountManagedByCaller(accountType, callingUid)) {
- String msg = "caller uid " + callingUid + " is different than the authenticator's uid";
- Log.w(TAG, msg);
- return false;
- }
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "caller uid " + callingUid + " is the same as the authenticator's uid");
- }
- return true;
+ private boolean isReadAccountsPermitted(int callingUid, String accountType) {
+ /*
+ * Settings app (which is in the same uid as AcocuntManagerService), apps with the
+ * GET_ACCOUNTS permission or authenticators that own the account type should be able to
+ * access accounts of the specified account.
+ */
+ boolean isPermitted =
+ isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS);
+ boolean isAccountManagedByCaller = isAccountManagedByCaller(accountType, callingUid);
+ Log.w(TAG, String.format(
+ "isReadAccountPermitted: isPermitted: %s, isAM: %s",
+ isPermitted,
+ isAccountManagedByCaller));
+ return isPermitted || isAccountManagedByCaller;
}
- private void checkReadAccountsPermission() {
- checkBinderPermission(Manifest.permission.GET_ACCOUNTS);
+ /** Succeeds if any of the specified permissions are granted. */
+ private void checkReadAccountsPermitted(
+ int callingUid,
+ String accountType) {
+ if (!isReadAccountsPermitted(callingUid, accountType)) {
+ String msg = String.format(
+ "caller uid %s cannot access %s accounts",
+ callingUid,
+ accountType);
+ Log.w(TAG, " " + msg);
+ throw new SecurityException(msg);
+ }
}
private boolean canUserModifyAccounts(int userId) {
@@ -4008,8 +4056,8 @@ public class AccountManagerService
String callingPackage,
byte[] pkgSigDigest) {
synchronized (accounts.cacheLock) {
- TokenCache cache = getTokenCacheForAccountLocked(accounts, account);
- return cache.get(tokenType, callingPackage, pkgSigDigest);
+ return accounts.accountTokenCaches.get(
+ account, tokenType, callingPackage, pkgSigDigest);
}
}
@@ -4094,17 +4142,6 @@ public class AccountManagerService
return authTokensForAccount;
}
- protected TokenCache getTokenCacheForAccountLocked(UserAccounts accounts, Account account) {
- WeakReference<TokenCache> cacheRef = accounts.accountTokenCaches.get(account);
- TokenCache cache;
- if (cacheRef == null || (cache = cacheRef.get()) == null) {
- cache = new TokenCache();
- cacheRef = new WeakReference<>(cache);
- accounts.accountTokenCaches.put(account, cacheRef);
- }
- return cache;
- }
-
private Context getContextForUser(UserHandle user) {
try {
return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java
index 70a7010..be91f98 100644
--- a/services/core/java/com/android/server/accounts/TokenCache.java
+++ b/services/core/java/com/android/server/accounts/TokenCache.java
@@ -16,6 +16,12 @@
package com.android.server.accounts;
+import android.accounts.Account;
+import android.util.LruCache;
+import android.util.Pair;
+
+import com.android.internal.util.Preconditions;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -23,10 +29,12 @@ import java.util.List;
import java.util.Objects;
/**
- * TokenCaches manage tokens associated with an account in memory.
+ * TokenCaches manage time limited authentication tokens in memory.
*/
/* default */ class TokenCache {
+ private static final int MAX_CACHE_CHARS = 64000;
+
private static class Value {
public final String token;
public final long expiryEpochMillis;
@@ -38,11 +46,13 @@ import java.util.Objects;
}
private static class Key {
+ public final Account account;
public final String packageName;
public final String tokenType;
public final byte[] sigDigest;
- public Key(String tokenType, String packageName, byte[] sigDigest) {
+ public Key(Account account, String tokenType, String packageName, byte[] sigDigest) {
+ this.account = account;
this.tokenType = tokenType;
this.packageName = packageName;
this.sigDigest = sigDigest;
@@ -52,7 +62,8 @@ import java.util.Objects;
public boolean equals(Object o) {
if (o != null && o instanceof Key) {
Key cacheKey = (Key) o;
- return Objects.equals(packageName, cacheKey.packageName)
+ return Objects.equals(account, cacheKey.account)
+ && Objects.equals(packageName, cacheKey.packageName)
&& Objects.equals(tokenType, cacheKey.tokenType)
&& Arrays.equals(sigDigest, cacheKey.sigDigest);
} else {
@@ -62,46 +73,109 @@ import java.util.Objects;
@Override
public int hashCode() {
- return packageName.hashCode() ^ tokenType.hashCode() ^ Arrays.hashCode(sigDigest);
+ return account.hashCode()
+ ^ packageName.hashCode()
+ ^ tokenType.hashCode()
+ ^ Arrays.hashCode(sigDigest);
}
}
- /**
- * Map associating basic token lookup information with with actual tokens (and optionally their
- * expiration times).
- */
- private HashMap<Key, Value> mCachedTokens = new HashMap<>();
+ private static class TokenLruCache extends LruCache<Key, Value> {
- /**
- * Map associated tokens with an Evictor that will manage evicting the token from the cache.
- * This reverse lookup is needed because very little information is given at token invalidation
- * time.
- */
- private HashMap<String, Evictor> mTokenEvictors = new HashMap<>();
+ private class Evictor {
+ private final List<Key> mKeys;
+
+ public Evictor() {
+ mKeys = new ArrayList<>();
+ }
+
+ public void add(Key k) {
+ mKeys.add(k);
+ }
+
+ public void evict() {
+ for (Key k : mKeys) {
+ TokenLruCache.this.remove(k);
+ }
+ }
+ }
+
+ /**
+ * Map associated tokens with an Evictor that will manage evicting the token from the
+ * cache. This reverse lookup is needed because very little information is given at token
+ * invalidation time.
+ */
+ private HashMap<Pair<String, String>, Evictor> mTokenEvictors = new HashMap<>();
+ private HashMap<Account, Evictor> mAccountEvictors = new HashMap<>();
+
+ public TokenLruCache() {
+ super(MAX_CACHE_CHARS);
+ }
+
+ @Override
+ protected int sizeOf(Key k, Value v) {
+ return v.token.length();
+ }
+
+ @Override
+ protected void entryRemoved(boolean evicted, Key k, Value oldVal, Value newVal) {
+ // When a token has been removed, clean up the associated Evictor.
+ if (oldVal != null && newVal == null) {
+ /*
+ * This is recursive, but it won't spiral out of control because LruCache is
+ * thread safe and the Evictor can only be removed once.
+ */
+ Evictor evictor = mTokenEvictors.remove(oldVal.token);
+ if (evictor != null) {
+ evictor.evict();
+ }
+ }
+ }
- private class Evictor {
- private final String mToken;
- private final List<Key> mKeys;
+ public void putToken(Key k, Value v) {
+ // Prepare for removal by token string.
+ Evictor tokenEvictor = mTokenEvictors.get(v.token);
+ if (tokenEvictor == null) {
+ tokenEvictor = new Evictor();
+ }
+ tokenEvictor.add(k);
+ mTokenEvictors.put(new Pair<>(k.account.type, v.token), tokenEvictor);
- public Evictor(String token) {
- mKeys = new ArrayList<>();
- mToken = token;
+ // Prepare for removal by associated account.
+ Evictor accountEvictor = mAccountEvictors.get(k.account);
+ if (accountEvictor == null) {
+ accountEvictor = new Evictor();
+ }
+ accountEvictor.add(k);
+ mAccountEvictors.put(k.account, tokenEvictor);
+
+ // Only cache the token once we can remove it directly or by account.
+ put(k, v);
}
- public void add(Key k) {
- mKeys.add(k);
+ public void evict(String accountType, String token) {
+ Evictor evictor = mTokenEvictors.get(new Pair<>(accountType, token));
+ if (evictor != null) {
+ evictor.evict();
+ }
+
}
- public void evict() {
- for (Key k : mKeys) {
- mCachedTokens.remove(k);
+ public void evict(Account account) {
+ Evictor evictor = mAccountEvictors.get(account);
+ if (evictor != null) {
+ evictor.evict();
}
- // Clear out the evictor reference.
- mTokenEvictors.remove(mToken);
}
}
/**
+ * Map associating basic token lookup information with with actual tokens (and optionally their
+ * expiration times).
+ */
+ private TokenLruCache mCachedTokens = new TokenLruCache();
+
+ /**
* Caches the specified token until the specified expiryMillis. The token will be associated
* with the given token type, package name, and digest of signatures.
*
@@ -112,51 +186,44 @@ import java.util.Objects;
* @param expiryMillis
*/
public void put(
+ Account account,
String token,
String tokenType,
String packageName,
byte[] sigDigest,
long expiryMillis) {
+ Preconditions.checkNotNull(account);
if (token == null || System.currentTimeMillis() > expiryMillis) {
return;
}
- Key k = new Key(tokenType, packageName, sigDigest);
- // Prep evictor. No token should be cached without a corresponding evictor.
- Evictor evictor = mTokenEvictors.get(token);
- if (evictor == null) {
- evictor = new Evictor(token);
- }
- evictor.add(k);
- mTokenEvictors.put(token, evictor);
- // Then cache values.
+ Key k = new Key(account, tokenType, packageName, sigDigest);
Value v = new Value(token, expiryMillis);
- mCachedTokens.put(k, v);
+ mCachedTokens.putToken(k, v);
}
/**
* Evicts the specified token from the cache. This should be called as part of a token
* invalidation workflow.
*/
- public void remove(String token) {
- Evictor evictor = mTokenEvictors.get(token);
- if (evictor == null) {
- // This condition is expected if the token isn't cached.
- return;
- }
- evictor.evict();
+ public void remove(String accountType, String token) {
+ mCachedTokens.evict(accountType, token);
+ }
+
+ public void remove(Account account) {
+ mCachedTokens.evict(account);
}
/**
* Gets a token from the cache if possible.
*/
- public String get(String tokenType, String packageName, byte[] sigDigest) {
- Key k = new Key(tokenType, packageName, sigDigest);
+ public String get(Account account, String tokenType, String packageName, byte[] sigDigest) {
+ Key k = new Key(account, tokenType, packageName, sigDigest);
Value v = mCachedTokens.get(k);
long currentTime = System.currentTimeMillis();
if (v != null && currentTime < v.expiryEpochMillis) {
return v.token;
} else if (v != null) {
- remove(v.token);
+ remove(account.type, v.token);
}
return null;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 333db5d..899139f 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Set;
import android.app.ActivityThread;
+import android.app.AppOpsManager;
import android.os.Build;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -302,8 +303,8 @@ public final class ActiveServices {
return getServiceMap(callingUser).mServicesByName;
}
- ComponentName startServiceLocked(IApplicationThread caller, Intent service,
- String resolvedType, int callingPid, int callingUid, int userId)
+ ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
+ int callingPid, int callingUid, String callingPackage, int userId)
throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
@@ -324,7 +325,7 @@ public final class ActiveServices {
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType,
+ retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg);
if (res == null) {
return null;
@@ -490,7 +491,7 @@ public final class ActiveServices {
}
// If this service is active, make sure it is stopped.
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
+ ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false);
if (r != null) {
if (r.record != null) {
@@ -508,8 +509,8 @@ public final class ActiveServices {
return 0;
}
- IBinder peekServiceLocked(Intent service, String resolvedType) {
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
+ IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
+ ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(),
UserHandle.getCallingUserId(), false, false);
@@ -694,8 +695,8 @@ public final class ActiveServices {
}
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
- String resolvedType, IServiceConnection connection, int flags, int userId)
- throws TransactionTooLargeException {
+ String resolvedType, IServiceConnection connection, int flags,
+ String callingPackage, int userId) throws TransactionTooLargeException {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
@@ -746,7 +747,7 @@ public final class ActiveServices {
final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType,
+ retrieveServiceLocked(service, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
if (res == null) {
return 0;
@@ -1022,7 +1023,7 @@ public final class ActiveServices {
}
private ServiceLookupResult retrieveServiceLocked(Intent service,
- String resolvedType, int callingPid, int callingUid, int userId,
+ String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg) {
ServiceRecord r = null;
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
@@ -1112,7 +1113,18 @@ public final class ActiveServices {
+ ", uid=" + callingUid
+ " requires " + r.permission);
return new ServiceLookupResult(null, r.permission);
+ } else if (r.permission != null && callingPackage != null) {
+ final int opCode = AppOpsManager.permissionToOpCode(r.permission);
+ if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
+ opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: Accessing service " + r.name
+ + " from pid=" + callingPid
+ + ", uid=" + callingUid
+ + " requires appop " + AppOpsManager.opToName(opCode));
+ return null;
+ }
}
+
if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
resolvedType, r.appInfo)) {
return null;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 959fd37..477c26c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18,9 +18,7 @@ package com.android.server.am;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -15554,13 +15552,18 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType, int userId) throws TransactionTooLargeException {
+ String resolvedType, String callingPackage, int userId)
+ throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ if (callingPackage == null) {
+ throw new IllegalArgumentException("callingPackage cannot be null");
+ }
+
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startService: " + service + " type=" + resolvedType);
synchronized(this) {
@@ -15568,20 +15571,21 @@ public final class ActivityManagerService extends ActivityManagerNative
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
- resolvedType, callingPid, callingUid, userId);
+ resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
- ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, int userId)
+ ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
+ String callingPackage, int userId)
throws TransactionTooLargeException {
synchronized(this) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startServiceInPackage: " + service + " type=" + resolvedType);
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(null, service,
- resolvedType, -1, uid, userId);
+ resolvedType, -1, uid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -15602,14 +15606,19 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public IBinder peekService(Intent service, String resolvedType) {
+ public IBinder peekService(Intent service, String resolvedType, String callingPackage) {
enforceNotIsolatedCaller("peekService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+
+ if (callingPackage == null) {
+ throw new IllegalArgumentException("callingPackage cannot be null");
+ }
+
synchronized(this) {
- return mServices.peekServiceLocked(service, resolvedType);
+ return mServices.peekServiceLocked(service, resolvedType, callingPackage);
}
}
@@ -15779,8 +15788,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public int bindService(IApplicationThread caller, IBinder token, Intent service,
- String resolvedType, IServiceConnection connection, int flags, int userId)
- throws TransactionTooLargeException {
+ String resolvedType, IServiceConnection connection, int flags, String callingPackage,
+ int userId) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
@@ -15788,9 +15797,13 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ if (callingPackage == null) {
+ throw new IllegalArgumentException("callingPackage cannot be null");
+ }
+
synchronized(this) {
- return mServices.bindServiceLocked(caller, token, service, resolvedType,
- connection, flags, userId);
+ return mServices.bindServiceLocked(caller, token, service,
+ resolvedType, connection, flags, callingPackage, userId);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 0714d36..8c3a950 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2829,7 +2829,7 @@ final class ActivityStack {
+ " res=" + resultCode + " data=" + resultData);
if (resultTo.userId != r.userId) {
if (resultData != null) {
- resultData.setContentUserHint(r.userId);
+ resultData.prepareToLeaveUser(r.userId);
}
}
if (r.info.applicationInfo.uid > 0) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4ce5c7e..c12aff6 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -187,12 +187,12 @@ public final class ActivityStackSupervisor implements DisplayListener {
Manifest.permission.CALL_PHONE);
}
- /** Action not restricted for the calling package. */
- private static final int ACTION_RESTRICTION_NONE = 0;
- /** Action restricted for the calling package by not granting a used permission. */
- private static final int ACTION_RESTRICTION_PERMISSION = 1;
- /** Action restricted for the calling package by not allowing a used permission's app op. */
- private static final int ACTION_RESTRICTION_APPOP = 2;
+ /** Action restriction: launching the activity is not restricted. */
+ private static final int ACTIVITY_RESTRICTION_NONE = 0;
+ /** Action restriction: launching the activity is restricted by a permission. */
+ private static final int ACTIVITY_RESTRICTION_PERMISSION = 1;
+ /** Action restriction: launching the activity is restricted by an app op. */
+ private static final int ACTIVITY_RESTRICTION_APPOP = 2;
/** Status Bar Service **/
private IBinder mToken = new Binder();
@@ -1539,51 +1539,61 @@ public final class ActivityStackSupervisor implements DisplayListener {
return err;
}
+ boolean abort = false;
+
final int startAnyPerm = mService.checkPermission(
START_ANY_ACTIVITY, callingPid, callingUid);
- final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
- callingUid, aInfo.applicationInfo.uid, aInfo.exported);
- final int actionRestriction = getActionRestrictionForCallingPackage(
- intent.getAction(), callingPackage, callingPid, callingUid);
- if (startAnyPerm != PERMISSION_GRANTED && (componentPerm != PERMISSION_GRANTED
- || actionRestriction == ACTION_RESTRICTION_PERMISSION)) {
- if (resultRecord != null) {
- resultStack.sendActivityResultLocked(-1,
- resultRecord, resultWho, requestCode,
- Activity.RESULT_CANCELED, null);
+ if (startAnyPerm != PERMISSION_GRANTED) {
+ final int componentRestriction = getComponentRestrictionForCallingPackage(
+ aInfo, callingPackage, callingPid, callingUid);
+ final int actionRestriction = getActionRestrictionForCallingPackage(
+ intent.getAction(), callingPackage, callingPid, callingUid);
+
+ if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
+ || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
+ if (resultRecord != null) {
+ resultStack.sendActivityResultLocked(-1,
+ resultRecord, resultWho, requestCode,
+ Activity.RESULT_CANCELED, null);
+ }
+ String msg;
+ if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
+ msg = "Permission Denial: starting " + intent.toString()
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")" + " with revoked permission "
+ + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
+ } else if (!aInfo.exported) {
+ msg = "Permission Denial: starting " + intent.toString()
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")"
+ + " not exported from uid " + aInfo.applicationInfo.uid;
+ } else {
+ msg = "Permission Denial: starting " + intent.toString()
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")"
+ + " requires " + aInfo.permission;
+ }
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
}
- String msg;
- if (actionRestriction == ACTION_RESTRICTION_PERMISSION) {
- msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ")" + " with revoked permission "
- + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
- } else if (!aInfo.exported) {
- msg = "Permission Denial: starting " + intent.toString()
+
+ if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
+ String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
- + " not exported from uid " + aInfo.applicationInfo.uid;
- } else {
- msg = "Permission Denial: starting " + intent.toString()
+ + " requires " + AppOpsManager.permissionToOp(
+ ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()));
+ Slog.w(TAG, message);
+ abort = true;
+ } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
+ String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
- + " requires " + aInfo.permission;
+ + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission);
+ Slog.w(TAG, message);
+ abort = true;
}
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
-
- boolean abort = false;
-
- if (startAnyPerm != PERMISSION_GRANTED
- && actionRestriction == ACTION_RESTRICTION_APPOP) {
- String msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ")"
- + " requires " + aInfo.permission;
- Slog.w(TAG, msg);
- abort = true;
}
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
@@ -1664,15 +1674,40 @@ public final class ActivityStackSupervisor implements DisplayListener {
return err;
}
+ private int getComponentRestrictionForCallingPackage(ActivityInfo activityInfo,
+ String callingPackage, int callingPid, int callingUid) {
+ if (activityInfo.permission == null) {
+ return ACTIVITY_RESTRICTION_NONE;
+ }
+
+ if (mService.checkComponentPermission(activityInfo.permission, callingPid, callingUid,
+ activityInfo.applicationInfo.uid, activityInfo.exported)
+ == PackageManager.PERMISSION_DENIED) {
+ return ACTIVITY_RESTRICTION_PERMISSION;
+ }
+
+ final int opCode = AppOpsManager.permissionToOpCode(activityInfo.permission);
+ if (opCode == AppOpsManager.OP_NONE) {
+ return ACTIVITY_RESTRICTION_NONE;
+ }
+
+ if (mService.mAppOpsService.noteOperation(opCode, callingUid,
+ callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ return ACTIVITY_RESTRICTION_APPOP;
+ }
+
+ return ACTIVITY_RESTRICTION_NONE;
+ }
+
private int getActionRestrictionForCallingPackage(String action,
String callingPackage, int callingPid, int callingUid) {
if (action == null) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
String permission = ACTION_TO_RUNTIME_PERMISSION.get(action);
if (permission == null) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
final PackageInfo packageInfo;
@@ -1681,29 +1716,29 @@ public final class ActivityStackSupervisor implements DisplayListener {
.getPackageInfo(callingPackage, PackageManager.GET_PERMISSIONS);
} catch (PackageManager.NameNotFoundException e) {
Slog.i(TAG, "Cannot find package info for " + callingPackage);
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
if (!ArrayUtils.contains(packageInfo.requestedPermissions, permission)) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
if (mService.checkPermission(permission, callingPid, callingUid) ==
PackageManager.PERMISSION_DENIED) {
- return ACTION_RESTRICTION_PERMISSION;
+ return ACTIVITY_RESTRICTION_PERMISSION;
}
final int opCode = AppOpsManager.permissionToOpCode(permission);
if (opCode == AppOpsManager.OP_NONE) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
if (mService.mAppOpsService.noteOperation(opCode, callingUid,
callingPackage) != AppOpsManager.MODE_ALLOWED) {
- return ACTION_RESTRICTION_APPOP;
+ return ACTIVITY_RESTRICTION_APPOP;
}
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
ActivityStack computeStackFocus(ActivityRecord r, boolean newTask) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 2335071..30aa411 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -463,7 +463,7 @@ public final class BroadcastQueue {
}
}
- private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
+ private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
if (filter.requiredPermission != null) {
@@ -477,9 +477,23 @@ public final class BroadcastQueue {
+ " requires " + filter.requiredPermission
+ " due to registered receiver " + filter);
skip = true;
+ } else {
+ final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
+ if (opCode != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
+ r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: broadcasting "
+ + r.intent.toString()
+ + " from " + r.callerPackage + " (pid="
+ + r.callingPid + ", uid=" + r.callingUid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ filter.requiredPermission)
+ + " due to registered receiver " + filter);
+ skip = true;
+ }
}
}
- if (!skip && r.requiredPermission != null) {
+ if (!skip) {
int perm = mService.checkComponentPermission(r.requiredPermission,
filter.receiverList.pid, filter.receiverList.uid, -1, true);
if (perm != PackageManager.PERMISSION_GRANTED) {
@@ -493,17 +507,42 @@ public final class BroadcastQueue {
+ " (uid " + r.callingUid + ")");
skip = true;
}
- }
- if (r.appOp != AppOpsManager.OP_NONE) {
- int mode = mService.mAppOpsService.noteOperation(r.appOp,
- filter.receiverList.uid, filter.packageName);
- if (mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "App op " + r.appOp + " not allowed for broadcast to uid "
- + filter.receiverList.uid + " pkg " + filter.packageName);
- skip = true;
+ int appOp = AppOpsManager.OP_NONE;
+ if (r.requiredPermission != null) {
+ appOp = AppOpsManager.permissionToOpCode(r.requiredPermission);
+ if (appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(appOp,
+ filter.receiverList.uid, filter.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent.toString()
+ + " to " + filter.receiverList.app
+ + " (pid=" + filter.receiverList.pid
+ + ", uid=" + filter.receiverList.uid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
+ }
+ if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(r.appOp,
+ filter.receiverList.uid, filter.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent.toString()
+ + " to " + filter.receiverList.app
+ + " (pid=" + filter.receiverList.pid
+ + ", uid=" + filter.receiverList.uid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
}
}
+
if (!skip) {
skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, filter.receiverList.uid);
@@ -804,8 +843,23 @@ public final class BroadcastQueue {
+ " due to receiver " + component.flattenToShortString());
}
skip = true;
+ } else if (info.activityInfo.permission != null) {
+ final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
+ if (opCode != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
+ r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: broadcasting "
+ + r.intent.toString()
+ + " from " + r.callerPackage + " (pid="
+ + r.callingPid + ", uid=" + r.callingUid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ info.activityInfo.permission)
+ + " due to registered receiver "
+ + component.flattenToShortString());
+ skip = true;
+ }
}
- if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
+ if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
r.requiredPermission != null) {
try {
perm = AppGlobals.getPackageManager().
@@ -825,17 +879,36 @@ public final class BroadcastQueue {
skip = true;
}
}
- if (r.appOp != AppOpsManager.OP_NONE) {
- int mode = mService.mAppOpsService.noteOperation(r.appOp,
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName);
- if (mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "App op " + r.appOp + " not allowed for broadcast to uid "
- + info.activityInfo.applicationInfo.uid + " pkg "
- + info.activityInfo.packageName);
+ int appOp = AppOpsManager.OP_NONE;
+ if (!skip && r.requiredPermission != null) {
+ appOp = AppOpsManager.permissionToOpCode(r.requiredPermission);
+ if (appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(appOp,
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent + " to "
+ + component.flattenToShortString()
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
skip = true;
}
}
+ if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(r.appOp,
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent + " to "
+ + component.flattenToShortString()
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
if (!skip) {
skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index ece3ffb..5b46799 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -305,7 +305,8 @@ final class PendingIntentRecord extends IIntentSender.Stub {
break;
case ActivityManager.INTENT_SENDER_SERVICE:
try {
- owner.startServiceInPackage(uid, finalIntent, resolvedType, userId);
+ owner.startServiceInPackage(uid, finalIntent,
+ resolvedType, key.packageName, userId);
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startService intent", e);
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 310e361..e472928 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -47,6 +47,7 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.LocalLog;
import android.util.LocalLog.ReadOnlyLocalLog;
import android.util.Log;
@@ -59,6 +60,7 @@ import com.android.server.connectivity.NetworkAgentInfo;
import java.io.IOException;
import java.net.HttpURLConnection;
+import java.net.InetAddress;
import java.net.URL;
import java.util.List;
import java.util.Random;
@@ -273,7 +275,7 @@ public class NetworkMonitor extends StateMachine {
@Override
protected void log(String s) {
- Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
+ if (DBG) Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
}
private void validationLog(String s) {
@@ -290,18 +292,15 @@ public class NetworkMonitor extends StateMachine {
private class DefaultState extends State {
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_NETWORK_LINGER:
- if (DBG) log("Lingering");
+ log("Lingering");
transitionTo(mLingeringState);
return HANDLED;
case CMD_NETWORK_CONNECTED:
- if (DBG) log("Connected");
transitionTo(mEvaluatingState);
return HANDLED;
case CMD_NETWORK_DISCONNECTED:
- if (DBG) log("Disconnected - quitting");
if (mLaunchCaptivePortalAppBroadcastReceiver != null) {
mContext.unregisterReceiver(mLaunchCaptivePortalAppBroadcastReceiver);
mLaunchCaptivePortalAppBroadcastReceiver = null;
@@ -310,13 +309,14 @@ public class NetworkMonitor extends StateMachine {
return HANDLED;
case CMD_FORCE_REEVALUATION:
case CMD_CAPTIVE_PORTAL_RECHECK:
- if (DBG) log("Forcing reevaluation");
+ log("Forcing reevaluation for UID " + message.arg1);
mUidResponsibleForReeval = message.arg1;
transitionTo(mEvaluatingState);
return HANDLED;
case CMD_CAPTIVE_PORTAL_APP_FINISHED:
if (!mCaptivePortalLoggedInResponseToken.equals((String)message.obj))
return HANDLED;
+ log("CaptivePortal App responded with " + message.arg1);
// Previous token was sent out, come up with a new one.
mCaptivePortalLoggedInResponseToken = String.valueOf(new Random().nextLong());
switch (message.arg1) {
@@ -354,14 +354,12 @@ public class NetworkMonitor extends StateMachine {
private class ValidatedState extends State {
@Override
public void enter() {
- if (DBG) log("Validated");
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_VALID, 0, mNetworkAgentInfo));
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_NETWORK_CONNECTED:
transitionTo(mValidatedState);
@@ -377,7 +375,6 @@ public class NetworkMonitor extends StateMachine {
private class MaybeNotifyState extends State {
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_LAUNCH_CAPTIVE_PORTAL_APP:
final Intent intent = new Intent(
@@ -421,7 +418,6 @@ public class NetworkMonitor extends StateMachine {
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_REEVALUATE:
if (message.arg1 != mReevaluateToken || mUserDoesNotWant)
@@ -546,12 +542,6 @@ public class NetworkMonitor extends StateMachine {
}
@Override
- public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString());
- return NOT_HANDLED;
- }
-
- @Override
public void exit() {
removeMessages(CMD_CAPTIVE_PORTAL_RECHECK);
}
@@ -583,9 +573,9 @@ public class NetworkMonitor extends StateMachine {
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_NETWORK_CONNECTED:
+ log("Unlingered");
// Go straight to active as we've already evaluated.
transitionTo(mValidatedState);
return HANDLED;
@@ -655,15 +645,31 @@ public class NetworkMonitor extends StateMachine {
// fact block fetching of the generate_204 URL which would lead to false negative
// results for network validation.
boolean fetchPac = false;
- {
- final ProxyInfo proxyInfo = mNetworkAgentInfo.linkProperties.getHttpProxy();
- if (proxyInfo != null && !Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) {
- url = new URL(proxyInfo.getPacFileUrl().toString());
- fetchPac = true;
+ final ProxyInfo proxyInfo = mNetworkAgentInfo.linkProperties.getHttpProxy();
+ if (proxyInfo != null && !Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) {
+ url = new URL(proxyInfo.getPacFileUrl().toString());
+ fetchPac = true;
+ }
+ final StringBuffer connectInfo = new StringBuffer();
+ String hostToResolve = null;
+ // Only resolve a host if HttpURLConnection is about to, to avoid any potentially
+ // unnecessary resolution.
+ if (proxyInfo == null || fetchPac) {
+ hostToResolve = url.getHost();
+ } else if (proxyInfo != null) {
+ hostToResolve = proxyInfo.getHost();
+ }
+ if (!TextUtils.isEmpty(hostToResolve)) {
+ connectInfo.append(", " + hostToResolve + "=");
+ final InetAddress[] addresses =
+ mNetworkAgentInfo.network.getAllByName(hostToResolve);
+ for (InetAddress address : addresses) {
+ connectInfo.append(address.getHostAddress());
+ if (address != addresses[addresses.length-1]) connectInfo.append(",");
}
}
validationLog("Checking " + url.toString() + " on " +
- mNetworkAgentInfo.networkInfo.getExtraInfo());
+ mNetworkAgentInfo.networkInfo.getExtraInfo() + connectInfo);
urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
urlConnection.setInstanceFollowRedirects(fetchPac);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
@@ -729,7 +735,6 @@ public class NetworkMonitor extends StateMachine {
long requestTimestampMs, long responseTimestampMs) {
if (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 0) {
- if (DBG) log("Don't send network conditions - lacking user consent.");
return;
}
@@ -763,7 +768,7 @@ public class NetworkMonitor extends StateMachine {
if (cellInfo.isRegistered()) {
numRegisteredCellInfo++;
if (numRegisteredCellInfo > 1) {
- if (DBG) log("more than one registered CellInfo. Can't " +
+ log("more than one registered CellInfo. Can't " +
"tell which is active. Bailing.");
return;
}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 2c57833..c13401f 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -31,6 +31,7 @@ import android.content.SyncInfo;
import android.content.SyncRequest;
import android.content.SyncStatusInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.database.IContentObserver;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
@@ -46,6 +47,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;
+import com.android.server.LocalServices;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -153,6 +155,18 @@ public final class ContentService extends IContentService.Stub {
/*package*/ ContentService(Context context, boolean factoryTest) {
mContext = context;
mFactoryTest = factoryTest;
+
+ // Let the package manager query for the sync adapters for a given authority
+ // as we grant default permissions to sync adapters for specifix authorities.
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ packageManagerInternal.setSyncAdapterPackagesprovider(
+ new PackageManagerInternal.SyncAdapterPackagesProvider() {
+ @Override
+ public String[] getPackages(String authority, int userId) {
+ return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
+ }
+ });
}
public void systemReady() {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d4b7256..f618c3e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -146,6 +146,7 @@ import android.util.SparseIntArray;
import android.util.TrustedTime;
import android.util.Xml;
+import com.android.server.EventLogTags;
import libcore.io.IoUtils;
import com.android.internal.R;
@@ -1764,7 +1765,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (mDeviceIdleMode != enabled) {
mDeviceIdleMode = enabled;
if (mSystemReady) {
- updateRulesForGlobalChangeLocked(true);
+ updateRulesForDeviceIdleLocked();
+ }
+ if (enabled) {
+ EventLogTags.writeDeviceIdleOnPhase("net");
+ } else {
+ EventLogTags.writeDeviceIdleOffPhase("net");
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 87b4f8c..6a1401c 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -28,7 +28,7 @@ public interface NotificationDelegate {
void onNotificationError(int callingUid, int callingPid,
String pkg, String tag, int id,
int uid, int initialPid, String message, int userId);
- void onPanelRevealed(boolean clearEffects);
+ void onPanelRevealed(boolean clearEffects, int numItems);
void onPanelHidden();
void clearEffects();
void onNotificationVisibilityChanged(
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d6a7bf93..87e9d42 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -567,8 +567,8 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public void onPanelRevealed(boolean clearEffects) {
- EventLogTags.writeNotificationPanelRevealed();
+ public void onPanelRevealed(boolean clearEffects, int items) {
+ EventLogTags.writeNotificationPanelRevealed(items);
if (clearEffects) {
clearEffects();
}
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 4ec825a..e459e26 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal.PackagesProvider;
+import android.content.pm.PackageManagerInternal.SyncAdapterPackagesProvider;
import android.content.pm.PackageParser;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
@@ -146,6 +147,7 @@ final class DefaultPermissionGrantPolicy {
private PackagesProvider mVoiceInteractionPackagesProvider;
private PackagesProvider mSmsAppPackagesProvider;
private PackagesProvider mDialerAppPackagesProvider;
+ private SyncAdapterPackagesProvider mSyncAdapterPackagesProvider;
public DefaultPermissionGrantPolicy(PackageManagerService service) {
mService = service;
@@ -171,6 +173,10 @@ final class DefaultPermissionGrantPolicy {
mDialerAppPackagesProvider = provider;
}
+ public void setSyncAdapterPackagesProviderrLPw(SyncAdapterPackagesProvider provider) {
+ mSyncAdapterPackagesProvider = provider;
+ }
+
public void grantDefaultPermissions(int userId) {
grantPermissionsToSysComponentsAndPrivApps(userId);
grantDefaultSystemHandlerPermissions(userId);
@@ -216,6 +222,7 @@ final class DefaultPermissionGrantPolicy {
final PackagesProvider voiceInteractionPackagesProvider;
final PackagesProvider smsAppPackagesProvider;
final PackagesProvider dialerAppPackagesProvider;
+ final SyncAdapterPackagesProvider syncAdapterPackagesProvider;
synchronized (mService.mPackages) {
imePackagesProvider = mImePackagesProvider;
@@ -223,6 +230,7 @@ final class DefaultPermissionGrantPolicy {
voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
smsAppPackagesProvider = mSmsAppPackagesProvider;
dialerAppPackagesProvider = mDialerAppPackagesProvider;
+ syncAdapterPackagesProvider = mSyncAdapterPackagesProvider;
}
String[] imePackageNames = (imePackagesProvider != null)
@@ -235,6 +243,10 @@ final class DefaultPermissionGrantPolicy {
? smsAppPackagesProvider.getPackages(userId) : null;
String[] dialerAppPackageNames = (dialerAppPackagesProvider != null)
? dialerAppPackagesProvider.getPackages(userId) : null;
+ String[] contactsSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
+ syncAdapterPackagesProvider.getPackages(ContactsContract.AUTHORITY, userId) : null;
+ String[] calendarSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
+ syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;
synchronized (mService.mPackages) {
// Installers
@@ -275,20 +287,6 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(setupPackage, SETTINGS_PERMISSIONS, userId);
}
- // Dialer
- if (dialerAppPackageNames != null) {
- for (String dialerAppPackageName : dialerAppPackageNames) {
- PackageParser.Package dialerPackage = getPackageLPr(dialerAppPackageName);
- if (dialerPackage != null
- && doesPackageSupportRuntimePermissions(dialerPackage)) {
- grantRuntimePermissionsLPw(dialerPackage, PHONE_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId);
- }
- }
- }
-
// Camera
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
PackageParser.Package cameraPackage = getDefaultSystemHandlerActivityPackageLPr(
@@ -304,14 +302,14 @@ final class DefaultPermissionGrantPolicy {
PackageParser.Package mediaStorePackage = getDefaultProviderAuthorityPackageLPr(
MediaStore.AUTHORITY, userId);
if (mediaStorePackage != null) {
- grantRuntimePermissionsLPw(mediaStorePackage, STORAGE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(mediaStorePackage, STORAGE_PERMISSIONS, true, userId);
}
// Downloads provider
PackageParser.Package downloadsPackage = getDefaultProviderAuthorityPackageLPr(
"downloads", userId);
if (downloadsPackage != null) {
- grantRuntimePermissionsLPw(downloadsPackage, STORAGE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(downloadsPackage, STORAGE_PERMISSIONS, true, userId);
}
// Downloads UI
@@ -320,7 +318,7 @@ final class DefaultPermissionGrantPolicy {
downloadsUiIntent, userId);
if (downloadsUiPackage != null
&& doesPackageSupportRuntimePermissions(downloadsUiPackage)) {
- grantRuntimePermissionsLPw(downloadsUiPackage, STORAGE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(downloadsUiPackage, STORAGE_PERMISSIONS, true, userId);
}
// Storage provider
@@ -330,15 +328,37 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(storagePackage, STORAGE_PERMISSIONS, userId);
}
+ // Dialer
+ if (dialerAppPackageNames == null) {
+ Intent dialerIntent = new Intent(Intent.ACTION_DIAL);
+ PackageParser.Package dialerPackage = getDefaultSystemHandlerActivityPackageLPr(
+ dialerIntent, userId);
+ if (dialerPackage != null) {
+ grantDefaultPermissionsToDefaultSystemDialerAppLPr(dialerPackage, userId);
+ }
+ } else {
+ for (String dialerAppPackageName : dialerAppPackageNames) {
+ PackageParser.Package dialerPackage = getSystemPackageLPr(dialerAppPackageName);
+ if (dialerPackage != null) {
+ grantDefaultPermissionsToDefaultSystemDialerAppLPr(dialerPackage, userId);
+ }
+ }
+ }
+
// SMS
- if (smsAppPackageNames != null) {
+ if (smsAppPackageNames == null) {
+ Intent smsIntent = new Intent(Intent.ACTION_MAIN);
+ smsIntent.addCategory(Intent.CATEGORY_APP_MESSAGING);
+ PackageParser.Package smsPackage = getDefaultSystemHandlerActivityPackageLPr(
+ smsIntent, userId);
+ if (smsPackage != null) {
+ grantDefaultPermissionsToDefaultSystemSmsAppLPr(smsPackage, userId);
+ }
+ } else {
for (String smsPackageName : smsAppPackageNames) {
- PackageParser.Package smsPackage = getPackageLPr(smsPackageName);
- if (smsPackage != null
- && doesPackageSupportRuntimePermissions(smsPackage)) {
- grantRuntimePermissionsLPw(smsPackage, PHONE_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(smsPackage, CONTACTS_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(smsPackage, SMS_PERMISSIONS, userId);
+ PackageParser.Package smsPackage = getSystemPackageLPr(smsPackageName);
+ if (smsPackage != null) {
+ grantDefaultPermissionsToDefaultSystemSmsAppLPr(smsPackage, userId);
}
}
}
@@ -360,11 +380,24 @@ final class DefaultPermissionGrantPolicy {
CalendarContract.AUTHORITY, userId);
if (calendarProviderPackage != null) {
grantRuntimePermissionsLPw(calendarProviderPackage, CONTACTS_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(calendarProviderPackage, CALENDAR_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(calendarProviderPackage, CALENDAR_PERMISSIONS,
+ true, userId);
grantRuntimePermissionsLPw(calendarProviderPackage, ACCOUNTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(calendarProviderPackage, STORAGE_PERMISSIONS, userId);
}
+ // Calendar provider sync adapters
+ List<PackageParser.Package> calendarSyncAdapters = getHeadlessSyncAdapterPackagesLPr(
+ calendarSyncAdapterPackages,
+ userId);
+ final int calendarSyncAdapterCount = calendarSyncAdapters.size();
+ for (int i = 0; i < calendarSyncAdapterCount; i++) {
+ PackageParser.Package calendarSyncAdapter = calendarSyncAdapters.get(i);
+ if (doesPackageSupportRuntimePermissions(calendarSyncAdapter)) {
+ grantRuntimePermissionsLPw(calendarSyncAdapter, CALENDAR_PERMISSIONS, userId);
+ }
+ }
+
// Contacts
Intent contactsIntent = new Intent(Intent.ACTION_MAIN);
contactsIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
@@ -377,11 +410,24 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(contactsPackage, ACCOUNTS_PERMISSIONS, userId);
}
+ // Contacts provider sync adapters
+ List<PackageParser.Package> contactsSyncAdapters = getHeadlessSyncAdapterPackagesLPr(
+ contactsSyncAdapterPackages,
+ userId);
+ final int contactsSyncAdapterCount = contactsSyncAdapters.size();
+ for (int i = 0; i < contactsSyncAdapterCount; i++) {
+ PackageParser.Package contactsSyncAdapter = contactsSyncAdapters.get(i);
+ if (doesPackageSupportRuntimePermissions(contactsSyncAdapter)) {
+ grantRuntimePermissionsLPw(contactsSyncAdapter, CONTACTS_PERMISSIONS, userId);
+ }
+ }
+
// Contacts provider
PackageParser.Package contactsProviderPackage = getDefaultProviderAuthorityPackageLPr(
ContactsContract.AUTHORITY, userId);
if (contactsProviderPackage != null) {
- grantRuntimePermissionsLPw(contactsProviderPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(contactsProviderPackage, CONTACTS_PERMISSIONS,
+ true, userId);
grantRuntimePermissionsLPw(contactsProviderPackage, ACCOUNTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(contactsProviderPackage, STORAGE_PERMISSIONS, userId);
}
@@ -488,7 +534,8 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(locationPackage, MICROPHONE_PERMISSIONS, userId);
grantRuntimePermissionsLPw(locationPackage, PHONE_PERMISSIONS, userId);
grantRuntimePermissionsLPw(locationPackage, SMS_PERMISSIONS, userId);
- grantRuntimePermissionsLPw(locationPackage, LOCATION_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, LOCATION_PERMISSIONS,
+ true, userId);
grantRuntimePermissionsLPw(locationPackage, CAMERA_PERMISSIONS, userId);
grantRuntimePermissionsLPw(locationPackage, SENSORS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(locationPackage, STORAGE_PERMISSIONS, userId);
@@ -512,6 +559,27 @@ final class DefaultPermissionGrantPolicy {
}
}
+ private void grantDefaultPermissionsToDefaultSystemDialerAppLPr(
+ PackageParser.Package dialerPackage, int userId) {
+ if (doesPackageSupportRuntimePermissions(dialerPackage)) {
+ grantRuntimePermissionsLPw(dialerPackage, PHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId);
+ }
+ }
+
+
+ private void grantDefaultPermissionsToDefaultSystemSmsAppLPr(
+ PackageParser.Package smsPackage, int userId) {
+ if (doesPackageSupportRuntimePermissions(smsPackage)) {
+ grantRuntimePermissionsLPw(smsPackage, PHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(smsPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(smsPackage, SMS_PERMISSIONS, userId);
+ }
+ }
+
+
public void grantDefaultPermissionsToDefaultSmsAppLPr(String packageName, int userId) {
Log.i(TAG, "Granting permissions to default sms app for user:" + userId);
if (packageName == null) {
@@ -613,6 +681,31 @@ final class DefaultPermissionGrantPolicy {
return null;
}
+ private List<PackageParser.Package> getHeadlessSyncAdapterPackagesLPr(
+ String[] syncAdapterPackageNames, int userId) {
+ List<PackageParser.Package> syncAdapterPackages = new ArrayList<>();
+
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+
+ for (String syncAdapterPackageName : syncAdapterPackageNames) {
+ homeIntent.setPackage(syncAdapterPackageName);
+
+ List<ResolveInfo> homeActivities = mService.queryIntentActivities(homeIntent,
+ homeIntent.resolveType(mService.mContext.getContentResolver()), 0, userId);
+ if (!homeActivities.isEmpty()) {
+ continue;
+ }
+
+ PackageParser.Package syncAdapterPackage = getSystemPackageLPr(syncAdapterPackageName);
+ if (syncAdapterPackage != null) {
+ syncAdapterPackages.add(syncAdapterPackage);
+ }
+ }
+
+ return syncAdapterPackages;
+ }
+
private PackageParser.Package getDefaultProviderAuthorityPackageLPr(
String authority, int userId) {
ProviderInfo provider = mService.resolveContentProvider(authority, 0, userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1385440..305eb8e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -388,6 +388,15 @@ public class PackageManagerService extends IPackageManager.Stub {
/** Permission grant: grant as runtime a permission that was granted as an install time one. */
private static final int GRANT_UPGRADE = 5;
+ /** Canonical intent used to identify what counts as a "web browser" app */
+ private static final Intent sBrowserIntent;
+ static {
+ sBrowserIntent = new Intent();
+ sBrowserIntent.setAction(Intent.ACTION_VIEW);
+ sBrowserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ sBrowserIntent.setData(Uri.parse("http:"));
+ }
+
final ServiceThread mHandlerThread;
final PackageHandler mHandler;
@@ -1300,6 +1309,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (data != null) {
InstallArgs args = data.args;
PackageInstalledInfo res = data.res;
+ final String packageName = res.pkg.applicationInfo.packageName;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
res.removedInfo.sendBroadcast(false, true, false);
@@ -1348,22 +1358,18 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- res.pkg.applicationInfo.packageName,
- extras, null, null, firstUsers);
+ packageName, extras, null, null, firstUsers);
final boolean update = res.removedInfo.removedPackage != null;
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- res.pkg.applicationInfo.packageName,
- extras, null, null, updateUsers);
+ packageName, extras, null, null, updateUsers);
if (update) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- res.pkg.applicationInfo.packageName,
- extras, null, null, updateUsers);
+ packageName, extras, null, null, updateUsers);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
- null, null,
- res.pkg.applicationInfo.packageName, null, updateUsers);
+ null, null, packageName, null, updateUsers);
// treat asec-hosted packages like removable media on upgrade
if (res.pkg.isForwardLocked() || isExternal(res.pkg)) {
@@ -1373,7 +1379,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
int[] uidArray = new int[] { res.pkg.applicationInfo.uid };
ArrayList<String> pkgList = new ArrayList<String>(1);
- pkgList.add(res.pkg.applicationInfo.packageName);
+ pkgList.add(packageName);
sendResourcesChangedBroadcast(true, true,
pkgList,uidArray, null);
}
@@ -1383,6 +1389,19 @@ public class PackageManagerService extends IPackageManager.Stub {
deleteOld = true;
}
+ // If this app is a browser and it's newly-installed for some
+ // users, clear any default-browser state in those users
+ if (firstUsers.length > 0) {
+ // the app's nature doesn't depend on the user, so we can just
+ // check its browser nature in any user and generalize.
+ if (packageIsBrowser(packageName, firstUsers[0])) {
+ synchronized (mPackages) {
+ for (int userId : firstUsers) {
+ mSettings.setDefaultBrowserPackageNameLPw(null, userId);
+ }
+ }
+ }
+ }
// Log current value of "unknown sources" setting
EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
getUnknownSourcesSettings());
@@ -2405,14 +2424,9 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private List<String> resolveAllBrowserApps(int userId) {
- // Match all generic http: browser apps
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- intent.setData(Uri.parse("http:"));
-
- // Resolve that intent and check that the handleAllWebDataURI boolean is set
- List<ResolveInfo> list = queryIntentActivities(intent, null, 0, userId);
+ // Resolve the canonical browser intent and check that the handleAllWebDataURI boolean is set
+ List<ResolveInfo> list = queryIntentActivities(sBrowserIntent, null,
+ PackageManager.MATCH_ALL, userId);
final int count = list.size();
List<String> result = new ArrayList<String>(count);
@@ -2430,6 +2444,19 @@ public class PackageManagerService extends IPackageManager.Stub {
return result;
}
+ private boolean packageIsBrowser(String packageName, int userId) {
+ List<ResolveInfo> list = queryIntentActivities(sBrowserIntent, null,
+ PackageManager.MATCH_ALL, userId);
+ final int N = list.size();
+ for (int i = 0; i < N; i++) {
+ ResolveInfo info = list.get(i);
+ if (packageName.equals(info.activityInfo.packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void checkDefaultBrowser() {
final int myUserId = UserHandle.myUserId();
final String packageName = getDefaultBrowserPackageName(myUserId);
@@ -8355,6 +8382,14 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
if (!allowed && (bp.protectionLevel
+ & PermissionInfo.PROTECTION_FLAG_PRE23) != 0
+ && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.MNC) {
+ // If this was a previously normal/dangerous permission that got moved
+ // to a system permission as part of the runtime permission redesign, then
+ // we still want to blindly grant it to old apps.
+ allowed = true;
+ }
+ if (!allowed && (bp.protectionLevel
& PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
// For development permissions, a development permission
// is granted only if it was already granted.
@@ -9163,7 +9198,8 @@ public class PackageManagerService extends IPackageManager.Stub {
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.startService(null, intent, null, UserHandle.USER_OWNER);
+ am.startService(null, intent, null, mContext.getOpPackageName(),
+ UserHandle.USER_OWNER);
} catch (RemoteException e) {
}
}
@@ -15970,6 +16006,13 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider) {
+ synchronized (mPackages) {
+ mDefaultPermissionPolicy.setSyncAdapterPackagesProviderrLPw(provider);
+ }
+ }
+
+ @Override
public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
synchronized (mPackages) {
mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultSmsAppLPr(
@@ -15990,8 +16033,13 @@ public class PackageManagerService extends IPackageManager.Stub {
public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps");
synchronized (mPackages) {
- mDefaultPermissionPolicy.grantDefaultPermissionsToEnabledCarrierAppsLPr(
- packageNames, userId);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mDefaultPermissionPolicy.grantDefaultPermissionsToEnabledCarrierAppsLPr(
+ packageNames, userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 17a595d..3393d7d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -549,6 +549,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Display mDisplay;
+ private int mDisplayRotation;
+
int mLandscapeRotation = 0; // default landscape rotation
int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
int mPortraitRotation = 0; // default portrait rotation
@@ -3304,12 +3306,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
- public void getInsetHintLw(WindowManager.LayoutParams attrs, Rect outContentInsets,
- Rect outStableInsets) {
+ public void getInsetHintLw(WindowManager.LayoutParams attrs, int displayRotation,
+ Rect outContentInsets, Rect outStableInsets, Rect outOutsets) {
final int fl = PolicyControl.getWindowFlags(null, attrs);
final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
+ final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
+ if (useOutsets) {
+ int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
+ if (outset > 0) {
+ if (displayRotation == Surface.ROTATION_0) {
+ outOutsets.bottom += outset;
+ } else if (displayRotation == Surface.ROTATION_90) {
+ outOutsets.right += outset;
+ } else if (displayRotation == Surface.ROTATION_180) {
+ outOutsets.top += outset;
+ } else if (displayRotation == Surface.ROTATION_270) {
+ outOutsets.left += outset;
+ }
+ }
+ }
+
if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
== (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
int availRight, availBottom;
@@ -3349,10 +3367,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
outStableInsets.setEmpty();
}
+ private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
+ return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
+ }
+
/** {@inheritDoc} */
@Override
public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
int displayRotation) {
+ mDisplayRotation = displayRotation;
final int overscanLeft, overscanTop, overscanRight, overscanBottom;
if (isDefaultDisplay) {
switch (displayRotation) {
@@ -4139,19 +4163,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// need to provide information to the clients that want to pretend that you can draw there.
// We only want to apply outsets to certain types of windows. For example, we never want to
// apply the outsets to floating dialogs, because they wouldn't make sense there.
- final boolean useOutsets = attrs.type == TYPE_WALLPAPER
- || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
+ final boolean useOutsets = shouldUseOutsets(attrs, fl);
if (isDefaultDisplay && useOutsets) {
osf = mTmpOutsetFrame;
osf.set(cf.left, cf.top, cf.right, cf.bottom);
int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
if (outset > 0) {
- int rotation = Surface.ROTATION_0;
- try {
- rotation = mWindowManager.getRotation();
- } catch (RemoteException e) {
- }
+ int rotation = mDisplayRotation;
if (rotation == Surface.ROTATION_0) {
osf.bottom += outset;
} else if (rotation == Surface.ROTATION_90) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 5a0bee9..3f59755 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2311,6 +2311,11 @@ public final class PowerManagerService extends SystemService
if (mDeviceIdleMode != enabled) {
mDeviceIdleMode = enabled;
updateWakeLockDisabledStatesLocked();
+ if (enabled) {
+ EventLogTags.writeDeviceIdleOnPhase("power");
+ } else {
+ EventLogTags.writeDeviceIdleOffPhase("power");
+ }
}
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 7640837..5ceb6ad 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -571,11 +571,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
* LED, vibration, and ringing
*/
@Override
- public void onPanelRevealed(boolean clearNotificationEffects) {
+ public void onPanelRevealed(boolean clearNotificationEffects, int numItems) {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
- mNotificationDelegate.onPanelRevealed(clearNotificationEffects);
+ mNotificationDelegate.onPanelRevealed(clearNotificationEffects, numItems);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index b165b42..c2ce572 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -31,8 +31,11 @@ import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.telecom.DefaultDialerManager;
+import android.util.IntArray;
import android.util.Slog;
+import android.util.SparseBooleanArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.SmsApplication;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -59,6 +62,41 @@ public class TelecomLoaderService extends SystemService {
}, 0);
SmsApplication.getDefaultMmsApplication(mContext, false);
ServiceManager.addService(Context.TELECOM_SERVICE, service);
+
+ synchronized (mLock) {
+ if (mDefaultSmsAppRequests != null || mDefaultDialerAppRequests != null) {
+ final PackageManagerInternal packageManagerInternal = LocalServices
+ .getService(PackageManagerInternal.class);
+
+ if (mDefaultSmsAppRequests != null) {
+ ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
+ mContext, true);
+ if (smsComponent != null) {
+ final int requestCount = mDefaultSmsAppRequests.size();
+ for (int i = requestCount - 1; i >= 0; i--) {
+ final int userid = mDefaultSmsAppRequests.get(i);
+ mDefaultSmsAppRequests.remove(i);
+ packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
+ smsComponent.getPackageName(), userid);
+ }
+ }
+ }
+
+ if (mDefaultDialerAppRequests != null) {
+ String packageName = DefaultDialerManager.getDefaultDialerApplication(
+ mContext);
+ if (packageName != null) {
+ final int requestCount = mDefaultDialerAppRequests.size();
+ for (int i = requestCount - 1; i >= 0; i--) {
+ final int userId = mDefaultDialerAppRequests.get(i);
+ mDefaultDialerAppRequests.remove(i);
+ packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
+ packageName, userId);
+ }
+ }
+ }
+ }
+ }
} catch (RemoteException e) {
Slog.w(TAG, "Failed linking to death.");
}
@@ -76,7 +114,17 @@ public class TelecomLoaderService extends SystemService {
private static final String SERVICE_ACTION = "com.android.ITelecomService";
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private IntArray mDefaultSmsAppRequests;
+
+ @GuardedBy("mLock")
+ private IntArray mDefaultDialerAppRequests;
+
private final Context mContext;
+
+ @GuardedBy("mLock")
private TelecomServiceConnection mServiceConnection;
public TelecomLoaderService(Context context) {
@@ -98,24 +146,27 @@ public class TelecomLoaderService extends SystemService {
}
private void connectToTelecom() {
- if (mServiceConnection != null) {
- // TODO: Is unbinding worth doing or wait for system to rebind?
- mContext.unbindService(mServiceConnection);
- mServiceConnection = null;
- }
+ synchronized (mLock) {
+ if (mServiceConnection != null) {
+ // TODO: Is unbinding worth doing or wait for system to rebind?
+ mContext.unbindService(mServiceConnection);
+ mServiceConnection = null;
+ }
- TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
- Intent intent = new Intent(SERVICE_ACTION);
- intent.setComponent(SERVICE_COMPONENT);
- int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
- | Context.BIND_AUTO_CREATE;
+ TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
+ Intent intent = new Intent(SERVICE_ACTION);
+ intent.setComponent(SERVICE_COMPONENT);
+ int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_AUTO_CREATE;
- // Bind to Telecom and register the service
- if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {
- mServiceConnection = serviceConnection;
+ // Bind to Telecom and register the service
+ if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {
+ mServiceConnection = serviceConnection;
+ }
}
}
+
private void registerDefaultAppProviders() {
final PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
@@ -125,6 +176,15 @@ public class TelecomLoaderService extends SystemService {
new PackageManagerInternal.PackagesProvider() {
@Override
public String[] getPackages(int userId) {
+ synchronized (mLock) {
+ if (mServiceConnection == null) {
+ if (mDefaultSmsAppRequests == null) {
+ mDefaultSmsAppRequests = new IntArray();
+ }
+ mDefaultSmsAppRequests.add(userId);
+ return null;
+ }
+ }
ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
mContext, true);
if (smsComponent != null) {
@@ -139,6 +199,15 @@ public class TelecomLoaderService extends SystemService {
new PackageManagerInternal.PackagesProvider() {
@Override
public String[] getPackages(int userId) {
+ synchronized (mLock) {
+ if (mServiceConnection == null) {
+ if (mDefaultDialerAppRequests == null) {
+ mDefaultDialerAppRequests = new IntArray();
+ }
+ mDefaultDialerAppRequests.add(userId);
+ return null;
+ }
+ }
String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
if (packageName != null) {
return new String[]{packageName};
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 726db4e..15da829 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -105,7 +105,7 @@ public class TrustManagerService extends SystemService {
private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
private final Receiver mReceiver = new Receiver();
- private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
+ private final SparseBooleanArray mUserHasAuthenticated = new SparseBooleanArray();
/* package */ final TrustArchive mArchive = new TrustArchive();
private final Context mContext;
private final LockPatternUtils mLockPatternUtils;
@@ -118,6 +118,9 @@ public class TrustManagerService extends SystemService {
@GuardedBy("mDeviceLockedForUser")
private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
+ @GuardedBy("mUserHasAuthenticatedSinceBoot")
+ private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
+
private boolean mTrustAgentsCanRun = false;
private int mCurrentUser = UserHandle.USER_OWNER;
@@ -556,31 +559,34 @@ public class TrustManagerService extends SystemService {
}
private boolean getUserHasAuthenticated(int userId) {
- synchronized (mUserHasAuthenticatedSinceBoot) {
- return mUserHasAuthenticatedSinceBoot.get(userId);
- }
+ return mUserHasAuthenticated.get(userId);
}
/**
* @return whether the value has changed
*/
private boolean setUserHasAuthenticated(int userId) {
- synchronized (mUserHasAuthenticatedSinceBoot) {
- if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
+ if (!mUserHasAuthenticated.get(userId)) {
+ mUserHasAuthenticated.put(userId, true);
+ synchronized (mUserHasAuthenticatedSinceBoot) {
mUserHasAuthenticatedSinceBoot.put(userId, true);
- return true;
}
- return false;
+ return true;
}
+ return false;
}
private void clearUserHasAuthenticated(int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ mUserHasAuthenticated.clear();
+ } else {
+ mUserHasAuthenticated.put(userId, false);
+ }
+ }
+
+ private boolean getUserHasAuthenticatedSinceBoot(int userId) {
synchronized (mUserHasAuthenticatedSinceBoot) {
- if (userId == UserHandle.USER_ALL) {
- mUserHasAuthenticatedSinceBoot.clear();
- } else {
- mUserHasAuthenticatedSinceBoot.put(userId, false);
- }
+ return mUserHasAuthenticatedSinceBoot.get(userId);
}
}
@@ -734,7 +740,7 @@ public class TrustManagerService extends SystemService {
Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, null);
long token = Binder.clearCallingIdentity();
try {
- return getUserHasAuthenticated(userId);
+ return getUserHasAuthenticatedSinceBoot(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -788,6 +794,9 @@ public class TrustManagerService extends SystemService {
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
+ fout.print(", hasAuthenticated=" + dumpBool(getUserHasAuthenticated(user.id)));
+ fout.print(", hasAuthenticatedSinceBoot="
+ + dumpBool(getUserHasAuthenticatedSinceBoot(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
@@ -909,7 +918,7 @@ public class TrustManagerService extends SystemService {
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
- mUserHasAuthenticatedSinceBoot.delete(userId);
+ mUserHasAuthenticated.delete(userId);
synchronized (mUserIsTrusted) {
mUserIsTrusted.delete(userId);
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 5995e9c..0eee815 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -531,14 +531,14 @@ public class AppTransition implements Dump {
// Clip third of the from size of launch icon, expand to full width/height
Animation clipAnimLR = new ClipRectLRAnimation(
- centerX - mNextAppTransitionStartWidth / 3,
- centerX + mNextAppTransitionStartWidth / 3,
+ centerX - mNextAppTransitionStartWidth / 2,
+ centerX + mNextAppTransitionStartWidth / 2,
0, appWidth);
clipAnimLR.setInterpolator(mClipHorizontalInterpolator);
clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f));
Animation clipAnimTB = new ClipRectTBAnimation(
- centerY - mNextAppTransitionStartHeight / 3 - translationY,
- centerY + mNextAppTransitionStartHeight / 3 - translationY,
+ centerY - mNextAppTransitionStartHeight / 2 - translationY,
+ centerY + mNextAppTransitionStartHeight / 2 - translationY,
0, appHeight);
clipAnimTB.setInterpolator(mTouchResponseInterpolator);
clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index e9c5ac7..a8ba0f9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -158,15 +158,15 @@ final class Session extends IWindowSession.Stub
int viewVisibility, Rect outContentInsets, Rect outStableInsets,
InputChannel outInputChannel) {
return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
- outContentInsets, outStableInsets, outInputChannel);
+ outContentInsets, outStableInsets, null /* outOutsets */, outInputChannel);
}
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
- InputChannel outInputChannel) {
+ Rect outOutsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
- outContentInsets, outStableInsets, outInputChannel);
+ outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
@Override
@@ -180,7 +180,7 @@ final class Session extends IWindowSession.Stub
public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
- outContentInsets, outStableInsets, null);
+ outContentInsets, outStableInsets, null /* outOutsets */, null);
}
public void remove(IWindow window) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index cee3825..fc86920 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2357,7 +2357,8 @@ public class WindowManagerService extends IWindowManager.Stub
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
- Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
+ Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
+ InputChannel outInputChannel) {
int[] appOp = new int[1];
int res = mPolicy.checkAddPermission(attrs, appOp);
if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -2594,7 +2595,8 @@ public class WindowManagerService extends IWindowManager.Stub
winAnimator.mEnteringAnimation = true;
if (displayContent.isDefaultDisplay) {
- mPolicy.getInsetHintLw(win.mAttrs, outContentInsets, outStableInsets);
+ mPolicy.getInsetHintLw(win.mAttrs, mRotation, outContentInsets, outStableInsets,
+ outOutsets);
} else {
outContentInsets.setEmpty();
outStableInsets.setEmpty();
@@ -9627,6 +9629,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (w.mContentInsetsChanged
|| w.mVisibleInsetsChanged
|| winAnimator.mSurfaceResized
+ || w.mOutsetsChanged
|| configChanged) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
Slog.v(TAG, "Resize reasons for w=" + w + ": "
@@ -9636,6 +9639,8 @@ public class WindowManagerService extends IWindowManager.Stub
+ " " + w.mVisibleInsets.toShortString()
+ " stableInsetsChanged=" + w.mStableInsetsChanged
+ " " + w.mStableInsets.toShortString()
+ + " outsetsChanged=" + w.mOutsetsChanged
+ + " " + w.mOutsets.toShortString()
+ " surfaceResized=" + winAnimator.mSurfaceResized
+ " configChanged=" + configChanged);
}