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

Commit a598462f authored by Soonil Nagarkar's avatar Soonil Nagarkar
Browse files

Reduce allocations in hot paths

Prevent lambda allocations in common paths in location.

Test: presubmits
Change-Id: Ia4fc7680e8e4304fcd6164a9aded56ed32492cbc
parent 3b726119
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.location;

import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Binder;
@@ -62,7 +64,12 @@ abstract class AbstractListenerManager<TRequest, TListener> {
        }

        private void execute(Consumer<TListener> operation) {
            mExecutor.execute(() -> {
            mExecutor.execute(
                    obtainRunnable(Registration<TRequest, TListener>::accept, this, operation)
                            .recycleOnUse());
        }

        private void accept(Consumer<TListener> operation) {
            TListener listener = mListener;
            if (listener == null) {
                return;
@@ -75,7 +82,6 @@ abstract class AbstractListenerManager<TRequest, TListener> {
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
            });
        }
    }

+80 −64
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import static android.Manifest.permission.LOCATION_HARDWARE;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.app.AlarmManager.ELAPSED_REALTIME;

import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
@@ -57,6 +59,7 @@ import android.util.ArrayMap;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.location.ProviderProperties;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledRunnable;

import java.util.Collections;
import java.util.List;
@@ -81,8 +84,6 @@ import java.util.function.Consumer;
@RequiresFeature(PackageManager.FEATURE_LOCATION)
public class LocationManager {

    private static final String TAG = "LocationManager";

    /**
     * For apps targeting Android K and above, supplied {@link PendingIntent}s must be targeted to a
     * specific package.
@@ -91,7 +92,7 @@ public class LocationManager {
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
    public static final long TARGETED_PENDING_INTENT = 148963590L;
    private static final long TARGETED_PENDING_INTENT = 148963590L;

    /**
     * For apps targeting Android K and above, incomplete locations may not be passed to
@@ -2604,9 +2605,20 @@ public class LocationManager {
                return;
            }

            mExecutor.execute(() -> {
            PooledRunnable runnable =
                    obtainRunnable(GetCurrentLocationTransport::acceptResult, this, location)
                            .recycleOnUse();
            try {
                mExecutor.execute(runnable);
            } catch (RejectedExecutionException e) {
                runnable.recycle();
                throw e;
            }
        }

        private void acceptResult(Location location) {
            Consumer<Location> consumer;
                synchronized (GetCurrentLocationTransport.this) {
            synchronized (this) {
                if (mConsumer == null) {
                    return;
                }
@@ -2615,7 +2627,6 @@ public class LocationManager {
            }

            consumer.accept(location);
            });
        }
    }

@@ -2649,8 +2660,19 @@ public class LocationManager {
                return;
            }

            PooledRunnable runnable =
                    obtainRunnable(LocationListenerTransport::acceptLocation, this, currentExecutor,
                            location).recycleOnUse();
            try {
                currentExecutor.execute(() -> {
                currentExecutor.execute(runnable);
            } catch (RejectedExecutionException e) {
                runnable.recycle();
                locationCallbackFinished();
                throw e;
            }
        }

        private void acceptLocation(Executor currentExecutor, Location location) {
            try {
                if (currentExecutor != mExecutor) {
                    return;
@@ -2666,11 +2688,6 @@ public class LocationManager {
            } finally {
                locationCallbackFinished();
            }
                });
            } catch (RejectedExecutionException e) {
                locationCallbackFinished();
                throw e;
            }
        }

        @Override
@@ -2680,25 +2697,13 @@ public class LocationManager {
                return;
            }

            PooledRunnable runnable =
                    obtainRunnable(LocationListenerTransport::acceptProviderChange, this,
                            currentExecutor, provider, true).recycleOnUse();
            try {
                currentExecutor.execute(() -> {
                    try {
                        if (currentExecutor != mExecutor) {
                            return;
                        }

                        // we may be under the binder identity if a direct executor is used
                        long identity = Binder.clearCallingIdentity();
                        try {
                            mListener.onProviderEnabled(provider);
                        } finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                    } finally {
                        locationCallbackFinished();
                    }
                });
                currentExecutor.execute(runnable);
            } catch (RejectedExecutionException e) {
                runnable.recycle();
                locationCallbackFinished();
                throw e;
            }
@@ -2711,8 +2716,20 @@ public class LocationManager {
                return;
            }

            PooledRunnable runnable =
                    obtainRunnable(LocationListenerTransport::acceptProviderChange, this,
                            currentExecutor, provider, false).recycleOnUse();
            try {
                currentExecutor.execute(() -> {
                currentExecutor.execute(runnable);
            } catch (RejectedExecutionException e) {
                runnable.recycle();
                locationCallbackFinished();
                throw e;
            }
        }

        private void acceptProviderChange(Executor currentExecutor, String provider,
                boolean enabled) {
            try {
                if (currentExecutor != mExecutor) {
                    return;
@@ -2721,18 +2738,17 @@ public class LocationManager {
                // we may be under the binder identity if a direct executor is used
                long identity = Binder.clearCallingIdentity();
                try {
                    if (enabled) {
                        mListener.onProviderEnabled(provider);
                    } else {
                        mListener.onProviderDisabled(provider);
                    }
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            } finally {
                locationCallbackFinished();
            }
                });
            } catch (RejectedExecutionException e) {
                locationCallbackFinished();
                throw e;
            }
        }

        @Override
+14 −3
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.location;

import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;

import android.annotation.Nullable;
import android.content.Context;
import android.location.Location;
@@ -335,7 +337,8 @@ public abstract class AbstractLocationProvider {
     */
    public final void setRequest(ProviderRequest request) {
        // all calls into the provider must be moved onto the provider thread to prevent deadlock
        mExecutor.execute(() -> onSetRequest(request));
        mExecutor.execute(obtainRunnable(AbstractLocationProvider::onSetRequest, this, request)
                .recycleOnUse());
    }

    /**
@@ -348,7 +351,13 @@ public abstract class AbstractLocationProvider {
     */
    public final void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
        // all calls into the provider must be moved onto the provider thread to prevent deadlock
        mExecutor.execute(() -> onExtraCommand(uid, pid, command, extras));

        // the integer boxing done here likely cancels out any gains from removing lambda
        // allocation, but since this an infrequently used api with no real performance needs, we
        // we use pooled lambdas anyways for consistency.
        mExecutor.execute(
                obtainRunnable(AbstractLocationProvider::onExtraCommand, this, uid, pid, command,
                        extras).recycleOnUse());
    }

    /**
@@ -361,7 +370,9 @@ public abstract class AbstractLocationProvider {
     */
    public final void requestSetAllowed(boolean allowed) {
        // all calls into the provider must be moved onto the provider thread to prevent deadlock
        mExecutor.execute(() -> onRequestSetAllowed(allowed));
        mExecutor.execute(
                obtainRunnable(AbstractLocationProvider::onRequestSetAllowed, this, allowed)
                        .recycleOnUse());
    }

    /**
+8 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ import static android.provider.Settings.Secure.LOCATION_COARSE_ACCURACY_M;
import static android.provider.Settings.Secure.LOCATION_MODE;
import static android.provider.Settings.Secure.LOCATION_MODE_OFF;

import static com.android.server.LocationManagerService.D;
import static com.android.server.LocationManagerService.TAG;

import android.app.ActivityManager;
import android.content.Context;
import android.database.ContentObserver;
@@ -37,6 +40,7 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
@@ -423,6 +427,10 @@ public class SettingsHelper {

        @Override
        public void onChange(boolean selfChange, Uri uri, int userId) {
            if (D) {
                Log.d(TAG, "location setting changed [u" + userId + "]: " + uri);
            }

            for (UserSettingChangedListener listener : mListeners) {
                listener.onSettingChanged(userId);
            }
+26 −2
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package com.android.server.location;

import static android.os.UserManager.DISALLOW_SHARE_LOCATION;

import static com.android.server.LocationManagerService.D;
import static com.android.server.LocationManagerService.TAG;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -30,6 +33,7 @@ import android.os.Binder;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
@@ -122,13 +126,13 @@ public class UserInfoHelper {
                    case Intent.ACTION_USER_STARTED:
                        userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                        if (userId != UserHandle.USER_NULL) {
                            onUserChanged(userId, UserListener.USER_STARTED);
                            onUserStarted(userId);
                        }
                        break;
                    case Intent.ACTION_USER_STOPPED:
                        userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                        if (userId != UserHandle.USER_NULL) {
                            onUserChanged(userId, UserListener.USER_STOPPED);
                            onUserStopped(userId);
                        }
                        break;
                    case Intent.ACTION_MANAGED_PROFILE_ADDED:
@@ -161,6 +165,10 @@ public class UserInfoHelper {
            return;
        }

        if (D) {
            Log.d(TAG, "current user switched from u" + mCurrentUserId + " to u" + newUserId);
        }

        int oldUserId = mCurrentUserId;
        mCurrentUserId = newUserId;

@@ -168,6 +176,22 @@ public class UserInfoHelper {
        onUserChanged(newUserId, UserListener.USER_SWITCHED);
    }

    private void onUserStarted(@UserIdInt int userId) {
        if (D) {
            Log.d(TAG, "u" + userId + " started");
        }

        onUserChanged(userId, UserListener.USER_STARTED);
    }

    private void onUserStopped(@UserIdInt int userId) {
        if (D) {
            Log.d(TAG, "u" + userId + " stopped");
        }

        onUserChanged(userId, UserListener.USER_STOPPED);
    }

    private void onUserChanged(@UserIdInt int userId, @UserListener.UserChange int change) {
        for (UserListener listener : mListeners) {
            listener.onUserChanged(userId, change);