diff options
Diffstat (limited to 'services')
26 files changed, 387 insertions, 187 deletions
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 4c6b772..6ab52c6 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -479,7 +479,7 @@ final class UiModeManagerService extends SystemService { // keep screen on when charging and in car mode boolean keepScreenOn = mCharging && ((mCarModeEnabled && mCarModeKeepsScreenOn && - (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_NO_WAKE_LOCK) == 0) || + (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_ALLOW_SLEEP) == 0) || (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn)); if (keepScreenOn != mWakeLock.isHeld()) { if (keepScreenOn) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index d6e51f3..0bdb964 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import android.os.DeadObjectException; import android.os.Handler; import android.os.Looper; import android.os.SystemProperties; @@ -1424,6 +1425,9 @@ public final class ActiveServices { app.repProcState); r.postNotification(); created = true; + } catch (DeadObjectException e) { + Slog.w(TAG, "Application dead when creating service " + r); + mAm.appDiedLocked(app); } finally { if (!created) { app.services.remove(r); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6054401..2ae8e8a 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4201,6 +4201,10 @@ public final class ActivityManagerService extends ActivityManagerNative } } + final void appDiedLocked(ProcessRecord app) { + appDiedLocked(app, app.pid, app.thread); + } + final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread) { @@ -5639,17 +5643,13 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void dismissKeyguardOnNextActivity() { - enforceNotIsolatedCaller("dismissKeyguardOnNextActivity"); + public void keyguardWaitingForActivityDrawn() { + enforceNotIsolatedCaller("keyguardWaitingForActivityDrawn"); final long token = Binder.clearCallingIdentity(); try { synchronized (this) { if (DEBUG_LOCKSCREEN) logLockScreen(""); - if (mLockScreenShown) { - mLockScreenShown = false; - comeOutOfSleepIfNeededLocked(); - } - mStackSupervisor.setDismissKeyguard(true); + mWindowManager.keyguardWaitingForActivityDrawn(); } } finally { Binder.restoreCallingIdentity(token); @@ -8478,7 +8478,7 @@ public final class ActivityManagerService extends ActivityManagerNative "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); - appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread); + appDiedLocked(cpr.proc); if (!lastRef) { // This wasn't the last ref our process had on // the provider... we have now been killed, bail. @@ -8928,7 +8928,7 @@ public final class ActivityManagerService extends ActivityManagerNative + ") early provider death"); final long ident = Binder.clearCallingIdentity(); try { - appDiedLocked(proc, proc.pid, proc.thread); + appDiedLocked(proc); } finally { Binder.restoreCallingIdentity(ident); } @@ -9263,8 +9263,7 @@ public final class ActivityManagerService extends ActivityManagerNative void logLockScreen(String msg) { if (DEBUG_LOCKSCREEN) Slog.d(TAG, Debug.getCallers(2) + ":" + msg + " mLockScreenShown=" + mLockScreenShown + " mWentToSleep=" + - mWentToSleep + " mSleeping=" + mSleeping + " mDismissKeyguardOnNextActivity=" + - mStackSupervisor.mDismissKeyguardOnNextActivity); + mWentToSleep + " mSleeping=" + mSleeping); } private void comeOutOfSleepIfNeededLocked() { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 4653742..3f02184 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -46,7 +46,6 @@ import com.android.internal.os.BatteryStatsImpl; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ItemMatcher; import com.android.server.am.ActivityStackSupervisor.ActivityContainer; -import com.android.server.am.ActivityStackSupervisor.ActivityDisplay; import com.android.server.wm.AppTransition; import com.android.server.wm.TaskGroup; import com.android.server.wm.WindowManagerService; @@ -1059,7 +1058,7 @@ final class ActivityStack { if (next.nowVisible) { // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now. - mStackSupervisor.dismissKeyguard(); + mStackSupervisor.notifyActivityDrawnForKeyguard(); } // schedule an idle timeout in case the app doesn't do it for us. diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 3d23cb7..74759a6 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -167,9 +167,6 @@ public final class ActivityStackSupervisor implements DisplayListener { WindowManagerService mWindowManager; DisplayManager mDisplayManager; - /** Dismiss the keyguard after the next activity is displayed? */ - boolean mDismissKeyguardOnNextActivity = false; - /** Identifier counter for all ActivityStacks */ private int mLastStackId = HOME_STACK_ID; @@ -363,12 +360,9 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - void dismissKeyguard() { + void notifyActivityDrawnForKeyguard() { if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(""); - if (mDismissKeyguardOnNextActivity) { - mDismissKeyguardOnNextActivity = false; - mWindowManager.dismissKeyguard(); - } + mWindowManager.notifyActivityDrawnForKeyguard(); } ActivityStack getFocusedStack() { @@ -439,9 +433,8 @@ public final class ActivityStackSupervisor implements DisplayListener { return mService.startHomeActivityLocked(mCurrentUser); } - void setDismissKeyguard(boolean dismiss) { - if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(" dismiss=" + dismiss); - mDismissKeyguardOnNextActivity = dismiss; + void keyguardWaitingForActivityDrawn() { + mWindowManager.keyguardWaitingForActivityDrawn(); } TaskRecord anyTaskForIdLocked(int id) { @@ -660,7 +653,7 @@ public final class ActivityStackSupervisor implements DisplayListener { w.thisTime = w.totalTime; } mService.notifyAll(); - dismissKeyguard(); + notifyActivityDrawnForKeyguard(); } void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, @@ -1165,7 +1158,7 @@ public final class ActivityStackSupervisor implements DisplayListener { Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); - mService.appDiedLocked(app, app.pid, app.thread); + mService.appDiedLocked(app); stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; @@ -1371,7 +1364,6 @@ public final class ActivityStackSupervisor implements DisplayListener { resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } - setDismissKeyguard(false); ActivityOptions.abort(options); return err; } @@ -1386,7 +1378,6 @@ public final class ActivityStackSupervisor implements DisplayListener { resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } - setDismissKeyguard(false); String msg; if (!aInfo.exported) { msg = "Permission Denial: starting " + intent.toString() @@ -1425,7 +1416,6 @@ public final class ActivityStackSupervisor implements DisplayListener { } // We pretend to the caller that it was really started, but // they will just get a cancel result. - setDismissKeyguard(false); ActivityOptions.abort(options); return ActivityManager.START_SUCCESS; } @@ -1444,7 +1434,6 @@ public final class ActivityStackSupervisor implements DisplayListener { PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack); mPendingActivityLaunches.add(pal); - setDismissKeyguard(false); ActivityOptions.abort(options); return ActivityManager.START_SWITCHES_CANCELED; } @@ -1466,12 +1455,12 @@ public final class ActivityStackSupervisor implements DisplayListener { err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options); - if (allPausedActivitiesComplete()) { + if (err < 0) { // If someone asked to have the keyguard dismissed on the next // activity start, but we are not actually doing an activity // switch... just dismiss the keyguard now, because we // probably want to see whatever is behind it. - dismissKeyguard(); + notifyActivityDrawnForKeyguard(); } return err; } @@ -2852,8 +2841,6 @@ public final class ActivityStackSupervisor implements DisplayListener { } public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity="); - pw.println(mDismissKeyguardOnNextActivity); pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack); pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack); pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout); diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 72ac29a..e39f0b1 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -265,7 +265,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE | DisplayDeviceInfo.FLAG_NEVER_BLANK; } - if ((mInfo.flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { mInfo.flags &= ~DisplayDeviceInfo.FLAG_NEVER_BLANK; } else { mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 591cf25..2407253 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -258,6 +258,12 @@ final class Constants { static final int MHL_RAP_ACTION_CONTENT_ON = 0x10; static final int MHL_RAP_ACTION_CONTENT_OFF = 0x11; + // MHL RAPK messages. + static final int MHL_RAPK_NO_ERROR = 0x00; + static final int MHL_RAPK_UNRECOGNIZED_ACTION = 0x01; + static final int MHL_RAPK_UNSUPPORTED_ACTION = 0x02; + static final int MHL_RAPK_RESPONDER_BUSY = 0x03; + static final int MHL_INVALID_ADOPTER_ID = -1; static final int MHL_INVALID_DEVICE_ID = -1; diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 0e57afd..e49d831 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -198,6 +198,10 @@ public final class HdmiControlService extends SystemService { @GuardedBy("mLock") private boolean mProhibitMode; + // Set to true while the input change by MHL is allowed. + @GuardedBy("mLock") + private boolean mMhlInputChangeEnabled; + // List of listeners registered by callers that want to get notified of // system audio mode changes. private final ArrayList<IHdmiSystemAudioModeChangeListener> @@ -269,6 +273,7 @@ public final class HdmiControlService extends SystemService { mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON; mProhibitMode = false; mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true); + mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true); mCecController = HdmiCecController.create(this); if (mCecController != null) { @@ -353,10 +358,12 @@ public final class HdmiControlService extends SystemService { // No need to propagate to HAL. break; case Global.MHL_INPUT_SWITCHING_ENABLED: - setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled)); + setMhlInputChangeEnabled(enabled); break; case Global.MHL_POWER_CHARGE_ENABLED: - setOption(OPTION_MHL_POWER_CHARGE, toInt(enabled)); + if (mMhlController != null) { + mMhlController.setOption(OPTION_MHL_POWER_CHARGE, toInt(enabled)); + } break; } } @@ -1741,4 +1748,20 @@ public final class HdmiControlService extends SystemService { assertRunOnServiceThread(); mActivePortId = portId; } + + void setMhlInputChangeEnabled(boolean enabled) { + if (mMhlController != null) { + mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled)); + } + + synchronized (mLock) { + mMhlInputChangeEnabled = enabled; + } + } + + boolean isMhlInputChangeEnabled() { + synchronized (mLock) { + return mMhlInputChangeEnabled; + } + } } diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index 201d9b4..753ae39 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -1372,6 +1372,7 @@ public class GpsLocationProvider implements LocationProviderInterface { switch (status) { case GPS_REQUEST_AGPS_DATA_CONN: if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN"); + Log.v(TAG, "Received SUPL IP addr[]: " + ipaddr); // Set mAGpsDataConnectionState before calling startUsingNetworkFeature // to avoid a race condition with handleUpdateNetworkState() mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING; @@ -1380,6 +1381,7 @@ public class GpsLocationProvider implements LocationProviderInterface { if (ipaddr != null) { try { mAGpsDataConnectionIpAddr = InetAddress.getByAddress(ipaddr); + Log.v(TAG, "IP address converted to: " + mAGpsDataConnectionIpAddr); } catch (UnknownHostException e) { Log.e(TAG, "Bad IP Address: " + ipaddr, e); mAGpsDataConnectionIpAddr = null; @@ -1426,6 +1428,8 @@ public class GpsLocationProvider implements LocationProviderInterface { case GPS_AGPS_DATA_CONN_FAILED: if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED"); break; + default: + Log.d(TAG, "Received Unknown AGPS status: " + status); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 3eb2b7e..d6afe68 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1761,26 +1761,27 @@ public class NotificationManagerService extends SystemService { if (hasValidSound) { boolean looping = (notification.flags & Notification.FLAG_INSISTENT) != 0; - int audioStreamType; - if (notification.audioStreamType >= 0) { - audioStreamType = notification.audioStreamType; + AudioAttributes audioAttributes; + if (notification.audioAttributes != null) { + audioAttributes = notification.audioAttributes; } else { - audioStreamType = DEFAULT_STREAM_TYPE; + audioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT; } mSoundNotification = record; // do not play notifications if stream volume is 0 (typically because // ringer mode is silent) or if there is a user of exclusive audio focus - if ((mAudioManager.getStreamVolume(audioStreamType) != 0) - && !mAudioManager.isAudioFocusExclusive()) { + if ((mAudioManager.getStreamVolume( + AudioAttributes.toLegacyStreamType(audioAttributes)) != 0) + && !mAudioManager.isAudioFocusExclusive()) { final long identity = Binder.clearCallingIdentity(); try { final IRingtonePlayer player = mAudioManager.getRingtonePlayer(); if (player != null) { if (DBG) Slog.v(TAG, "Playing sound " + soundUri - + " on stream " + audioStreamType); + + " with attributes " + audioAttributes); player.playAsync(soundUri, record.sbn.getUser(), looping, - audioStreamType); + audioAttributes); buzzBeepBlinked = true; } } catch (RemoteException e) { @@ -2424,8 +2425,9 @@ public class NotificationManagerService extends SystemService { // pulse repeatedly mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED, ledOnMS, ledOffMS); - mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS); } + // let SystemUI make an independent decision + mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 6be6b60..89bd1d4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -253,6 +253,10 @@ public class PackageManagerService extends IPackageManager.Stub { // package apks to install directory. private static final String INSTALL_PACKAGE_SUFFIX = "-"; + // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate + // that the cpuAbiOverride must be clear. + private static final String CLEAR_ABI_OVERRIDE = "-"; + static final int SCAN_MONITOR = 1<<0; static final int SCAN_NO_DEX = 1<<1; static final int SCAN_FORCE_DEX = 1<<2; @@ -3195,7 +3199,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (fromSource != null) { packageNames = fromSource.get(targetUserId); } - if (packageNames.contains(intent.getPackage())) { + if (packageNames != null && packageNames.contains(intent.getPackage())) { return true; } // We need the package name, so we try to resolve with the loosest flags possible @@ -4093,8 +4097,7 @@ public class PackageManagerService extends IPackageManager.Stub { continue; } try { - scanPackageLI(file, flags | PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, - null, null); + scanPackageLI(file, flags | PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage()); @@ -4175,7 +4178,7 @@ public class PackageManagerService extends IPackageManager.Stub { * Returns null in case of errors and the error code is stored in mLastScanError */ private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanMode, - long currentTime, UserHandle user, String abiOverride) throws PackageManagerException { + long currentTime, UserHandle user) throws PackageManagerException { if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); parseFlags |= mDefParseFlags; PackageParser pp = new PackageParser(); @@ -4371,7 +4374,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Note that we invoke the following method only if we are about to unpack an application PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode - | SCAN_UPDATE_SIGNATURE, currentTime, user, abiOverride); + | SCAN_UPDATE_SIGNATURE, currentTime, user); /* * If the system app should be overridden by a previously installed @@ -4998,8 +5001,26 @@ public class PackageManagerService extends IPackageManager.Stub { return res; } + /** + * Derive the value of the {@code cpuAbiOverride} based on the provided + * value and an optional stored value from the package settings. + */ + private static String deriveAbiOverride(String abiOverride, PackageSetting settings) { + String cpuAbiOverride = null; + + if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) { + cpuAbiOverride = null; + } else if (abiOverride != null) { + cpuAbiOverride = abiOverride; + } else if (settings != null) { + cpuAbiOverride = settings.cpuAbiOverrideString; + } + + return cpuAbiOverride; + } + private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags, - int scanMode, long currentTime, UserHandle user, String abiOverride) + int scanMode, long currentTime, UserHandle user) throws PackageManagerException { final File scanFile = new File(pkg.codePath); if (pkg.applicationInfo.getCodePath() == null || @@ -5155,7 +5176,7 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Package " + pkg.packageName + " was transferred to another, but its .apk remains"); } - + // Just create the setting, don't add it yet. For already existing packages // the PkgSetting exists already and doesn't have to be created. pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile, @@ -5435,14 +5456,8 @@ public class PackageManagerService extends IPackageManager.Stub { final String path = scanFile.getPath(); final String codePath = pkg.applicationInfo.getCodePath(); + final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting); if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) { - // For the case where we had previously uninstalled an update, get rid - // of any native binaries we might have unpackaged. Note that this assumes - // that system app updates were not installed via ASEC. - // - // TODO(multiArch): Is this cleanup really necessary ? - NativeLibraryHelper.removeNativeBinariesFromDirLI( - new File(codePath, LIB_DIR_NAME), false /* delete dirs */); setBundledAppAbisAndRoots(pkg, pkgSetting); // If we haven't found any native libraries for the app, check if it has @@ -5497,7 +5512,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Warn if we've set an abiOverride for multi-lib packages.. // By definition, we need to copy both 32 and 64 bit libraries for // such packages. - if (abiOverride != null) { + if (pkg.cpuAbiOverride != null && !CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) { Slog.w(TAG, "Ignoring abiOverride for multi arch application."); } @@ -5540,15 +5555,15 @@ public class PackageManagerService extends IPackageManager.Stub { } } } else { - String[] abiList = (abiOverride != null) ? - new String[] { abiOverride } : Build.SUPPORTED_ABIS; + String[] abiList = (cpuAbiOverride != null) ? + new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS; // Enable gross and lame hacks for apps that are built with old // SDK tools. We must scan their APKs for renderscript bitcode and // not launch them if it's present. Don't bother checking on devices // that don't have 64 bit support. boolean needsRenderScriptOverride = false; - if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && abiOverride == null && + if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { abiList = Build.SUPPORTED_32_BIT_ABIS; needsRenderScriptOverride = true; @@ -5569,8 +5584,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (copyRet >= 0) { pkg.applicationInfo.primaryCpuAbi = abiList[copyRet]; - } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && abiOverride != null) { - pkg.applicationInfo.primaryCpuAbi = abiOverride; + } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) { + pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride; } else if (needsRenderScriptOverride) { pkg.applicationInfo.primaryCpuAbi = abiList[0]; } @@ -5615,6 +5630,10 @@ public class PackageManagerService extends IPackageManager.Stub { pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; + pkgSetting.cpuAbiOverrideString = cpuAbiOverride; + // Copy the derived override back to the parsed package, so that we can + // update the package settings accordingly. + pkg.cpuAbiOverride = cpuAbiOverride; Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa=" @@ -6241,7 +6260,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private static String calculateApkRoot(final String codePathString) { + private static String calculateBundledApkRoot(final String codePathString) { final File codePath = new File(codePathString); final File codeRoot; if (FileUtils.contains(Environment.getRootDirectory(), codePath)) { @@ -6281,14 +6300,9 @@ public class PackageManagerService extends IPackageManager.Stub { final ApplicationInfo info = pkg.applicationInfo; final String codePath = pkg.codePath; final File codeFile = new File(codePath); - // If "/system/lib64/apkname" exists, assume that is the per-package - // native library directory to use; otherwise use "/system/lib/apkname". - final String apkRoot = calculateApkRoot(info.sourceDir); - final boolean bundledApp = isSystemApp(info) && !isUpdatedSystemApp(info); final boolean asecApp = isForwardLocked(info) || isExternal(info); - info.nativeLibraryRootDir = null; info.nativeLibraryRootRequiresIsa = false; info.nativeLibraryDir = null; @@ -6297,6 +6311,9 @@ public class PackageManagerService extends IPackageManager.Stub { if (isApkFile(codeFile)) { // Monolithic install if (bundledApp) { + // 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(info.sourceDir); final boolean is64Bit = VMRuntime.is64BitInstructionSet( getPrimaryInstructionSet(info)); @@ -6352,7 +6369,7 @@ public class PackageManagerService extends IPackageManager.Stub { // If "/system/lib64/apkname" exists, assume that is the per-package // native library directory to use; otherwise use "/system/lib/apkname". - final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir); + 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 @@ -9278,7 +9295,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Warn if we've set an abiOverride for multi-lib packages.. // By definition, we need to copy both 32 and 64 bit libraries for // such packages. - if (abiOverride != null) { + if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) { Slog.w(TAG, "Ignoring abiOverride for multi arch application."); } @@ -9295,10 +9312,11 @@ public class PackageManagerService extends IPackageManager.Stub { maybeThrowExceptionForMultiArchCopy("Failure copying 64 bit native libraries", copyRet); } } else { - String[] abiList = (abiOverride != null) ? - new String[] { abiOverride } : Build.SUPPORTED_ABIS; + final String cpuAbiOverride = deriveAbiOverride(this.abiOverride, null /* package setting */); + String[] abiList = (cpuAbiOverride != null) ? + new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS; - if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && abiOverride == null && + if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { abiList = Build.SUPPORTED_32_BIT_ABIS; } @@ -9566,7 +9584,7 @@ public class PackageManagerService extends IPackageManager.Stub { final String newCachePath = imcs.copyPackageToContainer( originFile.getAbsolutePath(), cid, getEncryptKey(), isExternal(), - isFwdLocked(), abiOverride); + isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */)); if (newCachePath != null) { setCachePath(newCachePath); @@ -9917,7 +9935,7 @@ public class PackageManagerService extends IPackageManager.Stub { */ private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user, - String installerPackageName, PackageInstalledInfo res, String abiOverride) { + String installerPackageName, PackageInstalledInfo res) { // Remember this for later, in case we need to rollback this install String pkgName = pkg.packageName; @@ -9944,7 +9962,7 @@ public class PackageManagerService extends IPackageManager.Stub { try { PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode, - System.currentTimeMillis(), user, abiOverride); + System.currentTimeMillis(), user); updateSettingsLI(newPackage, installerPackageName, null, null, res); // delete the partially installed application. the data directory will have to be @@ -9980,7 +9998,7 @@ public class PackageManagerService extends IPackageManager.Stub { private void replacePackageLI(PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user, - String installerPackageName, PackageInstalledInfo res, String abiOverride) { + String installerPackageName, PackageInstalledInfo res) { PackageParser.Package oldPackage; String pkgName = pkg.packageName; int[] allUsers; @@ -10019,19 +10037,17 @@ public class PackageManagerService extends IPackageManager.Stub { boolean sysPkg = (isSystemApp(oldPackage)); if (sysPkg) { replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, - user, allUsers, perUserInstalled, installerPackageName, res, - abiOverride); + user, allUsers, perUserInstalled, installerPackageName, res); } else { replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, - user, allUsers, perUserInstalled, installerPackageName, res, - abiOverride); + user, allUsers, perUserInstalled, installerPackageName, res); } } private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage, PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user, int[] allUsers, boolean[] perUserInstalled, - String installerPackageName, PackageInstalledInfo res, String abiOverride) { + String installerPackageName, PackageInstalledInfo res) { String pkgName = deletedPackage.packageName; boolean deletedPkg = true; boolean updatedSettings = false; @@ -10056,7 +10072,7 @@ public class PackageManagerService extends IPackageManager.Stub { deleteCodeCacheDirsLI(pkgName); try { final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, - scanMode | SCAN_UPDATE_TIME, System.currentTimeMillis(), user, abiOverride); + scanMode | SCAN_UPDATE_TIME, System.currentTimeMillis(), user); updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res); updatedSettings = true; } catch (PackageManagerException e) { @@ -10089,8 +10105,7 @@ public class PackageManagerService extends IPackageManager.Stub { int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME; try { - scanPackageLI(restoreFile, oldParseFlags, oldScanMode, origUpdateTime, null, - null); + scanPackageLI(restoreFile, oldParseFlags, oldScanMode, origUpdateTime, null); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade: " + e.getMessage()); @@ -10112,7 +10127,7 @@ public class PackageManagerService extends IPackageManager.Stub { private void replaceSystemPackageLI(PackageParser.Package deletedPackage, PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user, int[] allUsers, boolean[] perUserInstalled, - String installerPackageName, PackageInstalledInfo res, String abiOverride) { + String installerPackageName, PackageInstalledInfo res) { if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg + ", old=" + deletedPackage); boolean updatedSettings = false; @@ -10172,7 +10187,7 @@ public class PackageManagerService extends IPackageManager.Stub { PackageParser.Package newPackage = null; try { - newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user, abiOverride); + newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user); if (newPackage.mExtras != null) { final PackageSetting newPkgSetting = (PackageSetting) newPackage.mExtras; newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime; @@ -10204,8 +10219,7 @@ public class PackageManagerService extends IPackageManager.Stub { } // Add back the old system package try { - scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user, - null); + scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to restore original package: " + e.getMessage()); } @@ -10336,6 +10350,9 @@ public class PackageManagerService extends IPackageManager.Stub { return; } + // Mark that we have an install time CPU ABI override. + pkg.cpuAbiOverride = args.abiOverride; + String pkgName = res.name = pkg.packageName; if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) { if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) { @@ -10454,10 +10471,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (replace) { replacePackageLI(pkg, parseFlags, scanMode, args.user, - installerPackageName, res, args.abiOverride); + installerPackageName, res); } else { installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user, - installerPackageName, res, args.abiOverride); + installerPackageName, res); } synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(pkgName); @@ -10893,8 +10910,7 @@ public class PackageManagerService extends IPackageManager.Stub { final PackageParser.Package newPkg; try { - newPkg = scanPackageLI(disabledPs.codePath, parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, - null, null); + newPkg = scanPackageLI(disabledPs.codePath, parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to restore system package:" + newPs.name + ": " + e.getMessage()); return false; @@ -12852,7 +12868,7 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mInstallLock) { PackageParser.Package pkg = null; try { - pkg = scanPackageLI(new File(codePath), parseFlags, 0, 0, null, null); + pkg = scanPackageLI(new File(codePath), parseFlags, 0, 0, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to scan " + codePath + ": " + e.getMessage()); } diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index a6571cf..696aa34 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -31,9 +31,11 @@ final class PackageSetting extends PackageSettingBase { PackageSetting(String name, String realName, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, - String secondaryCpuAbiString, int pVersionCode, int pkgFlags) { + String secondaryCpuAbiString, String cpuAbiOverrideString, + int pVersionCode, int pkgFlags) { super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, - primaryCpuAbiString, secondaryCpuAbiString, pVersionCode, pkgFlags); + primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, + pVersionCode, pkgFlags); } /** diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index e29332c..bf13fd9 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -64,8 +64,25 @@ class PackageSettingBase extends GrantedPermissions { @Deprecated String legacyNativeLibraryPathString; + /** + * The primary CPU abi for this package. This value is regenerated at every + * boot scan. + */ String primaryCpuAbiString; + + /** + * The secondary CPU abi for this package. This value is regenerated at every + * boot scan. + */ String secondaryCpuAbiString; + + /** + * The install time CPU override, if any. This value is written at install time + * and doesn't change during the life of an install. If non-null, + * {@code primaryCpuAbiString} will contain the same value. + */ + String cpuAbiOverrideString; + long timeStamp; long firstInstallTime; long lastUpdateTime; @@ -94,12 +111,13 @@ class PackageSettingBase extends GrantedPermissions { String installerPackageName; PackageSettingBase(String name, String realName, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, - String secondaryCpuAbiString, int pVersionCode, int pkgFlags) { + String secondaryCpuAbiString, String cpuAbiOverrideString, + int pVersionCode, int pkgFlags) { super(pkgFlags); this.name = name; this.realName = realName; init(codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString, - secondaryCpuAbiString, pVersionCode); + secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode); } /** @@ -118,6 +136,7 @@ class PackageSettingBase extends GrantedPermissions { legacyNativeLibraryPathString = base.legacyNativeLibraryPathString; primaryCpuAbiString = base.primaryCpuAbiString; secondaryCpuAbiString = base.secondaryCpuAbiString; + cpuAbiOverrideString = base.cpuAbiOverrideString; timeStamp = base.timeStamp; firstInstallTime = base.firstInstallTime; lastUpdateTime = base.lastUpdateTime; @@ -145,7 +164,8 @@ class PackageSettingBase extends GrantedPermissions { } void init(File codePath, File resourcePath, String legacyNativeLibraryPathString, - String primaryCpuAbiString, String secondaryCpuAbiString, int pVersionCode) { + String primaryCpuAbiString, String secondaryCpuAbiString, + String cpuAbiOverrideString, int pVersionCode) { this.codePath = codePath; this.codePathString = codePath.toString(); this.resourcePath = resourcePath; @@ -153,6 +173,7 @@ class PackageSettingBase extends GrantedPermissions { this.legacyNativeLibraryPathString = legacyNativeLibraryPathString; this.primaryCpuAbiString = primaryCpuAbiString; this.secondaryCpuAbiString = secondaryCpuAbiString; + this.cpuAbiOverrideString = cpuAbiOverrideString; this.versionCode = pVersionCode; } @@ -185,6 +206,7 @@ class PackageSettingBase extends GrantedPermissions { primaryCpuAbiString = base.primaryCpuAbiString; secondaryCpuAbiString = base.secondaryCpuAbiString; + cpuAbiOverrideString = base.cpuAbiOverrideString; timeStamp = base.timeStamp; firstInstallTime = base.firstInstallTime; lastUpdateTime = base.lastUpdateTime; diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java index 85be651..5d30e76 100644 --- a/services/core/java/com/android/server/pm/PendingPackage.java +++ b/services/core/java/com/android/server/pm/PendingPackage.java @@ -22,10 +22,12 @@ final class PendingPackage extends PackageSettingBase { final int sharedId; PendingPackage(String name, String realName, File codePath, File resourcePath, - String nativeLibrary32PathString, String nativeLibrary64PathString, - String requiredCpuAbiString, int sharedId, int pVersionCode, int pkgFlags) { - super(name, realName, codePath, resourcePath, nativeLibrary32PathString, nativeLibrary64PathString, - requiredCpuAbiString, pVersionCode, pkgFlags); + String legacyNativeLibraryPathString, String primaryCpuAbiString, + String secondaryCpuAbiString, String cpuAbiOverrideString, int sharedId, + int pVersionCode, int pkgFlags) { + super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, + primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, + pVersionCode, pkgFlags); this.sharedId = sharedId; } } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index cd2aa22..c346f71 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -325,8 +325,8 @@ final class Settings { PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, - String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi, int pkgFlags, - UserHandle user, boolean add) { + String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi, + int pkgFlags, UserHandle user, boolean add) { final String name = pkg.packageName; PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi, @@ -417,7 +417,8 @@ final class Settings { } PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath, p.legacyNativeLibraryPathString, p.primaryCpuAbiString, - p.secondaryCpuAbiString, p.appId, p.versionCode, p.pkgFlags); + p.secondaryCpuAbiString, p.secondaryCpuAbiString, + p.appId, p.versionCode, p.pkgFlags); mDisabledSysPackages.remove(name); return ret; } @@ -432,7 +433,7 @@ final class Settings { PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, - int uid, int vc, int pkgFlags) { + String cpuAbiOverrideString, int uid, int vc, int pkgFlags) { PackageSetting p = mPackages.get(name); if (p != null) { if (p.appId == uid) { @@ -443,7 +444,8 @@ final class Settings { return null; } p = new PackageSetting(name, realName, codePath, resourcePath, - legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags); + legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, + cpuAbiOverrideString, vc, pkgFlags); p.appId = uid; if (addUserIdLPw(uid, p, name)) { mPackages.put(name, p); @@ -512,11 +514,13 @@ final class Settings { private PackageSetting getPackageLPw(String name, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, - int vc, int pkgFlags, UserHandle installUser, boolean add, boolean allowInstall) { + int vc, int pkgFlags, UserHandle installUser, boolean add, + boolean allowInstall) { PackageSetting p = mPackages.get(name); if (p != null) { p.primaryCpuAbiString = primaryCpuAbiString; p.secondaryCpuAbiString = secondaryCpuAbiString; + if (!p.codePath.equals(codePath)) { // Check to see if its a disabled system app if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) { @@ -560,7 +564,8 @@ final class Settings { if (origPackage != null) { // We are consuming the data from an existing package. p = new PackageSetting(origPackage.name, name, codePath, resourcePath, - legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags); + legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, + null /* cpuAbiOverrideString */, vc, pkgFlags); if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + name + " is adopting original package " + origPackage.name); // Note that we will retain the new package's signature so @@ -577,7 +582,8 @@ final class Settings { p.setTimeStamp(codePath.lastModified()); } else { p = new PackageSetting(name, realName, codePath, resourcePath, - legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags); + legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, + null /* cpuAbiOverrideString */, vc, pkgFlags); p.setTimeStamp(codePath.lastModified()); p.sharedUser = sharedUser; // If this is not a system app, it starts out stopped. @@ -720,6 +726,7 @@ final class Settings { // Update the required Cpu Abi p.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; p.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; + p.cpuAbiOverrideString = pkg.cpuAbiOverride; // Update version code if needed if (pkg.mVersionCode != p.versionCode) { p.versionCode = pkg.mVersionCode; @@ -1888,6 +1895,9 @@ final class Settings { if (pkg.secondaryCpuAbiString != null) { serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString); } + if (pkg.cpuAbiOverrideString != null) { + serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString); + } if (pkg.sharedUser == null) { serializer.attribute(null, "userId", Integer.toString(pkg.appId)); @@ -1938,6 +1948,9 @@ final class Settings { if (pkg.secondaryCpuAbiString != null) { serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString); } + if (pkg.cpuAbiOverrideString != null) { + serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString); + } serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags)); serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); @@ -2248,8 +2261,8 @@ final class Settings { PackageSetting p = getPackageLPw(pp.name, null, pp.realName, (SharedUserSetting) idObj, pp.codePath, pp.resourcePath, pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString, - pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, - null, true /* add */, false /* allowInstall */); + pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, null, + true /* add */, false /* allowInstall */); if (p == null) { PackageManagerService.reportSettingsProblem(Log.WARN, "Unable to create application package for " + pp.name); @@ -2673,6 +2686,7 @@ final class Settings { String primaryCpuAbiStr = parser.getAttributeValue(null, "primaryCpuAbi"); String secondaryCpuAbiStr = parser.getAttributeValue(null, "secondaryCpuAbi"); + String cpuAbiOverrideStr = parser.getAttributeValue(null, "cpuAbiOverride"); if (primaryCpuAbiStr == null && legacyCpuAbiStr != null) { primaryCpuAbiStr = legacyCpuAbiStr; @@ -2698,7 +2712,7 @@ final class Settings { } PackageSetting ps = new PackageSetting(name, realName, codePathFile, new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr, - secondaryCpuAbiStr, versionCode, pkgFlags); + secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags); String timeStampStr = parser.getAttributeValue(null, "ft"); if (timeStampStr != null) { try { @@ -2768,6 +2782,7 @@ final class Settings { String legacyNativeLibraryPathStr = null; String primaryCpuAbiString = null; String secondaryCpuAbiString = null; + String cpuAbiOverrideString = null; String systemStr = null; String installerPackageName = null; String uidError = null; @@ -2792,6 +2807,7 @@ final class Settings { legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); primaryCpuAbiString = parser.getAttributeValue(null, "primaryCpuAbi"); secondaryCpuAbiString = parser.getAttributeValue(null, "secondaryCpuAbi"); + cpuAbiOverrideString = parser.getAttributeValue(null, "cpuAbiOverride"); if (primaryCpuAbiString == null && legacyCpuAbiString != null) { primaryCpuAbiString = legacyCpuAbiString; @@ -2874,7 +2890,7 @@ final class Settings { } else if (userId > 0) { packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString, - secondaryCpuAbiString, userId, versionCode, pkgFlags); + secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags); if (PackageManagerService.DEBUG_SETTINGS) Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId=" + userId + " pkg=" + packageSetting); @@ -2892,7 +2908,8 @@ final class Settings { if (userId > 0) { packageSetting = new PendingPackage(name.intern(), realName, new File( codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr, - primaryCpuAbiString, legacyCpuAbiString, userId, versionCode, pkgFlags); + primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, + userId, versionCode, pkgFlags); packageSetting.setTimeStamp(timeStamp); packageSetting.firstInstallTime = firstInstallTime; packageSetting.lastUpdateTime = lastUpdateTime; diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 33ecc4d..ad87993 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -125,6 +125,10 @@ public class UserManagerService extends IUserManager.Stub { // Number of attempts before jumping to the next BACKOFF_TIMES slot private static final int BACKOFF_INC_INTERVAL = 5; + // Maximum number of managed profiles permitted is 1. This cannot be increased + // without first making sure that the rest of the framework is prepared for it. + private static final int MAX_MANAGED_PROFILES = 1; + // Amount of time to force the user to wait before entering the PIN again, after failing // BACKOFF_INC_INTERVAL times. private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 }; @@ -510,7 +514,8 @@ public class UserManagerService extends IUserManager.Stub { // Skip over users being removed for (int i = 0; i < totalUserCount; i++) { UserInfo user = mUsers.valueAt(i); - if (!mRemovingUserIds.get(user.id)) { + if (!mRemovingUserIds.get(user.id) + && !user.isGuest()) { aliveUserCount++; } } @@ -1093,6 +1098,7 @@ public class UserManagerService extends IUserManager.Stub { Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled."); return null; } + final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0; final long ident = Binder.clearCallingIdentity(); UserInfo userInfo = null; try { @@ -1103,7 +1109,21 @@ public class UserManagerService extends IUserManager.Stub { parent = getUserInfoLocked(parentId); if (parent == null) return null; } - if (isUserLimitReachedLocked()) return null; + // If we're not adding a guest user and the limit has been reached, + // cannot add a user. + if (!isGuest && isUserLimitReachedLocked()) { + return null; + } + // If we're adding a guest and there already exists one, bail. + if (isGuest && numberOfUsersOfTypeLocked(UserInfo.FLAG_GUEST, true) > 0) { + return null; + } + // Limit number of managed profiles that can be created + if ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0 + && numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true) + >= MAX_MANAGED_PROFILES) { + return null; + } int userId = getNextAvailableIdLocked(); userInfo = new UserInfo(userId, name, null, flags); File userPath = new File(mBaseUserPath, Integer.toString(userId)); @@ -1142,6 +1162,19 @@ public class UserManagerService extends IUserManager.Stub { return userInfo; } + private int numberOfUsersOfTypeLocked(int flags, boolean excludeDying) { + int count = 0; + for (int i = mUsers.size() - 1; i >= 0; i--) { + UserInfo user = mUsers.valueAt(i); + if (!excludeDying || !mRemovingUserIds.get(user.id)) { + if ((user.flags & flags) != 0) { + count++; + } + } + } + return count; + } + /** * Removes a user and all data directories created for that user. This method should be called * after the user's processes have been terminated. diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java index d4ed86d..7253716 100644 --- a/services/core/java/com/android/server/trust/TrustArchive.java +++ b/services/core/java/com/android/server/trust/TrustArchive.java @@ -129,8 +129,8 @@ public class TrustArchive { } switch (ev.type) { case TYPE_GRANT_TRUST: - writer.printf(", message=\"%s\", duration=%s", - ev.message, formatDuration(ev.duration)); + writer.printf(", message=\"%s\", duration=%s, initiatedByUser=%d", + ev.message, formatDuration(ev.duration), ev.userInitiated ? 1 : 0); break; case TYPE_MANAGING_TRUST: writer.printf(", managingTrust=" + ev.managingTrust); diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index badead6..490536e 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -93,7 +93,7 @@ public class TrustManagerService extends SystemService { private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>(); private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>(); - private final DevicePolicyReceiver mDevicePolicyReceiver = new DevicePolicyReceiver(); + private final Receiver mReceiver = new Receiver(); private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray(); /* package */ final TrustArchive mArchive = new TrustArchive(); private final Context mContext; @@ -115,7 +115,7 @@ public class TrustManagerService extends SystemService { public void onBootPhase(int phase) { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) { mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); - mDevicePolicyReceiver.register(mContext); + mReceiver.register(mContext); refreshAgentList(); } } @@ -373,7 +373,13 @@ public class TrustManagerService extends SystemService { } } - if (successful && !mUserHasAuthenticatedSinceBoot.get(userId)) { + if (successful) { + updateUserHasAuthenticated(userId); + } + } + + private void updateUserHasAuthenticated(int userId) { + if (!mUserHasAuthenticatedSinceBoot.get(userId)) { mUserHasAuthenticatedSinceBoot.put(userId, true); updateTrust(userId, false); } @@ -597,7 +603,7 @@ public class TrustManagerService extends SystemService { } }; - private class DevicePolicyReceiver extends BroadcastReceiver { + private class Receiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { @@ -605,14 +611,18 @@ public class TrustManagerService extends SystemService { intent.getAction())) { refreshAgentList(); updateDevicePolicyFeatures(getSendingUserId()); + } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) { + updateUserHasAuthenticated(getSendingUserId()); } } public void register(Context context) { + IntentFilter filter = new IntentFilter(); + filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); + filter.addAction(Intent.ACTION_USER_PRESENT); context.registerReceiverAsUser(this, UserHandle.ALL, - new IntentFilter( - DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), + filter, null /* permission */, null /* scheduler */); } diff --git a/services/core/java/com/android/server/tv/PersistentDataStore.java b/services/core/java/com/android/server/tv/PersistentDataStore.java index 852e640..4af8f2c 100644 --- a/services/core/java/com/android/server/tv/PersistentDataStore.java +++ b/services/core/java/com/android/server/tv/PersistentDataStore.java @@ -91,6 +91,7 @@ final class PersistentDataStore { } public void setParentalControlsEnabled(boolean enabled) { + loadIfNeeded(); if (mParentalControlsEnabled != enabled) { mParentalControlsEnabled = enabled; mParentalControlsEnabledChanged = true; @@ -114,6 +115,7 @@ final class PersistentDataStore { } public void addBlockedRating(TvContentRating rating) { + loadIfNeeded(); if (rating != null && !mBlockedRatings.contains(rating)) { mBlockedRatings.add(rating); mBlockedRatingsChanged = true; @@ -122,6 +124,7 @@ final class PersistentDataStore { } public void removeBlockedRating(TvContentRating rating) { + loadIfNeeded(); if (rating != null && mBlockedRatings.contains(rating)) { mBlockedRatings.remove(rating); mBlockedRatingsChanged = true; diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index dc5bc84..2de305e 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -212,8 +212,6 @@ public final class TvInputManagerService extends SystemService { private void buildTvInputListLocked(int userId) { UserState userState = getUserStateLocked(userId); - - Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); userState.packageSet.clear(); if (DEBUG) Slog.d(TAG, "buildTvInputList"); @@ -229,41 +227,42 @@ public final class TvInputManagerService extends SystemService { + android.Manifest.permission.BIND_TV_INPUT); continue; } - try { - inputList.clear(); - ComponentName component = new ComponentName(si.packageName, si.name); - if (hasHardwarePermission(pm, component)) { - ServiceState serviceState = userState.serviceStateMap.get(component); - if (serviceState == null) { - // We see this hardware TV input service for the first time; we need to - // prepare the ServiceState object so that we can connect to the service and - // let it add TvInputInfo objects to mInputList if there's any. - serviceState = new ServiceState(component, userId); - userState.serviceStateMap.put(component, serviceState); - } else { - inputList.addAll(serviceState.mInputList); - } + + ComponentName component = new ComponentName(si.packageName, si.name); + if (hasHardwarePermission(pm, component)) { + ServiceState serviceState = userState.serviceStateMap.get(component); + if (serviceState == null) { + // We see this hardware TV input service for the first time; we need to + // prepare the ServiceState object so that we can connect to the service and + // let it add TvInputInfo objects to mInputList if there's any. + serviceState = new ServiceState(component, userId); + userState.serviceStateMap.put(component, serviceState); } else { - inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); + inputList.addAll(serviceState.mInputList); } - - for (TvInputInfo info : inputList) { - if (DEBUG) Slog.d(TAG, "add " + info.getId()); - TvInputState state = userState.inputMap.get(info.getId()); - if (state == null) { - state = new TvInputState(); - } - state.mInfo = info; - inputMap.put(info.getId(), state); + } else { + try { + inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); + } catch (XmlPullParserException | IOException e) { + Slog.e(TAG, "Failed to load TV input " + si.name, e); + continue; } + } - // Reconnect the service if existing input is updated. - updateServiceConnectionLocked(component, userId); + // Reconnect the service if existing input is updated. + updateServiceConnectionLocked(component, userId); + userState.packageSet.add(si.packageName); + } - userState.packageSet.add(si.packageName); - } catch (IOException | XmlPullParserException e) { - Slog.e(TAG, "Can't load TV input " + si.name, e); + Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); + for (TvInputInfo info : inputList) { + if (DEBUG) Slog.d(TAG, "add " + info.getId()); + TvInputState state = userState.inputMap.get(info.getId()); + if (state == null) { + state = new TvInputState(); } + state.mInfo = info; + inputMap.put(info.getId(), state); } for (String inputId : inputMap.keySet()) { @@ -338,7 +337,6 @@ public final class TvInputManagerService extends SystemService { Slog.e(TAG, "error in unregisterCallback", e); } } - serviceState.mClientTokens.clear(); mContext.unbindService(serviceState.mConnection); } userState.serviceStateMap.clear(); @@ -401,9 +399,7 @@ public final class TvInputManagerService extends SystemService { } private static boolean shouldMaintainConnection(ServiceState serviceState) { - return !serviceState.mClientTokens.isEmpty() - || !serviceState.mSessionTokens.isEmpty() - || serviceState.mIsHardware; + return !serviceState.mSessionTokens.isEmpty() || serviceState.mIsHardware; // TODO: Find a way to maintain connection only when necessary. } @@ -996,12 +992,13 @@ public final class TvInputManagerService extends SystemService { } private void ensureParentalControlsPermission() { - if (mContext.checkCallingPermission( - android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException( - "The caller does not have parental controls permission"); - } + // STOPSHIP: Uncomment when b/16984416 is resolved. + //if (mContext.checkCallingPermission( + // android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) + // != PackageManager.PERMISSION_GRANTED) { + // throw new SecurityException( + // "The caller does not have parental controls permission"); + //} } @Override @@ -1610,13 +1607,6 @@ public final class TvInputManagerService extends SystemService { pw.increaseIndent(); - pw.println("mClientTokens:"); - pw.increaseIndent(); - for (IBinder token : service.mClientTokens) { - pw.println("" + token); - } - pw.decreaseIndent(); - pw.println("mSessionTokens:"); pw.increaseIndent(); for (IBinder token : service.mSessionTokens) { @@ -1753,7 +1743,6 @@ public final class TvInputManagerService extends SystemService { } private final class ServiceState { - private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); private final ServiceConnection mConnection; private final ComponentName mComponent; @@ -1808,7 +1797,7 @@ public final class TvInputManagerService extends SystemService { // If there are any other sessions based on this session, they should be released. UserState userState = getUserStateLocked(mUserId); for (SessionState sessionState : userState.sessionStateMap.values()) { - if (mSession != null && mSession == sessionState.mHardwareSessionToken) { + if (mSessionToken == sessionState.mHardwareSessionToken) { try { sessionState.mSession.release(); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 0e1340c..f6ec86d 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -159,7 +159,7 @@ public class AppTransition implements Dump { private final int mConfigShortAnimTime; private final Interpolator mDecelerateInterpolator; private final Interpolator mThumbnailFadeoutInterpolator; - private final Interpolator mThumbnailCubicInterpolator; + private final Interpolator mThumbnailFastOutSlowInInterpolator; private int mCurrentUserId = 0; @@ -170,7 +170,7 @@ public class AppTransition implements Dump { com.android.internal.R.integer.config_shortAnimTime); mDecelerateInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.decelerate_cubic); - mThumbnailCubicInterpolator = AnimationUtils.loadInterpolator(context, + mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); mThumbnailFadeoutInterpolator = new Interpolator() { @Override @@ -635,7 +635,7 @@ public class AppTransition implements Dump { } return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, - THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailCubicInterpolator); + THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailFastOutSlowInInterpolator); } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e7ebae7..cd9f050 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -462,6 +462,9 @@ public class WindowManagerService extends IWindowManager.Stub int mRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; boolean mAltOrientation = false; + + private boolean mKeyguardWaitingForActivityDrawn; + class RotationWatcher { IRotationWatcher watcher; IBinder.DeathRecipient deathRecipient; @@ -2311,6 +2314,10 @@ public class WindowManagerService extends IWindowManager.Stub + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } + } else if (token.appWindowToken != null) { + Slog.i(TAG, "Non-null appWindowToken for system window of type=" + type); + // app token should be null for any other window types. + token.appWindowToken = null; } win = new WindowState(this, session, client, token, @@ -5247,6 +5254,20 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void keyguardWaitingForActivityDrawn() { + synchronized (mWindowMap) { + mKeyguardWaitingForActivityDrawn = true; + } + } + + public void notifyActivityDrawnForKeyguard() { + synchronized (mWindowMap) { + if (mKeyguardWaitingForActivityDrawn) { + mPolicy.notifyActivityDrawnForKeyguardLw(); + } + } + } + void showGlobalActions() { mPolicy.showGlobalActions(); } diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp index 2519ff8..37a3eaa 100644 --- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp +++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp @@ -66,7 +66,12 @@ static inline void ThrowOnError( } ALOGE("Error %d in '%s'", resultCode, methodName); - env->FatalError(methodName); + // TODO: this layer needs to be refactored to return error codes to Java + // raising a FatalError is harsh, and because FLP Hardware Provider is loaded inside the system + // service, it can cause the device to reboot, or remain in a reboot loop + // a simple exception is still dumped to logcat, but it is handled more gracefully + jclass exceptionClass = env->FindClass("java/lang/RuntimeException"); + env->ThrowNew(exceptionClass, methodName); } static bool IsValidCallbackThread() { diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp index 46327d7..c398908 100644 --- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp @@ -28,6 +28,7 @@ #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" +#include <arpa/inet.h> #include <string.h> #include <pthread.h> #include <linux/in.h> @@ -189,8 +190,10 @@ static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order) jbyte ipv4[4]; if (net_order) { + ALOGV("Converting IPv4 address(net_order) %x", ip); memcpy(ipv4, &ip, sizeof(ipv4)); } else { + ALOGV("Converting IPv4 address(host_order) %x", ip); //endianess transparent conversion from int to char[] ipv4[0] = (jbyte) (ip & 0xFF); ipv4[1] = (jbyte)((ip>>8) & 0xFF); @@ -210,6 +213,7 @@ static void agps_status_callback(AGpsStatus* agps_status) size_t status_size = agps_status->size; if (status_size == sizeof(AGpsStatus_v3)) { + ALOGV("AGpsStatus is V3: %d", status_size); switch (agps_status->addr.ss_family) { case AF_INET: @@ -220,6 +224,12 @@ static void agps_status_callback(AGpsStatus* agps_status) if (byteArray != NULL) { isSupported = true; } + IF_ALOGD() { + // log the IP for reference in case there is a bogus value pushed by HAL + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN); + ALOGD("AGPS IP is v4: %s", str); + } } break; case AF_INET6: @@ -232,6 +242,12 @@ static void agps_status_callback(AGpsStatus* agps_status) } else { ALOGE("Unable to allocate byte array for IPv6 address."); } + IF_ALOGD() { + // log the IP for reference in case there is a bogus value pushed by HAL + char str[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN); + ALOGD("AGPS IP is v6: %s", str); + } } break; default: @@ -239,14 +255,17 @@ static void agps_status_callback(AGpsStatus* agps_status) break; } } else if (status_size >= sizeof(AGpsStatus_v2)) { + ALOGV("AGpsStatus is V2+: %d", status_size); // for back-compatibility reasons we check in v2 that the data structure size is greater or // equal to the declared size in gps.h uint32_t ipaddr = agps_status->ipaddr; + ALOGV("AGPS IP is v4: %x", ipaddr); byteArray = convert_to_ipv4(ipaddr, false /* net_order */); if (ipaddr == INADDR_NONE || byteArray != NULL) { isSupported = true; } } else if (status_size >= sizeof(AGpsStatus_v1)) { + ALOGV("AGpsStatus is V1+: %d", status_size); // because we have to check for >= with regards to v2, we also need to relax the check here // and only make sure that the size is at least what we expect isSupported = true; @@ -255,6 +274,8 @@ static void agps_status_callback(AGpsStatus* agps_status) } if (isSupported) { + jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0; + ALOGV("Passing AGPS IP addr: size %d", byteArrayLength); env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type, agps_status->status, byteArray); diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 2e309be..6e13732 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -47,6 +47,18 @@ public class UserManagerTest extends AndroidTestCase { } } }, filter); + + removeExistingUsers(); + } + + private void removeExistingUsers() { + List<UserInfo> list = mUserManager.getUsers(); + boolean found = false; + for (UserInfo user : list) { + if (user.id != UserHandle.USER_OWNER) { + removeUser(user.id); + } + } } public void testHasPrimary() throws Exception { @@ -95,6 +107,29 @@ public class UserManagerTest extends AndroidTestCase { assertFalse(findUser(userInfo.id)); } + public void testAddGuest() throws Exception { + UserInfo userInfo1 = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST); + UserInfo userInfo2 = mUserManager.createUser("Guest 2", UserInfo.FLAG_GUEST); + assertNotNull(userInfo1); + assertNull(userInfo2); + + // Cleanup + removeUser(userInfo1.id); + } + + // Make sure only one managed profile can be created + public void testAddManagedProfile() throws Exception { + UserInfo userInfo1 = mUserManager.createProfileForUser("Managed 1", + UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER); + UserInfo userInfo2 = mUserManager.createProfileForUser("Managed 2", + UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER); + assertNotNull(userInfo1); + assertNull(userInfo2); + + // Cleanup + removeUser(userInfo1.id); + } + private boolean findUser(int id) { List<UserInfo> list = mUserManager.getUsers(); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java index f0ecafe..cc0d8df 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java @@ -130,8 +130,8 @@ public class DatabaseHelper extends SQLiteOpenHelper { synchronized(this) { SQLiteDatabase db = getWritableDatabase(); - String soundModelClause = SoundModelContract.KEY_MODEL_UUID + "=" - + modelUuid.toString(); + String soundModelClause = SoundModelContract.KEY_MODEL_UUID + "='" + + modelUuid.toString() + "'"; try { return db.delete(SoundModelContract.TABLE, soundModelClause, null) != 0; |