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

Commit c41967e7 authored by Shai Barack's avatar Shai Barack Committed by Android (Google) Code Review
Browse files

Merge "Reduce lock contention in ContextImpl" into main

parents 0ddacc17 8da0f1e2
Loading
Loading
Loading
Loading
+156 −75
Original line number Diff line number Diff line
@@ -272,10 +272,17 @@ class ContextImpl extends Context {

    @UnsupportedAppUsage
    private Context mOuterContext;

    private final Object mThemeLock = new Object();

    @UnsupportedAppUsage
    @GuardedBy("mThemeLock")
    private int mThemeResource = 0;

    @UnsupportedAppUsage
    @GuardedBy("mThemeLock")
    private Resources.Theme mTheme = null;

    @UnsupportedAppUsage
    private PackageManager mPackageManager;
    private Context mReceiverRestrictedContext = null;
@@ -288,7 +295,6 @@ class ContextImpl extends Context {

    private ContentCaptureOptions mContentCaptureOptions = null;

    private final Object mSync = new Object();
    /**
     * Indicates this {@link Context} can not handle UI components properly and is not associated
     * with a {@link Display} instance.
@@ -340,21 +346,18 @@ class ContextImpl extends Context {
     */
    private boolean mOwnsToken = false;

    @GuardedBy("mSync")
    private File mDatabasesDir;
    @GuardedBy("mSync")
    @UnsupportedAppUsage
    private File mPreferencesDir;
    @GuardedBy("mSync")
    private File mFilesDir;
    @GuardedBy("mSync")
    private File mCratesDir;
    @GuardedBy("mSync")
    private File mNoBackupFilesDir;
    @GuardedBy("mSync")
    private File mCacheDir;
    @GuardedBy("mSync")
    private File mCodeCacheDir;
    private final Object mDirsLock = new Object();
    private volatile File mDatabasesDir;
    @UnsupportedAppUsage private volatile File mPreferencesDir;
    private volatile File mFilesDir;
    private volatile File mCratesDir;
    private volatile File mNoBackupFilesDir;
    private volatile File[] mExternalFilesDirs;
    private volatile File[] mObbDirs;
    private volatile File mCacheDir;
    private volatile File mCodeCacheDir;
    private volatile File[] mExternalCacheDirs;
    private volatile File[] mExternalMediaDirs;

    // The system service cache for the system services that are cached per-ContextImpl.
    @UnsupportedAppUsage
@@ -458,7 +461,7 @@ class ContextImpl extends Context {

    @Override
    public void setTheme(int resId) {
        synchronized (mSync) {
        synchronized (mThemeLock) {
            if (mThemeResource != resId) {
                mThemeResource = resId;
                initializeTheme();
@@ -468,14 +471,14 @@ class ContextImpl extends Context {

    @Override
    public int getThemeResId() {
        synchronized (mSync) {
        synchronized (mThemeLock) {
            return mThemeResource;
        }
    }

    @Override
    public Resources.Theme getTheme() {
        synchronized (mSync) {
        synchronized (mThemeLock) {
            if (mTheme != null) {
                return mTheme;
            }
@@ -488,6 +491,7 @@ class ContextImpl extends Context {
        }
    }

    @GuardedBy("mThemeLock")
    private void initializeTheme() {
        if (mTheme == null) {
            mTheme = mResources.newTheme();
@@ -737,12 +741,18 @@ class ContextImpl extends Context {

    @UnsupportedAppUsage
    private File getPreferencesDir() {
        synchronized (mSync) {
            if (mPreferencesDir == null) {
                mPreferencesDir = new File(getDataDir(), "shared_prefs");
        File localPreferencesDir = mPreferencesDir;
        if (localPreferencesDir == null) {
            synchronized (mDirsLock) {
                localPreferencesDir = mPreferencesDir;
                if (localPreferencesDir == null) {
                    localPreferencesDir = new File(getDataDir(), "shared_prefs");
                    ensurePrivateDirExists(localPreferencesDir);
                    mPreferencesDir = localPreferencesDir;
                }
            }
            return ensurePrivateDirExists(mPreferencesDir);
        }
        return localPreferencesDir;
    }

    @Override
@@ -784,16 +794,16 @@ class ContextImpl extends Context {
    /**
     * Common-path handling of app data dir creation
     */
    private static File ensurePrivateDirExists(File file) {
        return ensurePrivateDirExists(file, 0771, -1, null);
    private static void ensurePrivateDirExists(File file) {
        ensurePrivateDirExists(file, 0771, -1, null);
    }

    private static File ensurePrivateCacheDirExists(File file, String xattr) {
    private static void ensurePrivateCacheDirExists(File file, String xattr) {
        final int gid = UserHandle.getCacheAppGid(Process.myUid());
        return ensurePrivateDirExists(file, 02771, gid, xattr);
        ensurePrivateDirExists(file, 02771, gid, xattr);
    }

    private static File ensurePrivateDirExists(File file, int mode, int gid, String xattr) {
    private static void ensurePrivateDirExists(File file, int mode, int gid, String xattr) {
        if (!file.exists()) {
            final String path = file.getAbsolutePath();
            try {
@@ -821,17 +831,22 @@ class ContextImpl extends Context {
                }
            }
        }
        return file;
    }

    @Override
    public File getFilesDir() {
        synchronized (mSync) {
            if (mFilesDir == null) {
                mFilesDir = new File(getDataDir(), "files");
        File localFilesDir = mFilesDir;
        if (localFilesDir == null) {
            localFilesDir = mFilesDir;
            synchronized (mDirsLock) {
                if (localFilesDir == null) {
                    localFilesDir = new File(getDataDir(), "files");
                    ensurePrivateDirExists(localFilesDir);
                    mFilesDir = localFilesDir;
                }
            }
            return ensurePrivateDirExists(mFilesDir);
        }
        return localFilesDir;
    }

    @Override
@@ -841,26 +856,38 @@ class ContextImpl extends Context {
        final Path absoluteNormalizedCratePath = cratesRootPath.resolve(crateId)
                .toAbsolutePath().normalize();

        synchronized (mSync) {
            if (mCratesDir == null) {
                mCratesDir = cratesRootPath.toFile();
        File localCratesDir = mCratesDir;
        if (localCratesDir == null) {
            synchronized (mDirsLock) {
                localCratesDir = mCratesDir;
                if (localCratesDir == null) {
                    localCratesDir = cratesRootPath.toFile();
                    ensurePrivateDirExists(localCratesDir);
                    mCratesDir = localCratesDir;
                }
            }
            ensurePrivateDirExists(mCratesDir);
        }

        File cratedDir = absoluteNormalizedCratePath.toFile();
        return ensurePrivateDirExists(cratedDir);
        File crateDir = absoluteNormalizedCratePath.toFile();
        ensurePrivateDirExists(crateDir);
        return crateDir;
    }

    @Override
    public File getNoBackupFilesDir() {
        synchronized (mSync) {
            if (mNoBackupFilesDir == null) {
                mNoBackupFilesDir = new File(getDataDir(), "no_backup");
        File localNoBackupFilesDir = mNoBackupFilesDir;
        if (localNoBackupFilesDir == null) {
            synchronized (mDirsLock) {
                localNoBackupFilesDir = mNoBackupFilesDir;
                if (localNoBackupFilesDir == null) {
                    localNoBackupFilesDir = new File(getDataDir(), "no_backup");
                    ensurePrivateDirExists(localNoBackupFilesDir);
                    mNoBackupFilesDir = localNoBackupFilesDir;
                }
            return ensurePrivateDirExists(mNoBackupFilesDir);
            }
        }
        return localNoBackupFilesDir;
    }

    @Override
    public File getExternalFilesDir(String type) {
@@ -871,14 +898,25 @@ class ContextImpl extends Context {

    @Override
    public File[] getExternalFilesDirs(String type) {
        synchronized (mSync) {
            File[] dirs = Environment.buildExternalStorageAppFilesDirs(getPackageName());
        File[] localExternalFilesDirs = mExternalFilesDirs;
        if (localExternalFilesDirs == null) {
            synchronized (mDirsLock) {
                localExternalFilesDirs = mExternalFilesDirs;
                if (localExternalFilesDirs == null) {
                    localExternalFilesDirs =
                            Environment.buildExternalStorageAppFilesDirs(getPackageName());
                    if (type != null) {
                dirs = Environment.buildPaths(dirs, type);
                        localExternalFilesDirs =
                                Environment.buildPaths(localExternalFilesDirs, type);
                    }
                    localExternalFilesDirs = ensureExternalDirsExistOrFilter(
                            localExternalFilesDirs, true /* tryCreateInProcess */);
                    mExternalFilesDirs = localExternalFilesDirs;
                }
            return ensureExternalDirsExistOrFilter(dirs, true /* tryCreateInProcess */);
            }
        }
        return localExternalFilesDirs;
    }

    @Override
    public File getObbDir() {
@@ -889,30 +927,51 @@ class ContextImpl extends Context {

    @Override
    public File[] getObbDirs() {
        synchronized (mSync) {
            File[] dirs = Environment.buildExternalStorageAppObbDirs(getPackageName());
            return ensureExternalDirsExistOrFilter(dirs, true /* tryCreateInProcess */);
        File[] localObbDirs = mObbDirs;
        if (mObbDirs == null) {
            synchronized (mDirsLock) {
                localObbDirs = mObbDirs;
                if (localObbDirs == null) {
                    localObbDirs = Environment.buildExternalStorageAppObbDirs(getPackageName());
                    localObbDirs = ensureExternalDirsExistOrFilter(
                            localObbDirs, true /* tryCreateInProcess */);
                    mObbDirs = localObbDirs;
                }
            }
        }
        return localObbDirs;
    }

    @Override
    public File getCacheDir() {
        synchronized (mSync) {
            if (mCacheDir == null) {
                mCacheDir = new File(getDataDir(), "cache");
        File localCacheDir = mCacheDir;
        if (localCacheDir == null) {
            synchronized (mDirsLock) {
                localCacheDir = mCacheDir;
                if (localCacheDir == null) {
                    localCacheDir = new File(getDataDir(), "cache");
                    ensurePrivateCacheDirExists(localCacheDir, XATTR_INODE_CACHE);
                    mCacheDir = localCacheDir;
                }
            return ensurePrivateCacheDirExists(mCacheDir, XATTR_INODE_CACHE);
            }
        }
        return localCacheDir;
    }

    @Override
    public File getCodeCacheDir() {
        synchronized (mSync) {
            if (mCodeCacheDir == null) {
                mCodeCacheDir = getCodeCacheDirBeforeBind(getDataDir());
        File localCodeCacheDir = mCodeCacheDir;
        if (localCodeCacheDir == null) {
            synchronized (mDirsLock) {
                localCodeCacheDir = mCodeCacheDir;
                if (localCodeCacheDir == null) {
                    localCodeCacheDir = getCodeCacheDirBeforeBind(getDataDir());
                    ensurePrivateCacheDirExists(localCodeCacheDir, XATTR_INODE_CODE_CACHE);
                    mCodeCacheDir = localCodeCacheDir;
                }
            }
            return ensurePrivateCacheDirExists(mCodeCacheDir, XATTR_INODE_CODE_CACHE);
        }
        return localCodeCacheDir;
    }

    /**
@@ -933,22 +992,38 @@ class ContextImpl extends Context {

    @Override
    public File[] getExternalCacheDirs() {
        synchronized (mSync) {
            File[] dirs = Environment.buildExternalStorageAppCacheDirs(getPackageName());
            // We don't try to create cache directories in-process, because they need special
            // setup for accurate quota tracking. This ensures the cache dirs are always
            // created through StorageManagerService.
            return ensureExternalDirsExistOrFilter(dirs, false /* tryCreateInProcess */);
        File[] localExternalCacheDirs = mExternalCacheDirs;
        if (localExternalCacheDirs == null) {
            synchronized (mDirsLock) {
                localExternalCacheDirs = mExternalCacheDirs;
                if (localExternalCacheDirs == null) {
                    localExternalCacheDirs =
                            Environment.buildExternalStorageAppCacheDirs(getPackageName());
                    localExternalCacheDirs = ensureExternalDirsExistOrFilter(
                            localExternalCacheDirs, false /* tryCreateInProcess */);
                    mExternalCacheDirs = localExternalCacheDirs;
                }
            }
        }
        return localExternalCacheDirs;
    }

    @Override
    public File[] getExternalMediaDirs() {
        synchronized (mSync) {
            File[] dirs = Environment.buildExternalStorageAppMediaDirs(getPackageName());
            return ensureExternalDirsExistOrFilter(dirs, true /* tryCreateInProcess */);
        File[] localExternalMediaDirs = mExternalMediaDirs;
        if (localExternalMediaDirs == null) {
            synchronized (mDirsLock) {
                localExternalMediaDirs = mExternalMediaDirs;
                if (localExternalMediaDirs == null) {
                    localExternalMediaDirs = Environment.buildExternalStorageAppMediaDirs(getPackageName());
                    localExternalMediaDirs = ensureExternalDirsExistOrFilter(
                            localExternalMediaDirs, true /* tryCreateInProcess */);
                    mExternalMediaDirs = localExternalMediaDirs;
                }
            }
        }
        return localExternalMediaDirs;
    }

    /**
     * @hide
@@ -1046,16 +1121,22 @@ class ContextImpl extends Context {
    }

    private File getDatabasesDir() {
        synchronized (mSync) {
            if (mDatabasesDir == null) {
        File localDatabasesDir = mDatabasesDir;
        if (localDatabasesDir == null) {
            synchronized (mDirsLock) {
                localDatabasesDir = mDatabasesDir;
                if (localDatabasesDir == null) {
                    if ("android".equals(getPackageName())) {
                    mDatabasesDir = new File("/data/system");
                        localDatabasesDir = new File("/data/system");
                    } else {
                    mDatabasesDir = new File(getDataDir(), "databases");
                        localDatabasesDir = new File(getDataDir(), "databases");
                    }
                    ensurePrivateDirExists(localDatabasesDir);
                    mDatabasesDir = localDatabasesDir;
                }
            }
            return ensurePrivateDirExists(mDatabasesDir);
        }
        return localDatabasesDir;
    }

    @Override