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

Commit 6bb6687f authored by Jay Aliomer's avatar Jay Aliomer
Browse files

Local Wallpaper Color high resource usage

Fixes: b/182482946
Test: WallpaperManagerTest
Change-Id: Ic4161e43e30f71886984d22a47b086d647188613
parent d3035fe4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -167,7 +167,8 @@ interface IWallpaperManager {
    * @hide
    */
    void removeOnLocalColorsChangedListener(
            in ILocalWallpaperColorConsumer callback, int which, int userId, int displayId);
            in ILocalWallpaperColorConsumer callback, in List<RectF> area,
            int which, int userId, int displayId);

    /**
    * @hide
+40 −18
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import android.os.StrictMode;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.view.Display;
@@ -315,8 +316,20 @@ public class WallpaperManager {
        private int mCachedWallpaperUserId;
        private Bitmap mDefaultWallpaper;
        private Handler mMainLooperHandler;
        private ArrayMap<LocalWallpaperColorConsumer, ILocalWallpaperColorConsumer>
                mLocalColorCallbacks = new ArrayMap<>();
        private ArrayMap<RectF, ArraySet<LocalWallpaperColorConsumer>> mLocalColorAreas =
                new ArrayMap<>();
        private ILocalWallpaperColorConsumer mLocalColorCallback =
                new ILocalWallpaperColorConsumer.Stub() {
                    @Override
                    public void onColorsChanged(RectF area, WallpaperColors colors) {
                        ArraySet<LocalWallpaperColorConsumer> callbacks =
                                mLocalColorAreas.get(area);
                        if (callbacks == null) return;
                        for (LocalWallpaperColorConsumer callback: callbacks) {
                            callback.onColorsChanged(area, colors);
                        }
                    }
                };

        Globals(IWallpaperManager service, Looper looper) {
            mService = service;
@@ -358,37 +371,46 @@ public class WallpaperManager {
            }
        }

        private ILocalWallpaperColorConsumer wrap(LocalWallpaperColorConsumer callback) {
            ILocalWallpaperColorConsumer callback2 = new ILocalWallpaperColorConsumer.Stub() {
                @Override
                public void onColorsChanged(RectF area, WallpaperColors colors) {
                    callback.onColorsChanged(area, colors);
                }
            };
            mLocalColorCallbacks.put(callback, callback2);
            return callback2;
        }

        public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,
                @NonNull List<RectF> regions, int which, int userId, int displayId) {
            for (RectF area: regions) {
                ArraySet<LocalWallpaperColorConsumer> callbacks = mLocalColorAreas.get(area);
                if (callbacks == null) {
                    callbacks = new ArraySet<>();
                    mLocalColorAreas.put(area, callbacks);
                }
                callbacks.add(callback);
            }
            try {
                mService.addOnLocalColorsChangedListener(wrap(callback) , regions, which,
                mService.addOnLocalColorsChangedListener(mLocalColorCallback , regions, which,
                                                         userId, displayId);
            } catch (RemoteException e) {
                // Can't get colors, connection lost.
                Log.e(TAG, "Can't register for local color updates", e);
            }
        }

        public void removeOnColorsChangedListener(
                @NonNull LocalWallpaperColorConsumer callback, int which, int userId,
                int displayId) {
            ILocalWallpaperColorConsumer callback2 = mLocalColorCallbacks.remove(callback);
            if (callback2 == null) return;
            final ArrayList<RectF> removeAreas = new ArrayList<>();
            for (RectF area : mLocalColorAreas.keySet()) {
                ArraySet<LocalWallpaperColorConsumer> callbacks = mLocalColorAreas.get(area);
                if (callbacks == null) continue;
                callbacks.remove(callback);
                if (callbacks.size() == 0) {
                    mLocalColorAreas.remove(area);
                    removeAreas.add(area);
                }
            }
            try {
                if (removeAreas.size() > 0) {
                    mService.removeOnLocalColorsChangedListener(
                        callback2, which, userId, displayId);
                            mLocalColorCallback, removeAreas, which, userId, displayId);
                }
            } catch (RemoteException e) {
                // Can't get colors, connection lost.
                Log.e(TAG, "Can't unregister for local color updates", e);
            }
        }

+28 −27
Original line number Diff line number Diff line
@@ -90,7 +90,6 @@ import android.system.Os;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -2447,8 +2446,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub

    @Override
    public void removeOnLocalColorsChangedListener(
            @NonNull ILocalWallpaperColorConsumer callback, int which, int userId,
            int displayId) throws RemoteException {
            @NonNull ILocalWallpaperColorConsumer callback, List<RectF> removeAreas, int which,
            int userId, int displayId) throws RemoteException {
        if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
            throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
        }
@@ -2457,43 +2456,45 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            throw new SecurityException("calling user id does not match");
        }
        final long identity = Binder.clearCallingIdentity();
        ArrayList<RectF> removeAreas = new ArrayList<>();
        ArrayList<Pair<RemoteCallbackList, ILocalWallpaperColorConsumer>>
                callbacksToRemove = new ArrayList<>();
        ArrayList<RectF> purgeAreas = new ArrayList<>();
        IBinder binder = callback.asBinder();
        try {
            synchronized (mLock) {
                ArraySet<RectF> areas = mLocalColorCallbackAreas.remove(callback.asBinder());
                mLocalColorCallbackDisplayId.remove(callback.asBinder());
                if (areas == null) areas = new ArraySet<>();
                for (RectF area : areas) {
                    RemoteCallbackList callbacks = mLocalColorAreaCallbacks.get(area);
                    if (callbacks == null) continue;
                    callbacksToRemove.add(new Pair<>(callbacks, callback));
                    if (callbacks.getRegisteredCallbackCount() == 0) {
                        mLocalColorAreaCallbacks.remove(area);
                        removeAreas.add(area);
                    }
                ArraySet<RectF> currentAreas = mLocalColorCallbackAreas.get(binder);
                if (currentAreas == null) return;
                currentAreas.removeAll(removeAreas);
                if (currentAreas.size() == 0) {
                    mLocalColorCallbackDisplayId.remove(binder);
                    for (RectF removeArea : removeAreas) {
                        RemoteCallbackList<ILocalWallpaperColorConsumer> remotes =
                                mLocalColorAreaCallbacks.get(removeArea);
                        if (remotes == null) continue;
                        remotes.unregister(callback);
                        if (remotes.getRegisteredCallbackCount() == 0) {
                            mLocalColorAreaCallbacks.remove(removeArea);
                            purgeAreas.add(removeArea);
                            ArraySet<RectF> displayAreas = mLocalColorDisplayIdAreas.get(displayId);
                            if (displayAreas != null) {
                        displayAreas.remove(area);
                                displayAreas.remove(removeArea);
                                if (displayAreas.size() == 0) {
                                    mLocalColorDisplayIdAreas.remove(displayId);
                                }
                            }
                        }
                    }
            for (int i = 0; i < callbacksToRemove.size(); i++) {
                Pair<RemoteCallbackList, ILocalWallpaperColorConsumer>
                        pair = callbacksToRemove.get(i);
                pair.first.unregister(pair.second);
                }
            }

        } catch (Exception e) {
            // ignore any exception
        } finally {
            Binder.restoreCallingIdentity(identity);
        }

        if (removeAreas.size() == 0) return;
        if (purgeAreas.size() == 0) return;
        IWallpaperEngine engine = getEngine(which, userId, displayId);
        if (engine == null) return;
        engine.removeLocalColorsAreas(removeAreas);
        engine.removeLocalColorsAreas(purgeAreas);
    }

    @Override