summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java142
-rw-r--r--services/core/java/com/android/server/MountService.java69
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java25
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java21
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java37
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java21
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java40
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java12
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);