UserDataPreparer.java revision 5c0ecfdb37b082bd6bd490270193b676ecb481c2
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.server.pm; 18 19import android.content.Context; 20import android.os.Environment; 21import android.os.FileUtils; 22import android.os.storage.StorageManager; 23import android.os.storage.VolumeInfo; 24import android.util.Log; 25 26import java.util.Objects; 27 28import static com.android.server.pm.PackageManagerService.logCriticalInfo; 29 30/** 31 * Helper class for preparing and destroying user storage 32 */ 33class UserDataPreparer { 34 private final Object mInstallLock; 35 private final Context mContext; 36 private final boolean mOnlyCore; 37 private final Installer mInstaller; 38 39 UserDataPreparer(Installer installer, Object installLock, Context context, boolean onlyCore) { 40 mInstallLock = installLock; 41 mContext = context; 42 mOnlyCore = onlyCore; 43 mInstaller = installer; 44 } 45 46 /** 47 * Prepare storage areas for given user on all mounted devices. 48 */ 49 void prepareUserData(int userId, int userSerial, int flags) { 50 synchronized (mInstallLock) { 51 final StorageManager storage = mContext.getSystemService(StorageManager.class); 52 for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { 53 final String volumeUuid = vol.getFsUuid(); 54 prepareUserDataLI(volumeUuid, userId, userSerial, flags, true); 55 } 56 } 57 } 58 59 private void prepareUserDataLI(String volumeUuid, int userId, int userSerial, int flags, 60 boolean allowRecover) { 61 // Prepare storage and verify that serial numbers are consistent; if 62 // there's a mismatch we need to destroy to avoid leaking data 63 final StorageManager storage = mContext.getSystemService(StorageManager.class); 64 try { 65 storage.prepareUserStorage(volumeUuid, userId, userSerial, flags); 66 67 if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && !mOnlyCore) { 68 UserManagerService.enforceSerialNumber( 69 Environment.getDataUserDeDirectory(volumeUuid, userId), userSerial); 70 if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) { 71 UserManagerService.enforceSerialNumber( 72 Environment.getDataSystemDeDirectory(userId), userSerial); 73 } 74 } 75 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && !mOnlyCore) { 76 UserManagerService.enforceSerialNumber( 77 Environment.getDataUserCeDirectory(volumeUuid, userId), userSerial); 78 if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) { 79 UserManagerService.enforceSerialNumber( 80 Environment.getDataSystemCeDirectory(userId), userSerial); 81 } 82 } 83 84 mInstaller.createUserData(volumeUuid, userId, userSerial, flags); 85 } catch (Exception e) { 86 logCriticalInfo(Log.WARN, "Destroying user " + userId + " on volume " + volumeUuid 87 + " because we failed to prepare: " + e); 88 destroyUserDataLI(volumeUuid, userId, 89 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); 90 91 if (allowRecover) { 92 // Try one last time; if we fail again we're really in trouble 93 prepareUserDataLI(volumeUuid, userId, userSerial, flags, false); 94 } 95 } 96 } 97 98 /** 99 * Destroy storage areas for given user on all mounted devices. 100 */ 101 void destroyUserData(int userId, int flags) { 102 synchronized (mInstallLock) { 103 final StorageManager storage = mContext.getSystemService(StorageManager.class); 104 for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { 105 final String volumeUuid = vol.getFsUuid(); 106 destroyUserDataLI(volumeUuid, userId, flags); 107 } 108 } 109 } 110 111 void destroyUserDataLI(String volumeUuid, int userId, int flags) { 112 final StorageManager storage = mContext.getSystemService(StorageManager.class); 113 try { 114 // Clean up app data, profile data, and media data 115 mInstaller.destroyUserData(volumeUuid, userId, flags); 116 117 // Clean up system data 118 if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) { 119 if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) { 120 FileUtils.deleteContentsAndDir(Environment.getUserSystemDirectory(userId)); 121 FileUtils.deleteContentsAndDir(Environment.getDataSystemDeDirectory(userId)); 122 FileUtils.deleteContentsAndDir(Environment.getDataMiscDeDirectory(userId)); 123 } 124 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { 125 FileUtils.deleteContentsAndDir(Environment.getDataSystemCeDirectory(userId)); 126 FileUtils.deleteContentsAndDir(Environment.getDataMiscCeDirectory(userId)); 127 } 128 } 129 130 // Data with special labels is now gone, so finish the job 131 storage.destroyUserStorage(volumeUuid, userId, flags); 132 133 } catch (Exception e) { 134 logCriticalInfo(Log.WARN, 135 "Failed to destroy user " + userId + " on volume " + volumeUuid + ": " + e); 136 } 137 } 138 139} 140