Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba94170a authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Some clean up of app install and user management." into jb-mr1-dev

parents f3db7179 4428e17c
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -331,13 +331,17 @@ public abstract class RegisteredServicesCache<V> {
                notifyListener(v1, true /* removed */);
            }
            if (changes.length() > 0) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
                            serviceInfos.size() + " services:\n" + changes);
                }
                writePersistentServicesLocked();
            } else {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
                            serviceInfos.size() + " services unchanged");
                }
            }
            mPersistentServicesFileDidNotExist = false;
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -197,7 +197,7 @@ class ServerThread extends Thread {
            
            Slog.i(TAG, "User Service");
            ServiceManager.addService(Context.USER_SERVICE,
                    UserManagerService.getInstance(context));
                    UserManagerService.getInstance());


            mContentResolver = context.getContentResolver();
+91 −54
Original line number Diff line number Diff line
@@ -950,8 +950,8 @@ public class PackageManagerService extends IPackageManager.Stub {
            mUserAppDataDir = new File(dataDir, "user");
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");

            sUserManager = UserManagerService.getInstance(context);
            sUserManager.setInstaller(this, mInstaller);
            sUserManager = new UserManagerService(context, this,
                    mInstallLock, mPackages);

            readPermissions();

@@ -1145,8 +1145,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                        String msg = "System package " + ps.name
                                + " no longer exists; wiping its data";
                        reportSettingsProblem(Log.WARN, msg);
                        mInstaller.remove(ps.name, 0);
                        sUserManager.removePackageForAllUsers(ps.name);
                        removeDataDirsLI(ps.name);
                    } else {
                        final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
@@ -1195,9 +1194,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                    if (deletedPkg == null) {
                        msg = "Updated system package " + deletedAppName
                                + " no longer exists; wiping its data";

                        mInstaller.remove(deletedAppName, 0);
                        sUserManager.removePackageForAllUsers(deletedAppName);
                        removeDataDirsLI(deletedAppName);
                    } else {
                        msg = "Updated system app + " + deletedAppName
                                + " no longer present; removing system privileges for "
@@ -1332,13 +1329,7 @@ public class PackageManagerService extends IPackageManager.Stub {

    void cleanupInstallFailedPackage(PackageSetting ps) {
        Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
        int retCode = mInstaller.remove(ps.name, 0);
        if (retCode < 0) {
            Slog.w(TAG, "Couldn't remove app data directory for package: "
                       + ps.name + ", retcode=" + retCode);
        } else {
            sUserManager.removePackageForAllUsers(ps.name);
        }
        removeDataDirsLI(ps.name);
        if (ps.codePath != null) {
            if (!ps.codePath.delete()) {
                Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
@@ -1818,10 +1809,12 @@ public class PackageManagerService extends IPackageManager.Stub {
            public void run() {
                mHandler.removeCallbacks(this);
                int retCode = -1;
                synchronized (mInstallLock) {
                    retCode = mInstaller.freeCache(freeStorageSize);
                    if (retCode < 0) {
                        Slog.w(TAG, "Couldn't clear application caches");
                    }
                }
                if (observer != null) {
                    try {
                        observer.onRemoveCompleted(null, (retCode >= 0));
@@ -1841,10 +1834,12 @@ public class PackageManagerService extends IPackageManager.Stub {
            public void run() {
                mHandler.removeCallbacks(this);
                int retCode = -1;
                synchronized (mInstallLock) {
                    retCode = mInstaller.freeCache(freeStorageSize);
                    if (retCode < 0) {
                        Slog.w(TAG, "Couldn't clear application caches");
                    }
                }
                if(pi != null) {
                    try {
                        // Callback via pending intent
@@ -2994,10 +2989,12 @@ public class PackageManagerService extends IPackageManager.Stub {
                    }
                    ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
                            ps.readUserState(userId), userId);
                    if (info != null) {
                        finalList.add(info);
                    }
                }
            }
        }

        if (finalList != null) {
            Collections.sort(finalList, mProviderInitOrderSorter);
@@ -3027,8 +3024,11 @@ public class PackageManagerService extends IPackageManager.Stub {
                final PackageParser.Instrumentation p = i.next();
                if (targetPackage == null
                        || targetPackage.equals(p.info.targetPackage)) {
                    finalList.add(PackageParser.generateInstrumentationInfo(p,
                            flags));
                    InstrumentationInfo ii = PackageParser.generateInstrumentationInfo(p,
                            flags);
                    if (ii != null) {
                        finalList.add(ii);
                    }
                }
            }
        }
@@ -3189,7 +3189,7 @@ public class PackageManagerService extends IPackageManager.Stub {

                    InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
                            ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
                    synchronized (mInstaller) {
                    synchronized (mInstallLock) {
                        args.cleanUpResourcesLI();
                    }
                    synchronized (mPackages) {
@@ -3245,7 +3245,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                            + " better than installed " + ps.versionCode);
                    InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
                            ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
                    synchronized (mInstaller) {
                    synchronized (mInstallLock) {
                        args.cleanUpResourcesLI();
                    }
                }
@@ -3479,6 +3479,36 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
    }

    private int createDataDirsLI(String packageName, int uid) {
        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 res;
    }

    private int removeDataDirsLI(String packageName) {
        int[] users = sUserManager.getUserIds();
        int res = 0;
        for (int user : users) {
            int resInner = mInstaller.remove(packageName, user);
            if (resInner < 0) {
                res = resInner;
            }
        }
        return res;
    }

    private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
            int parseFlags, int scanMode, long currentTime, UserHandle user) {
        File scanFile = new File(pkg.mScanPath);
@@ -3831,11 +3861,9 @@ public class PackageManagerService extends IPackageManager.Stub {
                            || (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 = mInstaller.remove(pkgName, 0);
                        int ret = removeDataDirsLI(pkgName);
                        if (ret >= 0) {
                            // TODO: Kill the processes first
                            // Remove the data directories for all users
                            sUserManager.removePackageForAllUsers(pkgName);
                            // Old data gone!
                            String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
                                    ? "System package " : "Third party package ";
@@ -3847,8 +3875,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                            recovered = true;

                            // And now re-install the app.
                            ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
                                    pkg.applicationInfo.uid);
                            ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
                            if (ret == -1) {
                                // Ack should not happen!
                                msg = prefix + pkg.packageName
@@ -3857,9 +3884,6 @@ public class PackageManagerService extends IPackageManager.Stub {
                                mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                                return null;
                            }
                            // Create data directories for all users
                            sUserManager.installPackageForAllUsers(pkgName,
                                    pkg.applicationInfo.uid);
                        }
                        if (!recovered) {
                            mHasSystemUidErrors = true;
@@ -3897,15 +3921,12 @@ public class PackageManagerService extends IPackageManager.Stub {
                        Log.v(TAG, "Want this data dir: " + dataPath);
                }
                //invoke installer to do the actual installation
                int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
                        pkg.applicationInfo.uid);
                int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
                if (ret < 0) {
                    // Error from installer
                    mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                    return null;
                }
                // Create data directories for all users
                sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);

                if (dataPath.exists()) {
                    pkg.applicationInfo.dataDir = dataPath.getPath();
@@ -5078,6 +5099,9 @@ public class PackageManagerService extends IPackageManager.Stub {
            }
            ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
                    ps.readUserState(userId), userId);
            if (si == null) {
                return null;
            }
            final ResolveInfo res = new ResolveInfo();
            res.serviceInfo = si;
            if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
@@ -7819,15 +7843,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            }
        }
        if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
            int retCode = mInstaller.remove(packageName, 0);
            if (retCode < 0) {
                Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
                           + packageName + ", retcode=" + retCode);
                // we don't consider this to be a failure of the core package deletion
            } else {
                // TODO: Kill the processes first
                sUserManager.removePackageForAllUsers(packageName);
            }
            removeDataDirsLI(packageName);
            schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
        }
        // writer
@@ -9742,15 +9758,36 @@ public class PackageManagerService extends IPackageManager.Stub {
    }

    /** Called by UserManagerService */
    void cleanUpUser(int userHandle) {
    void cleanUpUserLILPw(int userHandle) {
        // Disable all the packages for the user first
        synchronized (mPackages) {
        Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
        for (Entry<String, PackageSetting> entry : entries) {
            entry.getValue().removeUser(userHandle);
        }
        if (mDirtyUsers.remove(userHandle));
        mSettings.removeUserLPr(userHandle);
        if (mInstaller != null) {
            // Technically, we shouldn't be doing this with the package lock
            // held.  However, this is very rare, and there is already so much
            // other disk I/O going on, that we'll let it slide for now.
            mInstaller.removeUserDataDirs(userHandle);
        }
    }

    /** Called by UserManagerService */
    void createNewUserLILPw(int userHandle, File path) {
        if (mInstaller != null) {
            path.mkdir();
            FileUtils.setPermissions(path.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
                    | FileUtils.S_IXOTH, -1, -1);
            for (PackageSetting ps : mSettings.mPackages.values()) {
                // Only system apps are initially installed.
                ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
                // Need to create a data directory for all apps under this user.
                mInstaller.createUserData(ps.name,
                        UserHandle.getUid(userHandle, ps.appId), userHandle);
            }
            mSettings.writePackageRestrictionsLPr(userHandle);
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -2476,7 +2476,7 @@ final class Settings {
    private List<UserInfo> getAllUsers() {
        long id = Binder.clearCallingIdentity();
        try {
            return UserManagerService.getInstance(mContext).getUsers();
            return UserManagerService.getInstance().getUsers();
        } catch (NullPointerException npe) {
            // packagemanager not yet initialized
        } finally {
+92 −127
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import com.android.internal.util.FastXmlSerializer;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Binder;
@@ -34,10 +33,8 @@ import android.os.FileUtils;
import android.os.IUserManager;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
@@ -72,31 +69,59 @@ public class UserManagerService extends IUserManager.Stub {
    private static final String USER_LIST_FILENAME = "userlist.xml";
    private static final String USER_PHOTO_FILENAME = "photo.png";

    private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
    private final Context mContext;
    private final PackageManagerService mPm;
    private final Object mInstallLock;
    private final Object mPackagesLock;

    private final File mUsersDir;
    private final File mUserListFile;
    private final File mBaseUserPath;

    private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();

    private int[] mUserIds;
    private boolean mGuestEnabled;
    private int mNextSerialNumber;

    private Installer mInstaller;
    private File mBaseUserPath;
    private Context mContext;
    private static UserManagerService sInstance;
    private PackageManagerService mPm;

    public synchronized static UserManagerService getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new UserManagerService(context);
        }
    public static UserManagerService getInstance() {
        synchronized (UserManagerService.class) {
            return sInstance;
        }
    }

    /**
     * Available for testing purposes.
     */
    UserManagerService(File dataDir, File baseUserPath) {
        this(null, null, new Object(), new Object(), dataDir, baseUserPath);
    }

    /**
     * Called by package manager to create the service.  This is closely
     * associated with the package manager, and the given lock is the
     * package manager's own lock.
     */
    UserManagerService(Context context, PackageManagerService pm,
            Object installLock, Object packagesLock) {
        this(context, pm, installLock, packagesLock,
                Environment.getDataDirectory(),
                new File(Environment.getDataDirectory(), "user"));
    }

    /**
     * Available for testing purposes.
     */
    private UserManagerService(Context context, PackageManagerService pm,
            Object installLock, Object packagesLock,
            File dataDir, File baseUserPath) {
        synchronized (UserManagerService.class) {
            mContext = context;
            mPm = pm;
            mInstallLock = installLock;
            mPackagesLock = packagesLock;
            mUsersDir = new File(dataDir, USER_INFO_DIR);
            mUsersDir.mkdirs();
            // Make zeroth user directory, for services to migrate their files to that location
@@ -109,22 +134,14 @@ public class UserManagerService extends IUserManager.Stub {
                    -1, -1);
            mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
            readUserList();
            sInstance = this;
        }

    public UserManagerService(Context context) {
        this(Environment.getDataDirectory(), new File(Environment.getDataDirectory(), "user"));
        mContext = context;
    }

    void setInstaller(PackageManagerService pm, Installer installer) {
        mInstaller = installer;
        mPm = pm;
    }

    @Override
    public List<UserInfo> getUsers() {
        checkManageUsersPermission("query users");
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
            for (int i = 0; i < mUsers.size(); i++) {
                users.add(mUsers.valueAt(i));
@@ -136,7 +153,7 @@ public class UserManagerService extends IUserManager.Stub {
    @Override
    public UserInfo getUserInfo(int userId) {
        checkManageUsersPermission("query user");
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            return getUserInfoLocked(userId);
        }
    }
@@ -149,7 +166,7 @@ public class UserManagerService extends IUserManager.Stub {
    }

    public boolean exists(int userId) {
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            return ArrayUtils.contains(mUserIds, userId);
        }
    }
@@ -157,7 +174,7 @@ public class UserManagerService extends IUserManager.Stub {
    @Override
    public void setUserName(int userId, String name) {
        checkManageUsersPermission("rename users");
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            UserInfo info = mUsers.get(userId);
            if (name != null && !name.equals(info.name)) {
                info.name = name;
@@ -169,7 +186,7 @@ public class UserManagerService extends IUserManager.Stub {
    @Override
    public ParcelFileDescriptor setUserIcon(int userId) {
        checkManageUsersPermission("update users");
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            UserInfo info = mUsers.get(userId);
            if (info == null) return null;
            ParcelFileDescriptor fd = updateIconBitmapLocked(info);
@@ -183,7 +200,7 @@ public class UserManagerService extends IUserManager.Stub {
    @Override
    public void setGuestEnabled(boolean enable) {
        checkManageUsersPermission("enable guest users");
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            if (mGuestEnabled != enable) {
                mGuestEnabled = enable;
                // Erase any guest user that currently exists
@@ -206,7 +223,7 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public boolean isGuestEnabled() {
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            return mGuestEnabled;
        }
    }
@@ -262,13 +279,17 @@ public class UserManagerService extends IUserManager.Stub {
     * @return the array of user ids.
     */
    int[] getUserIds() {
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            return mUserIds;
        }
    }

    int[] getUserIdsLPr() {
        return mUserIds;
    }

    private void readUserList() {
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            readUserListLocked();
        }
    }
@@ -501,15 +522,15 @@ public class UserManagerService extends IUserManager.Stub {
        int userId = getNextAvailableId();
        UserInfo userInfo = new UserInfo(userId, name, null, flags);
        File userPath = new File(mBaseUserPath, Integer.toString(userId));
        if (!createPackageFolders(userId, userPath)) {
            return null;
        }
        synchronized (mUsers) {
        synchronized (mInstallLock) {
            synchronized (mPackagesLock) {
                userInfo.serialNumber = mNextSerialNumber++;
                mUsers.put(userId, userInfo);
                writeUserListLocked();
                writeUserLocked(userInfo);
                updateUserIdsLocked();
                mPm.createNewUserLILPw(userId, userPath);
            }
        }
        if (userInfo != null) {
            Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
@@ -528,24 +549,37 @@ public class UserManagerService extends IUserManager.Stub {
     */
    public boolean removeUser(int userHandle) {
        checkManageUsersPermission("Only the system can remove users");
        boolean result;
        synchronized (mUsers) {
            result = removeUserLocked(userHandle);
        synchronized (mInstallLock) {
            synchronized (mPackagesLock) {
                final UserInfo user = mUsers.get(userHandle);
                if (userHandle == 0 || user == null) {
                    return false;
                }

                // Cleanup package manager settings
        mPm.cleanUpUser(userHandle);
                mPm.cleanUpUserLILPw(userHandle);

                // Remove this user from the list
                mUsers.remove(userHandle);
                // Remove user file
                AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
                userFile.delete();
                // Update the user list
                writeUserListLocked();
                updateUserIdsLocked();
            }
        }

        // Let other services shutdown any activity
        Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
        mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
        return result;
        return true;
    }

    @Override
    public int getUserSerialNumber(int userHandle) {
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            if (!exists(userHandle)) return -1;
            return getUserInfoLocked(userHandle).serialNumber;
        }
@@ -553,7 +587,7 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public int getUserHandle(int userSerialNumber) {
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            for (int userId : mUserIds) {
                if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId;
            }
@@ -562,53 +596,6 @@ public class UserManagerService extends IUserManager.Stub {
        }
    }

    private boolean removeUserLocked(int userHandle) {
        final UserInfo user = mUsers.get(userHandle);
        if (userHandle == 0 || user == null) {
            return false;
        }

        // Remove this user from the list
        mUsers.remove(userHandle);
        // Remove user file
        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
        userFile.delete();
        // Update the user list
        writeUserListLocked();
        updateUserIdsLocked();

        removePackageFolders(userHandle);
        return true;
    }

    public void installPackageForAllUsers(String packageName, int uid) {
        for (int userId : mUserIds) {
            // Don't do it for the primary user, it will become recursive.
            if (userId == 0)
                continue;
            mInstaller.createUserData(packageName, UserHandle.getUid(userId, uid),
                    userId);
        }
    }

    public void clearUserDataForAllUsers(String packageName) {
        for (int userId : mUserIds) {
            // Don't do it for the primary user, it will become recursive.
            if (userId == 0)
                continue;
            mInstaller.clearUserData(packageName, userId);
        }
    }

    public void removePackageForAllUsers(String packageName) {
        for (int userId : mUserIds) {
            // Don't do it for the primary user, it will become recursive.
            if (userId == 0)
                continue;
            mInstaller.remove(packageName, userId);
        }
    }

    /**
     * Caches the list of user ids in an array, adjusting the array size when necessary.
     */
@@ -627,7 +614,7 @@ public class UserManagerService extends IUserManager.Stub {
     * @return
     */
    private int getNextAvailableId() {
        synchronized (mUsers) {
        synchronized (mPackagesLock) {
            int i = 0;
            while (i < Integer.MAX_VALUE) {
                if (mUsers.indexOfKey(i) < 0) {
@@ -638,26 +625,4 @@ public class UserManagerService extends IUserManager.Stub {
            return i;
        }
    }

    private boolean createPackageFolders(int id, File userPath) {
        // mInstaller may not be available for unit-tests.
        if (mInstaller == null) return true;

        // Create the user path
        userPath.mkdir();
        FileUtils.setPermissions(userPath.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
                | FileUtils.S_IXOTH, -1, -1);

        mInstaller.cloneUserData(0, id, false);

        return true;
    }

    boolean removePackageFolders(int id) {
        // mInstaller may not be available for unit-tests.
        if (mInstaller == null) return true;

        mInstaller.removeUserDataDirs(id);
        return true;
    }
}