diff options
Diffstat (limited to 'services/core/java')
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); } |