diff options
Diffstat (limited to 'services')
10 files changed, 266 insertions, 112 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 3691a3a..9c6e16f 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -100,6 +100,7 @@ import android.util.Xml; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.NetworkStatsFactory; @@ -768,7 +769,8 @@ public class ConnectivityService extends IConnectivityManager.Stub return mNextNetworkRequestId++; } - private int reserveNetId() { + @VisibleForTesting + protected int reserveNetId() { synchronized (mNetworkForNetId) { for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) { int netId = mNextNetId; @@ -1665,6 +1667,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd"; // Overridden for testing purposes to avoid writing to SystemProperties. + @VisibleForTesting protected int getDefaultTcpRwnd() { return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0); } @@ -2027,20 +2030,22 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: { + final int netId = msg.arg2; if (msg.arg1 == 0) { - setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null); + setProvNotificationVisibleIntent(false, netId, null, 0, null, null); } else { final NetworkAgentInfo nai; synchronized (mNetworkForNetId) { - nai = mNetworkForNetId.get(msg.arg2); + nai = mNetworkForNetId.get(netId); } if (nai == null) { loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); break; } nai.captivePortalDetected = true; - setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(), - nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj); + setProvNotificationVisibleIntent(true, netId, NotificationType.SIGN_IN, + nai.networkInfo.getType(),nai.networkInfo.getExtraInfo(), + (PendingIntent)msg.obj); } break; } @@ -2397,9 +2402,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } if (nai.everValidated) { - // The network validated while the dialog box was up. Don't make any changes. There's a - // TODO in the dialog code to make it go away if the network validates; once that's - // implemented, taking action here will be confusing. + // The network validated while the dialog box was up. Take no action. return; } @@ -2419,16 +2422,28 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, accept ? 1 : 0); } - // TODO: should we also disconnect from the network if accept is false? + if (!accept) { + // Tell the NetworkAgent that the network does not have Internet access (because that's + // what we just told the user). This will hint to Wi-Fi not to autojoin this network in + // the future. We do this now because NetworkMonitor might not yet have finished + // validating and thus we might not yet have received an EVENT_NETWORK_TESTED. + nai.asyncChannel.sendMessage(NetworkAgent.CMD_REPORT_NETWORK_STATUS, + NetworkAgent.INVALID_NETWORK, 0, null); + // TODO: Tear the network down once we have determined how to tell WifiStateMachine not + // to reconnect to it immediately. http://b/20739299 + } + } private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) { + if (DBG) log("scheduleUnvalidatedPrompt " + nai.network); mHandler.sendMessageDelayed( mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network), PROMPT_UNVALIDATED_DELAY_MS); } private void handlePromptUnvalidated(Network network) { + if (DBG) log("handlePromptUnvalidated " + network); NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); // Only prompt if the network is unvalidated and was explicitly selected by the user, and if @@ -2439,31 +2454,16 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } - // TODO: What should we do if we've already switched to this network because we had no - // better option? There are two obvious alternatives. - // - // 1. Decide that there's no point prompting because this is our only usable network. - // However, because we didn't prompt, if later on a validated network comes along, we'll - // either a) silently switch to it - bad if the user wanted to connect to stay on this - // unvalidated network - or b) prompt the user at that later time - bad because the user - // might not understand why they are now being prompted. - // - // 2. Always prompt the user, even if we have no other network to use. The user could then - // try to find an alternative network to join (remember, if we got here, then the user - // selected this network manually). This is bad because the prompt isn't really very - // useful. - // - // For now we do #1, but we can revisit that later. - if (isDefaultNetwork(nai)) { - return; - } - Intent intent = new Intent(ConnectivityManager.ACTION_PROMPT_UNVALIDATED); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK, network); + intent.setData(Uri.fromParts("netId", Integer.toString(network.netId), null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName("com.android.settings", "com.android.settings.wifi.WifiNoInternetDialog"); - mContext.startActivityAsUser(intent, UserHandle.CURRENT); + + PendingIntent pendingIntent = PendingIntent.getActivityAsUser( + mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); + setProvNotificationVisibleIntent(true, nai.network.netId, NotificationType.NO_INTERNET, + nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(), pendingIntent); } private class InternalHandler extends Handler { @@ -3243,7 +3243,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private static final String NOTIFICATION_ID = "CaptivePortal.Notification"; - private volatile boolean mIsNotificationVisible = false; + private static enum NotificationType { SIGN_IN, NO_INTERNET; }; private void setProvNotificationVisible(boolean visible, int networkType, String action) { if (DBG) { @@ -3254,21 +3254,31 @@ public class ConnectivityService extends IConnectivityManager.Stub PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); // Concatenate the range of types onto the range of NetIDs. int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE); - setProvNotificationVisibleIntent(visible, id, networkType, null, pendingIntent); + setProvNotificationVisibleIntent(visible, id, NotificationType.SIGN_IN, + networkType, null, pendingIntent); } /** - * Show or hide network provisioning notificaitons. + * Show or hide network provisioning notifications. + * + * We use notifications for two purposes: to notify that a network requires sign in + * (NotificationType.SIGN_IN), or to notify that a network does not have Internet access + * (NotificationType.NO_INTERNET). We display at most one notification per ID, so on a + * particular network we can display the notification type that was most recently requested. + * So for example if a captive portal fails to reply within a few seconds of connecting, we + * might first display NO_INTERNET, and then when the captive portal check completes, display + * SIGN_IN. * * @param id an identifier that uniquely identifies this notification. This must match * between show and hide calls. We use the NetID value but for legacy callers * we concatenate the range of types with the range of NetIDs. */ - private void setProvNotificationVisibleIntent(boolean visible, int id, int networkType, - String extraInfo, PendingIntent intent) { + private void setProvNotificationVisibleIntent(boolean visible, int id, + NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent) { if (DBG) { - log("setProvNotificationVisibleIntent: E visible=" + visible + " networkType=" + - networkType + " extraInfo=" + extraInfo); + log("setProvNotificationVisibleIntent " + notifyType + " visible=" + visible + + " networkType=" + getNetworkTypeName(networkType) + + " extraInfo=" + extraInfo); } Resources r = Resources.getSystem(); @@ -3280,27 +3290,38 @@ public class ConnectivityService extends IConnectivityManager.Stub CharSequence details; int icon; Notification notification = new Notification(); - switch (networkType) { - case ConnectivityManager.TYPE_WIFI: - title = r.getString(R.string.wifi_available_sign_in, 0); - details = r.getString(R.string.network_available_sign_in_detailed, - extraInfo); - icon = R.drawable.stat_notify_wifi_in_range; - break; - case ConnectivityManager.TYPE_MOBILE: - case ConnectivityManager.TYPE_MOBILE_HIPRI: - title = r.getString(R.string.network_available_sign_in, 0); - // TODO: Change this to pull from NetworkInfo once a printable - // name has been added to it - details = mTelephonyManager.getNetworkOperatorName(); - icon = R.drawable.stat_notify_rssi_in_range; - break; - default: - title = r.getString(R.string.network_available_sign_in, 0); - details = r.getString(R.string.network_available_sign_in_detailed, - extraInfo); - icon = R.drawable.stat_notify_rssi_in_range; - break; + if (notifyType == NotificationType.NO_INTERNET && + networkType == ConnectivityManager.TYPE_WIFI) { + title = r.getString(R.string.wifi_no_internet, 0); + details = r.getString(R.string.wifi_no_internet_detailed); + icon = R.drawable.stat_notify_wifi_in_range; // TODO: Need new icon. + } else if (notifyType == NotificationType.SIGN_IN) { + switch (networkType) { + case ConnectivityManager.TYPE_WIFI: + title = r.getString(R.string.wifi_available_sign_in, 0); + details = r.getString(R.string.network_available_sign_in_detailed, + extraInfo); + icon = R.drawable.stat_notify_wifi_in_range; + break; + case ConnectivityManager.TYPE_MOBILE: + case ConnectivityManager.TYPE_MOBILE_HIPRI: + title = r.getString(R.string.network_available_sign_in, 0); + // TODO: Change this to pull from NetworkInfo once a printable + // name has been added to it + details = mTelephonyManager.getNetworkOperatorName(); + icon = R.drawable.stat_notify_rssi_in_range; + break; + default: + title = r.getString(R.string.network_available_sign_in, 0); + details = r.getString(R.string.network_available_sign_in_detailed, + extraInfo); + icon = R.drawable.stat_notify_rssi_in_range; + break; + } + } else { + Slog.wtf(TAG, "Unknown notification type " + notifyType + "on network type " + + getNetworkTypeName(networkType)); + return; } notification.when = 0; @@ -3315,18 +3336,17 @@ public class ConnectivityService extends IConnectivityManager.Stub try { notificationManager.notify(NOTIFICATION_ID, id, notification); } catch (NullPointerException npe) { - loge("setNotificaitionVisible: visible notificationManager npe=" + npe); + loge("setNotificationVisible: visible notificationManager npe=" + npe); npe.printStackTrace(); } } else { try { notificationManager.cancel(NOTIFICATION_ID, id); } catch (NullPointerException npe) { - loge("setNotificaitionVisible: cancel notificationManager npe=" + npe); + loge("setNotificationVisible: cancel notificationManager npe=" + npe); npe.printStackTrace(); } } - mIsNotificationVisible = visible; } /** Location to an updatable file listing carrier provisioning urls. diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 14f8a00..aa7d1f8 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -28,12 +28,15 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG; import android.Manifest; import android.app.ActivityManagerNative; import android.app.AppOpsManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.ObbInfo; import android.mtp.MtpStorage; @@ -76,7 +79,6 @@ import android.util.Xml; import libcore.io.IoUtils; import libcore.util.EmptyArray; -import libcore.util.HexEncoding; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -619,6 +621,26 @@ class MountService extends IMountService.Stub private final Handler mHandler; + private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + + try { + if (Intent.ACTION_USER_ADDED.equals(action)) { + final UserManager um = mContext.getSystemService(UserManager.class); + final int userSerialNumber = um.getUserSerialNumber(userId); + mConnector.execute("volume", "user_added", userId, userSerialNumber); + } else if (Intent.ACTION_USER_REMOVED.equals(action)) { + mConnector.execute("volume", "user_removed", userId); + } + } catch (NativeDaemonConnectorException e) { + Slog.w(TAG, "Failed to send user details to vold", e); + } + } + }; + @Override public void waitForAsecScan() { waitForLatch(mAsecsScanned, "mAsecsScanned"); @@ -674,8 +696,15 @@ class MountService extends IMountService.Stub try { mConnector.execute("volume", "reset"); + + // Tell vold about all existing and started users + final UserManager um = mContext.getSystemService(UserManager.class); + final List<UserInfo> users = um.getUsers(); + for (UserInfo user : users) { + mConnector.execute("volume", "user_added", user.id, user.serialNumber); + } for (int userId : mStartedUsers) { - mConnector.execute("volume", "start_user", userId); + mConnector.execute("volume", "user_started", userId); } } catch (NativeDaemonConnectorException e) { Slog.w(TAG, "Failed to reset vold", e); @@ -690,7 +719,7 @@ class MountService extends IMountService.Stub // staging area is ready so it's ready for zygote-forked apps to // bind mount against. try { - mConnector.execute("volume", "start_user", userId); + mConnector.execute("volume", "user_started", userId); } catch (NativeDaemonConnectorException ignored) { } @@ -715,7 +744,7 @@ class MountService extends IMountService.Stub Slog.d(TAG, "onCleanupUser " + userId); try { - mConnector.execute("volume", "cleanup_user", userId); + mConnector.execute("volume", "user_stopped", userId); } catch (NativeDaemonConnectorException ignored) { } @@ -1209,6 +1238,11 @@ class MountService extends IMountService.Stub Thread crypt_thread = new Thread(mCryptConnector, CRYPTD_TAG); crypt_thread.start(); + final IntentFilter userFilter = new IntentFilter(); + userFilter.addAction(Intent.ACTION_USER_ADDED); + userFilter.addAction(Intent.ACTION_USER_REMOVED); + mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler); + // Add ourself to the Watchdog monitors if enabled. if (WATCHDOG_ENABLE) { Watchdog.getInstance().addMonitor(this); @@ -2078,23 +2112,6 @@ class MountService extends IMountService.Stub } } - private static String toHex(String password) { - if (password == null) { - return ""; - } - byte[] bytes = password.getBytes(StandardCharsets.UTF_8); - return new String(HexEncoding.encode(bytes)); - } - - private static String fromHex(String hexPassword) throws IllegalArgumentException { - if (hexPassword == null) { - return null; - } - - final byte[] bytes = HexEncoding.decode(hexPassword.toCharArray(), false); - return new String(bytes, StandardCharsets.UTF_8); - } - @Override public int decryptStorage(String password) { if (TextUtils.isEmpty(password)) { @@ -2112,7 +2129,7 @@ class MountService extends IMountService.Stub final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "checkpw", new SensitiveArg(toHex(password))); + event = mCryptConnector.execute("cryptfs", "checkpw", new SensitiveArg(password)); final int code = Integer.parseInt(event.getMessage()); if (code == 0) { @@ -2152,7 +2169,7 @@ class MountService extends IMountService.Stub try { mCryptConnector.execute("cryptfs", "enablecrypto", "inplace", CRYPTO_TYPES[type], - new SensitiveArg(toHex(password))); + new SensitiveArg(password)); } catch (NativeDaemonConnectorException e) { // Encryption failed return e.getCode(); @@ -2177,7 +2194,7 @@ class MountService extends IMountService.Stub try { NativeDaemonEvent event = mCryptConnector.execute("cryptfs", "changepw", CRYPTO_TYPES[type], - new SensitiveArg(toHex(password))); + new SensitiveArg(password)); return Integer.parseInt(event.getMessage()); } catch (NativeDaemonConnectorException e) { // Encryption failed @@ -2210,7 +2227,7 @@ class MountService extends IMountService.Stub final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "verifypw", new SensitiveArg(toHex(password))); + event = mCryptConnector.execute("cryptfs", "verifypw", new SensitiveArg(password)); Slog.i(TAG, "cryptfs verifypw => " + event.getMessage()); return Integer.parseInt(event.getMessage()); } catch (NativeDaemonConnectorException e) { @@ -2300,7 +2317,7 @@ class MountService extends IMountService.Stub // -1 equals no password return null; } - return fromHex(event.getMessage()); + return event.getMessage(); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } catch (IllegalArgumentException e) { diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index a5b0e59..36d64aa 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -842,9 +842,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { @Override public void notifyCarrierNetworkChange(boolean active) { - if (!checkNotifyPermissionOrCarrierPrivilege("notifyCarrierNetworkChange()")) { - return; - } + enforceNotifyPermissionOrCarrierPrivilege("notifyCarrierNetworkChange()"); + if (VDBG) { log("notifyCarrierNetworkChange: active=" + active); } @@ -1511,15 +1510,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { android.Manifest.permission.READ_PRECISE_PHONE_STATE); } - private boolean checkNotifyPermissionOrCarrierPrivilege(String method) { - if (checkNotifyPermission() || checkCarrierPrivilege()) { - return true; + private void enforceNotifyPermissionOrCarrierPrivilege(String method) { + if (checkNotifyPermission()) { + return; } - String msg = "Modify Phone State or Carrier Privilege Permission Denial: " + method - + " from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid(); - if (DBG) log(msg); - return false; + enforceCarrierPrivilege(); } private boolean checkNotifyPermission(String method) { @@ -1537,17 +1533,20 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { == PackageManager.PERMISSION_GRANTED; } - private boolean checkCarrierPrivilege() { + private void enforceCarrierPrivilege() { TelephonyManager tm = TelephonyManager.getDefault(); String[] pkgs = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid()); for (String pkg : pkgs) { if (tm.checkCarrierPrivilegesForPackage(pkg) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { - return true; + return; } } - return false; + String msg = "Carrier Privilege Permission Denial: from pid=" + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid(); + if (DBG) log(msg); + throw new SecurityException(msg); } private void checkListenerPermission(int events) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 577a4f9..23e62e2 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2019,15 +2019,22 @@ public final class ActivityStackSupervisor implements DisplayListener { r, top.task); top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage); } else { - // A special case: we need to - // start the activity because it is not currently - // running, and the caller has asked to clear the - // current task to have this activity at the top. + // A special case: we need to start the activity because it is not + // currently running, and the caller has asked to clear the current + // task to have this activity at the top. addingToTask = true; - // Now pretend like this activity is being started - // by the top of its task, so it is put in the - // right place. + // Now pretend like this activity is being started by the top of its + // task, so it is put in the right place. sourceRecord = intentActivity; + TaskRecord task = sourceRecord.task; + if (task != null && task.stack == null) { + // Target stack got cleared when we all activities were removed + // above. Go ahead and reset it. + targetStack = computeStackFocus(sourceRecord, false /* newTask */); + targetStack.addTask( + task, !launchTaskBehind /* toTop */, false /* moving */); + } + } } else if (r.realActivity.equals(intentActivity.task.realActivity)) { // In this case the top activity on the task is the diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index a1738a2..ca24e3a 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -571,6 +571,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub { throw new IOException("No suitable external storage available"); } + } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) { + // For now, installs to adopted media are treated as internal from + // an install flag point-of-view. + params.setInstallFlagsInternal(); + } else { // For now, installs to adopted media are treated as internal from // an install flag point-of-view. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e2cc3f7..7bdbec6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -6368,6 +6368,16 @@ public class PackageManagerService extends IPackageManager.Stub { if ((scanFlags & SCAN_NEW_INSTALL) == 0) { derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */); + + // Some system apps still use directory structure for native libraries + // in which case we might end up not detecting abi solely based on apk + // structure. Try to detect abi based on directory structure. + if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && + pkg.applicationInfo.primaryCpuAbi == null) { + setBundledAppAbisAndRoots(pkg, pkgSetting); + setNativeLibraryPaths(pkg); + } + } else { if ((scanFlags & SCAN_MOVE) != 0) { // We haven't run dex-opt for this move (since we've moved the compiled output too) @@ -7273,6 +7283,33 @@ public class PackageManagerService extends IPackageManager.Stub { } /** + * Calculate the abis and roots for a bundled app. These can uniquely + * be determined from the contents of the system partition, i.e whether + * it contains 64 or 32 bit shared libraries etc. We do not validate any + * of this information, and instead assume that the system was built + * sensibly. + */ + private void setBundledAppAbisAndRoots(PackageParser.Package pkg, + PackageSetting pkgSetting) { + final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath()); + + // If "/system/lib64/apkname" exists, assume that is the per-package + // native library directory to use; otherwise use "/system/lib/apkname". + final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir); + setBundledAppAbi(pkg, apkRoot, apkName); + // pkgSetting might be null during rescan following uninstall of updates + // to a bundled app, so accommodate that possibility. The settings in + // that case will be established later from the parsed package. + // + // If the settings aren't null, sync them up with what we've just derived. + // note that apkRoot isn't stored in the package settings. + if (pkgSetting != null) { + pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; + pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; + } + } + + /** * Deduces the ABI of a bundled app and sets the relevant fields on the * parsed pkg object. * diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index feb0285..ab1206b 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3129,7 +3129,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void uninstallCaCert(ComponentName admin, String alias) { + public void uninstallCaCerts(ComponentName admin, String[] aliases) { enforceCanManageCaCerts(admin); final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); @@ -3137,7 +3137,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { try { final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); try { - keyChainConnection.getService().deleteCaCertificate(alias); + for (int i = 0 ; i < aliases.length; i++) { + keyChainConnection.getService().deleteCaCertificate(aliases[i]); + } } catch (RemoteException e) { Log.e(LOG_TAG, "from CaCertUninstaller: ", e); } finally { diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index 56f1d48c..6684be4 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -235,6 +235,27 @@ public class ConnectivityServiceTest extends AndroidTestCase { // Prevent wrapped ConnectivityService from trying to write to SystemProperties. return 0; } + + @Override + protected int reserveNetId() { + while (true) { + final int netId = super.reserveNetId(); + + // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks + // can have odd side-effects, like network validations succeeding. + final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks(); + boolean overlaps = false; + for (Network network : networks) { + if (netId == network.netId) { + overlaps = true; + break; + } + } + if (overlaps) continue; + + return netId; + } + } } @Override diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index d6a7dd1..588f8c6 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -91,6 +91,7 @@ public class UsbDeviceManager { private static final int MSG_SYSTEM_READY = 3; private static final int MSG_BOOT_COMPLETED = 4; private static final int MSG_USER_SWITCHED = 5; + private static final int MSG_SET_USB_DATA_UNLOCKED = 6; private static final int AUDIO_MODE_SOURCE = 1; @@ -314,6 +315,7 @@ public class UsbDeviceManager { // current USB state private boolean mConnected; private boolean mConfigured; + private boolean mUsbDataUnlocked; private String mCurrentFunctions; private UsbAccessory mCurrentAccessory; private int mUsbNotificationId; @@ -350,7 +352,7 @@ public class UsbDeviceManager { SystemProperties.get(UsbManager.ADB_PERSISTENT_PROPERTY, "adb"), UsbManager.USB_FUNCTION_ADB); - mCurrentFunctions = mAdbEnabled ? "adb" : "none"; + mCurrentFunctions = mAdbEnabled ? "adb" : UsbManager.USB_FUNCTION_MTP; String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim(); updateState(state); @@ -459,6 +461,15 @@ public class UsbDeviceManager { } } + /** + * Stop and start the USB driver. This is needed to close all outstanding + * USB connections. + */ + private void restartCurrentFunction() { + setUsbConfig("none"); + setUsbConfig(mCurrentFunctions); + } + private void setEnabledFunctions(String functions) { if (DEBUG) Slog.d(TAG, "setEnabledFunctions " + functions); @@ -531,6 +542,7 @@ public class UsbDeviceManager { intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(UsbManager.USB_CONNECTED, mConnected); intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured); + intent.putExtra(UsbManager.USB_DATA_UNLOCKED, mUsbDataUnlocked); if (mCurrentFunctions != null) { String[] functions = mCurrentFunctions.split(","); @@ -599,6 +611,10 @@ public class UsbDeviceManager { case MSG_UPDATE_STATE: mConnected = (msg.arg1 == 1); mConfigured = (msg.arg2 == 1); + if (!mConnected) { + // When a disconnect occurs, relock access to sensitive user data + mUsbDataUnlocked = false; + } updateUsbNotification(); updateAdbNotification(); if (containsFunction(mCurrentFunctions, @@ -621,6 +637,12 @@ public class UsbDeviceManager { String functions = (String)msg.obj; setEnabledFunctions(functions); break; + case MSG_SET_USB_DATA_UNLOCKED: + mUsbDataUnlocked = (msg.arg1 == 1); + updateUsbNotification(); + updateUsbState(); + restartCurrentFunction(); + break; case MSG_SYSTEM_READY: setUsbConfig(mCurrentFunctions); updatePersistentProperty(); @@ -676,7 +698,9 @@ public class UsbDeviceManager { int id = 0; Resources r = mContext.getResources(); if (mConnected) { - if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) { + if (!mUsbDataUnlocked) { + id = com.android.internal.R.string.usb_charging_notification_title; + } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) { id = com.android.internal.R.string.usb_mtp_notification_title; } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) { id = com.android.internal.R.string.usb_ptp_notification_title; @@ -771,7 +795,7 @@ public class UsbDeviceManager { } private String getDefaultFunctions() { - return "none"; + return UsbManager.USB_FUNCTION_MTP; } public void dump(FileDescriptor fd, PrintWriter pw) { @@ -817,6 +841,16 @@ public class UsbDeviceManager { mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions); } + public void setUsbDataUnlocked(boolean unlocked) { + if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked(" + unlocked + ")"); + mHandler.sendMessage(MSG_SET_USB_DATA_UNLOCKED, unlocked); + } + + public boolean isUsbDataUnlocked() { + if (DEBUG) Slog.d(TAG, "isUsbDataUnlocked() -> " + mHandler.mUsbDataUnlocked); + return mHandler.mUsbDataUnlocked; + } + private void readOemUsbOverrideConfig() { String[] configList = mContext.getResources().getStringArray( com.android.internal.R.array.config_oemUsbModeOverride); diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 51281a2..7a3426c 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -271,6 +271,18 @@ public class UsbService extends IUsbManager.Stub { } @Override + public void setUsbDataUnlocked(boolean unlocked) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.setUsbDataUnlocked(unlocked); + } + + @Override + public boolean isUsbDataUnlocked() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + return mDeviceManager.isUsbDataUnlocked(); + } + + @Override public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); |