Merge "Revert "Revert "Release cblocks back to the free pool""" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
cc265a58de
@@ -6660,6 +6660,20 @@ public final class Settings {
|
|||||||
@Readable
|
@Readable
|
||||||
public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
|
public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not compress blocks should be released on install.
|
||||||
|
* <p>The setting only determines if the platform will attempt to release
|
||||||
|
* compress blocks; it does not guarantee that the files will have their
|
||||||
|
* compress blocks released. Compression is currently only supported on
|
||||||
|
* some f2fs filesystems.
|
||||||
|
* <p>
|
||||||
|
* Type: int (0 for false, 1 for true)
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String RELEASE_COMPRESS_BLOCKS_ON_INSTALL =
|
||||||
|
"release_compress_blocks_on_install";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of input methods that are currently enabled. This is a string
|
* List of input methods that are currently enabled. This is a string
|
||||||
* containing the IDs of all enabled input methods, each ID separated
|
* containing the IDs of all enabled input methods, each ID separated
|
||||||
|
|||||||
296
core/java/com/android/internal/content/F2fsUtils.java
Normal file
296
core/java/com/android/internal/content/F2fsUtils.java
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.internal.content;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.incremental.IncrementalManager;
|
||||||
|
import android.provider.Settings.Secure;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods to work with the f2fs file system.
|
||||||
|
*/
|
||||||
|
public final class F2fsUtils {
|
||||||
|
private static final String TAG = "F2fsUtils";
|
||||||
|
private static final boolean DEBUG_F2FS = false;
|
||||||
|
|
||||||
|
/** Directory containing kernel features */
|
||||||
|
private static final File sKernelFeatures =
|
||||||
|
new File("/sys/fs/f2fs/features");
|
||||||
|
/** File containing features enabled on "/data" */
|
||||||
|
private static final File sUserDataFeatures =
|
||||||
|
new File("/dev/sys/fs/by-name/userdata/features");
|
||||||
|
private static final File sDataDirectory = Environment.getDataDirectory();
|
||||||
|
/** Name of the compression feature */
|
||||||
|
private static final String COMPRESSION_FEATURE = "compression";
|
||||||
|
|
||||||
|
private static final boolean sKernelCompressionAvailable;
|
||||||
|
private static final boolean sUserDataCompressionAvailable;
|
||||||
|
|
||||||
|
static {
|
||||||
|
sKernelCompressionAvailable = isCompressionEnabledInKernel();
|
||||||
|
if (!sKernelCompressionAvailable) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "f2fs compression DISABLED; feature not part of the kernel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sUserDataCompressionAvailable = isCompressionEnabledOnUserData();
|
||||||
|
if (!sUserDataCompressionAvailable) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "f2fs compression DISABLED; feature not enabled on filesystem");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases compressed blocks from eligible installation artifacts.
|
||||||
|
* <p>
|
||||||
|
* Modern f2fs implementations starting in {@code S} support compression
|
||||||
|
* natively within the file system. The data blocks of specific installation
|
||||||
|
* artifacts [eg. .apk, .so, ...] can be compressed at the file system level,
|
||||||
|
* making them look and act like any other uncompressed file, but consuming
|
||||||
|
* a fraction of the space.
|
||||||
|
* <p>
|
||||||
|
* However, the unused space is not free'd automatically. Instead, we must
|
||||||
|
* manually tell the file system to release the extra blocks [the delta between
|
||||||
|
* the compressed and uncompressed block counts] back to the free pool.
|
||||||
|
* <p>
|
||||||
|
* Because of how compression works within the file system, once the blocks
|
||||||
|
* have been released, the file becomes read-only and cannot be modified until
|
||||||
|
* the free'd blocks have again been reserved from the free pool.
|
||||||
|
*/
|
||||||
|
public static void releaseCompressedBlocks(ContentResolver resolver, File file) {
|
||||||
|
if (!sKernelCompressionAvailable || !sUserDataCompressionAvailable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Retrieving this setting means we need to delay releasing cblocks
|
||||||
|
// of any APKs installed during the PackageManagerService constructor. Instead
|
||||||
|
// of being able to release them in the constructor, they can only be released
|
||||||
|
// immediately prior to the system being available. When we no longer need to
|
||||||
|
// read this setting, move cblock release back to the package manager constructor.
|
||||||
|
final boolean releaseCompressBlocks =
|
||||||
|
Secure.getInt(resolver, Secure.RELEASE_COMPRESS_BLOCKS_ON_INSTALL, 1) != 0;
|
||||||
|
if (!releaseCompressBlocks) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "SKIP; release compress blocks not enabled");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isCompressionAllowed(file)) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "SKIP; compression not allowed");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final File[] files = getFilesToRelease(file);
|
||||||
|
if (files == null || files.length == 0) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "SKIP; no files to compress");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = files.length - 1; i >= 0; --i) {
|
||||||
|
final long releasedBlocks = nativeReleaseCompressedBlocks(files[i].getAbsolutePath());
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "RELEASED " + releasedBlocks + " blocks"
|
||||||
|
+ " from \"" + files[i] + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if compression is allowed on the file system containing
|
||||||
|
* the given file.
|
||||||
|
* <p>
|
||||||
|
* NOTE: The return value does not mean if the given file, or any other file
|
||||||
|
* on the same file system, is actually compressed. It merely determines whether
|
||||||
|
* not files <em>may</em> be compressed.
|
||||||
|
*/
|
||||||
|
private static boolean isCompressionAllowed(@NonNull File file) {
|
||||||
|
final String filePath;
|
||||||
|
try {
|
||||||
|
filePath = file.getCanonicalPath();
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "f2fs compression DISABLED; could not determine path");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (IncrementalManager.isIncrementalPath(filePath)) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "f2fs compression DISABLED; file on incremental fs");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!isChild(sDataDirectory, filePath)) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "f2fs compression DISABLED; file not on /data");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "f2fs compression ENABLED");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the given child is a descendant of the base.
|
||||||
|
*/
|
||||||
|
private static boolean isChild(@NonNull File base, @NonNull String childPath) {
|
||||||
|
try {
|
||||||
|
base = base.getCanonicalFile();
|
||||||
|
|
||||||
|
File parentFile = new File(childPath).getCanonicalFile();
|
||||||
|
while (parentFile != null) {
|
||||||
|
if (base.equals(parentFile)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
parentFile = parentFile.getParentFile();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the compression feature is enabled in the kernel.
|
||||||
|
* <p>
|
||||||
|
* NOTE: This doesn't mean compression is enabled on a particular file system
|
||||||
|
* or any files have been compressed. Only that the functionality is enabled
|
||||||
|
* on the device.
|
||||||
|
*/
|
||||||
|
private static boolean isCompressionEnabledInKernel() {
|
||||||
|
final File[] features = sKernelFeatures.listFiles();
|
||||||
|
if (features == null || features.length == 0) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "ERROR; no kernel features");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = features.length - 1; i >= 0; --i) {
|
||||||
|
final File feature = features[i];
|
||||||
|
if (COMPRESSION_FEATURE.equals(features[i].getName())) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "FOUND kernel compression feature");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "ERROR; kernel compression feature not found");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the compression feature is enabled on user data [ie. "/data"].
|
||||||
|
* <p>
|
||||||
|
* NOTE: This doesn't mean any files have been compressed. Only that the functionality
|
||||||
|
* is enabled on the file system.
|
||||||
|
*/
|
||||||
|
private static boolean isCompressionEnabledOnUserData() {
|
||||||
|
if (!sUserDataFeatures.exists()
|
||||||
|
|| !sUserDataFeatures.isFile()
|
||||||
|
|| !sUserDataFeatures.canRead()) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "ERROR; filesystem features not available");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final List<String> configLines;
|
||||||
|
try {
|
||||||
|
configLines = Files.readAllLines(sUserDataFeatures.toPath());
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "ERROR; couldn't read filesystem features");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (configLines == null
|
||||||
|
|| configLines.size() > 1
|
||||||
|
|| TextUtils.isEmpty(configLines.get(0))) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "ERROR; no filesystem features");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final String[] features = configLines.get(0).split(",");
|
||||||
|
for (int i = features.length - 1; i >= 0; --i) {
|
||||||
|
if (COMPRESSION_FEATURE.equals(features[i].trim())) {
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "FOUND filesystem compression feature");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DEBUG_F2FS) {
|
||||||
|
Slog.d(TAG, "ERROR; filesystem compression feature not found");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all files contained within the directory at any depth from the given path.
|
||||||
|
*/
|
||||||
|
private static List<File> getFilesRecursive(@NonNull File path) {
|
||||||
|
final File[] allFiles = path.listFiles();
|
||||||
|
if (allFiles == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final ArrayList<File> files = new ArrayList<>();
|
||||||
|
for (File f : allFiles) {
|
||||||
|
if (f.isDirectory()) {
|
||||||
|
files.addAll(getFilesRecursive(f));
|
||||||
|
} else if (f.isFile()) {
|
||||||
|
files.add(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all files contained within the directory at any depth from the given path.
|
||||||
|
*/
|
||||||
|
private static File[] getFilesToRelease(@NonNull File codePath) {
|
||||||
|
final List<File> files = getFilesRecursive(codePath);
|
||||||
|
if (files == null) {
|
||||||
|
if (codePath.isFile()) {
|
||||||
|
return new File[] { codePath };
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (files.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return files.toArray(new File[files.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native long nativeReleaseCompressedBlocks(String path);
|
||||||
|
|
||||||
|
}
|
||||||
5
core/java/com/android/internal/content/OWNERS
Normal file
5
core/java/com/android/internal/content/OWNERS
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Bug component: 36137
|
||||||
|
include /core/java/android/content/pm/OWNERS
|
||||||
|
|
||||||
|
per-file ReferrerIntent.aidl = file:/services/core/java/com/android/server/am/OWNERS
|
||||||
|
per-file ReferrerIntent.java = file:/services/core/java/com/android/server/am/OWNERS
|
||||||
@@ -84,6 +84,7 @@ cc_library_shared {
|
|||||||
android: {
|
android: {
|
||||||
srcs: [
|
srcs: [
|
||||||
"AndroidRuntime.cpp",
|
"AndroidRuntime.cpp",
|
||||||
|
"com_android_internal_content_F2fsUtils.cpp",
|
||||||
"com_android_internal_content_NativeLibraryHelper.cpp",
|
"com_android_internal_content_NativeLibraryHelper.cpp",
|
||||||
"com_google_android_gles_jni_EGLImpl.cpp",
|
"com_google_android_gles_jni_EGLImpl.cpp",
|
||||||
"com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
|
"com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ extern int register_android_content_res_ObbScanner(JNIEnv* env);
|
|||||||
extern int register_android_content_res_Configuration(JNIEnv* env);
|
extern int register_android_content_res_Configuration(JNIEnv* env);
|
||||||
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
|
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
|
||||||
extern int register_android_security_Scrypt(JNIEnv *env);
|
extern int register_android_security_Scrypt(JNIEnv *env);
|
||||||
|
extern int register_com_android_internal_content_F2fsUtils(JNIEnv* env);
|
||||||
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
|
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
|
||||||
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
|
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
|
||||||
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
|
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
|
||||||
@@ -1624,6 +1625,7 @@ static const RegJNIRec gRegJNI[] = {
|
|||||||
|
|
||||||
REG_JNI(register_android_animation_PropertyValuesHolder),
|
REG_JNI(register_android_animation_PropertyValuesHolder),
|
||||||
REG_JNI(register_android_security_Scrypt),
|
REG_JNI(register_android_security_Scrypt),
|
||||||
|
REG_JNI(register_com_android_internal_content_F2fsUtils),
|
||||||
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
|
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
|
||||||
REG_JNI(register_com_android_internal_os_DmabufInfoReader),
|
REG_JNI(register_com_android_internal_os_DmabufInfoReader),
|
||||||
REG_JNI(register_com_android_internal_os_FuseAppLoop),
|
REG_JNI(register_com_android_internal_os_FuseAppLoop),
|
||||||
|
|||||||
84
core/jni/com_android_internal_content_F2fsUtils.cpp
Normal file
84
core/jni/com_android_internal_content_F2fsUtils.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "F2fsUtils"
|
||||||
|
|
||||||
|
#include "core_jni_helpers.h"
|
||||||
|
|
||||||
|
#include <nativehelper/ScopedUtfChars.h>
|
||||||
|
#include <nativehelper/jni_macros.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <linux/f2fs.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
|
||||||
|
#include <android-base/unique_fd.h>
|
||||||
|
|
||||||
|
#include <utils/Log.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
using namespace std::literals;
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
static jlong com_android_internal_content_F2fsUtils_nativeReleaseCompressedBlocks(JNIEnv *env,
|
||||||
|
jclass clazz,
|
||||||
|
jstring path) {
|
||||||
|
unsigned long long blkcnt;
|
||||||
|
int ret;
|
||||||
|
ScopedUtfChars filePath(env, path);
|
||||||
|
|
||||||
|
android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC, 0));
|
||||||
|
if (fd < 0) {
|
||||||
|
ALOGW("Failed to open file: %s (%d)\n", filePath.c_str(), errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long flags = 0;
|
||||||
|
ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
|
||||||
|
if (ret < 0) {
|
||||||
|
ALOGW("Failed to get flags for file: %s (%d)\n", filePath.c_str(), errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((flags & FS_COMPR_FL) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ioctl(fd, F2FS_IOC_RELEASE_COMPRESS_BLOCKS, &blkcnt);
|
||||||
|
if (ret < 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
return blkcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::array gMethods = {
|
||||||
|
MAKE_JNI_NATIVE_METHOD(
|
||||||
|
"nativeReleaseCompressedBlocks", "(Ljava/lang/String;)J",
|
||||||
|
com_android_internal_content_F2fsUtils_nativeReleaseCompressedBlocks),
|
||||||
|
};
|
||||||
|
|
||||||
|
int register_com_android_internal_content_F2fsUtils(JNIEnv *env) {
|
||||||
|
return RegisterMethodsOrDie(env, "com/android/internal/content/F2fsUtils", gMethods.data(),
|
||||||
|
gMethods.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace android
|
||||||
@@ -341,6 +341,7 @@ import com.android.internal.R;
|
|||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.app.ResolverActivity;
|
import com.android.internal.app.ResolverActivity;
|
||||||
|
import com.android.internal.content.F2fsUtils;
|
||||||
import com.android.internal.content.NativeLibraryHelper;
|
import com.android.internal.content.NativeLibraryHelper;
|
||||||
import com.android.internal.content.PackageHelper;
|
import com.android.internal.content.PackageHelper;
|
||||||
import com.android.internal.content.om.OverlayConfig;
|
import com.android.internal.content.om.OverlayConfig;
|
||||||
@@ -896,6 +897,20 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
* Only non-null during an OTA, and even then it is nulled again once systemReady().
|
* Only non-null during an OTA, and even then it is nulled again once systemReady().
|
||||||
*/
|
*/
|
||||||
private @Nullable ArraySet<String> mExistingPackages = null;
|
private @Nullable ArraySet<String> mExistingPackages = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of code paths that need to be released when the system becomes ready.
|
||||||
|
* <p>
|
||||||
|
* NOTE: We have to delay releasing cblocks for no other reason than we cannot
|
||||||
|
* retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}. When
|
||||||
|
* we no longer need to read that setting, cblock release can occur in the
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* @see Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL
|
||||||
|
* @see #systemReady()
|
||||||
|
*/
|
||||||
|
private @Nullable List<File> mReleaseOnSystemReady;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not system app permissions should be promoted from install to runtime.
|
* Whether or not system app permissions should be promoted from install to runtime.
|
||||||
*/
|
*/
|
||||||
@@ -7966,6 +7981,21 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
IoUtils.closeQuietly(handle);
|
IoUtils.closeQuietly(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ret == PackageManager.INSTALL_SUCCEEDED) {
|
||||||
|
// NOTE: During boot, we have to delay releasing cblocks for no other reason than
|
||||||
|
// we cannot retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}.
|
||||||
|
// When we no longer need to read that setting, cblock release can occur always
|
||||||
|
// occur here directly
|
||||||
|
if (!mSystemReady) {
|
||||||
|
if (mReleaseOnSystemReady == null) {
|
||||||
|
mReleaseOnSystemReady = new ArrayList<>();
|
||||||
|
}
|
||||||
|
mReleaseOnSystemReady.add(dstCodePath);
|
||||||
|
} else {
|
||||||
|
final ContentResolver resolver = mContext.getContentResolver();
|
||||||
|
F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ret != PackageManager.INSTALL_SUCCEEDED) {
|
if (ret != PackageManager.INSTALL_SUCCEEDED) {
|
||||||
if (!dstCodePath.exists()) {
|
if (!dstCodePath.exists()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -17853,6 +17883,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
|
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
|
||||||
mRet = args.copyApk();
|
mRet = args.copyApk();
|
||||||
}
|
}
|
||||||
|
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
|
||||||
|
F2fsUtils.releaseCompressedBlocks(
|
||||||
|
mContext.getContentResolver(), new File(args.getCodePath()));
|
||||||
|
}
|
||||||
if (mParentInstallParams != null) {
|
if (mParentInstallParams != null) {
|
||||||
mParentInstallParams.tryProcessInstallRequest(args, mRet);
|
mParentInstallParams.tryProcessInstallRequest(args, mRet);
|
||||||
} else {
|
} else {
|
||||||
@@ -17860,7 +17894,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
processInstallRequestsAsync(
|
processInstallRequestsAsync(
|
||||||
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
|
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
|
||||||
Collections.singletonList(new InstallRequest(args, res)));
|
Collections.singletonList(new InstallRequest(args, res)));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24235,8 +24268,15 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
public void systemReady() {
|
public void systemReady() {
|
||||||
enforceSystemOrRoot("Only the system can claim the system is ready");
|
enforceSystemOrRoot("Only the system can claim the system is ready");
|
||||||
|
|
||||||
mSystemReady = true;
|
|
||||||
final ContentResolver resolver = mContext.getContentResolver();
|
final ContentResolver resolver = mContext.getContentResolver();
|
||||||
|
if (mReleaseOnSystemReady != null) {
|
||||||
|
for (int i = mReleaseOnSystemReady.size() - 1; i >= 0; --i) {
|
||||||
|
final File dstCodePath = mReleaseOnSystemReady.get(i);
|
||||||
|
F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
|
||||||
|
}
|
||||||
|
mReleaseOnSystemReady = null;
|
||||||
|
}
|
||||||
|
mSystemReady = true;
|
||||||
ContentObserver co = new ContentObserver(mHandler) {
|
ContentObserver co = new ContentObserver(mHandler) {
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
|
|||||||
Reference in New Issue
Block a user