diff options
Diffstat (limited to 'services/java')
5 files changed, 193 insertions, 160 deletions
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java index 079f723..6ff33d7 100755 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/java/com/android/server/BluetoothManagerService.java @@ -1,5 +1,17 @@ /* - * Copyright (C) 2012 Google Inc. + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.android.server; diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index b9f5b5b..749dc66 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -602,6 +602,15 @@ final class ActivityRecord { } } + void updateOptionsLocked(ActivityOptions options) { + if (options != null) { + if (pendingOptions != null) { + pendingOptions.abort(); + } + pendingOptions = options; + } + } + void applyOptionsLocked() { if (pendingOptions != null) { final int animationType = pendingOptions.getAnimationType(); @@ -653,6 +662,12 @@ final class ActivityRecord { } } + ActivityOptions takeOptionsLocked() { + ActivityOptions opts = pendingOptions; + pendingOptions = null; + return opts; + } + void removeUriPermissionsLocked() { if (uriPermissions != null) { uriPermissions.removeUriPermissionsLocked(); diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 4bcb339..4546dc3 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1963,6 +1963,8 @@ final class ActivityStack { int taskTopI = -1; int replyChainEnd = -1; int lastReparentPos = -1; + ActivityOptions topOptions = null; + boolean canMoveOptions = true; for (int i=mHistory.size()-1; i>=-1; i--) { ActivityRecord below = i >= 0 ? mHistory.get(i) : null; @@ -2048,6 +2050,7 @@ final class ActivityStack { } int dstPos = 0; ThumbnailHolder curThumbHolder = target.thumbHolder; + boolean gotOptions = !canMoveOptions; for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) { p = mHistory.get(srcPos); if (p.finishing) { @@ -2057,6 +2060,13 @@ final class ActivityStack { + " out to target's task " + target.task); p.setTask(target.task, curThumbHolder, false); curThumbHolder = p.thumbHolder; + canMoveOptions = false; + if (!gotOptions && topOptions == null) { + topOptions = p.takeOptionsLocked(); + if (topOptions != null) { + gotOptions = true; + } + } if (DEBUG_ADD_REMOVE) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); @@ -2101,11 +2111,19 @@ final class ActivityStack { replyChainEnd = targetI; } ActivityRecord p = null; + boolean gotOptions = !canMoveOptions; for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) { p = mHistory.get(srcPos); if (p.finishing) { continue; } + canMoveOptions = false; + if (!gotOptions && topOptions == null) { + topOptions = p.takeOptionsLocked(); + if (topOptions != null) { + gotOptions = true; + } + } if (finishActivityLocked(p, srcPos, Activity.RESULT_CANCELED, null, "reset", false)) { replyChainEnd--; @@ -2245,7 +2263,17 @@ final class ActivityStack { target = below; targetI = i; } - + + if (topOptions != null) { + // If we got some ActivityOptions from an activity on top that + // was removed from the task, propagate them to the new real top. + if (taskTop != null) { + taskTop.updateOptionsLocked(topOptions); + } else { + topOptions.abort(); + } + } + return taskTop; } @@ -2296,6 +2324,10 @@ final class ActivityStack { if (r.finishing) { continue; } + ActivityOptions opts = r.takeOptionsLocked(); + if (opts != null) { + ret.updateOptionsLocked(opts); + } if (finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "clear", false)) { i--; diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java index 0247911..71a6a01 100644 --- a/services/java/com/android/server/pm/Installer.java +++ b/services/java/com/android/server/pm/Installer.java @@ -243,14 +243,14 @@ public final class Installer { return execute(builder.toString()); } - public int fixUid(String name, int uid, int userId) { + public int fixUid(String name, int uid, int gid) { StringBuilder builder = new StringBuilder("fixuid"); builder.append(' '); builder.append(name); builder.append(' '); builder.append(uid); builder.append(' '); - builder.append(userId); + builder.append(gid); return execute(builder.toString()); } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 9e2ad8e..6ef39ac 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -1008,8 +1008,6 @@ public class PackageManagerService extends IPackageManager.Stub { mHandler = new PackageHandler(mHandlerThread.getLooper()); File dataDir = Environment.getDataDirectory(); - mAppInstallDir = new File(dataDir, "app"); - mAppLibInstallDir = new File(dataDir, "app-lib"); mAppDataDir = new File(dataDir, "data"); mAsecInternalPath = new File(dataDir, "app-asec").getPath(); mUserAppDataDir = new File(dataDir, "user"); @@ -1220,6 +1218,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } + mAppInstallDir = new File(dataDir, "app"); + mAppLibInstallDir = new File(dataDir, "app-lib"); //look for any incomplete package installations ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr(); //clean up list @@ -3577,22 +3577,22 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private int createDataDirForUserLI(String packageName, int uid, int userId) { - if (userId == 0) { - return mInstaller.install(packageName, uid, uid); - } else { - return mInstaller.createUserData(packageName, UserHandle.getUid(userId, uid), userId); - } - } - private int createDataDirsLI(String packageName, int uid) { - for (int userId : sUserManager.getUserIds()) { - int res = createDataDirForUserLI(packageName, uid, userId); - if (res < 0) { - return res; + int[] users = sUserManager.getUserIds(); + int res = mInstaller.install(packageName, uid, uid); + if (res < 0) { + return res; + } + for (int user : users) { + if (user != 0) { + res = mInstaller.createUserData(packageName, + UserHandle.getUid(user, uid), user); + if (res < 0) { + return res; + } } } - return 0; + return res; } private int removeDataDirsLI(String packageName) { @@ -3931,49 +3931,134 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { // This is a normal package, need to make its data directory. - dataPath = getDataPathForPackage(pkg.packageName, UserHandle.USER_OWNER); + dataPath = getDataPathForPackage(pkg.packageName, 0); - if (!ensureDataDirExistsForAllUsers(pkg.packageName, pkg.applicationInfo.uid)) { - if (DEBUG_PACKAGE_SCANNING) { - if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) { - Log.v(TAG, "Want this data dir: " + dataPath); + boolean uidError = false; + + if (dataPath.exists()) { + int currentUid = 0; + try { + StructStat stat = Libcore.os.stat(dataPath.getPath()); + currentUid = stat.st_uid; + } catch (ErrnoException e) { + Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); + } + + // If we have mismatched owners for the data path, we have a problem. + if (currentUid != pkg.applicationInfo.uid) { + boolean recovered = false; + if (currentUid == 0) { + // The directory somehow became owned by root. Wow. + // This is probably because the system was stopped while + // installd was in the middle of messing with its libs + // directory. Ask installd to fix that. + int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid, + pkg.applicationInfo.uid); + if (ret >= 0) { + recovered = true; + String msg = "Package " + pkg.packageName + + " unexpectedly changed to uid 0; recovered to " + + + pkg.applicationInfo.uid; + reportSettingsProblem(Log.WARN, msg); + } + } + if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0 + || (scanMode&SCAN_BOOTING) != 0)) { + // If this is a system app, we can at least delete its + // current data so the application will still work. + int ret = removeDataDirsLI(pkgName); + if (ret >= 0) { + // TODO: Kill the processes first + // Old data gone! + String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0 + ? "System package " : "Third party package "; + String msg = prefix + pkg.packageName + + " has changed from uid: " + + currentUid + " to " + + pkg.applicationInfo.uid + "; old data erased"; + reportSettingsProblem(Log.WARN, msg); + recovered = true; + + // And now re-install the app. + ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); + if (ret == -1) { + // Ack should not happen! + msg = prefix + pkg.packageName + + " could not have data directory re-created after delete."; + reportSettingsProblem(Log.WARN, msg); + mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; + return null; + } + } + if (!recovered) { + mHasSystemUidErrors = true; + } + } else if (!recovered) { + // If we allow this install to proceed, we will be broken. + // Abort, abort! + mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED; + return null; + } + if (!recovered) { + pkg.applicationInfo.dataDir = "/mismatched_uid/settings_" + + pkg.applicationInfo.uid + "/fs_" + + currentUid; + pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir; + String msg = "Package " + pkg.packageName + + " has mismatched uid: " + + currentUid + " on disk, " + + pkg.applicationInfo.uid + " in settings"; + // writer + synchronized (mPackages) { + mSettings.mReadMessages.append(msg); + mSettings.mReadMessages.append('\n'); + uidError = true; + if (!pkgSetting.uidError) { + reportSettingsProblem(Log.ERROR, msg); + } + } } } - - // Error from installer - mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; - return null; - } else { pkg.applicationInfo.dataDir = dataPath.getPath(); - } - - final boolean isSystemApp = (parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0; - final boolean isBootScan = (scanMode & SCAN_BOOTING) != 0; + } else { + if (DEBUG_PACKAGE_SCANNING) { + if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) + Log.v(TAG, "Want this data dir: " + dataPath); + } + //invoke installer to do the actual installation + int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); + if (ret < 0) { + // Error from installer + mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; + return null; + } - final boolean uidCorrect = ensureDataDirUidIsCorrectForAllUsers(pkg.packageName, - pkg.applicationInfo.uid, isSystemApp, isBootScan); - if (!uidCorrect) { - pkg.applicationInfo.dataDir = "/mismatched_uid/settings_" + pkg.applicationInfo.uid - + "/fs_mismatched"; - pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir; + if (dataPath.exists()) { + pkg.applicationInfo.dataDir = dataPath.getPath(); + } else { + Slog.w(TAG, "Unable to create data directory: " + dataPath); + pkg.applicationInfo.dataDir = null; + } } - pkgSetting.uidError = !uidCorrect; - /* - * Set the native library dir to the default if we got here without - * anyone telling us different (e.g., apps stored on SD card have - * their native libraries stored in the ASEC container with the - * APK). This happens during an upgrade from a package settings file - * that doesn't have a native library path attribute at all. + * Set the data dir to the default "/data/data/<package name>/lib" + * if we got here without anyone telling us different (e.g., apps + * stored on SD card have their native libraries stored in the ASEC + * container with the APK). + * + * This happens during an upgrade from a package settings file that + * doesn't have a native library path attribute at all. */ - if (pkg.applicationInfo.nativeLibraryDir == null) { + if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) { if (pkgSetting.nativeLibraryPathString == null) { setInternalAppNativeLibraryPath(pkg, pkgSetting); } else { pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; } } + + pkgSetting.uidError = uidError; } String path = scanFile.getPath(); @@ -4362,100 +4447,6 @@ public class PackageManagerService extends IPackageManager.Stub { return pkg; } - /** - * Checks to see whether a package data directory is owned by the correct - * user. If it isn't, it will attempt to fix it if it's a system application - * or if this is the boot scan. - * - * @return {@code true} if successful, {@code false} if recovery failed - */ - private boolean ensureDataDirUidIsCorrectForAllUsers(String packageName, int appUid, - boolean isSystemApp, boolean isBootScan) { - boolean mismatch = false; - - for (int userId : sUserManager.getUserIds()) { - final File dataPath = getDataPathForPackage(packageName, userId); - - int currentUid = 0; - try { - final StructStat stat = Libcore.os.stat(dataPath.getPath()); - currentUid = stat.st_uid; - } catch (ErrnoException e) { - Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); - } - - final int expectedUid = UserHandle.getUid(userId, appUid); - - // If we have mismatched owners for the data path, we have a - // problem. - if (currentUid != expectedUid) { - if (currentUid == 0) { - // The directory somehow became owned by root. Wow. - // This is probably because the system was stopped while - // installd was in the middle of messing with its libs - // directory. Ask installd to fix that. - final int ret; - synchronized (mInstaller) { - ret = mInstaller.fixUid(packageName, expectedUid, userId); - } - if (ret >= 0) { - String msg = "Package " + packageName - + " unexpectedly changed to uid 0; recovered to " + expectedUid; - reportSettingsProblem(Log.WARN, msg); - } else { - mismatch = true; - String prefix = isSystemApp ? "System package " : "Third party package "; - String msg = prefix + packageName + " has changed from uid: " + currentUid - + " to " + expectedUid; - reportSettingsProblem(Log.WARN, msg); - } - } - } - } - - if (mismatch) { - if (isSystemApp || isBootScan) { - // If this is a system app, we can at least delete its - // current data so the application will still work. - int ret; - synchronized (mInstallLock) { - ret = removeDataDirsLI(packageName); - } - if (ret >= 0) { - // TODO: Kill the processes first - // Old data gone! - String prefix = isSystemApp - ? "System package " : "Third party package "; - String msg = prefix + packageName + " old data erased"; - reportSettingsProblem(Log.WARN, msg); - - // And now re-install the app. - synchronized (mInstallLock) { - ret = createDataDirsLI(packageName, appUid); - } - if (ret == -1) { - // Ack should not happen! - msg = prefix + packageName - + " could not have data directory re-created after delete."; - reportSettingsProblem(Log.WARN, msg); - mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; - return false; - } - } else { - mHasSystemUidErrors = true; - return false; - } - } else { - // If we allow this install to proceed, we will be broken. - // Abort, abort! - mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED; - return false; - } - } - - return true; - } - private void setInternalAppNativeLibraryPath(PackageParser.Package pkg, PackageSetting pkgSetting) { final String apkLibPath = getApkName(pkgSetting.codePathString); @@ -7512,22 +7503,6 @@ public class PackageManagerService extends IPackageManager.Stub { PackageRemovedInfo removedInfo; } - private boolean ensureDataDirExistsForAllUsers(String packageName, int uid) { - boolean exists = true; - for (int userId : sUserManager.getUserIds()) { - final File dataPath = getDataPathForPackage(packageName, userId); - if (!dataPath.exists()) { - synchronized (mInstallLock) { - if (createDataDirForUserLI(packageName, uid, userId) < 0) { - Slog.e(TAG, "Couldn't create data path " + dataPath.getPath()); - } - } - exists &= dataPath.exists(); - } - } - return exists; - } - /* * Install a non-existing package. */ @@ -7537,8 +7512,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Remember this for later, in case we need to rollback this install String pkgName = pkg.packageName; - boolean dataDirExists = ensureDataDirExistsForAllUsers(pkg.packageName, - pkg.applicationInfo.uid); + boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists(); synchronized(mPackages) { if (mSettings.mRenamedPackages.containsKey(pkgName)) { // A package with the same name is already installed, though @@ -8291,7 +8265,7 @@ public class PackageManagerService extends IPackageManager.Stub { removePackageDataLI(ps, outInfo, flags, writeSettings); // Delete application code and resources - if (deleteCodeAndResources) { + if (deleteCodeAndResources && (outInfo != null)) { outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); } |
