diff options
| -rw-r--r-- | core/java/android/provider/Settings.java | 14 | ||||
| -rw-r--r-- | core/java/com/android/internal/content/F2fsUtils.java | 296 | ||||
| -rw-r--r-- | core/java/com/android/internal/content/OWNERS | 5 | ||||
| -rw-r--r-- | core/jni/Android.bp | 1 | ||||
| -rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
| -rw-r--r-- | core/jni/com_android_internal_content_F2fsUtils.cpp | 84 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 44 |
7 files changed, 2 insertions, 444 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3116b2612c67..5cfb665745a8 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6624,20 +6624,6 @@ public final class Settings { 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 * containing the IDs of all enabled input methods, each ID separated * by ':'. diff --git a/core/java/com/android/internal/content/F2fsUtils.java b/core/java/com/android/internal/content/F2fsUtils.java deleted file mode 100644 index 27f1b308ed9c..000000000000 --- a/core/java/com/android/internal/content/F2fsUtils.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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); - -} diff --git a/core/java/com/android/internal/content/OWNERS b/core/java/com/android/internal/content/OWNERS deleted file mode 100644 index c42bee69410d..000000000000 --- a/core/java/com/android/internal/content/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -# 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 diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 4502a33fbb63..146863342f47 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -84,7 +84,6 @@ cc_library_shared { android: { srcs: [ "AndroidRuntime.cpp", - "com_android_internal_content_F2fsUtils.cpp", "com_android_internal_content_NativeLibraryHelper.cpp", "com_google_android_gles_jni_EGLImpl.cpp", "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index dca5d969257b..7e8fc7e6ba4f 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -190,7 +190,6 @@ extern int register_android_content_res_ObbScanner(JNIEnv* env); extern int register_android_content_res_Configuration(JNIEnv* env); extern int register_android_animation_PropertyValuesHolder(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_om_OverlayConfig(JNIEnv *env); extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env); @@ -1622,7 +1621,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_animation_PropertyValuesHolder), 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_os_DmabufInfoReader), REG_JNI(register_com_android_internal_os_FuseAppLoop), diff --git a/core/jni/com_android_internal_content_F2fsUtils.cpp b/core/jni/com_android_internal_content_F2fsUtils.cpp deleted file mode 100644 index 8b9d59c416a0..000000000000 --- a/core/jni/com_android_internal_content_F2fsUtils.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7b1b2e5a9e4c..14861c2ddf4c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -341,7 +341,6 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; -import com.android.internal.content.F2fsUtils; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; import com.android.internal.content.om.OverlayConfig; @@ -897,20 +896,6 @@ public class PackageManagerService extends IPackageManager.Stub * Only non-null during an OTA, and even then it is nulled again once systemReady(). */ 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. */ @@ -7316,21 +7301,6 @@ public class PackageManagerService extends IPackageManager.Stub 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 (!dstCodePath.exists()) { return null; @@ -17202,10 +17172,6 @@ public class PackageManagerService extends IPackageManager.Stub if (mRet == PackageManager.INSTALL_SUCCEEDED) { mRet = args.copyApk(); } - if (mRet == PackageManager.INSTALL_SUCCEEDED) { - F2fsUtils.releaseCompressedBlocks( - mContext.getContentResolver(), new File(args.getCodePath())); - } if (mParentInstallParams != null) { mParentInstallParams.tryProcessInstallRequest(args, mRet); } else { @@ -17213,6 +17179,7 @@ public class PackageManagerService extends IPackageManager.Stub processInstallRequestsAsync( res.returnCode == PackageManager.INSTALL_SUCCEEDED, Collections.singletonList(new InstallRequest(args, res))); + } } } @@ -23547,15 +23514,8 @@ public class PackageManagerService extends IPackageManager.Stub public void systemReady() { enforceSystemOrRoot("Only the system can claim the system is ready"); - 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; + final ContentResolver resolver = mContext.getContentResolver(); ContentObserver co = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { |