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

Commit fbc8d1f8 authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Move the PlatformCompatCache in AMS to its own file"

parents 4e450701 5e3f9b57
Loading
Loading
Loading
Loading
+9 −178
Original line number Diff line number Diff line
@@ -69,10 +69,12 @@ import static com.android.server.am.ActivityManagerService.TAG_LRU;
import static com.android.server.am.ActivityManagerService.TAG_OOM_ADJ;
import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
import static com.android.server.am.AppProfiler.TAG_PSS;
import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY;
import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY;
import static com.android.server.am.PlatformCompatCache.CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME;
import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread;
@@ -93,31 +95,23 @@ import android.os.IBinder;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.compat.CompatChange;
import com.android.server.compat.PlatformCompat;
import com.android.server.am.PlatformCompatCache.CachedCompatChangeId;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.WindowProcessController;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -174,27 +168,6 @@ public class OomAdjuster {
    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
    static final long USE_SHORT_FGS_USAGE_INTERACTION_TIME = 183972877L;

    static final int CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY = 0;
    static final int CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY = 1;
    static final int CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME = 2;

    @IntDef(prefix = { "CACHED_COMPAT_CHANGE_" }, value = {
        CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY,
        CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY,
        CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME,
    })
    @Retention(RetentionPolicy.SOURCE)
    static @interface CachedCompatChangeId{}

    /**
     * Mapping from CACHED_COMPAT_CHANGE_* to the actual compat change id.
     */
    static final long[] CACHED_COMPAT_CHANGE_IDS_MAPPING = new long[] {
        PROCESS_CAPABILITY_CHANGE_ID,
        CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID,
        USE_SHORT_FGS_USAGE_INTERACTION_TIME,
    };

    /**
     * For some direct access we need to power manager.
     */
@@ -280,150 +253,12 @@ public class OomAdjuster {
    @GuardedBy("mService")
    private boolean mPendingFullOomAdjUpdate = false;

    final PlatformCompatCache mPlatformCompatCache;

    /** Overrideable by a test */
    @VisibleForTesting
    static class PlatformCompatCache {
        private final PlatformCompat mPlatformCompat;
        private final IPlatformCompat mIPlatformCompatProxy;
        private final LongSparseArray<CacheItem> mCaches = new LongSparseArray<>();
        private final boolean mCacheEnabled;

        PlatformCompatCache(long[] compatChanges) {
            IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
            if (b instanceof PlatformCompat) {
                mPlatformCompat = (PlatformCompat) ServiceManager.getService(
                        Context.PLATFORM_COMPAT_SERVICE);
                for (long changeId: compatChanges) {
                    mCaches.put(changeId, new CacheItem(mPlatformCompat, changeId));
                }
                mIPlatformCompatProxy = null;
                mCacheEnabled = true;
            } else {
                // we are in UT where the platform_compat is not running within the same process
                mIPlatformCompatProxy = IPlatformCompat.Stub.asInterface(b);
                mPlatformCompat = null;
                mCacheEnabled = false;
            }
        }

        boolean isChangeEnabled(long changeId, ApplicationInfo app) throws RemoteException {
            return mCacheEnabled ? mCaches.get(changeId).isChangeEnabled(app)
                    : mIPlatformCompatProxy.isChangeEnabled(changeId, app);
        }

        /**
         * Same as {@link #isChangeEnabled(long, ApplicationInfo)} but instead of throwing a
         * RemoteException from platform compat, it returns the default value provided.
         */
        boolean isChangeEnabled(long changeId, ApplicationInfo app, boolean defaultValue) {
            try {
                return mCacheEnabled ? mCaches.get(changeId).isChangeEnabled(app)
                        : mIPlatformCompatProxy.isChangeEnabled(changeId, app);
            } catch (RemoteException e) {
                Slog.w(TAG, "Error reading platform compat change " + changeId, e);
                return defaultValue;
            }
        }

        void invalidate(ApplicationInfo app) {
            for (int i = mCaches.size() - 1; i >= 0; i--) {
                mCaches.valueAt(i).invalidate(app);
            }
        }

        void onApplicationInfoChanged(ApplicationInfo app) {
            for (int i = mCaches.size() - 1; i >= 0; i--) {
                mCaches.valueAt(i).onApplicationInfoChanged(app);
            }
        }

        static class CacheItem implements CompatChange.ChangeListener {
            private final PlatformCompat mPlatformCompat;
            private final long mChangeId;
            private final Object mLock = new Object();

            private final ArrayMap<String, Pair<Boolean, WeakReference<ApplicationInfo>>> mCache =
                    new ArrayMap<>();

            CacheItem(PlatformCompat platformCompat, long changeId) {
                mPlatformCompat = platformCompat;
                mChangeId = changeId;
                mPlatformCompat.registerListener(changeId, this);
            }

            boolean isChangeEnabled(ApplicationInfo app) {
                synchronized (mLock) {
                    final int index = mCache.indexOfKey(app.packageName);
                    Pair<Boolean, WeakReference<ApplicationInfo>> p;
                    if (index < 0) {
                        return fetchLocked(app, index);
                    }
                    p = mCache.valueAt(index);
                    if (p.second.get() == app) {
                        return p.first;
                    }
                    // Cache is invalid, regenerate it
                    return fetchLocked(app, index);
                }
            }

            void invalidate(ApplicationInfo app) {
                synchronized (mLock) {
                    mCache.remove(app.packageName);
                }
            }

            @GuardedBy("mLock")
            boolean fetchLocked(ApplicationInfo app, int index) {
                final Pair<Boolean, WeakReference<ApplicationInfo>> p = new Pair<>(
                        mPlatformCompat.isChangeEnabledInternalNoLogging(mChangeId, app),
                        new WeakReference<>(app));
                if (index >= 0) {
                    mCache.setValueAt(index, p);
                } else {
                    mCache.put(app.packageName, p);
                }
                return p.first;
            }

            void onApplicationInfoChanged(ApplicationInfo app) {
                synchronized (mLock) {
                    final int index = mCache.indexOfKey(app.packageName);
                    if (index >= 0) {
                        fetchLocked(app, index);
                    }
                }
            }

            @Override
            public void onCompatChange(String packageName) {
                synchronized (mLock) {
                    final int index = mCache.indexOfKey(packageName);
                    if (index >= 0) {
                        final ApplicationInfo app = mCache.valueAt(index).second.get();
                        if (app != null) {
                            fetchLocked(app, index);
                        } else {
                            mCache.removeAt(index);
                        }
                    }
                }
            }
        }
    }

    /** Overrideable by a test */
    @VisibleForTesting
    protected PlatformCompatCache getPlatformCompatCache() {
        return mPlatformCompatCache;
    }

    boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId, ApplicationInfo app,
            boolean defaultValue) {
        return getPlatformCompatCache().isChangeEnabled(
                CACHED_COMPAT_CHANGE_IDS_MAPPING[cachedCompatChangeId], app, defaultValue);
    protected boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
            ApplicationInfo app, boolean defaultValue) {
        return PlatformCompatCache.getInstance()
                .isChangeEnabled(cachedCompatChangeId, app, defaultValue);
    }

    OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
@@ -477,10 +312,6 @@ public class OomAdjuster {
        mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1);
        mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1)
                / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
        mPlatformCompatCache = new PlatformCompatCache(new long[] {
                PROCESS_CAPABILITY_CHANGE_ID, CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID,
                USE_SHORT_FGS_USAGE_INTERACTION_TIME
        });
    }

    void initSettings() {
@@ -827,7 +658,7 @@ public class OomAdjuster {
        if (app != null) {
            mPendingProcessSet.remove(app);
            if (procDied) {
                getPlatformCompatCache().invalidate(app.info);
                PlatformCompatCache.getInstance().invalidate(app.info);
            }
        }
    }
+216 −0
Original line number Diff line number Diff line
/*
 * 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.server.am;

import static com.android.server.am.ActivityManagerService.TAG;
import static com.android.server.am.OomAdjuster.CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID;
import static com.android.server.am.OomAdjuster.PROCESS_CAPABILITY_CHANGE_ID;
import static com.android.server.am.OomAdjuster.USE_SHORT_FGS_USAGE_INTERACTION_TIME;

import android.annotation.IntDef;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.compat.CompatChange;
import com.android.server.compat.PlatformCompat;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;

/**
 * Local platform compat cache.
 */
final class PlatformCompatCache {

    static final int CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY = 0;
    static final int CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY = 1;
    static final int CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME = 2;

    @IntDef(prefix = { "CACHED_COMPAT_CHANGE_" }, value = {
        CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY,
        CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY,
        CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME,
    })
    @Retention(RetentionPolicy.SOURCE)
    static @interface CachedCompatChangeId{}

    /**
     * Mapping from CACHED_COMPAT_CHANGE_* to the actual compat change id.
     */
    static final long[] CACHED_COMPAT_CHANGE_IDS_MAPPING = new long[] {
        PROCESS_CAPABILITY_CHANGE_ID,
        CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID,
        USE_SHORT_FGS_USAGE_INTERACTION_TIME,
    };

    private final PlatformCompat mPlatformCompat;
    private final IPlatformCompat mIPlatformCompatProxy;
    private final LongSparseArray<CacheItem> mCaches = new LongSparseArray<>();
    private final boolean mCacheEnabled;

    private static PlatformCompatCache sPlatformCompatCache;

    private PlatformCompatCache(long[] compatChanges) {
        IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
        if (b instanceof PlatformCompat) {
            mPlatformCompat = (PlatformCompat) ServiceManager.getService(
                    Context.PLATFORM_COMPAT_SERVICE);
            for (long changeId: compatChanges) {
                mCaches.put(changeId, new CacheItem(mPlatformCompat, changeId));
            }
            mIPlatformCompatProxy = null;
            mCacheEnabled = true;
        } else {
            // we are in UT where the platform_compat is not running within the same process
            mIPlatformCompatProxy = IPlatformCompat.Stub.asInterface(b);
            mPlatformCompat = null;
            mCacheEnabled = false;
        }
    }

    static PlatformCompatCache getInstance() {
        if (sPlatformCompatCache == null) {
            sPlatformCompatCache = new PlatformCompatCache(new long[] {
                PROCESS_CAPABILITY_CHANGE_ID,
                CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID,
                USE_SHORT_FGS_USAGE_INTERACTION_TIME,
            });
        }
        return sPlatformCompatCache;
    }

    private boolean isChangeEnabled(long changeId, ApplicationInfo app, boolean defaultValue) {
        try {
            return mCacheEnabled ? mCaches.get(changeId).isChangeEnabled(app)
                    : mIPlatformCompatProxy.isChangeEnabled(changeId, app);
        } catch (RemoteException e) {
            Slog.w(TAG, "Error reading platform compat change " + changeId, e);
            return defaultValue;
        }
    }

    /**
     * @return If the given cached compat change id is enabled.
     */
    static boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
            ApplicationInfo app, boolean defaultValue) {
        return getInstance().isChangeEnabled(
                CACHED_COMPAT_CHANGE_IDS_MAPPING[cachedCompatChangeId], app, defaultValue);
    }

    /**
     * Invalidate the cache for the given app.
     */
    void invalidate(ApplicationInfo app) {
        for (int i = mCaches.size() - 1; i >= 0; i--) {
            mCaches.valueAt(i).invalidate(app);
        }
    }

    /**
     * Update the cache due to application info changes.
     */
    void onApplicationInfoChanged(ApplicationInfo app) {
        for (int i = mCaches.size() - 1; i >= 0; i--) {
            mCaches.valueAt(i).onApplicationInfoChanged(app);
        }
    }

    static class CacheItem implements CompatChange.ChangeListener {
        private final PlatformCompat mPlatformCompat;
        private final long mChangeId;
        private final Object mLock = new Object();

        private final ArrayMap<String, Pair<Boolean, WeakReference<ApplicationInfo>>> mCache =
                new ArrayMap<>();

        CacheItem(PlatformCompat platformCompat, long changeId) {
            mPlatformCompat = platformCompat;
            mChangeId = changeId;
            mPlatformCompat.registerListener(changeId, this);
        }

        boolean isChangeEnabled(ApplicationInfo app) {
            synchronized (mLock) {
                final int index = mCache.indexOfKey(app.packageName);
                Pair<Boolean, WeakReference<ApplicationInfo>> p;
                if (index < 0) {
                    return fetchLocked(app, index);
                }
                p = mCache.valueAt(index);
                if (p.second.get() == app) {
                    return p.first;
                }
                // Cache is invalid, regenerate it
                return fetchLocked(app, index);
            }
        }

        void invalidate(ApplicationInfo app) {
            synchronized (mLock) {
                mCache.remove(app.packageName);
            }
        }

        @GuardedBy("mLock")
        boolean fetchLocked(ApplicationInfo app, int index) {
            final Pair<Boolean, WeakReference<ApplicationInfo>> p = new Pair<>(
                    mPlatformCompat.isChangeEnabledInternalNoLogging(mChangeId, app),
                    new WeakReference<>(app));
            if (index >= 0) {
                mCache.setValueAt(index, p);
            } else {
                mCache.put(app.packageName, p);
            }
            return p.first;
        }

        void onApplicationInfoChanged(ApplicationInfo app) {
            synchronized (mLock) {
                final int index = mCache.indexOfKey(app.packageName);
                if (index >= 0) {
                    fetchLocked(app, index);
                }
            }
        }

        @Override
        public void onCompatChange(String packageName) {
            synchronized (mLock) {
                final int index = mCache.indexOfKey(packageName);
                if (index >= 0) {
                    final ApplicationInfo app = mCache.valueAt(index).second.get();
                    if (app != null) {
                        fetchLocked(app, index);
                    } else {
                        mCache.removeAt(index);
                    }
                }
            }
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -4753,7 +4753,7 @@ public final class ProcessList {
                        if (ai != null) {
                            if (ai.packageName.equals(app.info.packageName)) {
                                app.info = ai;
                                mService.mOomAdjuster.mPlatformCompatCache
                                PlatformCompatCache.getInstance()
                                        .onApplicationInfoChanged(ai);
                            }
                            app.getThread().scheduleApplicationInfoChanged(ai);
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;

import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.OomAdjuster.CachedCompatChangeId;
import static com.android.server.am.ProcessRecord.TAG;

import android.annotation.ElapsedRealtimeLong;
@@ -35,6 +34,7 @@ import android.util.TimeUtils;
import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.am.PlatformCompatCache.CachedCompatChangeId;

import java.io.PrintWriter;

+3 −17
Original line number Diff line number Diff line
@@ -63,32 +63,18 @@ public class OomAdjusterTests {

    static class MyOomAdjuster extends OomAdjuster {

        private final PlatformCompatCache mPlatformCompatCache;

        MyOomAdjuster(ActivityManagerService service, ProcessList processList,
                ActiveUids activeUids) {
            super(service, processList, activeUids);
            mPlatformCompatCache = new MyPlatformCompatCache(new long[]{});
        }

        static class MyPlatformCompatCache extends PlatformCompatCache {

            MyPlatformCompatCache(long[] compatChanges) {
                super(compatChanges);
        }

        @Override
            boolean isChangeEnabled(long changeId, ApplicationInfo app, boolean defaultValue) {
        protected boolean isChangeEnabled(int changeId, ApplicationInfo app,
                boolean defaultValue) {
            return true;
        }
    }

        @Override
        protected OomAdjuster.PlatformCompatCache getPlatformCompatCache() {
            return mPlatformCompatCache;
        }
    }

    @BeforeClass
    public static void setUpOnce() {
        sContext = getInstrumentation().getTargetContext();