diff options
46 files changed, 1341 insertions, 1202 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 0596b3d41eba..e3c61c89dcb9 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4484,11 +4484,11 @@ package android.media.session { } public static interface MediaSessionManager.OnMediaKeyEventDispatchedListener { - method public default void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token); + method public void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token); } public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener { - method public default void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token); + method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token); } public static interface MediaSessionManager.OnMediaKeyListener { diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index 0f33c56be42a..463a1b68f885 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -255,7 +255,15 @@ private: mValid = false; value = 0; // all primitive types can successfully cast 0 } else { - value = *((T*)mBuf); + // When alignof(T) == 1, hopefully the compiler can optimize away + // this conditional as always true. + if ((reinterpret_cast<uintptr_t>(mBuf) % alignof(T)) == 0) { + // We're properly aligned, and can safely make this assignment. + value = *((T*)mBuf); + } else { + // We need to use memcpy. It's slower, but safe. + memcpy(&value, mBuf, sizeof(T)); + } mBuf += sizeof(T); mRemainingLen -= sizeof(T); } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d8b5e7f3b5b0..f31c6148f89f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2873,7 +2873,13 @@ public class Activity extends ContextThemeWrapper } /** - * Called by the system when picture in picture mode should be entered if supported. + * This method is called by the system in various cases where picture in picture mode should be + * entered if supported. + * + * <p>It is up to the app developer to choose whether to call + * {@link #enterPictureInPictureMode(PictureInPictureParams)} at this time. For example, the + * system will call this method when the activity is being put into the background, so the app + * developer might want to switch an activity into PIP mode instead.</p> */ public void onPictureInPictureRequested() { // Previous recommendation was for apps to enter picture-in-picture in onUserLeaveHint() diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java index 89aa770d7f1c..92e9fe492442 100644 --- a/core/java/com/android/internal/app/NetInitiatedActivity.java +++ b/core/java/com/android/internal/app/NetInitiatedActivity.java @@ -23,7 +23,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; -import android.location.LocationManager; +import android.location.LocationManagerInternal; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -32,6 +32,7 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.location.GpsNetInitiatedHandler; +import com.android.server.LocalServices; /** * This activity is shown to the user for him/her to accept or deny network-initiated @@ -68,14 +69,14 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa private final Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { - case GPS_NO_RESPONSE_TIME_OUT: { - if (notificationId != -1) { - sendUserResponse(default_response); + case GPS_NO_RESPONSE_TIME_OUT: { + if (notificationId != -1) { + sendUserResponse(default_response); + } + finish(); } - finish(); - } - break; - default: + break; + default: } } }; @@ -137,9 +138,8 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa // Respond to NI Handler under GnssLocationProvider, 1 = accept, 2 = deny private void sendUserResponse(int response) { if (DEBUG) Log.d(TAG, "sendUserResponse, response: " + response); - LocationManager locationManager = (LocationManager) - this.getSystemService(Context.LOCATION_SERVICE); - locationManager.sendNiResponse(notificationId, response); + LocationManagerInternal lm = LocalServices.getService(LocationManagerInternal.class); + lm.sendNiResponse(notificationId, response); } @UnsupportedAppUsage diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp index 4de6c863638f..39483b55992b 100644 --- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp +++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp @@ -277,13 +277,6 @@ private: SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage) { - static bool gInited; - - if (!gInited) { - - gInited = true; - } - return new SkJavaOutputStream(env, stream, storage); } diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml index 39973715a47d..5c89da05a68c 100644 --- a/data/etc/hiddenapi-package-whitelist.xml +++ b/data/etc/hiddenapi-package-whitelist.xml @@ -53,10 +53,6 @@ Do NOT include any apps that are updatable via Play Store! <hidden-api-whitelisted-app package="com.android.providers.media" /> <hidden-api-whitelisted-app package="com.android.providers.tv" /> <hidden-api-whitelisted-app package="com.android.providers.userdictionary" /> - <!-- TODO (b/141954427): Remove networkstack --> - <hidden-api-whitelisted-app package="com.android.networkstack" /> - <!-- TODO (b/141954427): Remove wifistack --> - <hidden-api-whitelisted-app package="com.android.wifi" /> <hidden-api-whitelisted-app package="com.android.smspush" /> <hidden-api-whitelisted-app package="com.android.spare_parts" /> <hidden-api-whitelisted-app package="com.android.statementservice" /> diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 79bec920c10e..6a5c0ec9457a 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -69,8 +69,6 @@ interface ILocationManager double upperRightLatitude, double upperRightLongitude, int maxResults, in GeocoderParams params, out List<Address> addrs); - boolean sendNiResponse(int notifId, int userResponse); - boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, String packageName, String featureId, String listenerIdentifier); void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections, diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 0c5fe787bbbc..197787e5b6e6 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -2397,21 +2397,6 @@ public class LocationManager { } } - /** - * Used by NetInitiatedActivity to report user response - * for network initiated GPS fix requests. - * - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public boolean sendNiResponse(int notifId, int userResponse) { - try { - return mService.sendNiResponse(notifId, userResponse); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - private void checkPendingIntent(PendingIntent pendingIntent) { Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent"); if (!pendingIntent.isTargetedToPackage()) { diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java index 44d9d2372665..69162bab3167 100644 --- a/location/java/android/location/LocationManagerInternal.java +++ b/location/java/android/location/LocationManagerInternal.java @@ -41,4 +41,19 @@ public abstract class LocationManagerInternal { * @throws IllegalArgumentException if provider is null */ public abstract void requestSetProviderAllowed(@NonNull String provider, boolean allowed); + + /** + * Returns true if the given package belongs to a location provider, and so should be afforded + * some special privileges. + * + * @param packageName The package name to check + * @return True is the given package belongs to a location provider, false otherwise + */ + public abstract boolean isProviderPackage(@NonNull String packageName); + + /** + * Should only be used by GNSS code. + */ + // TODO: there is no reason for this to exist as part of any API. move all the logic into gnss + public abstract void sendNiResponse(int notifId, int userResponse); } diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index aece39d78694..5ef466dfd0e9 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -932,7 +932,7 @@ public final class MediaSessionManager { } /** - * Listener to receive when the media session service + * Listener to be called when the media session service dispatches a media key event. * @hide */ @SystemApi @@ -944,15 +944,15 @@ public final class MediaSessionManager { * is released. * * @param event Dispatched media key event. - * @param packageName Package + * @param packageName The package name * @param sessionToken The media session's token. Can be {@code null}. */ - default void onMediaKeyEventDispatched(@NonNull KeyEvent event, @NonNull String packageName, - @Nullable MediaSession.Token sessionToken) { } + void onMediaKeyEventDispatched(@NonNull KeyEvent event, @NonNull String packageName, + @Nullable MediaSession.Token sessionToken); } /** - * Listener to receive changes in the media key event session, which would receive the media key + * Listener to receive changes in the media key event session, which would receive a media key * event unless specified. * @hide */ @@ -964,13 +964,14 @@ public final class MediaSessionManager { * has specified the target. * <p> * The session token can be {@link null} if the media button session is unset. In that case, - * framework would dispatch to the last sessions's media button receiver. + * framework would dispatch to the last sessions's media button receiver. If the media + * button receive isn't set as well, then it * * @param packageName The package name who would receive the media key event. Can be empty. - * @param sessionToken The media session's token. Can be {@code null.} + * @param sessionToken The media session's token. Can be {@code null}. */ - default void onMediaKeyEventSessionChanged(@NonNull String packageName, - @Nullable MediaSession.Token sessionToken) { } + void onMediaKeyEventSessionChanged(@NonNull String packageName, + @Nullable MediaSession.Token sessionToken); } /** diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index ac06f95cadf4..e954163d51aa 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -866,10 +866,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mOverflowCallback.run(); } - if (update.addedBubble != null) { - mStackView.addBubble(update.addedBubble); - } - // Collapsing? Do this first before remaining steps. if (update.expandedChanged && !update.expanded) { mStackView.setExpanded(false); @@ -916,6 +912,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } + if (update.addedBubble != null) { + mStackView.addBubble(update.addedBubble); + } + if (update.updatedBubble != null) { mStackView.updateBubble(update.updatedBubble); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 685bb9490a9a..6062a3d45be0 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -526,8 +526,13 @@ public class BubbleStackView extends FrameLayout { R.layout.bubble_expanded_view, this /* root */, false /* attachToRoot */); mOverflowExpandedView.setOverflow(true); - mInflater.inflate(R.layout.bubble_overflow_button, this); - mOverflowBtn = findViewById(R.id.bubble_overflow_button); + mOverflowBtn = (ImageView) mInflater.inflate(R.layout.bubble_overflow_button, + this /* root */, + false /* attachToRoot */); + + mBubbleContainer.addView(mOverflowBtn, 0, + new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + mOverflowBtn.setOnClickListener(v -> { setSelectedBubble(null); }); @@ -541,11 +546,13 @@ public class BubbleStackView extends FrameLayout { ColorDrawable bg = new ColorDrawable(bgColor); AdaptiveIconDrawable adaptiveIcon = new AdaptiveIconDrawable(bg, fg); mOverflowBtn.setImageDrawable(adaptiveIcon); + mOverflowBtn.setVisibility(GONE); } void showExpandedViewContents(int displayId) { - if (mOverflowExpandedView.getVirtualDisplayId() == displayId) { + if (mOverflowExpandedView != null + && mOverflowExpandedView.getVirtualDisplayId() == displayId) { mOverflowExpandedView.setContentVisibility(true); } else if (mExpandedBubble != null && mExpandedBubble.getExpandedView().getVirtualDisplayId() == displayId) { @@ -714,7 +721,7 @@ public class BubbleStackView extends FrameLayout { private void updateSystemGestureExcludeRects() { // Exclude the region occupied by the first BubbleView in the stack Rect excludeZone = mSystemGestureExclusionRects.get(0); - if (mBubbleContainer.getChildCount() > 0) { + if (getBubbleCount() > 0) { View firstBubble = mBubbleContainer.getChildAt(0); excludeZone.set(firstBubble.getLeft(), firstBubble.getTop(), firstBubble.getRight(), firstBubble.getBottom()); @@ -775,7 +782,7 @@ public class BubbleStackView extends FrameLayout { Log.d(TAG, "addBubble: " + bubble); } - if (mBubbleContainer.getChildCount() == 0) { + if (getBubbleCount() == 0) { mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide(); } @@ -817,16 +824,13 @@ public class BubbleStackView extends FrameLayout { } if (mIsExpanded) { if (DEBUG_BUBBLE_STACK_VIEW) { - Log.d(TAG, "Expanded && overflow > 0. Show overflow button at"); - Log.d(TAG, "x: " + mExpandedAnimationController.getOverflowBtnLeft()); - Log.d(TAG, "y: " + mExpandedAnimationController.getExpandedY()); + Log.d(TAG, "Show overflow button."); } - mOverflowBtn.setX(mExpandedAnimationController.getOverflowBtnLeft()); - mOverflowBtn.setY(mExpandedAnimationController.getExpandedY()); mOverflowBtn.setVisibility(VISIBLE); - mExpandedAnimationController.setShowOverflowBtn(true); if (apply) { - mExpandedAnimationController.expandFromStack(null /* after */); + mExpandedAnimationController.expandFromStack(() -> { + updatePointerPosition(); + } /* after */); } } else { if (DEBUG_BUBBLE_STACK_VIEW) { @@ -947,7 +951,7 @@ public class BubbleStackView extends FrameLayout { if (mIsExpanded) { if (isIntersecting(mBubbleContainer, x, y)) { // Could be tapping or dragging a bubble while expanded - for (int i = 0; i < mBubbleContainer.getChildCount(); i++) { + for (int i = 0; i < getBubbleCount(); i++) { BadgedImageView view = (BadgedImageView) mBubbleContainer.getChildAt(i); if (isIntersecting(view, x, y)) { return view; @@ -1103,7 +1107,7 @@ public class BubbleStackView extends FrameLayout { /** Return the BubbleView at the given index from the bubble container. */ public BadgedImageView getBubbleAt(int i) { - return mBubbleContainer.getChildCount() > i + return getBubbleCount() > i ? (BadgedImageView) mBubbleContainer.getChildAt(i) : null; } @@ -1567,7 +1571,7 @@ public class BubbleStackView extends FrameLayout { return; } if (!mIsExpanded) { - if (mBubbleContainer.getChildCount() > 0) { + if (getBubbleCount() > 0) { mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect); } // Increase the touch target size of the bubble @@ -1661,7 +1665,7 @@ public class BubbleStackView extends FrameLayout { /** Sets the appropriate Z-order and dot position for each bubble in the stack. */ private void updateBubbleZOrdersAndDotPosition(boolean animate) { - int bubbleCount = mBubbleContainer.getChildCount(); + int bubbleCount = getBubbleCount(); for (int i = 0; i < bubbleCount; i++) { BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i); bv.setZ((mMaxBubbles * mBubbleElevation) - i); @@ -1677,30 +1681,23 @@ public class BubbleStackView extends FrameLayout { if (expandedBubble == null) { return; } - int index = getBubbleIndex(expandedBubble); - if (index >= mMaxBubbles) { - // In between state, where extra bubble will be overflowed, and new bubble added - index = 0; - } float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index); float halfBubble = mBubbleSize / 2f; float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble; // Padding might be adjusted for insets, so get it directly from the view bubbleCenter -= mExpandedViewContainer.getPaddingLeft(); - - if (index >= mMaxBubbles) { - Bubble first = mBubbleData.getBubbles().get(0); - first.getExpandedView().setPointerPosition(bubbleCenter); - } else { - expandedBubble.getExpandedView().setPointerPosition(bubbleCenter); - } + expandedBubble.getExpandedView().setPointerPosition(bubbleCenter); } /** * @return the number of bubbles in the stack view. */ public int getBubbleCount() { + if (BubbleExperimentConfig.allowBubbleOverflow(mContext)) { + // Subtract 1 for the overflow button which is always in the bubble container. + return mBubbleContainer.getChildCount() - 1; + } return mBubbleContainer.getChildCount(); } @@ -1797,7 +1794,7 @@ public class BubbleStackView extends FrameLayout { /** For debugging only */ List<Bubble> getBubblesOnScreen() { List<Bubble> bubbles = new ArrayList<>(); - for (int i = 0; i < mBubbleContainer.getChildCount(); i++) { + for (int i = 0; i < getBubbleCount(); i++) { View child = mBubbleContainer.getChildAt(i); if (child instanceof BadgedImageView) { String key = ((BadgedImageView) child).getKey(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java index 6d6969da8c8a..aa549dc23f9b 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -31,6 +31,7 @@ import androidx.dynamicanimation.animation.SpringForce; import com.android.systemui.Interpolators; import com.android.systemui.R; +import com.android.systemui.bubbles.BubbleExperimentConfig; import com.google.android.collect.Sets; @@ -67,13 +68,13 @@ public class ExpandedAnimationController private float mBubblePaddingTop; /** Size of each bubble. */ private float mBubbleSizePx; - /** Width of the overflow button. */ - private float mOverflowBtnWidth; + /** Space between bubbles in row above expanded view. */ + private float mSpaceBetweenBubbles; /** Height of the status bar. */ private float mStatusBarHeight; /** Size of display. */ private Point mDisplaySize; - /** Max number of bubbles shown in row above expanded view.*/ + /** Max number of bubbles shown in row above expanded view. */ private int mBubblesMaxRendered; /** What the current screen orientation is. */ private int mScreenOrientation; @@ -99,7 +100,6 @@ public class ExpandedAnimationController private boolean mSpringingBubbleToTouch = false; private int mExpandedViewPadding; - private boolean mShowOverflowBtn; public ExpandedAnimationController(Point displaySize, int expandedViewPadding, int orientation) { @@ -153,14 +153,6 @@ public class ExpandedAnimationController } } - public void setShowOverflowBtn(boolean showBtn) { - mShowOverflowBtn = showBtn; - } - - public boolean getShowOverflowBtn() { - return mShowOverflowBtn; - } - /** * Animates the bubbles along a curved path, either to expand them along the top or collapse * them back into a stack. @@ -369,10 +361,10 @@ public class ExpandedAnimationController } final WindowInsets insets = mLayout.getRootWindowInsets(); return mBubblePaddingTop + Math.max( - mStatusBarHeight, - insets.getDisplayCutout() != null - ? insets.getDisplayCutout().getSafeInsetTop() - : 0); + mStatusBarHeight, + insets.getDisplayCutout() != null + ? insets.getDisplayCutout().getSafeInsetTop() + : 0); } /** Description of current animation controller state. */ @@ -391,11 +383,15 @@ public class ExpandedAnimationController mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top); mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size); - mOverflowBtnWidth = mBubbleSizePx; mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered); + // Includes overflow button. + float totalGapWidth = getWidthForDisplayingBubbles() - (mExpandedViewPadding * 2) + - (mBubblesMaxRendered + 1) * mBubbleSizePx; + mSpaceBetweenBubbles = totalGapWidth / mBubblesMaxRendered; + // Ensure that all child views are at 1x scale, and visible, in case they were animating // in. mLayout.setVisibility(View.VISIBLE); @@ -506,18 +502,10 @@ public class ExpandedAnimationController * @return Bubble left x from left edge of screen. */ public float getBubbleLeft(int index) { - final float bubbleFromRowLeft = index * (mBubbleSizePx + getSpaceBetweenBubbles()); + final float bubbleFromRowLeft = index * (mBubbleSizePx + mSpaceBetweenBubbles); return getRowLeft() + bubbleFromRowLeft; } - public float getOverflowBtnLeft() { - if (mLayout == null || mLayout.getChildCount() == 0) { - return 0; - } - return getBubbleLeft(mLayout.getChildCount() - 1) + mBubbleSizePx - + getSpaceBetweenBubbles(); - } - /** * When expanded, the bubbles are centered in the screen. In portrait, all available space is * used. In landscape we have too much space so the value is restricted. This method accounts @@ -539,7 +527,7 @@ public class ExpandedAnimationController * Determines the available screen width without the cutout. * * @param subtractStableInsets Whether or not stable insets should also be removed from the - * returned width. + * returned width. * @return the total screen width available accounting for cutouts and insets, * iff {@param includeStableInsets} is true. */ @@ -566,38 +554,13 @@ public class ExpandedAnimationController if (mLayout == null) { return 0; } - - int bubbleCount = mLayout.getChildCount(); - - final float totalBubbleWidth = bubbleCount * mBubbleSizePx; - final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles(); - float rowWidth = totalGapWidth + totalBubbleWidth; - if (mShowOverflowBtn) { - rowWidth += getSpaceBetweenBubbles(); - rowWidth += mOverflowBtnWidth; - } + float rowWidth = (mLayout.getChildCount() * mBubbleSizePx) + + ((mLayout.getChildCount() - 1) * mSpaceBetweenBubbles); // This display size we're using includes the size of the insets, we want the true // center of the display minus the notch here, which means we should include the // stable insets (e.g. status bar, nav bar) in this calculation. final float trueCenter = getAvailableScreenWidth(false /* subtractStableInsets */) / 2f; - final float halfRow = rowWidth / 2f; - final float rowLeft = trueCenter - halfRow; - return rowLeft; - } - - /** - * @return Space between bubbles in row above expanded view. - */ - private float getSpaceBetweenBubbles() { - final float totalBubbleWidth = mBubblesMaxRendered * mBubbleSizePx; - final float rowMargins = mExpandedViewPadding * 2; - float totalGapWidth = getWidthForDisplayingBubbles() - rowMargins - totalBubbleWidth; - if (mShowOverflowBtn) { - totalGapWidth -= mBubbleSizePx; - } - final int gapCount = mBubblesMaxRendered - 1; - final float gapWidth = totalGapWidth / gapCount; - return gapWidth; + return trueCenter - (rowWidth / 2f); } } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java index e14581ffcde8..e8509b366c5b 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java @@ -26,6 +26,7 @@ import com.android.systemui.InitController; import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.SystemUIFactory; import com.android.systemui.fragments.FragmentService; +import com.android.systemui.keyguard.KeyguardSliceProvider; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.InjectionInflationController; @@ -105,4 +106,9 @@ public interface SystemUIRootComponent { * Member injection into the supplied argument. */ void inject(ContentProvider contentProvider); + + /** + * Member injection into the supplied argument. + */ + void inject(KeyguardSliceProvider keyguardSliceProvider); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java index e66a9fadb937..2cc3d9e22a7d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java @@ -52,13 +52,13 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SystemUIAppComponentFactory; +import com.android.systemui.SystemUIFactory; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.NextAlarmController; -import com.android.systemui.statusbar.policy.NextAlarmControllerImpl; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.wakelock.SettableWakeLock; import com.android.systemui.util.wakelock.WakeLock; @@ -68,6 +68,8 @@ import java.util.Locale; import java.util.TimeZone; import java.util.concurrent.TimeUnit; +import javax.inject.Inject; + /** * Simple Slice provider that shows the current date. */ @@ -108,26 +110,31 @@ public class KeyguardSliceProvider extends SliceProvider implements private final Handler mHandler; private final Handler mMediaHandler; private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm; - private DozeParameters mDozeParameters; + @Inject + public DozeParameters mDozeParameters; @VisibleForTesting protected SettableWakeLock mMediaWakeLock; - @VisibleForTesting - protected ZenModeController mZenModeController; + @Inject + public ZenModeController mZenModeController; private String mDatePattern; private DateFormat mDateFormat; private String mLastText; private boolean mRegistered; private String mNextAlarm; - private NextAlarmController mNextAlarmController; - @VisibleForTesting - protected AlarmManager mAlarmManager; - @VisibleForTesting - protected ContentResolver mContentResolver; + @Inject + public NextAlarmController mNextAlarmController; + @Inject + public AlarmManager mAlarmManager; + @Inject + public ContentResolver mContentResolver; private AlarmManager.AlarmClockInfo mNextAlarmInfo; private PendingIntent mPendingIntent; - protected NotificationMediaManager mMediaManager; - private StatusBarStateController mStatusBarStateController; - private KeyguardBypassController mKeyguardBypassController; + @Inject + public NotificationMediaManager mMediaManager; + @Inject + public StatusBarStateController mStatusBarStateController; + @Inject + public KeyguardBypassController mKeyguardBypassController; private CharSequence mMediaTitle; private CharSequence mMediaArtist; protected boolean mDozing; @@ -188,26 +195,6 @@ public class KeyguardSliceProvider extends SliceProvider implements mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI); } - /** - * Initialize dependencies that don't exist during {@link android.content.ContentProvider} - * instantiation. - * - * @param mediaManager {@link NotificationMediaManager} singleton. - * @param statusBarStateController {@link StatusBarStateController} singleton. - */ - public void initDependencies( - NotificationMediaManager mediaManager, - StatusBarStateController statusBarStateController, - KeyguardBypassController keyguardBypassController, - DozeParameters dozeParameters) { - mMediaManager = mediaManager; - mMediaManager.addCallback(this); - mStatusBarStateController = statusBarStateController; - mStatusBarStateController.addCallback(this); - mKeyguardBypassController = keyguardBypassController; - mDozeParameters = dozeParameters; - } - @AnyThread @Override public Slice onBindSlice(Uri sliceUri) { @@ -310,25 +297,19 @@ public class KeyguardSliceProvider extends SliceProvider implements @Override public boolean onCreateSliceProvider() { - if (mContextAvailableCallback != null) { - mContextAvailableCallback.onContextAvailable(getContext()); - } + mContextAvailableCallback.onContextAvailable(getContext()); + inject(); synchronized (KeyguardSliceProvider.sInstanceLock) { KeyguardSliceProvider oldInstance = KeyguardSliceProvider.sInstance; if (oldInstance != null) { oldInstance.onDestroy(); } - - mAlarmManager = getContext().getSystemService(AlarmManager.class); - mContentResolver = getContext().getContentResolver(); - mNextAlarmController = new NextAlarmControllerImpl(getContext()); - mNextAlarmController.addCallback(this); - mZenModeController = Dependency.get(ZenModeController.class); - mZenModeController.addCallback(this); mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern); mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0); - mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"), - "media"); + mMediaManager.addCallback(this); + mStatusBarStateController.addCallback(this); + mNextAlarmController.addCallback(this); + mZenModeController.addCallback(this); KeyguardSliceProvider.sInstance = this; registerClockUpdate(); updateClockLocked(); @@ -337,6 +318,13 @@ public class KeyguardSliceProvider extends SliceProvider implements } @VisibleForTesting + protected void inject() { + SystemUIFactory.getInstance().getRootComponent().inject(this); + mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"), + "media"); + } + + @VisibleForTesting protected void onDestroy() { synchronized (KeyguardSliceProvider.sInstanceLock) { mNextAlarmController.removeCallback(this); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index b682cb09b598..3fcd1c19370f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -31,7 +31,6 @@ import android.text.SpannableStringBuilder; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.util.Log; -import android.util.StatsLog; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; @@ -41,6 +40,7 @@ import android.view.Window; import android.widget.ImageView; import android.widget.TextView; +import com.android.internal.util.FrameworkStatsLog; import com.android.systemui.Dependency; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; @@ -122,7 +122,7 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic private void handleClick() { showDeviceMonitoringDialog(); DevicePolicyEventLogger - .createEvent(StatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED) + .createEvent(FrameworkStatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED) .write(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 976531d8b49d..d38f1b99cb9a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -79,6 +79,7 @@ public class NotificationLockscreenUserManagerImpl implements private final DeviceProvisionedController mDeviceProvisionedController; private final KeyguardStateController mKeyguardStateController; + private final Object mLock = new Object(); // Lazy private NotificationEntryManager mEntryManager; @@ -181,6 +182,7 @@ public class NotificationLockscreenUserManagerImpl implements protected final Context mContext; private final Handler mMainHandler; protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); + protected final ArrayList<UserInfo> mCurrentManagedProfiles = new ArrayList<>(); protected int mCurrentUserId = 0; protected NotificationPresenter mPresenter; @@ -300,7 +302,7 @@ public class NotificationLockscreenUserManagerImpl implements } public boolean isCurrentProfile(int userId) { - synchronized (mCurrentProfiles) { + synchronized (mLock) { return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null; } } @@ -417,6 +419,20 @@ public class NotificationLockscreenUserManagerImpl implements return mUsersAllowingPrivateNotifications.get(userHandle); } + /** + * If all managed profiles (work profiles) can show private data in public (secure & locked.) + */ + public boolean allowsManagedPrivateNotificationsInPublic() { + synchronized (mLock) { + for (UserInfo profile : mCurrentManagedProfiles) { + if (!userAllowsPrivateNotificationsInPublic(profile.id)) { + return false; + } + } + } + return true; + } + private boolean adminAllowsKeyguardFeature(int userHandle, int feature) { if (userHandle == UserHandle.USER_ALL) { return true; @@ -495,11 +511,15 @@ public class NotificationLockscreenUserManagerImpl implements } private void updateCurrentProfilesCache() { - synchronized (mCurrentProfiles) { + synchronized (mLock) { mCurrentProfiles.clear(); + mCurrentManagedProfiles.clear(); if (mUserManager != null) { for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) { mCurrentProfiles.put(user.id, user); + if (UserManager.USER_TYPE_PROFILE_MANAGED.equals(user.userType)) { + mCurrentManagedProfiles.add(user); + } } } } @@ -510,10 +530,29 @@ public class NotificationLockscreenUserManagerImpl implements }); } + /** + * If any of the profiles are in public mode. + */ public boolean isAnyProfilePublicMode() { - for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { - if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) { - return true; + synchronized (mLock) { + for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { + if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) { + return true; + } + } + } + return false; + } + + /** + * If any managed/work profiles are in public mode. + */ + public boolean isAnyManagedProfilePublicMode() { + synchronized (mLock) { + for (int i = mCurrentManagedProfiles.size() - 1; i >= 0; i--) { + if (isLockscreenPublicMode(mCurrentManagedProfiles.get(i).id)) { + return true; + } } } return false; @@ -620,9 +659,17 @@ public class NotificationLockscreenUserManagerImpl implements pw.print(" mAllowLockscreenRemoteInput="); pw.println(mAllowLockscreenRemoteInput); pw.print(" mCurrentProfiles="); - for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { - final int userId = mCurrentProfiles.valueAt(i).id; - pw.print("" + userId + " "); + synchronized (mLock) { + for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { + final int userId = mCurrentProfiles.valueAt(i).id; + pw.print("" + userId + " "); + } + } + pw.print(" mCurrentManagedProfiles="); + synchronized (mLock) { + for (UserInfo userInfo : mCurrentManagedProfiles) { + pw.print("" + userInfo.id + " "); + } } pw.println(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index ad1aa8370495..b4d0d479ff39 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -33,7 +33,7 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class KeyguardBypassController : Dumpable { +open class KeyguardBypassController : Dumpable { private val mKeyguardStateController: KeyguardStateController private val statusBarStateController: StatusBarStateController diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 4e8442f14dba..1726b4884aff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -144,7 +144,6 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.keyguard.DismissCallbackRegistry; -import com.android.systemui.keyguard.KeyguardSliceProvider; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; @@ -794,13 +793,6 @@ public class StatusBar extends SystemUI implements DemoMode, mBypassHeadsUpNotifier.setUp(mEntryManager); mBubbleController.setExpandListener(mBubbleExpandListener); mActivityIntentHelper = new ActivityIntentHelper(mContext); - KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance(); - if (sliceProvider != null) { - sliceProvider.initDependencies(mMediaManager, mStatusBarStateController, - mKeyguardBypassController, mDozeParameters); - } else { - Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies"); - } mColorExtractor.addOnColorsChangedListener(this); mStatusBarStateController.addCallback(this, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java index c9b6790166e3..92c1d7601106 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java @@ -51,6 +51,7 @@ import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.wakelock.SettableWakeLock; @@ -87,6 +88,8 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { private SettableWakeLock mMediaWakeLock; @Mock private DozeParameters mDozeParameters; + @Mock + private NextAlarmController mNextAlarmController; private KeyguardUpdateMonitor mKeyguardUpdateMonitor; private TestableKeyguardSliceProvider mProvider; private boolean mIsZenMode; @@ -97,9 +100,9 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { mKeyguardUpdateMonitor = mDependency.injectMockDependency(KeyguardUpdateMonitor.class); mIsZenMode = false; mProvider = new TestableKeyguardSliceProvider(); + mProvider.setContextAvailableCallback(context -> { }); mProvider.attachInfo(getContext(), null); - mProvider.initDependencies(mNotificationMediaManager, mStatusBarStateController, - mKeyguardBypassController, mDozeParameters); + reset(mContentResolver); SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST))); } @@ -254,13 +257,16 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { } @Override - public boolean onCreateSliceProvider() { - super.onCreateSliceProvider(); + protected void inject() { mAlarmManager = KeyguardSliceProviderTest.this.mAlarmManager; mContentResolver = KeyguardSliceProviderTest.this.mContentResolver; mZenModeController = KeyguardSliceProviderTest.this.mZenModeController; mMediaWakeLock = KeyguardSliceProviderTest.this.mMediaWakeLock; - return true; + mDozeParameters = KeyguardSliceProviderTest.this.mDozeParameters; + mNextAlarmController = KeyguardSliceProviderTest.this.mNextAlarmController; + mStatusBarStateController = KeyguardSliceProviderTest.this.mStatusBarStateController; + mKeyguardBypassController = KeyguardSliceProviderTest.this.mKeyguardBypassController; + mMediaManager = KeyguardSliceProviderTest.this.mNotificationMediaManager; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java index 3a6accea2b54..c6d57e6df028 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java @@ -95,7 +95,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { @Mock private KeyguardStateController mKeyguardStateController; - private int mCurrentUserId; + private UserInfo mCurrentUser; + private UserInfo mSecondaryUser; + private UserInfo mWorkUser; private TestNotificationLockscreenUserManager mLockscreenUserManager; @Before @@ -103,10 +105,14 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); - mCurrentUserId = ActivityManager.getCurrentUser(); + int currentUserId = ActivityManager.getCurrentUser(); + mCurrentUser = new UserInfo(currentUserId, "", 0); + mSecondaryUser = new UserInfo(currentUserId + 1, "", 0); + mWorkUser = new UserInfo(currentUserId + 2, "" /* name */, null /* iconPath */, 0, + UserManager.USER_TYPE_PROFILE_MANAGED); - when(mUserManager.getProfiles(mCurrentUserId)).thenReturn(Lists.newArrayList( - new UserInfo(mCurrentUserId, "", 0), new UserInfo(mCurrentUserId + 1, "", 0))); + when(mUserManager.getProfiles(currentUserId)).thenReturn(Lists.newArrayList( + mCurrentUser, mSecondaryUser, mWorkUser)); mDependency.injectTestDependency(Dependency.MAIN_HANDLER, Handler.createAsync(Looper.myLooper())); @@ -141,15 +147,31 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); - assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUserId)); + assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id)); } @Test public void testLockScreenAllowPrivateNotificationsFalse() { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, mCurrentUser.id); + mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); + assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id)); + } + + @Test + public void testLockScreenAllowsWorkPrivateNotificationsFalse() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, mWorkUser.id); + mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); + assertFalse(mLockscreenUserManager.allowsManagedPrivateNotificationsInPublic()); + } + + @Test + public void testLockScreenAllowsWorkPrivateNotificationsTrue() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mWorkUser.id); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); - assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUserId)); + assertTrue(mLockscreenUserManager.allowsManagedPrivateNotificationsInPublic()); } @Test @@ -163,16 +185,16 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { public void testActionUserSwitchedCallsOnUserSwitched() { Intent intent = new Intent() .setAction(ACTION_USER_SWITCHED) - .putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId + 1); + .putExtra(Intent.EXTRA_USER_HANDLE, mSecondaryUser.id); mLockscreenUserManager.getBaseBroadcastReceiverForTest().onReceive(mContext, intent); - verify(mPresenter, times(1)).onUserSwitched(mCurrentUserId + 1); + verify(mPresenter, times(1)).onUserSwitched(mSecondaryUser.id); } @Test public void testIsLockscreenPublicMode() { - assertFalse(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUserId)); - mLockscreenUserManager.setLockscreenPublicMode(true, mCurrentUserId); - assertTrue(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUserId)); + assertFalse(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id)); + mLockscreenUserManager.setLockscreenPublicMode(true, mCurrentUser.id); + assertTrue(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id)); } @Test diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index f1f2d2abea3f..3bc93cc13023 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -30,7 +30,6 @@ import static android.os.PowerManager.locationPowerSaveModeToString; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -88,6 +87,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.server.location.AbstractLocationProvider; import com.android.server.location.AbstractLocationProvider.State; +import com.android.server.location.AppForegroundHelper; import com.android.server.location.CallerIdentity; import com.android.server.location.GeocoderProxy; import com.android.server.location.GeofenceManager; @@ -98,12 +98,12 @@ import com.android.server.location.LocationProviderProxy; import com.android.server.location.LocationRequestStatistics; import com.android.server.location.LocationRequestStatistics.PackageProviderKey; import com.android.server.location.LocationRequestStatistics.PackageStatistics; -import com.android.server.location.LocationSettingsStore; import com.android.server.location.LocationUsageLogger; import com.android.server.location.MockProvider; import com.android.server.location.MockableLocationProvider; import com.android.server.location.PassiveProvider; -import com.android.server.location.UserInfoStore; +import com.android.server.location.SettingsHelper; +import com.android.server.location.UserInfoHelper; import com.android.server.location.gnss.GnssManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; @@ -140,7 +140,6 @@ public class LocationManagerService extends ILocationManager.Stub { public Lifecycle(Context context) { super(context); mService = new LocationManagerService(context); - LocalServices.addService(LocationManagerInternal.class, mService.new LocalService()); } @Override @@ -181,9 +180,6 @@ public class LocationManagerService extends ILocationManager.Stub { // maximum age of a location before it is no longer considered "current" private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000; - private static final int FOREGROUND_IMPORTANCE_CUTOFF - = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - // Location Providers may sometimes deliver location updates // slightly faster that requested - provide grace period so // we don't unnecessarily filter events that are otherwise on @@ -195,21 +191,23 @@ public class LocationManagerService extends ILocationManager.Stub { private final Object mLock = new Object(); private final Context mContext; private final Handler mHandler; - private final UserInfoStore mUserInfoStore; - private final LocationSettingsStore mSettingsStore; + private final LocalService mLocalService; + private final UserInfoHelper mUserInfoHelper; + private final SettingsHelper mSettingsHelper; + private final AppForegroundHelper mAppForegroundHelper; private final LocationUsageLogger mLocationUsageLogger; + @Nullable private GnssManagerService mGnssManagerService = null; + private final PassiveLocationProviderManager mPassiveManager; private AppOpsManager mAppOps; private PackageManager mPackageManager; private PowerManager mPowerManager; - private ActivityManager mActivityManager; private GeofenceManager mGeofenceManager; private LocationFudger mLocationFudger; private GeocoderProxy mGeocodeProvider; - @Nullable private GnssManagerService mGnssManagerService; @GuardedBy("mLock") private String mExtraLocationControllerPackage; @@ -245,8 +243,13 @@ public class LocationManagerService extends ILocationManager.Stub { private LocationManagerService(Context context) { mContext = context; mHandler = FgThread.getHandler(); - mUserInfoStore = new UserInfoStore(mContext); - mSettingsStore = new LocationSettingsStore(mContext, mHandler); + mLocalService = new LocalService(); + + LocalServices.addService(LocationManagerInternal.class, mLocalService); + + mUserInfoHelper = new UserInfoHelper(mContext); + mSettingsHelper = new SettingsHelper(mContext, mHandler); + mAppForegroundHelper = new AppForegroundHelper(mContext); mLocationUsageLogger = new LocationUsageLogger(); // set up passive provider - we do this early because it has no dependencies on system @@ -272,17 +275,23 @@ public class LocationManagerService extends ILocationManager.Stub { } private void onSystemReady() { - mUserInfoStore.onSystemReady(); - mSettingsStore.onSystemReady(); + mUserInfoHelper.onSystemReady(); + mSettingsHelper.onSystemReady(); + mAppForegroundHelper.onSystemReady(); + + if (GnssManagerService.isGnssSupported()) { + mGnssManagerService = new GnssManagerService(mContext, mSettingsHelper, + mAppForegroundHelper, mLocationUsageLogger); + mGnssManagerService.onSystemReady(); + } synchronized (mLock) { mPackageManager = mContext.getPackageManager(); mAppOps = mContext.getSystemService(AppOpsManager.class); mPowerManager = mContext.getSystemService(PowerManager.class); - mActivityManager = mContext.getSystemService(ActivityManager.class); mLocationFudger = new LocationFudger(mContext, mHandler); - mGeofenceManager = new GeofenceManager(mContext, mSettingsStore); + mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper); PowerManagerInternal localPowerManager = LocalServices.getService(PowerManagerInternal.class); @@ -313,17 +322,6 @@ public class LocationManagerService extends ILocationManager.Stub { } }); }); - mActivityManager.addOnUidImportanceListener( - (uid, importance) -> { - // listener invoked on ui thread, move to our thread to reduce risk of - // blocking ui thread - mHandler.post(() -> { - synchronized (mLock) { - onUidImportanceChangedLocked(uid, importance); - } - }); - }, - FOREGROUND_IMPORTANCE_CUTOFF); localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION, state -> { @@ -337,26 +335,13 @@ public class LocationManagerService extends ILocationManager.Stub { }); mBatterySaverMode = mPowerManager.getLocationPowerSaveMode(); - mSettingsStore.addOnLocationEnabledChangedListener((userId) -> { - synchronized (mLock) { - onLocationModeChangedLocked(userId); - } - }); - mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> { - synchronized (mLock) { - onBackgroundThrottleIntervalChangedLocked(); - } - }); - mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> { - synchronized (mLock) { - onBackgroundThrottleWhitelistChangedLocked(); - } - }); - mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> { - synchronized (mLock) { - onIgnoreSettingsWhitelistChangedLocked(); - } - }); + mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged); + mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener( + this::onBackgroundThrottleIntervalChanged); + mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener( + this::onBackgroundThrottleWhitelistChanged); + mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener( + this::onIgnoreSettingsWhitelistChanged); new PackageMonitor() { @Override @@ -367,11 +352,9 @@ public class LocationManagerService extends ILocationManager.Stub { } }.register(mContext, mHandler.getLooper(), true); - mUserInfoStore.addListener((oldUserId, newUserId) -> { - synchronized (mLock) { - onUserChangedLocked(oldUserId, newUserId); - } - }); + mUserInfoHelper.addListener(this::onUserChanged); + + mAppForegroundHelper.addListener(this::onAppForegroundChanged); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); @@ -398,7 +381,7 @@ public class LocationManagerService extends ILocationManager.Stub { // switching the user from null to current here performs the bulk of the initialization // work. the user being changed will cause a reload of all user specific settings, which // causes initialization, and propagates changes until a steady state is reached - onUserChangedLocked(UserHandle.USER_NULL, mUserInfoStore.getCurrentUserId()); + onUserChanged(UserHandle.USER_NULL, mUserInfoHelper.getCurrentUserId()); } } @@ -455,20 +438,23 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @GuardedBy("mLock") - private void onLocationModeChangedLocked(int userId) { + private void onLocationModeChanged(int userId) { + boolean enabled = mSettingsHelper.isLocationEnabled(userId); + if (D) { - Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId)); + Log.d(TAG, "[u" + userId + "] location enabled = " + enabled); } - Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION) - .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabledForUser(userId)) - .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) - .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); + synchronized (mLock) { + Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION) + .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) + .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); - for (LocationProviderManager manager : mProviderManagers) { + for (LocationProviderManager manager : mProviderManagers) { manager.onEnabledChangedLocked(userId); + } } } @@ -493,58 +479,55 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @GuardedBy("mLock") - private void onUidImportanceChangedLocked(int uid, int importance) { - boolean foreground = LocationManagerServiceUtils.isImportanceForeground(importance); - HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size()); - for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { - String provider = entry.getKey(); - for (UpdateRecord record : entry.getValue()) { - if (record.mReceiver.mCallerIdentity.mUid == uid - && record.mIsForegroundUid != foreground) { - if (D) { - Log.d(TAG, "request from uid " + uid + " is now " - + LocationManagerServiceUtils.foregroundAsString( - foreground)); - } - record.updateForeground(foreground); + private void onAppForegroundChanged(int uid, boolean foreground) { + synchronized (mLock) { + HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size()); + for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { + String provider = entry.getKey(); + for (UpdateRecord record : entry.getValue()) { + if (record.mReceiver.mCallerIdentity.mUid == uid + && record.mIsForegroundUid != foreground) { + record.updateForeground(foreground); - if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) { - affectedProviders.add(provider); + if (!isThrottlingExempt(record.mReceiver.mCallerIdentity)) { + affectedProviders.add(provider); + } } } } - } - for (String provider : affectedProviders) { - applyRequirementsLocked(provider); + for (String provider : affectedProviders) { + applyRequirementsLocked(provider); + } } } - @GuardedBy("mLock") - private void onBackgroundThrottleIntervalChangedLocked() { - for (LocationProviderManager manager : mProviderManagers) { - applyRequirementsLocked(manager); + private void onBackgroundThrottleIntervalChanged() { + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + applyRequirementsLocked(manager); + } } } - @GuardedBy("mLock") - private void onBackgroundThrottleWhitelistChangedLocked() { - for (LocationProviderManager manager : mProviderManagers) { - applyRequirementsLocked(manager); + private void onBackgroundThrottleWhitelistChanged() { + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + applyRequirementsLocked(manager); + } } } - @GuardedBy("lock") - private void onIgnoreSettingsWhitelistChangedLocked() { - for (LocationProviderManager manager : mProviderManagers) { - applyRequirementsLocked(manager); + private void onIgnoreSettingsWhitelistChanged() { + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + applyRequirementsLocked(manager); + } } } @GuardedBy("mLock") private void initializeProvidersLocked() { - if (GnssManagerService.isGnssSupported()) { - mGnssManagerService = new GnssManagerService(this, mContext, mLocationUsageLogger); + if (mGnssManagerService != null) { LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER); mProviderManagers.add(gnssManager); gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider()); @@ -627,19 +610,20 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @GuardedBy("mLock") - private void onUserChangedLocked(int oldUserId, int newUserId) { + private void onUserChanged(int oldUserId, int newUserId) { if (D) { Log.d(TAG, "foreground user is changing to " + newUserId); } - for (LocationProviderManager manager : mProviderManagers) { - // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility - mSettingsStore.setLocationProviderAllowed(manager.getName(), - manager.isEnabled(newUserId), newUserId); + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility + mSettingsHelper.setLocationProviderAllowed(manager.getName(), + manager.isEnabled(newUserId), newUserId); - manager.onEnabledChangedLocked(oldUserId); - manager.onEnabledChangedLocked(newUserId); + manager.onEnabledChangedLocked(oldUserId); + manager.onEnabledChangedLocked(newUserId); + } } } @@ -778,7 +762,7 @@ public class LocationManagerService extends ILocationManager.Stub { // it would be more correct to call this for all users, but we know this can // only affect the current user since providers are disabled for non-current // users - onEnabledChangedLocked(mUserInfoStore.getCurrentUserId()); + onEnabledChangedLocked(mUserInfoHelper.getCurrentUserId()); } } @@ -787,14 +771,14 @@ public class LocationManagerService extends ILocationManager.Stub { } public boolean isEnabled() { - return isEnabled(mUserInfoStore.getCurrentUserId()); + return isEnabled(mUserInfoHelper.getCurrentUserId()); } public boolean isEnabled(int userId) { synchronized (mLock) { // normalize user id to always refer to parent since profile state is always the // same as parent state - userId = mUserInfoStore.getParentUserId(userId); + userId = mUserInfoHelper.getParentUserId(userId); return mEnabled.get(userId, Boolean.FALSE); } } @@ -808,13 +792,13 @@ public class LocationManagerService extends ILocationManager.Stub { // normalize user id to always refer to parent since profile state is always the same // as parent state - userId = mUserInfoStore.getParentUserId(userId); + userId = mUserInfoHelper.getParentUserId(userId); // if any property that contributes to "enabled" here changes state, it MUST result // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to // guarantee that it will always eventually reach the correct state. - boolean enabled = (userId == mUserInfoStore.getCurrentUserId()) - && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().allowed; + boolean enabled = (userId == mUserInfoHelper.getCurrentUserId()) + && mSettingsHelper.isLocationEnabled(userId) && mProvider.getState().allowed; if (enabled == isEnabled(userId)) { return; @@ -829,7 +813,7 @@ public class LocationManagerService extends ILocationManager.Stub { // fused and passive provider never get public updates for legacy reasons if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) { // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility - mSettingsStore.setLocationProviderAllowed(mName, enabled, userId); + mSettingsHelper.setLocationProviderAllowed(mName, enabled, userId); Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION) .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName) @@ -1009,7 +993,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (manager == null) { continue; } - if (!manager.isEnabled() && !isSettingsExemptLocked(updateRecord)) { + if (!manager.isEnabled() && !isSettingsExempt(updateRecord)) { continue; } @@ -1475,13 +1459,13 @@ public class LocationManagerService extends ILocationManager.Stub { ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName()); if (records != null) { for (UpdateRecord record : records) { - if (!mUserInfoStore.isCurrentUserOrProfile( + if (!mUserInfoHelper.isCurrentUserOrProfile( UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { continue; } // requests that ignore location settings will never provide notifications - if (isSettingsExemptLocked(record)) { + if (isSettingsExempt(record)) { continue; } @@ -1520,14 +1504,7 @@ public class LocationManagerService extends ILocationManager.Stub { // if provider is not active, it should not respond to requests if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) { - long backgroundThrottleInterval; - - long identity = Binder.clearCallingIdentity(); - try { - backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs(); - } finally { - Binder.restoreCallingIdentity(identity); - } + long backgroundThrottleInterval = mSettingsHelper.getBackgroundThrottleIntervalMs(); ArrayList<LocationRequest> requests = new ArrayList<>(records.size()); @@ -1540,7 +1517,7 @@ public class LocationManagerService extends ILocationManager.Stub { // initialize the low power mode to true and set to false if any of the records requires providerRequest.setLowPowerMode(true); for (UpdateRecord record : records) { - if (!mUserInfoStore.isCurrentUserOrProfile( + if (!mUserInfoHelper.isCurrentUserOrProfile( UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { continue; } @@ -1554,7 +1531,7 @@ public class LocationManagerService extends ILocationManager.Stub { final boolean isBatterySaverDisablingLocation = shouldThrottleRequests || (isForegroundOnlyMode && !record.mIsForegroundUid); if (!manager.isEnabled() || isBatterySaverDisablingLocation) { - if (isSettingsExemptLocked(record)) { + if (isSettingsExempt(record)) { providerRequest.setLocationSettingsIgnored(true); providerRequest.setLowPowerMode(false); } else { @@ -1567,7 +1544,7 @@ public class LocationManagerService extends ILocationManager.Stub { // if we're forcing location, don't apply any throttling - if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExemptLocked( + if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExempt( record.mReceiver.mCallerIdentity)) { if (!record.mIsForegroundUid) { interval = Math.max(interval, backgroundThrottleInterval); @@ -1599,7 +1576,7 @@ public class LocationManagerService extends ILocationManager.Stub { // TODO: overflow long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2; for (UpdateRecord record : records) { - if (mUserInfoStore.isCurrentUserOrProfile( + if (mUserInfoHelper.isCurrentUserOrProfile( UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { LocationRequest locationRequest = record.mRequest; @@ -1648,41 +1625,39 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public String[] getBackgroundThrottlingWhitelist() { - return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]); + return mSettingsHelper.getBackgroundThrottlePackageWhitelist().toArray(new String[0]); } @Override public String[] getIgnoreSettingsWhitelist() { - return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]); + return mSettingsHelper.getIgnoreSettingsPackageWhitelist().toArray(new String[0]); } - @GuardedBy("mLock") - public boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) { + private boolean isThrottlingExempt(CallerIdentity callerIdentity) { if (callerIdentity.mUid == Process.SYSTEM_UID) { return true; } - if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains( + if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains( callerIdentity.mPackageName)) { return true; } - return isProviderPackage(callerIdentity.mPackageName); + return mLocalService.isProviderPackage(callerIdentity.mPackageName); } - @GuardedBy("mLock") - private boolean isSettingsExemptLocked(UpdateRecord record) { + private boolean isSettingsExempt(UpdateRecord record) { if (!record.mRealRequest.isLocationSettingsIgnored()) { return false; } - if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains( + if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains( record.mReceiver.mCallerIdentity.mPackageName)) { return true; } - return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName); + return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName); } @@ -1705,10 +1680,7 @@ public class LocationManagerService extends ILocationManager.Stub { mRealRequest = request; mRequest = request; mReceiver = receiver; - mIsForegroundUid = - LocationManagerServiceUtils.isImportanceForeground( - mActivityManager.getPackageImportance( - mReceiver.mCallerIdentity.mPackageName)); + mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.mUid); if (D && receiver.mCallerIdentity.mPid == Process.myPid()) { mStackTrace = new Throwable(); @@ -1753,7 +1725,7 @@ public class LocationManagerService extends ILocationManager.Stub { mReceiver.isListener(), mReceiver.isPendingIntent(), /* geofence= */ null, - mActivityManager.getPackageImportance(packageName)); + mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.mUid)); // remove from mRecordsByProvider ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); @@ -1923,7 +1895,7 @@ public class LocationManagerService extends ILocationManager.Stub { LocationStatsEnums.API_REQUEST_LOCATION_UPDATES, packageName, request, listener != null, intent != null, /* geofence= */ null, - mActivityManager.getPackageImportance(packageName)); + mAppForegroundHelper.getImportance(uid)); Receiver receiver; if (intent != null) { @@ -1961,7 +1933,7 @@ public class LocationManagerService extends ILocationManager.Stub { Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) + " " + name + " " + request + " from " + packageName + "(" + uid + " " + (record.mIsForegroundUid ? "foreground" : "background") - + (isThrottlingExemptLocked(receiver.mCallerIdentity) + + (isThrottlingExempt(receiver.mCallerIdentity) ? " [whitelisted]" : "") + ")"); } @@ -1970,7 +1942,7 @@ public class LocationManagerService extends ILocationManager.Stub { oldRecord.disposeLocked(false); } - if (!manager.isEnabled() && !isSettingsExemptLocked(record)) { + if (!manager.isEnabled() && !isSettingsExempt(record)) { // Notify the listener that updates are currently disabled - but only if the request // does not ignore location settings receiver.callProviderEnabledLocked(name, false); @@ -2060,7 +2032,7 @@ public class LocationManagerService extends ILocationManager.Stub { final int uid = Binder.getCallingUid(); final long identity = Binder.clearCallingIdentity(); try { - if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid), + if (mSettingsHelper.isLocationPackageBlacklisted(UserHandle.getUserId(uid), packageName)) { if (D) { Log.d(TAG, "not returning last loc for blacklisted app: " @@ -2077,8 +2049,8 @@ public class LocationManagerService extends ILocationManager.Stub { if (manager == null) return null; // only the current user or location providers may get location this way - if (!mUserInfoStore.isCurrentUserOrProfile(UserHandle.getUserId(uid)) - && !isProviderPackage(packageName)) { + if (!mUserInfoHelper.isCurrentUserOrProfile(UserHandle.getUserId(uid)) + && !mLocalService.isProviderPackage(packageName)) { return null; } @@ -2102,7 +2074,7 @@ public class LocationManagerService extends ILocationManager.Stub { String op = resolutionLevelToOpStr(allowedResolutionLevel); long locationAgeMs = TimeUnit.NANOSECONDS.toMillis( SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos()); - if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs() + if (locationAgeMs > mSettingsHelper.getMaxLastLocationAgeMs() && (mAppOps.unsafeCheckOp(op, uid, packageName) == AppOpsManager.MODE_FOREGROUND)) { return null; @@ -2145,29 +2117,21 @@ public class LocationManagerService extends ILocationManager.Stub { long locationAgeMs = TimeUnit.NANOSECONDS.toMillis( SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos()); - long identity = Binder.clearCallingIdentity(); - try { - if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) { - try { - listener.onLocationChanged(lastLocation); - return true; - } catch (RemoteException e) { - Log.w(TAG, e); - return false; - } + if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) { + try { + listener.onLocationChanged(lastLocation); + return true; + } catch (RemoteException e) { + Log.w(TAG, e); + return false; } + } - // packageName already validated by getLastLocation() call above - boolean foreground = LocationManagerServiceUtils.isImportanceForeground( - mActivityManager.getPackageImportance(packageName)); - if (!foreground) { - if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) { - // not allowed to request new locations, so we can't return anything - return false; - } + if (!mAppForegroundHelper.isAppForeground(Binder.getCallingUid())) { + if (locationAgeMs < mSettingsHelper.getBackgroundThrottleIntervalMs()) { + // not allowed to request new locations, so we can't return anything + return false; } - } finally { - Binder.restoreCallingIdentity(identity); } } @@ -2252,20 +2216,19 @@ public class LocationManagerService extends ILocationManager.Stub { Log.w(TAG, "proximity alerts are currently available only to the primary user"); return; } + + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_STARTED, + LocationStatsEnums.API_REQUEST_GEOFENCE, + packageName, + request, + /* hasListener= */ false, + true, + geofence, + mAppForegroundHelper.getImportance(uid)); + long identity = Binder.clearCallingIdentity(); try { - synchronized (mLock) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_STARTED, - LocationStatsEnums.API_REQUEST_GEOFENCE, - packageName, - request, - /* hasListener= */ false, - true, - geofence, - mActivityManager.getPackageImportance(packageName)); - } - mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel, uid, packageName, featureId, listenerIdentifier); } finally { @@ -2282,20 +2245,19 @@ public class LocationManagerService extends ILocationManager.Stub { if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_ENDED, + LocationStatsEnums.API_REQUEST_GEOFENCE, + packageName, + /* LocationRequest= */ null, + /* hasListener= */ false, + true, + geofence, + mAppForegroundHelper.getImportance(Binder.getCallingUid())); + // geo-fence manager uses the public location API, need to clear identity long identity = Binder.clearCallingIdentity(); try { - synchronized (mLock) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_ENDED, - LocationStatsEnums.API_REQUEST_GEOFENCE, - packageName, - /* LocationRequest= */ null, - /* hasListener= */ false, - true, - geofence, - mActivityManager.getPackageImportance(packageName)); - } mGeofenceManager.removeFence(geofence, intent); } finally { Binder.restoreCallingIdentity(identity); @@ -2392,12 +2354,6 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public boolean sendNiResponse(int notifId, int userResponse) { - return mGnssManagerService != null && mGnssManagerService.sendNiResponse(notifId, - userResponse); - } - - @Override public ProviderProperties getProviderProperties(String providerName) { LocationProviderManager manager = getLocationProviderManager(providerName); if (manager == null) { @@ -2408,20 +2364,13 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean isProviderPackage(String packageName) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG + " permission required"); - for (LocationProviderManager manager : mProviderManagers) { - if (manager.getPackages().contains(packageName)) { - return true; - } - } - return false; + mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null); + return mLocalService.isProviderPackage(packageName); } @Override public List<String> getProviderPackages(String providerName) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG + " permission required"); + mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null); LocationProviderManager manager = getLocationProviderManager(providerName); return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages()); } @@ -2461,28 +2410,19 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean isLocationEnabledForUser(int userId) { - // Check INTERACT_ACROSS_USERS permission if userId is not current user id. if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.INTERACT_ACROSS_USERS, - "Requires INTERACT_ACROSS_USERS permission"); + mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS, + null); } - long identity = Binder.clearCallingIdentity(); - try { - return mSettingsStore.isLocationEnabled(userId); - } finally { - Binder.restoreCallingIdentity(identity); - } + return mSettingsHelper.isLocationEnabled(userId); } @Override public boolean isProviderEnabledForUser(String providerName, int userId) { - // Check INTERACT_ACROSS_USERS permission if userId is not current user id. if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.INTERACT_ACROSS_USERS, - "Requires INTERACT_ACROSS_USERS permission"); + mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS, + null); } // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, @@ -2593,12 +2533,12 @@ public class LocationManagerService extends ILocationManager.Stub { Receiver receiver = r.mReceiver; boolean receiverDead = false; - if (!manager.isEnabled() && !isSettingsExemptLocked(r)) { + if (!manager.isEnabled() && !isSettingsExempt(r)) { continue; } int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid); - if (!mUserInfoStore.isCurrentUserOrProfile(receiverUserId) + if (!mUserInfoHelper.isCurrentUserOrProfile(receiverUserId) && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) { if (D) { Log.d(TAG, "skipping loc update for background user " + receiverUserId + @@ -2607,7 +2547,7 @@ public class LocationManagerService extends ILocationManager.Stub { continue; } - if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId, + if (mSettingsHelper.isLocationPackageBlacklisted(receiverUserId, receiver.mCallerIdentity.mPackageName)) { if (D) { Log.d(TAG, "skipping loc update for blacklisted app: " + @@ -2855,12 +2795,12 @@ public class LocationManagerService extends ILocationManager.Stub { ipw.println("User Info:"); ipw.increaseIndent(); - mUserInfoStore.dump(fd, ipw, args); + mUserInfoHelper.dump(fd, ipw, args); ipw.decreaseIndent(); ipw.println("Location Settings:"); ipw.increaseIndent(); - mSettingsStore.dump(fd, ipw, args); + mSettingsHelper.dump(fd, ipw, args); ipw.decreaseIndent(); ipw.println("Battery Saver Location Mode: " @@ -2960,5 +2900,22 @@ public class LocationManagerService extends ILocationManager.Stub { } } } + + @Override + public boolean isProviderPackage(String packageName) { + for (LocationProviderManager manager : mProviderManagers) { + if (manager.getPackages().contains(packageName)) { + return true; + } + } + return false; + } + + @Override + public void sendNiResponse(int notifId, int userResponse) { + if (mGnssManagerService != null) { + mGnssManagerService.sendNiResponse(notifId, userResponse); + } + } } } diff --git a/services/core/java/com/android/server/LocationManagerServiceUtils.java b/services/core/java/com/android/server/LocationManagerServiceUtils.java index 9c8ac19cc591..372e91e41772 100644 --- a/services/core/java/com/android/server/LocationManagerServiceUtils.java +++ b/services/core/java/com/android/server/LocationManagerServiceUtils.java @@ -17,8 +17,6 @@ package com.android.server; import android.annotation.NonNull; -import android.app.ActivityManager; -import android.content.Context; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; @@ -91,12 +89,8 @@ public class LocationManagerServiceUtils { /** * Link listener (i.e. callback) to a binder, so that it will be called upon binder's death. - * - * @param binder that calls listener upon death - * @return true if listener is successfully linked to binder, false otherwise */ - public boolean linkToListenerDeathNotificationLocked( - IBinder binder) { + public boolean linkToListenerDeathNotificationLocked(IBinder binder) { try { binder.linkToDeath(this, 0 /* flags */); return true; @@ -110,54 +104,13 @@ public class LocationManagerServiceUtils { /** * Unlink death listener (i.e. callback) from binder. - * - * @param binder that calls listener upon death - * @return true if binder is successfully unlinked from binder, false otherwise */ - public boolean unlinkFromListenerDeathNotificationLocked( - IBinder binder) { + public void unlinkFromListenerDeathNotificationLocked(IBinder binder) { try { binder.unlinkToDeath(this, 0 /* flags */); - return true; } catch (NoSuchElementException e) { - // if the death callback isn't connected (it should be...), log error, - // swallow the exception and return Log.w(TAG, "Could not unlink " + mListenerName + " death callback.", e); - return false; } } - - } - - /** - * Convert boolean foreground into "foreground" or "background" string. - * - * @param foreground boolean indicating foreground - * @return "foreground" string if true, false otherwise - */ - public static String foregroundAsString(boolean foreground) { - return foreground ? "foreground" : "background"; - } - - - /** - * Classifies importance level as foreground or not. - * - * @param importance level as int - * @return boolean indicating if importance level is foreground or greater - */ - public static boolean isImportanceForeground(int importance) { - return importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - } - - /** - * Get package importance level. - * - * @param packageName package name - * @return package importance level as int - */ - public static int getPackageImportance(String packageName, Context context) { - return ((ActivityManager) context.getSystemService( - Context.ACTIVITY_SERVICE)).getPackageImportance(packageName); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 8451d6baeb0a..d7201054dea6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -58,6 +58,8 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_CONTENT_PROVIDER_RETAIN_TIME = "content_provider_retain_time"; private static final String KEY_GC_TIMEOUT = "gc_timeout"; private static final String KEY_GC_MIN_INTERVAL = "gc_min_interval"; + private static final String KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = + "force_bg_check_on_restricted"; private static final String KEY_FULL_PSS_MIN_INTERVAL = "full_pss_min_interval"; private static final String KEY_FULL_PSS_LOWERED_INTERVAL = "full_pss_lowered_interval"; private static final String KEY_POWER_CHECK_INTERVAL = "power_check_interval"; @@ -96,6 +98,7 @@ final class ActivityManagerConstants extends ContentObserver { private static final long DEFAULT_GC_TIMEOUT = 5*1000; private static final long DEFAULT_GC_MIN_INTERVAL = 60*1000; private static final long DEFAULT_FULL_PSS_MIN_INTERVAL = 20*60*1000; + private static final boolean DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = true; private static final long DEFAULT_FULL_PSS_LOWERED_INTERVAL = 5*60*1000; private static final long DEFAULT_POWER_CHECK_INTERVAL = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000; private static final int DEFAULT_POWER_CHECK_MAX_CPU_1 = 25; @@ -177,6 +180,14 @@ final class ActivityManagerConstants extends ContentObserver { // The minimum amount of time between successive GC requests for a process. long GC_MIN_INTERVAL = DEFAULT_GC_MIN_INTERVAL; + /** + * Whether or not Background Check should be forced on any apps in the + * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket, + * regardless of target SDK version. + */ + boolean FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = + DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS; + // The minimum amount of time between successive PSS requests for a process. long FULL_PSS_MIN_INTERVAL = DEFAULT_FULL_PSS_MIN_INTERVAL; @@ -380,6 +391,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES: updateImperceptibleKillExemptions(); break; + case KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS: + updateForceRestrictedBackgroundCheck(); + break; default: break; } @@ -427,6 +441,7 @@ final class ActivityManagerConstants extends ContentObserver { updateMaxCachedProcesses(); updateActivityStartsLoggingEnabled(); updateBackgroundActivityStarts(); + updateForceRestrictedBackgroundCheck(); updateForegroundServiceStartsLoggingEnabled(); updateBackgroundFgsStartsRestriction(); updateOomAdjUpdatePolicy(); @@ -571,6 +586,13 @@ final class ActivityManagerConstants extends ContentObserver { == OOMADJ_UPDATE_POLICY_QUICK; } + private void updateForceRestrictedBackgroundCheck() { + FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS, + DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); + } + private void updateImperceptibleKillExemptions() { IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear(); IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages); @@ -658,6 +680,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(GC_TIMEOUT); pw.print(" "); pw.print(KEY_GC_MIN_INTERVAL); pw.print("="); pw.println(GC_MIN_INTERVAL); + pw.print(" "); pw.print(KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); pw.print("="); + pw.println(FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); pw.print(" "); pw.print(KEY_FULL_PSS_MIN_INTERVAL); pw.print("="); pw.println(FULL_PSS_MIN_INTERVAL); pw.print(" "); pw.print(KEY_FULL_PSS_LOWERED_INTERVAL); pw.print("="); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4c5f705433d6..2b160dddedbb 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -184,6 +184,7 @@ import android.app.WindowConfiguration.WindowingMode; import android.app.backup.IBackupManager; import android.app.usage.UsageEvents; import android.app.usage.UsageEvents.Event; +import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.appwidget.AppWidgetManager; import android.content.AutofillOptions; @@ -6051,6 +6052,11 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private boolean isInRestrictedBucket(int userId, String packageName, long nowElapsed) { + return UsageStatsManager.STANDBY_BUCKET_RESTRICTED + <= mUsageStatsService.getAppStandbyBucket(packageName, userId, nowElapsed); + } + // Unified app-op and target sdk check int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) { // Apps that target O+ are always subject to background check @@ -6060,7 +6066,17 @@ public class ActivityManagerService extends IActivityManager.Stub } return ActivityManager.APP_START_MODE_DELAYED_RIGID; } - // ...and legacy apps get an AppOp check + // It's a legacy app. If it's in the RESTRICTED bucket, always restrict on battery. + if (mOnBattery // Short-circuit in common case. + && mConstants.FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS + && isInRestrictedBucket( + UserHandle.getUserId(uid), packageName, SystemClock.elapsedRealtime())) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " in RESTRICTED bucket"); + } + return ActivityManager.APP_START_MODE_DELAYED; + } + // Not in the RESTRICTED bucket so policy is based on AppOp check. int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName, null, false, ""); if (DEBUG_BACKGROUND_CHECK) { diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 8dd3242c947a..be5350fe04d2 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -60,12 +60,12 @@ import android.security.KeyStore; import android.text.TextUtils; import android.util.Pair; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.SystemService; import java.util.ArrayList; @@ -1142,17 +1142,17 @@ public class BiometricService extends SystemService { + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT + ", RequireConfirmation: " + mCurrentAuthSession.mRequireConfirmation - + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED + + ", State: " + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED + ", Latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, statsModality(), mCurrentAuthSession.mUserId, mCurrentAuthSession.isCrypto(), BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, mCurrentAuthSession.mRequireConfirmation, - StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, latency, mInjector.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId)); } else { @@ -1174,7 +1174,7 @@ public class BiometricService extends SystemService { + ", Latency: " + latency); } // Auth canceled - StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, statsModality(), mCurrentAuthSession.mUserId, mCurrentAuthSession.isCrypto(), diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java index 60f0e8e6c63d..687d9353ebd1 100644 --- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java +++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java @@ -51,10 +51,10 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.SystemService; import java.util.ArrayList; @@ -371,7 +371,7 @@ public abstract class BiometricServiceBase extends SystemService + identifier.getName()); mUtils.removeBiometricForUser(getContext(), getTargetUserId(), identifier.getBiometricId()); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK); } @@ -551,7 +551,7 @@ public abstract class BiometricServiceBase extends SystemService + " failed to respond to cancel, starting client " + (mPendingClient != null ? mPendingClient.getOwnerString() : "null")); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), BiometricsProtoEnums.ISSUE_CANCEL_TIMED_OUT); mCurrentClient = null; @@ -673,8 +673,8 @@ public abstract class BiometricServiceBase extends SystemService 0 /*vendorCode */); }); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), - BiometricsProtoEnums.ISSUE_HAL_DEATH); + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + statsModality(), BiometricsProtoEnums.ISSUE_HAL_DEATH); } protected ClientMonitor getCurrentClient() { @@ -1249,7 +1249,7 @@ public abstract class BiometricServiceBase extends SystemService template.mIdentifier.getBiometricId(), 0 /* groupId */, template.mUserId, restricted, getContext().getPackageName()); removeInternal(client); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL); } else { diff --git a/services/core/java/com/android/server/biometrics/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/LoggableMonitor.java index ecf3864e3362..c03c77f41f57 100644 --- a/services/core/java/com/android/server/biometrics/LoggableMonitor.java +++ b/services/core/java/com/android/server/biometrics/LoggableMonitor.java @@ -21,7 +21,8 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.face.FaceManager; import android.util.Slog; -import android.util.StatsLog; + +import com.android.internal.util.FrameworkStatsLog; /** * Abstract class that adds logging functionality to the ClientMonitor classes. @@ -86,7 +87,7 @@ public abstract class LoggableMonitor { + ", AcquiredInfo: " + acquiredInfo + ", VendorCode: " + vendorCode); } - StatsLog.write(StatsLog.BIOMETRIC_ACQUIRED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED, statsModality(), targetUserId, isCryptoOperation(), @@ -114,7 +115,7 @@ public abstract class LoggableMonitor { } else { Slog.v(TAG, "Error latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, statsModality(), targetUserId, isCryptoOperation(), @@ -128,15 +129,15 @@ public abstract class LoggableMonitor { protected final void logOnAuthenticated(Context context, boolean authenticated, boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) { - int authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__UNKNOWN; + int authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__UNKNOWN; if (!authenticated) { - authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__REJECTED; + authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__REJECTED; } else { // Authenticated if (isBiometricPrompt && requireConfirmation) { - authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__PENDING_CONFIRMATION; + authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__PENDING_CONFIRMATION; } else { - authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED; + authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED; } } @@ -157,7 +158,7 @@ public abstract class LoggableMonitor { Slog.v(TAG, "Authentication latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, statsModality(), targetUserId, isCryptoOperation(), @@ -179,7 +180,7 @@ public abstract class LoggableMonitor { Slog.v(TAG, "Enroll latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_ENROLLED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED, statsModality(), targetUserId, latency, diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java index 9c421524d723..9f76e1ed113d 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -34,6 +34,16 @@ import java.util.List; */ public abstract class InputMethodManagerInternal { /** + * Listener for input method list changed events. + */ + public interface InputMethodListListener { + /** + * Called with the list of the installed IMEs when it's updated. + */ + void onInputMethodListUpdated(List<InputMethodInfo> info, @UserIdInt int userId); + } + + /** * Called by the power manager to tell the input method manager whether it * should start watching for wake events. */ @@ -85,6 +95,11 @@ public abstract class InputMethodManagerInternal { public abstract boolean switchToInputMethod(String imeId, @UserIdInt int userId); /** + * Registers a new {@link InputMethodListListener}. + */ + public abstract void registerInputMethodListListener(InputMethodListListener listener); + + /** * Fake implementation of {@link InputMethodManagerInternal}. All the methods do nothing. */ private static final InputMethodManagerInternal NOP = @@ -117,6 +132,10 @@ public abstract class InputMethodManagerInternal { public boolean switchToInputMethod(String imeId, int userId) { return false; } + + @Override + public void registerInputMethodListListener(InputMethodListListener listener) { + } }; /** diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 15698e9795ec..47622f38f3f2 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -154,6 +154,7 @@ import com.android.internal.view.InputBindResult; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener; import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings; import com.android.server.statusbar.StatusBarManagerService; @@ -172,6 +173,7 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; /** @@ -214,6 +216,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000; static final int MSG_SYSTEM_UNLOCK_USER = 5000; + static final int MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED = 5010; static final int MSG_INLINE_SUGGESTIONS_REQUEST = 6000; @@ -689,6 +692,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final String mSlotIme; /** + * Registered {@link InputMethodListListeners}. + * This variable can be accessed from both of MainThread and BinderThread. + */ + private final CopyOnWriteArrayList<InputMethodListListener> mInputMethodListListeners = + new CopyOnWriteArrayList<>(); + + /** * Internal state snapshot when {@link #MSG_START_INPUT} message is about to be posted to the * internal message queue. Any subsequent state change inside {@link InputMethodManagerService} * will not affect those tasks that are already posted. @@ -3946,10 +3956,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub case MSG_HARD_KEYBOARD_SWITCH_CHANGED: mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1); return true; - case MSG_SYSTEM_UNLOCK_USER: + case MSG_SYSTEM_UNLOCK_USER: { final int userId = msg.arg1; onUnlockUser(userId); return true; + } + case MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED: { + final int userId = msg.arg1; + final List<InputMethodInfo> imes = (List<InputMethodInfo>) msg.obj; + mInputMethodListListeners.forEach( + listener -> listener.onInputMethodListUpdated(imes, userId)); + return true; + } // --------------------------------------------------------------- case MSG_INLINE_SUGGESTIONS_REQUEST: @@ -4142,6 +4160,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // TODO: Make sure that mSwitchingController and mSettings are sharing the // the same enabled IMEs list. mSwitchingController.resetCircularListLocked(mContext); + + // Notify InputMethodListListeners of the new installed InputMethods. + final List<InputMethodInfo> inputMethodList = new ArrayList<>(mMethodList); + mHandler.obtainMessage(MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED, + mSettings.getCurrentUserId(), 0 /* unused */, inputMethodList).sendToTarget(); } // ---------------------------------------------------------------------- @@ -4606,6 +4629,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public boolean switchToInputMethod(String imeId, int userId) { return mService.switchToInputMethod(imeId, userId); } + + @Override + public void registerInputMethodListListener(InputMethodListListener listener) { + mService.mInputMethodListListeners.addIfAbsent(listener); + } } @BinderThread diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index d09c478e320f..54af69432ee0 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -207,6 +207,12 @@ public final class MultiClientInputMethodManagerService { reportNotSupported(); return false; } + + @Override + public void registerInputMethodListListener( + InputMethodListListener listener) { + reportNotSupported(); + } }); } diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java index 5afa48a2b34d..64bca78f294d 100644 --- a/services/core/java/com/android/server/location/AbstractLocationProvider.java +++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java @@ -21,6 +21,7 @@ import android.content.Context; import android.location.Location; import android.os.Binder; import android.os.Bundle; +import android.util.ArraySet; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; @@ -120,7 +121,8 @@ public abstract class AbstractLocationProvider { if (providerPackageNames.equals(this.providerPackageNames)) { return this; } else { - return new State(allowed, properties, providerPackageNames); + return new State(allowed, properties, + Collections.unmodifiableSet(new ArraySet<>(providerPackageNames))); } } diff --git a/services/core/java/com/android/server/location/AppForegroundHelper.java b/services/core/java/com/android/server/location/AppForegroundHelper.java new file mode 100644 index 000000000000..8ddfc652d333 --- /dev/null +++ b/services/core/java/com/android/server/location/AppForegroundHelper.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2020 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.location; + +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; +import static android.app.ActivityManager.RunningAppProcessInfo.Importance; + +import android.annotation.Nullable; +import android.app.ActivityManager; +import android.content.Context; +import android.os.Binder; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; +import com.android.server.FgThread; + +import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Provides accessors and listeners for all application foreground status. An application is + * considered foreground if it's uid's importance level is at or more important than + * {@link android.app.ActivityManager.RunningAppProcessInfo#IMPORTANCE_FOREGROUND_SERVICE}. + */ +public class AppForegroundHelper { + + /** + * Listener for application foreground state changes. + */ + public interface AppForegroundListener { + /** + * Called when an application's foreground state changes. + */ + void onAppForegroundChanged(int uid, boolean foreground); + } + + // importance constants decrement with increasing importance - this is our limit for an + // importance level we consider foreground. + private static final int FOREGROUND_IMPORTANCE_CUTOFF = IMPORTANCE_FOREGROUND_SERVICE; + + private static boolean isForeground(@Importance int importance) { + return importance <= FOREGROUND_IMPORTANCE_CUTOFF; + } + + private final Context mContext; + private final CopyOnWriteArrayList<AppForegroundListener> mListeners; + + @GuardedBy("this") + @Nullable private ActivityManager mActivityManager; + + public AppForegroundHelper(Context context) { + mContext = context; + mListeners = new CopyOnWriteArrayList<>(); + } + + /** Called when system is ready. */ + public synchronized void onSystemReady() { + if (mActivityManager != null) { + return; + } + + mActivityManager = Objects.requireNonNull(mContext.getSystemService(ActivityManager.class)); + mActivityManager.addOnUidImportanceListener(this::onAppForegroundChanged, + FOREGROUND_IMPORTANCE_CUTOFF); + } + + /** + * Adds a listener for app foreground changed events. Callbacks occur on an unspecified thread. + */ + public void addListener(AppForegroundListener listener) { + mListeners.add(listener); + } + + /** + * Removes a listener for app foreground changed events. + */ + public void removeListener(AppForegroundListener listener) { + mListeners.remove(listener); + } + + private void onAppForegroundChanged(int uid, @Importance int importance) { + // invoked on ui thread, move to fg thread so we don't block the ui thread + boolean foreground = isForeground(importance); + FgThread.getHandler().post(() -> { + for (AppForegroundListener listener : mListeners) { + listener.onAppForegroundChanged(uid, foreground); + } + }); + } + + /** + * Whether the given uid is currently foreground. + */ + public boolean isAppForeground(int uid) { + return isForeground(getImportance(uid)); + } + + /** + * Retrieves the current importance of the given uid. + * + * @deprecated Prefer {@link #isAppForeground(int)}. + */ + @Deprecated + @Importance + public int getImportance(int uid) { + synchronized (this) { + Preconditions.checkState(mActivityManager != null); + } + + long identity = Binder.clearCallingIdentity(); + try { + return mActivityManager.getUidImportance(uid); + } finally { + Binder.restoreCallingIdentity(identity); + } + } +} diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java index 81c06d7125f9..4e9c06761e54 100644 --- a/services/core/java/com/android/server/location/GeofenceManager.java +++ b/services/core/java/com/android/server/location/GeofenceManager.java @@ -77,7 +77,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish private final AppOpsManager mAppOps; private final PowerManager.WakeLock mWakeLock; - private final LocationSettingsStore mSettingsStore; + private final SettingsHelper mSettingsStore; private final Object mLock = new Object(); @@ -111,7 +111,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish */ private boolean mPendingUpdate; - public GeofenceManager(Context context, LocationSettingsStore settingsStore) { + public GeofenceManager(Context context, SettingsHelper settingsStore) { mContext = context; mHandler = new GeofenceHandler(FgThread.getHandler().getLooper()); diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 306e1e3afcd7..62fa5ec82aea 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -43,7 +43,6 @@ import android.os.BatteryStats; import android.os.Binder; import android.os.Bundle; import android.os.Handler; -import android.os.HandlerExecutor; import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; @@ -76,6 +75,7 @@ import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; import com.android.internal.location.gnssmetrics.GnssMetrics; import com.android.server.DeviceIdleInternal; +import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback; import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback; @@ -624,12 +624,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } } - public GnssLocationProvider(Context context, Handler handler) { - super(context, new HandlerExecutor(handler)); + public GnssLocationProvider(Context context) { + super(context, FgThread.getExecutor()); ensureInitialized(); - mLooper = handler.getLooper(); + mLooper = FgThread.getHandler().getLooper(); // Create a wake lock mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/SettingsHelper.java index 0e8720ebb08f..9163490fa777 100644 --- a/services/core/java/com/android/server/location/LocationSettingsStore.java +++ b/services/core/java/com/android/server/location/SettingsHelper.java @@ -54,7 +54,7 @@ import java.util.function.Supplier; /** * Provides accessors and listeners for all location related settings. */ -public class LocationSettingsStore { +public class SettingsHelper { /** * Listener for user-specific settings changes. @@ -99,7 +99,7 @@ public class LocationSettingsStore { private final StringSetCachedGlobalSetting mIgnoreSettingsPackageWhitelist; // TODO: get rid of handler - public LocationSettingsStore(Context context, Handler handler) { + public SettingsHelper(Context context, Handler handler) { mContext = context; mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler); @@ -118,7 +118,7 @@ public class LocationSettingsStore { } /** Called when system is ready. */ - public synchronized void onSystemReady() { + public void onSystemReady() { mLocationMode.register(); mBackgroundThrottleIntervalMs.register(); mLocationPackageBlacklist.register(); @@ -135,7 +135,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the location enabled setting. + * Add a listener for changes to the location enabled setting. Callbacks occur on an unspecified + * thread. */ public void addOnLocationEnabledChangedListener(UserSettingChangedListener listener) { mLocationMode.addListener(listener); @@ -156,7 +157,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the background throttle interval. + * Add a listener for changes to the background throttle interval. Callbacks occur on an + * unspecified thread. */ public void addOnBackgroundThrottleIntervalChangedListener( GlobalSettingChangedListener listener) { @@ -204,7 +206,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the background throttle package whitelist. + * Add a listener for changes to the background throttle package whitelist. Callbacks occur on + * an unspecified thread. */ public void addOnBackgroundThrottlePackageWhitelistChangedListener( GlobalSettingChangedListener listener) { @@ -227,7 +230,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the ignore settings package whitelist. + * Add a listener for changes to the ignore settings package whitelist. Callbacks occur on an + * unspecified thread. */ public void addOnIgnoreSettingsPackageWhitelistChangedListener( GlobalSettingChangedListener listener) { @@ -340,6 +344,8 @@ public class LocationSettingsStore { private abstract static class ObservingSetting extends ContentObserver { private final CopyOnWriteArrayList<UserSettingChangedListener> mListeners; + + @GuardedBy("this") private boolean mRegistered; private ObservingSetting(Handler handler) { @@ -347,11 +353,11 @@ public class LocationSettingsStore { mListeners = new CopyOnWriteArrayList<>(); } - protected boolean isRegistered() { + protected synchronized boolean isRegistered() { return mRegistered; } - protected void register(Context context, Uri uri) { + protected synchronized void register(Context context, Uri uri) { if (mRegistered) { return; } @@ -393,8 +399,13 @@ public class LocationSettingsStore { } public int getValueForUser(int defaultValue, int userId) { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName, - defaultValue, userId); + long identity = Binder.clearCallingIdentity(); + try { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName, + defaultValue, userId); + } finally { + Binder.restoreCallingIdentity(identity); + } } } @@ -417,7 +428,7 @@ public class LocationSettingsStore { mCachedUserId = UserHandle.USER_NULL; } - public synchronized void register() { + public void register() { register(mContext, Settings.Secure.getUriFor(mSettingName)); } @@ -426,12 +437,17 @@ public class LocationSettingsStore { List<String> value = mCachedValue; if (userId != mCachedUserId) { - String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), - mSettingName, userId); - if (TextUtils.isEmpty(setting)) { - value = Collections.emptyList(); - } else { - value = Arrays.asList(setting.split(",")); + long identity = Binder.clearCallingIdentity(); + try { + String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), + mSettingName, userId); + if (TextUtils.isEmpty(setting)) { + value = Collections.emptyList(); + } else { + value = Arrays.asList(setting.split(",")); + } + } finally { + Binder.restoreCallingIdentity(identity); } if (isRegistered()) { @@ -473,8 +489,13 @@ public class LocationSettingsStore { } public long getValue(long defaultValue) { - return Settings.Global.getLong(mContext.getContentResolver(), mSettingName, - defaultValue); + long identity = Binder.clearCallingIdentity(); + try { + return Settings.Global.getLong(mContext.getContentResolver(), mSettingName, + defaultValue); + } finally { + Binder.restoreCallingIdentity(identity); + } } } @@ -499,18 +520,23 @@ public class LocationSettingsStore { mValid = false; } - public synchronized void register() { + public void register() { register(mContext, Settings.Global.getUriFor(mSettingName)); } public synchronized Set<String> getValue() { ArraySet<String> value = mCachedValue; if (!mValid) { - value = new ArraySet<>(mBaseValuesSupplier.get()); - String setting = Settings.Global.getString(mContext.getContentResolver(), - mSettingName); - if (!TextUtils.isEmpty(setting)) { - value.addAll(Arrays.asList(setting.split(","))); + long identity = Binder.clearCallingIdentity(); + try { + value = new ArraySet<>(mBaseValuesSupplier.get()); + String setting = Settings.Global.getString(mContext.getContentResolver(), + mSettingName); + if (!TextUtils.isEmpty(setting)) { + value.addAll(Arrays.asList(setting.split(","))); + } + } finally { + Binder.restoreCallingIdentity(identity); } if (isRegistered()) { diff --git a/services/core/java/com/android/server/location/UserInfoStore.java b/services/core/java/com/android/server/location/UserInfoHelper.java index f282ed26a831..94f3a88cb859 100644 --- a/services/core/java/com/android/server/location/UserInfoStore.java +++ b/services/core/java/com/android/server/location/UserInfoHelper.java @@ -42,7 +42,7 @@ import java.util.concurrent.CopyOnWriteArrayList; /** * Provides accessors and listeners for all user info. */ -public class UserInfoStore { +public class UserInfoHelper { /** * Listener for current user changes. @@ -58,20 +58,16 @@ public class UserInfoStore { private final CopyOnWriteArrayList<UserChangedListener> mListeners; @GuardedBy("this") - @Nullable - private UserManager mUserManager; + @Nullable private UserManager mUserManager; - @GuardedBy("this") - @UserIdInt - private int mCurrentUserId; + @UserIdInt private volatile int mCurrentUserId; @GuardedBy("this") - @UserIdInt - private int mCachedParentUserId; + @UserIdInt private int mCachedParentUserId; @GuardedBy("this") private int[] mCachedProfileUserIds; - public UserInfoStore(Context context) { + public UserInfoHelper(Context context) { mContext = context; mListeners = new CopyOnWriteArrayList<>(); @@ -120,7 +116,7 @@ public class UserInfoStore { } /** - * Adds a listener for user changed events. + * Adds a listener for user changed events. Callbacks occur on an unspecified thread. */ public void addListener(UserChangedListener listener) { mListeners.add(listener); @@ -134,16 +130,13 @@ public class UserInfoStore { } private void onUserChanged(@UserIdInt int newUserId) { - int oldUserId; - synchronized (this) { - if (newUserId == mCurrentUserId) { - return; - } - - oldUserId = mCurrentUserId; - mCurrentUserId = newUserId; + if (newUserId == mCurrentUserId) { + return; } + int oldUserId = mCurrentUserId; + mCurrentUserId = newUserId; + for (UserChangedListener listener : mListeners) { listener.onUserChanged(oldUserId, newUserId); } @@ -161,7 +154,7 @@ public class UserInfoStore { * Returns the user id of the current user. */ @UserIdInt - public synchronized int getCurrentUserId() { + public int getCurrentUserId() { return mCurrentUserId; } @@ -169,9 +162,10 @@ public class UserInfoStore { * Returns true if the given user id is either the current user or a profile of the current * user. */ - public synchronized boolean isCurrentUserOrProfile(@UserIdInt int userId) { - return userId == mCurrentUserId || ArrayUtils.contains( - getProfileUserIdsForParentUser(mCurrentUserId), userId); + public boolean isCurrentUserOrProfile(@UserIdInt int userId) { + int currentUserId = mCurrentUserId; + return userId == currentUserId || ArrayUtils.contains( + getProfileUserIdsForParentUser(currentUserId), userId); } /** @@ -179,50 +173,44 @@ public class UserInfoStore { * is a parent or has no profiles. */ @UserIdInt - public synchronized int getParentUserId(@UserIdInt int userId) { - int parentUserId; - if (userId == mCachedParentUserId || ArrayUtils.contains(mCachedProfileUserIds, userId)) { - parentUserId = mCachedParentUserId; - } else { + public int getParentUserId(@UserIdInt int userId) { + synchronized (this) { + if (userId == mCachedParentUserId || ArrayUtils.contains(mCachedProfileUserIds, + userId)) { + return mCachedParentUserId; + } + Preconditions.checkState(mUserManager != null); + } - long identity = Binder.clearCallingIdentity(); - try { - UserInfo userInfo = mUserManager.getProfileParent(userId); - if (userInfo != null) { - parentUserId = userInfo.id; - } else { - // getProfileParent() returns null if the userId is already the parent... - parentUserId = userId; - } + int parentUserId; - // force profiles into cache - getProfileUserIdsForParentUser(parentUserId); - } finally { - Binder.restoreCallingIdentity(identity); - } + long identity = Binder.clearCallingIdentity(); + try { + UserInfo userInfo = mUserManager.getProfileParent(userId); + parentUserId = userInfo != null ? userInfo.id : userId; + } finally { + Binder.restoreCallingIdentity(identity); } + // force profiles into cache + getProfileUserIdsForParentUser(parentUserId); return parentUserId; } @GuardedBy("this") - private int[] getProfileUserIdsForParentUser(@UserIdInt int parentUserId) { - Preconditions.checkState(mUserManager != null); - - // only assert on debug builds as this is a more expensive check - if (Build.IS_DEBUGGABLE) { - long identity = Binder.clearCallingIdentity(); - try { - Preconditions.checkArgument(mUserManager.getProfileParent(parentUserId) == null); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - + private synchronized int[] getProfileUserIdsForParentUser(@UserIdInt int parentUserId) { if (parentUserId != mCachedParentUserId) { long identity = Binder.clearCallingIdentity(); try { + Preconditions.checkState(mUserManager != null); + + // more expensive check - check that argument really is a parent user id + if (Build.IS_DEBUGGABLE) { + Preconditions.checkArgument( + mUserManager.getProfileParent(parentUserId) == null); + } + mCachedParentUserId = parentUserId; mCachedProfileUserIds = mUserManager.getProfileIdsWithDisabled(parentUserId); } finally { @@ -236,8 +224,9 @@ public class UserInfoStore { /** * Dump info for debugging. */ - public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Current User: " + mCurrentUserId + " " + Arrays.toString( - getProfileUserIdsForParentUser(mCurrentUserId))); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + int currentUserId = mCurrentUserId; + pw.println("Current User: " + currentUserId + " " + Arrays.toString( + getProfileUserIdsForParentUser(currentUserId))); } } diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java index 1eb2c525ff22..2bab9fa67eb0 100644 --- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java +++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java @@ -16,10 +16,11 @@ package com.android.server.location.gnss; +import static android.app.AppOpsManager.OP_FINE_LOCATION; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.location.GnssCapabilities; @@ -31,8 +32,8 @@ import android.location.IGnssStatusListener; import android.location.IGpsGeofenceHardware; import android.location.INetInitiatedListener; import android.location.Location; +import android.location.LocationManagerInternal; import android.os.Binder; -import android.os.Handler; import android.os.IBinder; import android.os.IInterface; import android.os.Process; @@ -43,13 +44,12 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.FgThread; -import com.android.server.LocationManagerService; -import com.android.server.LocationManagerServiceUtils; +import com.android.internal.util.Preconditions; +import com.android.server.LocalServices; import com.android.server.LocationManagerServiceUtils.LinkedListener; import com.android.server.LocationManagerServiceUtils.LinkedListenerBase; +import com.android.server.location.AppForegroundHelper; import com.android.server.location.CallerIdentity; import com.android.server.location.GnssBatchingProvider; import com.android.server.location.GnssCapabilitiesProvider; @@ -60,6 +60,7 @@ import com.android.server.location.GnssNavigationMessageProvider; import com.android.server.location.GnssStatusListenerHelper; import com.android.server.location.LocationUsageLogger; import com.android.server.location.RemoteListenerHelper; +import com.android.server.location.SettingsHelper; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -70,10 +71,18 @@ import java.util.function.Function; /** Manages Gnss providers and related Gnss functions for LocationManagerService. */ public class GnssManagerService { + private static final String TAG = "GnssManagerService"; - private static final boolean D = Log.isLoggable(TAG, Log.DEBUG); - // Providers + public static boolean isGnssSupported() { + return GnssLocationProvider.isSupported(); + } + + private final Context mContext; + private final SettingsHelper mSettingsHelper; + private final AppForegroundHelper mAppForegroundHelper; + private final LocationUsageLogger mLocationUsageLogger; + private final GnssLocationProvider mGnssLocationProvider; private final GnssStatusListenerHelper mGnssStatusProvider; private final GnssMeasurementsProvider mGnssMeasurementsProvider; @@ -83,58 +92,59 @@ public class GnssManagerService { private final GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider; private final GnssCapabilitiesProvider mGnssCapabilitiesProvider; private final GnssBatchingProvider mGnssBatchingProvider; - private final INetInitiatedListener mNetInitiatedListener; private final IGpsGeofenceHardware mGpsGeofenceProxy; - private final LocationManagerService mLocationManagerService; - private final LocationUsageLogger mLocationUsageLogger; @GuardedBy("mGnssMeasurementsListeners") - private final ArrayMap<IBinder, - LinkedListener<IGnssMeasurementsListener>> + private final ArrayMap<IBinder, LinkedListener<IGnssMeasurementsListener>> mGnssMeasurementsListeners = new ArrayMap<>(); @GuardedBy("mGnssNavigationMessageListeners") - private final ArrayMap< - IBinder, LinkedListener<IGnssNavigationMessageListener>> + private final ArrayMap<IBinder, LinkedListener<IGnssNavigationMessageListener>> mGnssNavigationMessageListeners = new ArrayMap<>(); @GuardedBy("mGnssStatusListeners") private final ArrayMap<IBinder, LinkedListener<IGnssStatusListener>> mGnssStatusListeners = new ArrayMap<>(); + @GuardedBy("this") + @Nullable private LocationManagerInternal mLocationManagerInternal; + @GuardedBy("this") + @Nullable private AppOpsManager mAppOpsManager; + + private final Object mGnssBatchingLock = new Object(); + @GuardedBy("mGnssBatchingLock") - private IBatchedLocationCallback mGnssBatchingCallback; + @Nullable private IBatchedLocationCallback mGnssBatchingCallback; @GuardedBy("mGnssBatchingLock") - private LinkedListener<IBatchedLocationCallback> - mGnssBatchingDeathCallback; + @Nullable private LinkedListener<IBatchedLocationCallback> mGnssBatchingDeathCallback; @GuardedBy("mGnssBatchingLock") private boolean mGnssBatchingInProgress = false; - private final Object mGnssBatchingLock = new Object(); - private final Context mContext; - private final Handler mHandler; - - public GnssManagerService(LocationManagerService locationManagerService, - Context context, LocationUsageLogger locationUsageLogger) { - this(locationManagerService, context, - new GnssLocationProvider(context, FgThread.getHandler()), locationUsageLogger); + public GnssManagerService(Context context, SettingsHelper settingsHelper, + AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger) { + this(context, settingsHelper, appForegroundHelper, locationUsageLogger, null); } // Can use this constructor to inject GnssLocationProvider for testing @VisibleForTesting - public GnssManagerService(LocationManagerService locationManagerService, - Context context, - GnssLocationProvider gnssLocationProvider, - LocationUsageLogger locationUsageLogger) { + GnssManagerService(Context context, SettingsHelper settingsHelper, + AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger, + GnssLocationProvider gnssLocationProvider) { + Preconditions.checkState(isGnssSupported()); + mContext = context; - mHandler = FgThread.getHandler(); + mSettingsHelper = settingsHelper; + mAppForegroundHelper = appForegroundHelper; + mLocationUsageLogger = locationUsageLogger; - mGnssLocationProvider = - gnssLocationProvider; + if (gnssLocationProvider == null) { + gnssLocationProvider = new GnssLocationProvider(mContext); + } + mGnssLocationProvider = gnssLocationProvider; mGnssStatusProvider = mGnssLocationProvider.getGnssStatusProvider(); mGnssMeasurementsProvider = mGnssLocationProvider.getGnssMeasurementsProvider(); mGnssMeasurementCorrectionsProvider = @@ -144,108 +154,73 @@ public class GnssManagerService { mGnssMetricsProvider = mGnssLocationProvider.getGnssMetricsProvider(); mGnssCapabilitiesProvider = mGnssLocationProvider.getGnssCapabilitiesProvider(); mGnssBatchingProvider = mGnssLocationProvider.getGnssBatchingProvider(); - mNetInitiatedListener = mGnssLocationProvider.getNetInitiatedListener(); mGpsGeofenceProxy = mGnssLocationProvider.getGpsGeofenceProxy(); - mLocationManagerService = locationManagerService; - mLocationUsageLogger = locationUsageLogger; - - registerUidListener(); } - public static boolean isGnssSupported() { - return GnssLocationProvider.isSupported(); - } + /** Called when system is ready. */ + public synchronized void onSystemReady() { + if (mLocationManagerInternal != null) { + return; + } - private boolean hasGnssPermissions(String packageName) { - mContext.enforceCallingPermission( - Manifest.permission.ACCESS_FINE_LOCATION, - "Fine location permission not granted."); + mSettingsHelper.onSystemReady(); + mAppForegroundHelper.onSystemReady(); - int uid = Binder.getCallingUid(); - long identity = Binder.clearCallingIdentity(); - try { - return mContext.getSystemService( - AppOpsManager.class).checkOp(AppOpsManager.OP_FINE_LOCATION, uid, packageName) - == AppOpsManager.MODE_ALLOWED; - } finally { - Binder.restoreCallingIdentity(identity); - } + mLocationManagerInternal = LocalServices.getService(LocationManagerInternal.class); + mAppOpsManager = mContext.getSystemService(AppOpsManager.class); + + mAppForegroundHelper.addListener(this::onAppForegroundChanged); } + /** Retrieve the GnssLocationProvider. */ public GnssLocationProvider getGnssLocationProvider() { return mGnssLocationProvider; } + /** Retrieve the IGpsGeofenceHardware. */ public IGpsGeofenceHardware getGpsGeofenceProxy() { return mGpsGeofenceProxy; } /** * Get year of GNSS hardware. - * - * @return year of GNSS hardware as an int if possible, otherwise zero */ public int getGnssYearOfHardware() { - if (mGnssSystemInfoProvider != null) { - return mGnssSystemInfoProvider.getGnssYearOfHardware(); - } else { - return 0; - } + return mGnssSystemInfoProvider.getGnssYearOfHardware(); } /** * Get model name of GNSS hardware. - * - * @return GNSS hardware model name as a string if possible, otherwise null */ + @Nullable public String getGnssHardwareModelName() { - if (mGnssSystemInfoProvider != null) { - return mGnssSystemInfoProvider.getGnssHardwareModelName(); - } else { - return null; - } + return mGnssSystemInfoProvider.getGnssHardwareModelName(); } /** - * Get GNSS hardware capabilities. The capabilities are described in {@link - * android.location.GnssCapabilities} and their integer values correspond to the - * bit positions in the returned {@code long} value. - * - * @param packageName name of requesting package - * @return capabilities supported by the GNSS chipset + * Get GNSS hardware capabilities. The capabilities returned are a bitfield as described in + * {@link android.location.GnssCapabilities}. */ public long getGnssCapabilities(String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to obtain GNSS chipset capabilities."); - if (!hasGnssPermissions(packageName) || mGnssCapabilitiesProvider == null) { + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); + + if (!checkLocationAppOp(packageName)) { return GnssCapabilities.INVALID_CAPABILITIES; } + return mGnssCapabilitiesProvider.getGnssCapabilities(); } /** * Get size of GNSS batch (GNSS location results are batched together for power savings). - * Requires LOCATION_HARDWARE and GNSS permissions. - * - * @param packageName name of requesting package - * @return size of the GNSS batch collection */ public int getGnssBatchSize(String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "getGnssBatchSize called without GNSS permissions"); - return 0; - } - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not get GNSS batch size. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return 0; } @@ -257,27 +232,12 @@ public class GnssManagerService { /** * Starts GNSS batch collection. GNSS positions are collected in a batch before being delivered * as a collection. - * - * @param periodNanos duration over which to collect GPS positions before delivering as a - * batch - * @param wakeOnFifoFull specifying whether to wake on full queue - * @param packageName name of requesting package - * @return true of batch started successfully, false otherwise */ public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "startGnssBatch called without GNSS permissions"); - return false; - } - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not start GNSS batching. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return false; } @@ -285,7 +245,6 @@ public class GnssManagerService { if (mGnssBatchingInProgress) { // Current design does not expect multiple starts to be called repeatedly Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch"); - // Try to clean up anyway, and continue stopGnssBatch(); } @@ -296,26 +255,13 @@ public class GnssManagerService { /** * Adds a GNSS batching callback for delivering GNSS location batch results. - * - * @param callback called when batching operation is complete to deliver GPS positions - * @param packageName name of requesting package - * @return true if callback is successfully added, false otherwise */ public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName, @Nullable String featureId, @NonNull String listenerIdentity) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "addGnssBatchingCallback called without GNSS permissions"); - return false; - } - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not add GNSS batching callback. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return false; } @@ -333,11 +279,9 @@ public class GnssManagerService { stopGnssBatch(); removeGnssBatchingCallback(); }); - if (!mGnssBatchingDeathCallback.linkToListenerDeathNotificationLocked( - callback.asBinder())) { - return false; - } - return true; + + return mGnssBatchingDeathCallback.linkToListenerDeathNotificationLocked( + callback.asBinder()); } } @@ -347,27 +291,14 @@ public class GnssManagerService { * @param packageName name of requesting package */ public void flushGnssBatch(String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); - - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "flushGnssBatch called without GNSS permissions"); - return; - } + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not flush GNSS batch. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return; } synchronized (mGnssBatchingLock) { - if (!mGnssBatchingInProgress) { - Log.w(TAG, "flushGnssBatch called with no batch in progress"); - } mGnssBatchingProvider.flush(); } } @@ -376,17 +307,7 @@ public class GnssManagerService { * Removes GNSS batching callback. */ public void removeGnssBatchingCallback() { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); - - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not add GNSS batching callback. GNSS batching provider " - + "not available."); - return; - } + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null); synchronized (mGnssBatchingLock) { mGnssBatchingDeathCallback.unlinkFromListenerDeathNotificationLocked( @@ -398,44 +319,17 @@ public class GnssManagerService { /** * Stop GNSS batch collection. - * - * @return true if GNSS batch successfully stopped, false otherwise */ public boolean stopGnssBatch() { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null); - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not stop GNSS batch. GNSS batching provider " - + "not available."); - return false; - } synchronized (mGnssBatchingLock) { mGnssBatchingInProgress = false; return mGnssBatchingProvider.stop(); } } - private void registerUidListener() { - mContext.getSystemService( - ActivityManager.class).addOnUidImportanceListener( - (uid, importance) -> { - // listener invoked on ui thread, move to our thread to reduce risk - // of blocking ui thread - mHandler.post( - () -> { - onForegroundChanged(uid, - LocationManagerServiceUtils.isImportanceForeground( - importance)); - }); - }, - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); - } - - private void onForegroundChanged(int uid, boolean foreground) { + private void onAppForegroundChanged(int uid, boolean foreground) { synchronized (mGnssMeasurementsListeners) { updateListenersOnForegroundChangedLocked( mGnssMeasurementsListeners, @@ -463,8 +357,7 @@ public class GnssManagerService { } private <TListener extends IInterface> void updateListenersOnForegroundChangedLocked( - ArrayMap<IBinder, ? extends LinkedListenerBase> - gnssDataListeners, + Map<IBinder, ? extends LinkedListenerBase> gnssDataListeners, RemoteListenerHelper<TListener> gnssDataProvider, Function<IBinder, TListener> mapBinderToListener, int uid, @@ -477,18 +370,8 @@ public class GnssManagerService { continue; } - if (D) { - Log.d( - TAG, - linkedListener.getListenerName() - + " from uid " - + uid - + " is now " - + LocationManagerServiceUtils.foregroundAsString(foreground)); - } - TListener listener = mapBinderToListener.apply(entry.getKey()); - if (foreground || mLocationManagerService.isThrottlingExemptLocked(callerIdentity)) { + if (foreground || isThrottlingExempt(callerIdentity)) { gnssDataProvider.addListener(listener, callerIdentity); } else { gnssDataProvider.removeListener(listener); @@ -502,67 +385,49 @@ public class GnssManagerService { @Nullable String featureId, @NonNull String listenerIdentifier, RemoteListenerHelper<TListener> gnssDataProvider, - ArrayMap<IBinder, - LinkedListener<TListener>> gnssDataListeners, + ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners, Consumer<TListener> binderDeathCallback) { - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "addGnssDataListenerLocked called without GNSS permissions"); - return false; - } + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (gnssDataProvider == null) { - Log.e( - TAG, - "Can not add GNSS data listener. GNSS data provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return false; } - CallerIdentity callerIdentity = - new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName, - featureId, listenerIdentifier); - LinkedListener<TListener> linkedListener = - new LocationManagerServiceUtils.LinkedListener<>( - listener, listenerIdentifier, callerIdentity, binderDeathCallback); + CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), + Binder.getCallingPid(), packageName, featureId, listenerIdentifier); + LinkedListener<TListener> linkedListener = new LinkedListener<>(listener, + listenerIdentifier, callerIdentity, binderDeathCallback); IBinder binder = listener.asBinder(); if (!linkedListener.linkToListenerDeathNotificationLocked(binder)) { return false; } gnssDataListeners.put(binder, linkedListener); - long identity = Binder.clearCallingIdentity(); - try { - if (gnssDataProvider == mGnssMeasurementsProvider - || gnssDataProvider == mGnssStatusProvider) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_STARTED, - gnssDataProvider == mGnssMeasurementsProvider - ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER - : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, - packageName, - /* LocationRequest= */ null, - /* hasListener= */ true, - /* hasIntent= */ false, - /* geofence= */ null, - LocationManagerServiceUtils.getPackageImportance(packageName, - mContext)); - } - if (mLocationManagerService.isThrottlingExemptLocked(callerIdentity) - || LocationManagerServiceUtils.isImportanceForeground( - LocationManagerServiceUtils.getPackageImportance(packageName, mContext))) { - gnssDataProvider.addListener(listener, callerIdentity); - } - return true; - } finally { - Binder.restoreCallingIdentity(identity); + if (gnssDataProvider == mGnssMeasurementsProvider + || gnssDataProvider == mGnssStatusProvider) { + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_STARTED, + gnssDataProvider == mGnssMeasurementsProvider + ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER + : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, + packageName, + /* LocationRequest= */ null, + /* hasListener= */ true, + /* hasIntent= */ false, + /* geofence= */ null, + mAppForegroundHelper.getImportance(callerIdentity.mUid)); } + if (mAppForegroundHelper.isAppForeground(callerIdentity.mUid) + || isThrottlingExempt(callerIdentity)) { + gnssDataProvider.addListener(listener, callerIdentity); + } + return true; } - private <TListener extends IInterface> void removeGnssDataListener( + private <TListener extends IInterface> void removeGnssDataListenerLocked( TListener listener, RemoteListenerHelper<TListener> gnssDataProvider, - ArrayMap<IBinder, - LinkedListener<TListener>> gnssDataListeners) { + ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners) { if (gnssDataProvider == null) { Log.e( TAG, @@ -577,25 +442,19 @@ public class GnssManagerService { if (linkedListener == null) { return; } - long identity = Binder.clearCallingIdentity(); - try { - if (gnssDataProvider == mGnssMeasurementsProvider - || gnssDataProvider == mGnssStatusProvider) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_ENDED, - gnssDataProvider == mGnssMeasurementsProvider - ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER - : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, - linkedListener.getCallerIdentity().mPackageName, - /* LocationRequest= */ null, - /* hasListener= */ true, - /* hasIntent= */ false, - /* geofence= */ null, - LocationManagerServiceUtils.getPackageImportance( - linkedListener.getCallerIdentity().mPackageName, mContext)); - } - } finally { - Binder.restoreCallingIdentity(identity); + if (gnssDataProvider == mGnssMeasurementsProvider + || gnssDataProvider == mGnssStatusProvider) { + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_ENDED, + gnssDataProvider == mGnssMeasurementsProvider + ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER + : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, + linkedListener.getCallerIdentity().mPackageName, + /* LocationRequest= */ null, + /* hasListener= */ true, + /* hasIntent= */ false, + /* geofence= */ null, + mAppForegroundHelper.getImportance(Binder.getCallingUid())); } linkedListener.unlinkFromListenerDeathNotificationLocked(binder); gnssDataProvider.removeListener(listener); @@ -603,10 +462,6 @@ public class GnssManagerService { /** * Registers listener for GNSS status changes. - * - * @param listener called when GNSS status changes - * @param packageName name of requesting package - * @return true if listener is successfully registered, false otherwise */ public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName, @Nullable String featureId) { @@ -624,21 +479,15 @@ public class GnssManagerService { /** * Unregisters listener for GNSS status changes. - * - * @param listener called when GNSS status changes */ public void unregisterGnssStatusCallback(IGnssStatusListener listener) { synchronized (mGnssStatusListeners) { - removeGnssDataListener(listener, mGnssStatusProvider, mGnssStatusListeners); + removeGnssDataListenerLocked(listener, mGnssStatusProvider, mGnssStatusListeners); } } /** * Adds a GNSS measurements listener. - * - * @param listener called when GNSS measurements are received - * @param packageName name of requesting package - * @return true if listener is successfully added, false otherwise */ public boolean addGnssMeasurementsListener( IGnssMeasurementsListener listener, String packageName, @Nullable String featureId, @@ -657,47 +506,32 @@ public class GnssManagerService { /** * Injects GNSS measurement corrections. - * - * @param measurementCorrections GNSS measurement corrections - * @param packageName name of requesting package */ public void injectGnssMeasurementCorrections( GnssMeasurementCorrections measurementCorrections, String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to inject GNSS measurement corrections."); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "Can not inject GNSS corrections due to no permission."); - return; - } - if (mGnssMeasurementCorrectionsProvider == null) { - Log.e( - TAG, - "Can not inject GNSS corrections. GNSS measurement corrections provider " - + "not available."); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); + + if (!checkLocationAppOp(packageName)) { return; } + mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections( measurementCorrections); } /** * Removes a GNSS measurements listener. - * - * @param listener called when GNSS measurements are received */ public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { synchronized (mGnssMeasurementsListeners) { - removeGnssDataListener(listener, mGnssMeasurementsProvider, mGnssMeasurementsListeners); + removeGnssDataListenerLocked(listener, mGnssMeasurementsProvider, + mGnssMeasurementsListeners); } } /** * Adds a GNSS navigation message listener. - * - * @param listener called when navigation message is received - * @param packageName name of requesting package - * @return true if listener is successfully added, false otherwise */ public boolean addGnssNavigationMessageListener( IGnssNavigationMessageListener listener, String packageName, @@ -716,12 +550,10 @@ public class GnssManagerService { /** * Removes a GNSS navigation message listener. - * - * @param listener called when navigation message is received */ public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { synchronized (mGnssNavigationMessageListeners) { - removeGnssDataListener( + removeGnssDataListenerLocked( listener, mGnssNavigationMessageProvider, mGnssNavigationMessageListeners); } } @@ -729,43 +561,62 @@ public class GnssManagerService { /** * Send Ni Response, indicating a location request initiated by a network carrier. */ - public boolean sendNiResponse(int notifId, int userResponse) { - if (Binder.getCallingUid() != Process.myUid()) { - throw new SecurityException( - "calling sendNiResponse from outside of the system is not allowed"); - } + public void sendNiResponse(int notifId, int userResponse) { try { - return mNetInitiatedListener.sendNiResponse(notifId, userResponse); + mNetInitiatedListener.sendNiResponse(notifId, userResponse); } catch (RemoteException e) { Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); - return false; } } /** * Report location results to GNSS batching listener. - * - * @param locations batch of locations to report to GNSS batching callback */ public void onReportLocation(List<Location> locations) { - if (mGnssBatchingCallback == null) { - Log.e(TAG, "reportLocationBatch() called without active Callback"); + IBatchedLocationCallback gnssBatchingCallback; + synchronized (mGnssBatchingLock) { + gnssBatchingCallback = mGnssBatchingCallback; + } + + if (gnssBatchingCallback == null) { return; } try { - mGnssBatchingCallback.onLocationBatch(locations); + gnssBatchingCallback.onLocationBatch(locations); } catch (RemoteException e) { Log.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e); } } + private boolean isThrottlingExempt(CallerIdentity callerIdentity) { + if (callerIdentity.mUid == Process.SYSTEM_UID) { + return true; + } + + if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains( + callerIdentity.mPackageName)) { + return true; + } + + synchronized (this) { + Preconditions.checkState(mLocationManagerInternal != null); + } + return mLocationManagerInternal.isProviderPackage(callerIdentity.mPackageName); + } + + private boolean checkLocationAppOp(String packageName) { + synchronized (this) { + Preconditions.checkState(mAppOpsManager != null); + } + return mAppOpsManager.checkOp(OP_FINE_LOCATION, Binder.getCallingUid(), packageName) + == AppOpsManager.MODE_ALLOWED; + } + /** - * Dump for debugging. + * Dump info for debugging. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); if (args.length > 0 && args[0].equals("--gnssmetrics")) { @@ -778,11 +629,8 @@ public class GnssManagerService { ipw.println("GnssMeasurement Listeners:"); ipw.increaseIndent(); synchronized (mGnssMeasurementsListeners) { - for (LinkedListenerBase listener : - mGnssMeasurementsListeners - .values()) { - ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked( - listener.getCallerIdentity())); + for (LinkedListenerBase listener : mGnssMeasurementsListeners.values()) { + ipw.println(listener); } } ipw.decreaseIndent(); @@ -790,10 +638,8 @@ public class GnssManagerService { ipw.println("GnssNavigationMessage Listeners:"); ipw.increaseIndent(); synchronized (mGnssNavigationMessageListeners) { - for (LinkedListenerBase listener : - mGnssNavigationMessageListeners.values()) { - ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked( - listener.getCallerIdentity())); + for (LinkedListenerBase listener : mGnssNavigationMessageListeners.values()) { + ipw.println(listener); } } ipw.decreaseIndent(); @@ -801,10 +647,8 @@ public class GnssManagerService { ipw.println("GnssStatus Listeners:"); ipw.increaseIndent(); synchronized (mGnssStatusListeners) { - for (LinkedListenerBase listener : - mGnssStatusListeners.values()) { - ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked( - listener.getCallerIdentity())); + for (LinkedListenerBase listener : mGnssStatusListeners.values()) { + ipw.println(listener); } } ipw.decreaseIndent(); diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index 5c17bec0db47..7f73baefcabd 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -68,9 +68,8 @@ public class AppsFilter { // Logs all filtering instead of enforcing private static final boolean DEBUG_ALLOW_ALL = false; - - @SuppressWarnings("ConstantExpression") - private static final boolean DEBUG_LOGGING = false | DEBUG_ALLOW_ALL; + private static final boolean DEBUG_LOGGING = false; + private static final boolean FEATURE_ENABLED_BY_DEFAULT = false; /** * This contains a list of app UIDs that are implicitly queryable because another app explicitly @@ -136,7 +135,7 @@ public class AppsFilter { private static class FeatureConfigImpl implements FeatureConfig { private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled"; private final PackageManagerService.Injector mInjector; - private volatile boolean mFeatureEnabled = false; + private volatile boolean mFeatureEnabled = FEATURE_ENABLED_BY_DEFAULT; private FeatureConfigImpl(PackageManagerService.Injector injector) { mInjector = injector; @@ -145,14 +144,15 @@ public class AppsFilter { @Override public void onSystemReady() { mFeatureEnabled = DeviceConfig.getBoolean( - NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, false); + NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, + FEATURE_ENABLED_BY_DEFAULT); DeviceConfig.addOnPropertiesChangedListener( NAMESPACE_PACKAGE_MANAGER_SERVICE, FgThread.getExecutor(), properties -> { if (properties.getKeyset().contains(FILTERING_ENABLED_NAME)) { synchronized (FeatureConfigImpl.this) { mFeatureEnabled = properties.getBoolean(FILTERING_ENABLED_NAME, - false); + FEATURE_ENABLED_BY_DEFAULT); } } }); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 43ed25f944c6..431b4dc280f1 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -154,10 +154,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final boolean LOGD = true; private static final String REMOVE_MARKER_EXTENSION = ".removed"; - private static final int MSG_COMMIT = 1; - private static final int MSG_ON_PACKAGE_INSTALLED = 2; - private static final int MSG_SEAL = 3; - private static final int MSG_STREAM_AND_VALIDATE = 4; + private static final int MSG_STREAM_VALIDATE_AND_COMMIT = 1; + private static final int MSG_INSTALL = 2; + private static final int MSG_ON_PACKAGE_INSTALLED = 3; /** XML constants used for persisting a session */ static final String TAG_SESSION = "session"; @@ -415,14 +414,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @Override public boolean handleMessage(Message msg) { switch (msg.what) { - case MSG_SEAL: - handleSeal((IntentSender) msg.obj); + case MSG_STREAM_VALIDATE_AND_COMMIT: + handleStreamValidateAndCommit(); break; - case MSG_STREAM_AND_VALIDATE: - handleStreamAndValidate(); - break; - case MSG_COMMIT: - handleCommit(); + case MSG_INSTALL: + handleInstall(); break; case MSG_ON_PACKAGE_INSTALLED: final SomeArgs args = (SomeArgs) msg.obj; @@ -1011,24 +1007,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { + mParentSessionId + " and may not be committed directly."); } - assertCanBeCommitted(forTransfer); - - if (isMultiPackage()) { - for (int i = mChildSessionIds.size() - 1; i >= 0; --i) { - final int childSessionId = mChildSessionIds.keyAt(i); - mSessionProvider.getSession(childSessionId).assertCanBeCommitted(forTransfer); - } - } - - if (mIncrementalFileStorages != null) { - mIncrementalFileStorages.finishSetUp(); - } - - mHandler.obtainMessage(MSG_SEAL, statusReceiver).sendToTarget(); - } - - private void handleSeal(@NonNull IntentSender statusReceiver) { - if (!markAsSealed(statusReceiver)) { + if (!markAsSealed(statusReceiver, forTransfer)) { return; } if (isMultiPackage()) { @@ -1042,7 +1021,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // seal all children, regardless if any of them fail; we'll throw/return // as appropriate once all children have been processed if (!mSessionProvider.getSession(childSessionId) - .markAsSealed(childIntentSender)) { + .markAsSealed(childIntentSender, forTransfer)) { sealFailed = true; } } @@ -1051,20 +1030,24 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - dispatchStreamAndValidate(); + if (mIncrementalFileStorages != null) { + mIncrementalFileStorages.finishSetUp(); + } + + dispatchStreamValidateAndCommit(); } - private void dispatchStreamAndValidate() { - mHandler.obtainMessage(MSG_STREAM_AND_VALIDATE).sendToTarget(); + private void dispatchStreamValidateAndCommit() { + mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget(); } - private void handleStreamAndValidate() { + private void handleStreamValidateAndCommit() { // TODO(b/136132412): update with new APIs if (mIncrementalFileStorages != null) { mIncrementalFileStorages.startLoading(); } - boolean commitFailed = !markAsCommitted(); + boolean success = streamValidateAndCommit(); if (isMultiPackage()) { for (int i = mChildSessionIds.size() - 1; i >= 0; --i) { @@ -1072,17 +1055,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // commit all children, regardless if any of them fail; we'll throw/return // as appropriate once all children have been processed if (!mSessionProvider.getSession(childSessionId) - .markAsCommitted()) { - commitFailed = true; + .streamValidateAndCommit()) { + success = false; } } } - if (commitFailed) { + if (!success) { return; } - mHandler.obtainMessage(MSG_COMMIT).sendToTarget(); + mHandler.obtainMessage(MSG_INSTALL).sendToTarget(); } private final class FileSystemConnector extends @@ -1201,9 +1184,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } /** - * Sanity checks to make sure it's ok to commit the session. + * If this was not already called, the session will be sealed. + * + * This method may be called multiple times to update the status receiver validate caller + * permissions. */ - private void assertCanBeCommitted(boolean forTransfer) { + private boolean markAsSealed(@NonNull IntentSender statusReceiver, boolean forTransfer) { + Objects.requireNonNull(statusReceiver); + + List<PackageInstallerSession> childSessions = getChildSessions(); + synchronized (mLock) { assertCallerIsOwnerOrRootLocked(); assertPreparedAndNotDestroyedLocked("commit"); @@ -1226,21 +1216,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { throw new IllegalArgumentException("Session has been transferred"); } } - } - } - - /** - * If this was not already called, the session will be sealed. - * - * This method may be called multiple times to update the status receiver validate caller - * permissions. - */ - private boolean markAsSealed(@NonNull IntentSender statusReceiver) { - Objects.requireNonNull(statusReceiver); - - List<PackageInstallerSession> childSessions = getChildSessions(); - synchronized (mLock) { mRemoteStatusReceiver = statusReceiver; // After updating the observer, we can skip re-sealing. @@ -1263,10 +1239,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return true; } - private boolean markAsCommitted() { + private boolean streamValidateAndCommit() { synchronized (mLock) { - Objects.requireNonNull(mRemoteStatusReceiver); - if (mCommitted) { return true; } @@ -1519,7 +1493,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mCallback.onSessionSealedBlocking(this); } - private void handleCommit() { + private void handleInstall() { if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) { DevicePolicyEventLogger .createEvent(DevicePolicyEnums.INSTALL_PACKAGE) @@ -1548,7 +1522,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { synchronized (mLock) { - commitNonStagedLocked(childSessions); + installNonStagedLocked(childSessions); } } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); @@ -1559,25 +1533,25 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } @GuardedBy("mLock") - private void commitNonStagedLocked(List<PackageInstallerSession> childSessions) + private void installNonStagedLocked(List<PackageInstallerSession> childSessions) throws PackageManagerException { - final PackageManagerService.ActiveInstallSession committingSession = + final PackageManagerService.ActiveInstallSession installingSession = makeSessionActiveLocked(); - if (committingSession == null) { + if (installingSession == null) { return; } if (isMultiPackage()) { - List<PackageManagerService.ActiveInstallSession> activeChildSessions = + List<PackageManagerService.ActiveInstallSession> installingChildSessions = new ArrayList<>(childSessions.size()); boolean success = true; PackageManagerException failure = null; for (int i = 0; i < childSessions.size(); ++i) { final PackageInstallerSession session = childSessions.get(i); try { - final PackageManagerService.ActiveInstallSession activeSession = + final PackageManagerService.ActiveInstallSession installingChildSession = session.makeSessionActiveLocked(); - if (activeSession != null) { - activeChildSessions.add(activeSession); + if (installingChildSession != null) { + installingChildSessions.add(installingChildSession); } } catch (PackageManagerException e) { failure = e; @@ -1591,9 +1565,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { failure.error, failure.getLocalizedMessage(), null); return; } - mPm.installStage(activeChildSessions); + mPm.installStage(installingChildSessions); } else { - mPm.installStage(committingSession); + mPm.installStage(installingSession); } } @@ -2306,7 +2280,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // Mark and kick off another install pass synchronized (mLock) { mPermissionsManuallyAccepted = true; - mHandler.obtainMessage(MSG_COMMIT).sendToTarget(); + mHandler.obtainMessage(MSG_INSTALL).sendToTarget(); } } else { destroyInternal(); @@ -2536,9 +2510,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mDataLoaderFinished = true; if (hasParentSessionId()) { mSessionProvider.getSession( - mParentSessionId).dispatchStreamAndValidate(); + mParentSessionId).dispatchStreamValidateAndCommit(); } else { - dispatchStreamAndValidate(); + dispatchStreamValidateAndCommit(); } dataLoader.destroy(); break; diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java index f3a60185bfb6..81ec46634e8a 100644 --- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java +++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java @@ -18,12 +18,14 @@ package com.android.server.policy; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; +import static android.Manifest.permission.WRITE_MEDIA_STORAGE; import static android.app.AppOpsManager.OP_LEGACY_STORAGE; import static android.app.AppOpsManager.OP_NONE; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static java.lang.Integer.min; @@ -114,6 +116,7 @@ public abstract class SoftRestrictedPermissionPolicy { boolean shouldApplyRestriction; final int targetSDK; final boolean hasRequestedLegacyExternalStorage; + final boolean hasWriteMediaStorageGrantedForUid; if (appInfo != null) { PackageManager pm = context.getPackageManager(); @@ -123,11 +126,14 @@ public abstract class SoftRestrictedPermissionPolicy { targetSDK = getMinimumTargetSDK(context, appInfo, user); hasRequestedLegacyExternalStorage = hasUidRequestedLegacyExternalStorage( appInfo.uid, context); + hasWriteMediaStorageGrantedForUid = hasWriteMediaStorageGrantedForUid( + appInfo.uid, context); } else { isWhiteListed = false; shouldApplyRestriction = false; targetSDK = 0; hasRequestedLegacyExternalStorage = false; + hasWriteMediaStorageGrantedForUid = false; } // We have a check in PermissionPolicyService.PermissionToOpSynchroniser.setUidMode @@ -145,8 +151,9 @@ public abstract class SoftRestrictedPermissionPolicy { } @Override public boolean mayAllowExtraAppOp() { - return !shouldApplyRestriction && hasRequestedLegacyExternalStorage - && targetSDK <= Build.VERSION_CODES.Q; + return !shouldApplyRestriction && targetSDK <= Build.VERSION_CODES.Q + && (hasRequestedLegacyExternalStorage + || hasWriteMediaStorageGrantedForUid); } @Override public boolean mayDenyExtraAppOpIfGranted() { @@ -201,6 +208,22 @@ public abstract class SoftRestrictedPermissionPolicy { return false; } + private static boolean hasWriteMediaStorageGrantedForUid(int uid, @NonNull Context context) { + PackageManager packageManager = context.getPackageManager(); + String[] packageNames = packageManager.getPackagesForUid(uid); + if (packageNames == null) { + return false; + } + + for (String packageName : packageNames) { + if (packageManager.checkPermission(WRITE_MEDIA_STORAGE, packageName) + == PERMISSION_GRANTED) { + return true; + } + } + return false; + } + /** * @return If the permission can be granted */ diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index f3197cff04a7..1379d079f674 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -95,7 +95,6 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.StatsEvent; -import android.util.StatsLog; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; @@ -119,6 +118,7 @@ import com.android.internal.os.LooperStats; import com.android.internal.os.PowerProfile; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.StoragedUidIoStatsReader; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.BinderCallsStatsService; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -263,115 +263,115 @@ public class StatsPullAtomService extends SystemService { @Override public int onPullAtom(int atomTag, List<StatsEvent> data) { switch(atomTag) { - case StatsLog.WIFI_BYTES_TRANSFER: + case FrameworkStatsLog.WIFI_BYTES_TRANSFER: return pullWifiBytesTransfer(atomTag, data); - case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: + case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: return pullWifiBytesTransferBackground(atomTag, data); - case StatsLog.MOBILE_BYTES_TRANSFER: + case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: return pullMobileBytesTransfer(atomTag, data); - case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: + case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: return pullMobileBytesTransferBackground(atomTag, data); - case StatsLog.BLUETOOTH_BYTES_TRANSFER: + case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER: return pullBluetoothBytesTransfer(atomTag, data); - case StatsLog.KERNEL_WAKELOCK: + case FrameworkStatsLog.KERNEL_WAKELOCK: return pullKernelWakelock(atomTag, data); - case StatsLog.CPU_TIME_PER_FREQ: + case FrameworkStatsLog.CPU_TIME_PER_FREQ: return pullCpuTimePerFreq(atomTag, data); - case StatsLog.CPU_TIME_PER_UID: + case FrameworkStatsLog.CPU_TIME_PER_UID: return pullCpuTimePerUid(atomTag, data); - case StatsLog.CPU_TIME_PER_UID_FREQ: + case FrameworkStatsLog.CPU_TIME_PER_UID_FREQ: return pullCpuTimeperUidFreq(atomTag, data); - case StatsLog.CPU_ACTIVE_TIME: + case FrameworkStatsLog.CPU_ACTIVE_TIME: return pullCpuActiveTime(atomTag, data); - case StatsLog.CPU_CLUSTER_TIME: + case FrameworkStatsLog.CPU_CLUSTER_TIME: return pullCpuClusterTime(atomTag, data); - case StatsLog.WIFI_ACTIVITY_INFO: + case FrameworkStatsLog.WIFI_ACTIVITY_INFO: return pullWifiActivityInfo(atomTag, data); - case StatsLog.MODEM_ACTIVITY_INFO: + case FrameworkStatsLog.MODEM_ACTIVITY_INFO: return pullModemActivityInfo(atomTag, data); - case StatsLog.BLUETOOTH_ACTIVITY_INFO: + case FrameworkStatsLog.BLUETOOTH_ACTIVITY_INFO: return pullBluetoothActivityInfo(atomTag, data); - case StatsLog.SYSTEM_ELAPSED_REALTIME: + case FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME: return pullSystemElapsedRealtime(atomTag, data); - case StatsLog.SYSTEM_UPTIME: + case FrameworkStatsLog.SYSTEM_UPTIME: return pullSystemUptime(atomTag, data); - case StatsLog.PROCESS_MEMORY_STATE: + case FrameworkStatsLog.PROCESS_MEMORY_STATE: return pullProcessMemoryState(atomTag, data); - case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: + case FrameworkStatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: return pullProcessMemoryHighWaterMark(atomTag, data); - case StatsLog.PROCESS_MEMORY_SNAPSHOT: + case FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT: return pullProcessMemorySnapshot(atomTag, data); - case StatsLog.SYSTEM_ION_HEAP_SIZE: + case FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE: return pullSystemIonHeapSize(atomTag, data); - case StatsLog.ION_HEAP_SIZE: + case FrameworkStatsLog.ION_HEAP_SIZE: return pullIonHeapSize(atomTag, data); - case StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE: + case FrameworkStatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE: return pullProcessSystemIonHeapSize(atomTag, data); - case StatsLog.TEMPERATURE: + case FrameworkStatsLog.TEMPERATURE: return pullTemperature(atomTag, data); - case StatsLog.COOLING_DEVICE: + case FrameworkStatsLog.COOLING_DEVICE: return pullCooldownDevice(atomTag, data); - case StatsLog.BINDER_CALLS: + case FrameworkStatsLog.BINDER_CALLS: return pullBinderCallsStats(atomTag, data); - case StatsLog.BINDER_CALLS_EXCEPTIONS: + case FrameworkStatsLog.BINDER_CALLS_EXCEPTIONS: return pullBinderCallsStatsExceptions(atomTag, data); - case StatsLog.LOOPER_STATS: + case FrameworkStatsLog.LOOPER_STATS: return pullLooperStats(atomTag, data); - case StatsLog.DISK_STATS: + case FrameworkStatsLog.DISK_STATS: return pullDiskStats(atomTag, data); - case StatsLog.DIRECTORY_USAGE: + case FrameworkStatsLog.DIRECTORY_USAGE: return pullDirectoryUsage(atomTag, data); - case StatsLog.APP_SIZE: + case FrameworkStatsLog.APP_SIZE: return pullAppSize(atomTag, data); - case StatsLog.CATEGORY_SIZE: + case FrameworkStatsLog.CATEGORY_SIZE: return pullCategorySize(atomTag, data); - case StatsLog.NUM_FINGERPRINTS_ENROLLED: + case FrameworkStatsLog.NUM_FINGERPRINTS_ENROLLED: return pullNumBiometricsEnrolled( BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data); - case StatsLog.NUM_FACES_ENROLLED: + case FrameworkStatsLog.NUM_FACES_ENROLLED: return pullNumBiometricsEnrolled( BiometricsProtoEnums.MODALITY_FACE, atomTag, data); - case StatsLog.PROC_STATS: + case FrameworkStatsLog.PROC_STATS: return pullProcStats(ProcessStats.REPORT_ALL, atomTag, data); - case StatsLog.PROC_STATS_PKG_PROC: + case FrameworkStatsLog.PROC_STATS_PKG_PROC: return pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data); - case StatsLog.DISK_IO: + case FrameworkStatsLog.DISK_IO: return pullDiskIO(atomTag, data); - case StatsLog.POWER_PROFILE: + case FrameworkStatsLog.POWER_PROFILE: return pullPowerProfile(atomTag, data); - case StatsLog.PROCESS_CPU_TIME: + case FrameworkStatsLog.PROCESS_CPU_TIME: return pullProcessCpuTime(atomTag, data); - case StatsLog.CPU_TIME_PER_THREAD_FREQ: + case FrameworkStatsLog.CPU_TIME_PER_THREAD_FREQ: return pullCpuTimePerThreadFreq(atomTag, data); - case StatsLog.DEVICE_CALCULATED_POWER_USE: + case FrameworkStatsLog.DEVICE_CALCULATED_POWER_USE: return pullDeviceCalculatedPowerUse(atomTag, data); - case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: + case FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: return pullDeviceCalculatedPowerBlameUid(atomTag, data); - case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: + case FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: return pullDeviceCalculatedPowerBlameOther(atomTag, data); - case StatsLog.DEBUG_ELAPSED_CLOCK: + case FrameworkStatsLog.DEBUG_ELAPSED_CLOCK: return pullDebugElapsedClock(atomTag, data); - case StatsLog.DEBUG_FAILING_ELAPSED_CLOCK: + case FrameworkStatsLog.DEBUG_FAILING_ELAPSED_CLOCK: return pullDebugFailingElapsedClock(atomTag, data); - case StatsLog.BUILD_INFORMATION: + case FrameworkStatsLog.BUILD_INFORMATION: return pullBuildInformation(atomTag, data); - case StatsLog.ROLE_HOLDER: + case FrameworkStatsLog.ROLE_HOLDER: return pullRoleHolder(atomTag, data); - case StatsLog.DANGEROUS_PERMISSION_STATE: + case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE: return pullDangerousPermissionState(atomTag, data); - case StatsLog.TIME_ZONE_DATA_INFO: + case FrameworkStatsLog.TIME_ZONE_DATA_INFO: return pullTimeZoneDataInfo(atomTag, data); - case StatsLog.EXTERNAL_STORAGE_INFO: + case FrameworkStatsLog.EXTERNAL_STORAGE_INFO: return pullExternalStorageInfo(atomTag, data); - case StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO: + case FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO: return pullAppsOnExternalStorageInfo(atomTag, data); - case StatsLog.FACE_SETTINGS: + case FrameworkStatsLog.FACE_SETTINGS: return pullFaceSettings(atomTag, data); - case StatsLog.APP_OPS: + case FrameworkStatsLog.APP_OPS: return pullAppOps(atomTag, data); - case StatsLog.NOTIFICATION_REMOTE_VIEWS: + case FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS: return pullNotificationRemoteViews(atomTag, data); - case StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED: + case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED: return pullDangerousPermissionState(atomTag, data); default: throw new UnsupportedOperationException("Unknown tagId=" + atomTag); @@ -633,7 +633,7 @@ public class StatsPullAtomService extends SystemService { } private void registerWifiBytesTransfer() { - int tagId = StatsLog.WIFI_BYTES_TRANSFER; + int tagId = FrameworkStatsLog.WIFI_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3, 4, 5}) .build(); @@ -725,7 +725,7 @@ public class StatsPullAtomService extends SystemService { } private void registerWifiBytesTransferBackground() { - int tagId = StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG; + int tagId = FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3, 4, 5, 6}) .build(); @@ -763,7 +763,7 @@ public class StatsPullAtomService extends SystemService { } private void registerMobileBytesTransfer() { - int tagId = StatsLog.MOBILE_BYTES_TRANSFER; + int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3, 4, 5}) .build(); @@ -801,7 +801,7 @@ public class StatsPullAtomService extends SystemService { } private void registerMobileBytesTransferBackground() { - int tagId = StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG; + int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3, 4, 5, 6}) .build(); @@ -839,7 +839,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBluetoothBytesTransfer() { - int tagId = StatsLog.BLUETOOTH_BYTES_TRANSFER; + int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3}) .build(); @@ -912,7 +912,7 @@ public class StatsPullAtomService extends SystemService { } private void registerKernelWakelock() { - int tagId = StatsLog.KERNEL_WAKELOCK; + int tagId = FrameworkStatsLog.KERNEL_WAKELOCK; mStatsManager.registerPullAtomCallback( tagId, /* PullAtomMetadata */ null, @@ -940,7 +940,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCpuTimePerFreq() { - int tagId = StatsLog.CPU_TIME_PER_FREQ; + int tagId = FrameworkStatsLog.CPU_TIME_PER_FREQ; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3}) .build(); @@ -971,7 +971,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCpuTimePerUid() { - int tagId = StatsLog.CPU_TIME_PER_UID; + int tagId = FrameworkStatsLog.CPU_TIME_PER_UID; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3}) .build(); @@ -1000,7 +1000,7 @@ public class StatsPullAtomService extends SystemService { private void registerCpuTimePerUidFreq() { // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader - int tagId = StatsLog.CPU_TIME_PER_UID_FREQ; + int tagId = FrameworkStatsLog.CPU_TIME_PER_UID_FREQ; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {4}) .build(); @@ -1032,7 +1032,7 @@ public class StatsPullAtomService extends SystemService { private void registerCpuActiveTime() { // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader - int tagId = StatsLog.CPU_ACTIVE_TIME; + int tagId = FrameworkStatsLog.CPU_ACTIVE_TIME; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2}) .build(); @@ -1059,7 +1059,7 @@ public class StatsPullAtomService extends SystemService { private void registerCpuClusterTime() { // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader - int tagId = StatsLog.CPU_CLUSTER_TIME; + int tagId = FrameworkStatsLog.CPU_CLUSTER_TIME; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3}) .build(); @@ -1087,7 +1087,7 @@ public class StatsPullAtomService extends SystemService { } private void registerWifiActivityInfo() { - int tagId = StatsLog.WIFI_ACTIVITY_INFO; + int tagId = FrameworkStatsLog.WIFI_ACTIVITY_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1139,7 +1139,7 @@ public class StatsPullAtomService extends SystemService { } private void registerModemActivityInfo() { - int tagId = StatsLog.MODEM_ACTIVITY_INFO; + int tagId = FrameworkStatsLog.MODEM_ACTIVITY_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1177,7 +1177,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBluetoothActivityInfo() { - int tagId = StatsLog.BLUETOOTH_ACTIVITY_INFO; + int tagId = FrameworkStatsLog.BLUETOOTH_ACTIVITY_INFO; mStatsManager.registerPullAtomCallback( tagId, /* metadata */ null, @@ -1205,7 +1205,7 @@ public class StatsPullAtomService extends SystemService { } private void registerSystemElapsedRealtime() { - int tagId = StatsLog.SYSTEM_ELAPSED_REALTIME; + int tagId = FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setCoolDownNs(NS_PER_SEC) .setTimeoutNs(NS_PER_SEC / 2) @@ -1228,7 +1228,7 @@ public class StatsPullAtomService extends SystemService { } private void registerSystemUptime() { - int tagId = StatsLog.SYSTEM_UPTIME; + int tagId = FrameworkStatsLog.SYSTEM_UPTIME; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1247,7 +1247,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessMemoryState() { - int tagId = StatsLog.PROCESS_MEMORY_STATE; + int tagId = FrameworkStatsLog.PROCESS_MEMORY_STATE; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {4, 5, 6, 7, 8}) .build(); @@ -1293,7 +1293,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessMemoryHighWaterMark() { - int tagId = StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK; + int tagId = FrameworkStatsLog.PROCESS_MEMORY_HIGH_WATER_MARK; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1346,7 +1346,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessMemorySnapshot() { - int tagId = StatsLog.PROCESS_MEMORY_SNAPSHOT; + int tagId = FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1406,7 +1406,7 @@ public class StatsPullAtomService extends SystemService { } private void registerSystemIonHeapSize() { - int tagId = StatsLog.SYSTEM_ION_HEAP_SIZE; + int tagId = FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1426,7 +1426,7 @@ public class StatsPullAtomService extends SystemService { } private void registerIonHeapSize() { - int tagId = StatsLog.ION_HEAP_SIZE; + int tagId = FrameworkStatsLog.ION_HEAP_SIZE; mStatsManager.registerPullAtomCallback( tagId, /* PullAtomMetadata */ null, @@ -1446,7 +1446,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessSystemIonHeapSize() { - int tagId = StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE; + int tagId = FrameworkStatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1472,7 +1472,7 @@ public class StatsPullAtomService extends SystemService { } private void registerTemperature() { - int tagId = StatsLog.TEMPERATURE; + int tagId = FrameworkStatsLog.TEMPERATURE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1510,7 +1510,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCoolingDevice() { - int tagId = StatsLog.COOLING_DEVICE; + int tagId = FrameworkStatsLog.COOLING_DEVICE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1547,7 +1547,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBinderCallsStats() { - int tagId = StatsLog.BINDER_CALLS; + int tagId = FrameworkStatsLog.BINDER_CALLS; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {4, 5, 6, 8, 12}) .build(); @@ -1593,7 +1593,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBinderCallsStatsExceptions() { - int tagId = StatsLog.BINDER_CALLS_EXCEPTIONS; + int tagId = FrameworkStatsLog.BINDER_CALLS_EXCEPTIONS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1625,7 +1625,7 @@ public class StatsPullAtomService extends SystemService { } private void registerLooperStats() { - int tagId = StatsLog.LOOPER_STATS; + int tagId = FrameworkStatsLog.LOOPER_STATS; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {5, 6, 7, 8, 9}) .build(); @@ -1670,7 +1670,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDiskStats() { - int tagId = StatsLog.DISK_STATS; + int tagId = FrameworkStatsLog.DISK_STATS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1736,7 +1736,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDirectoryUsage() { - int tagId = StatsLog.DIRECTORY_USAGE; + int tagId = FrameworkStatsLog.DIRECTORY_USAGE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1752,7 +1752,7 @@ public class StatsPullAtomService extends SystemService { StatsEvent e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__DATA) + .writeInt(FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__DATA) .writeLong(statFsData.getAvailableBytes()) .writeLong(statFsData.getTotalBytes()) .build(); @@ -1760,7 +1760,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE) + .writeInt(FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE) .writeLong(statFsCache.getAvailableBytes()) .writeLong(statFsCache.getTotalBytes()) .build(); @@ -1768,7 +1768,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM) + .writeInt(FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM) .writeLong(statFsSystem.getAvailableBytes()) .writeLong(statFsSystem.getTotalBytes()) .build(); @@ -1777,7 +1777,7 @@ public class StatsPullAtomService extends SystemService { } private void registerAppSize() { - int tagId = StatsLog.APP_SIZE; + int tagId = FrameworkStatsLog.APP_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1821,7 +1821,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCategorySize() { - int tagId = StatsLog.CATEGORY_SIZE; + int tagId = FrameworkStatsLog.CATEGORY_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1839,7 +1839,7 @@ public class StatsPullAtomService extends SystemService { StatsEvent e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE) .writeLong(json.optLong( DiskStatsFileLogger.APP_SIZE_AGG_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1848,7 +1848,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE) .writeLong(json.optLong( DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1857,7 +1857,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE) .writeLong(json.optLong( DiskStatsFileLogger.APP_CACHE_AGG_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1866,7 +1866,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS) .writeLong(json.optLong( DiskStatsFileLogger.PHOTOS_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1875,7 +1875,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS) .writeLong( json.optLong(DiskStatsFileLogger.VIDEOS_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1884,7 +1884,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__AUDIO) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__AUDIO) .writeLong(json.optLong( DiskStatsFileLogger.AUDIO_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1893,7 +1893,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS) .writeLong( json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1901,7 +1901,7 @@ public class StatsPullAtomService extends SystemService { pulledData.add(e); e = StatsEvent.newBuilder() - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM) .writeLong(json.optLong( DiskStatsFileLogger.SYSTEM_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1910,7 +1910,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__OTHER) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__OTHER) .writeLong(json.optLong( DiskStatsFileLogger.MISC_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1924,7 +1924,7 @@ public class StatsPullAtomService extends SystemService { } private void registerNumFingerprintsEnrolled() { - int tagId = StatsLog.NUM_FINGERPRINTS_ENROLLED; + int tagId = FrameworkStatsLog.NUM_FINGERPRINTS_ENROLLED; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1934,7 +1934,7 @@ public class StatsPullAtomService extends SystemService { } private void registerNumFacesEnrolled() { - int tagId = StatsLog.NUM_FACES_ENROLLED; + int tagId = FrameworkStatsLog.NUM_FACES_ENROLLED; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1992,7 +1992,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcStats() { - int tagId = StatsLog.PROC_STATS; + int tagId = FrameworkStatsLog.PROC_STATS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2002,7 +2002,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcStatsPkgProc() { - int tagId = StatsLog.PROC_STATS_PKG_PROC; + int tagId = FrameworkStatsLog.PROC_STATS_PKG_PROC; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2071,7 +2071,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDiskIO() { - int tagId = StatsLog.DISK_IO; + int tagId = FrameworkStatsLog.DISK_IO; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}) .setCoolDownNs(3 * NS_PER_SEC) @@ -2108,7 +2108,7 @@ public class StatsPullAtomService extends SystemService { } private void registerPowerProfile() { - int tagId = StatsLog.POWER_PROFILE; + int tagId = FrameworkStatsLog.POWER_PROFILE; mStatsManager.registerPullAtomCallback( tagId, /* PullAtomMetadata */ null, @@ -2131,7 +2131,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessCpuTime() { - int tagId = StatsLog.PROCESS_CPU_TIME; + int tagId = FrameworkStatsLog.PROCESS_CPU_TIME; // Min cool-down is 5 sec, in line with what ActivityManagerService uses. PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setCoolDownNs(5 * NS_PER_SEC) @@ -2167,7 +2167,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCpuTimePerThreadFreq() { - int tagId = StatsLog.CPU_TIME_PER_THREAD_FREQ; + int tagId = FrameworkStatsLog.CPU_TIME_PER_THREAD_FREQ; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {7, 9, 11, 13, 15, 17, 19, 21}) .build(); @@ -2263,7 +2263,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDeviceCalculatedPowerUse() { - int tagId = StatsLog.DEVICE_CALCULATED_POWER_USE; + int tagId = FrameworkStatsLog.DEVICE_CALCULATED_POWER_USE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2283,7 +2283,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDeviceCalculatedPowerBlameUid() { - int tagId = StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID; + int tagId = FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_UID; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2313,7 +2313,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDeviceCalculatedPowerBlameOther() { - int tagId = StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER; + int tagId = FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2346,7 +2346,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDebugElapsedClock() { - int tagId = StatsLog.DEBUG_ELAPSED_CLOCK; + int tagId = FrameworkStatsLog.DEBUG_ELAPSED_CLOCK; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {1, 2, 3, 4}) .build(); @@ -2397,7 +2397,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDebugFailingElapsedClock() { - int tagId = StatsLog.DEBUG_FAILING_ELAPSED_CLOCK; + int tagId = FrameworkStatsLog.DEBUG_FAILING_ELAPSED_CLOCK; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {1, 2, 3, 4}) .build(); @@ -2438,7 +2438,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBuildInformation() { - int tagId = StatsLog.BUILD_INFORMATION; + int tagId = FrameworkStatsLog.BUILD_INFORMATION; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2465,7 +2465,7 @@ public class StatsPullAtomService extends SystemService { } private void registerRoleHolder() { - int tagId = StatsLog.ROLE_HOLDER; + int tagId = FrameworkStatsLog.ROLE_HOLDER; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2523,7 +2523,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDangerousPermissionState() { - int tagId = StatsLog.DANGEROUS_PERMISSION_STATE; + int tagId = FrameworkStatsLog.DANGEROUS_PERMISSION_STATE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2561,7 +2561,7 @@ public class StatsPullAtomService extends SystemService { } reportedUids.add(pkg.applicationInfo.uid); - if (atomTag == StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED + if (atomTag == FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED && ThreadLocalRandom.current().nextFloat() > 0.01f) { continue; } @@ -2588,7 +2588,7 @@ public class StatsPullAtomService extends SystemService { e.setAtomId(atomTag); e.writeString(permName); e.writeInt(pkg.applicationInfo.uid); - if (atomTag == StatsLog.DANGEROUS_PERMISSION_STATE) { + if (atomTag == FrameworkStatsLog.DANGEROUS_PERMISSION_STATE) { e.writeString(""); } e.writeBoolean((pkg.requestedPermissionsFlags[permNum] @@ -2609,7 +2609,7 @@ public class StatsPullAtomService extends SystemService { } private void registerTimeZoneDataInfo() { - int tagId = StatsLog.TIME_ZONE_DATA_INFO; + int tagId = FrameworkStatsLog.TIME_ZONE_DATA_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2636,7 +2636,7 @@ public class StatsPullAtomService extends SystemService { } private void registerExternalStorageInfo() { - int tagId = StatsLog.EXTERNAL_STORAGE_INFO; + int tagId = FrameworkStatsLog.EXTERNAL_STORAGE_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2656,11 +2656,11 @@ public class StatsPullAtomService extends SystemService { final DiskInfo diskInfo = vol.getDisk(); if (diskInfo != null && envState.equals(Environment.MEDIA_MOUNTED)) { // Get the type of the volume, if it is adoptable or portable. - int volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__OTHER; + int volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__OTHER; if (vol.getType() == TYPE_PUBLIC) { - volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PUBLIC; + volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PUBLIC; } else if (vol.getType() == TYPE_PRIVATE) { - volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PRIVATE; + volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PRIVATE; } // Get the type of external storage inserted in the device (sd cards, usb, etc.) @@ -2686,7 +2686,7 @@ public class StatsPullAtomService extends SystemService { } private void registerAppsOnExternalStorageInfo() { - int tagId = StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO; + int tagId = FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2742,7 +2742,7 @@ public class StatsPullAtomService extends SystemService { } private void registerFaceSettings() { - int tagId = StatsLog.FACE_SETTINGS; + int tagId = FrameworkStatsLog.FACE_SETTINGS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2796,7 +2796,7 @@ public class StatsPullAtomService extends SystemService { } private void registerAppOps() { - int tagId = StatsLog.APP_OPS; + int tagId = FrameworkStatsLog.APP_OPS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2907,7 +2907,7 @@ public class StatsPullAtomService extends SystemService { } private void registerNotificationRemoteViews() { - int tagId = StatsLog.NOTIFICATION_REMOTE_VIEWS; + int tagId = FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2951,7 +2951,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDangerousPermissionStateSampled() { - int tagId = StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED; + int tagId = FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2965,8 +2965,8 @@ public class StatsPullAtomService extends SystemService { private static final class ThermalEventListener extends IThermalEventListener.Stub { @Override public void notifyThrottling(Temperature temp) { - StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(), - temp.getName(), (int) (temp.getValue() * 10), temp.getStatus()); + FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, + temp.getType(), temp.getName(), (int) (temp.getValue() * 10), temp.getStatus()); } } @@ -2974,14 +2974,14 @@ public class StatsPullAtomService extends SystemService { ConnectivityManager.NetworkCallback { @Override public void onAvailable(Network network) { - StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, - StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED); + FrameworkStatsLog.write(FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, + FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED); } @Override public void onLost(Network network) { - StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, - StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED); + FrameworkStatsLog.write(FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, + FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED); } } } diff --git a/services/tests/mockingservicestests/src/com/android/server/location/AppForegroundHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/AppForegroundHelperTest.java new file mode 100644 index 000000000000..38ec4ce3e827 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/location/AppForegroundHelperTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 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.location; + +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import android.app.ActivityManager; +import android.content.Context; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +import java.util.ArrayList; +import java.util.List; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AppForegroundHelperTest { + + private static final long TIMEOUT_MS = 5000; + + @Mock private Context mContext; + @Mock private ActivityManager mActivityManager; + + private List<ActivityManager.OnUidImportanceListener> mListeners = new ArrayList<>(); + + private AppForegroundHelper mHelper; + + @Before + public void setUp() { + initMocks(this); + + doReturn(mActivityManager).when(mContext).getSystemService(ActivityManager.class); + doAnswer(invocation -> { + mListeners.add(invocation.getArgument(0)); + return null; + }).when(mActivityManager).addOnUidImportanceListener(any( + ActivityManager.OnUidImportanceListener.class), eq(IMPORTANCE_FOREGROUND_SERVICE)); + + mHelper = new AppForegroundHelper(mContext); + mHelper.onSystemReady(); + } + + private void setImportance(int uid, int importance) { + doReturn(importance).when(mActivityManager).getUidImportance(uid); + for (ActivityManager.OnUidImportanceListener listener : mListeners) { + listener.onUidImportance(uid, importance); + } + } + + @Test + public void testListeners() { + AppForegroundHelper.AppForegroundListener listener = mock( + AppForegroundHelper.AppForegroundListener.class); + mHelper.addListener(listener); + + setImportance(0, IMPORTANCE_FOREGROUND); + verify(listener, timeout(TIMEOUT_MS)).onAppForegroundChanged(0, true); + + setImportance(1, IMPORTANCE_FOREGROUND_SERVICE); + verify(listener, timeout(TIMEOUT_MS)).onAppForegroundChanged(1, true); + + setImportance(2, IMPORTANCE_VISIBLE); + verify(listener, timeout(TIMEOUT_MS)).onAppForegroundChanged(2, false); + } + + @Test + public void testIsAppForeground() { + setImportance(0, IMPORTANCE_FOREGROUND); + assertThat(mHelper.isAppForeground(0)).isEqualTo(true); + + setImportance(0, IMPORTANCE_FOREGROUND_SERVICE); + assertThat(mHelper.isAppForeground(0)).isEqualTo(true); + + setImportance(0, IMPORTANCE_VISIBLE); + assertThat(mHelper.isAppForeground(0)).isEqualTo(false); + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/location/UserInfoStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/location/UserInfoHelperTest.java index 06fb10257a37..389fdf9b0abc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/UserInfoStoreTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/UserInfoHelperTest.java @@ -57,7 +57,7 @@ import java.util.List; @Presubmit @SmallTest @RunWith(AndroidJUnit4.class) -public class UserInfoStoreTest { +public class UserInfoHelperTest { private static final int USER1_ID = 1; private static final int USER1_MANAGED_ID = 11; @@ -72,7 +72,7 @@ public class UserInfoStoreTest { private StaticMockitoSession mMockingSession; private List<BroadcastReceiver> mBroadcastReceivers = new ArrayList<>(); - private UserInfoStore mStore; + private UserInfoHelper mHelper; @Before public void setUp() { @@ -97,8 +97,8 @@ public class UserInfoStoreTest { doReturn(USER1_ID).when(ActivityManager::getCurrentUser); - mStore = new UserInfoStore(mContext); - mStore.onSystemReady(); + mHelper = new UserInfoHelper(mContext); + mHelper.onSystemReady(); } @After @@ -119,8 +119,9 @@ public class UserInfoStoreTest { @Test public void testListeners() { - UserInfoStore.UserChangedListener listener = mock(UserInfoStore.UserChangedListener.class); - mStore.addListener(listener); + UserInfoHelper.UserChangedListener listener = mock( + UserInfoHelper.UserChangedListener.class); + mHelper.addListener(listener); switchUser(USER1_ID); verify(listener, never()).onUserChanged(anyInt(), anyInt()); @@ -134,44 +135,44 @@ public class UserInfoStoreTest { @Test public void testCurrentUser() { - assertThat(mStore.getCurrentUserId()).isEqualTo(USER1_ID); + assertThat(mHelper.getCurrentUserId()).isEqualTo(USER1_ID); switchUser(USER2_ID); - assertThat(mStore.getCurrentUserId()).isEqualTo(USER2_ID); + assertThat(mHelper.getCurrentUserId()).isEqualTo(USER2_ID); switchUser(USER1_ID); - assertThat(mStore.getCurrentUserId()).isEqualTo(USER1_ID); + assertThat(mHelper.getCurrentUserId()).isEqualTo(USER1_ID); } @Test public void testIsCurrentUserOrProfile() { - assertThat(mStore.isCurrentUserOrProfile(USER1_ID)).isTrue(); - assertThat(mStore.isCurrentUserOrProfile(USER1_MANAGED_ID)).isTrue(); - assertThat(mStore.isCurrentUserOrProfile(USER2_ID)).isFalse(); - assertThat(mStore.isCurrentUserOrProfile(USER2_MANAGED_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_MANAGED_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_MANAGED_ID)).isFalse(); switchUser(USER2_ID); - assertThat(mStore.isCurrentUserOrProfile(USER1_ID)).isFalse(); - assertThat(mStore.isCurrentUserOrProfile(USER2_ID)).isTrue(); - assertThat(mStore.isCurrentUserOrProfile(USER1_MANAGED_ID)).isFalse(); - assertThat(mStore.isCurrentUserOrProfile(USER2_MANAGED_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_MANAGED_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_MANAGED_ID)).isTrue(); } @Test public void testGetParentUserId() { - assertThat(mStore.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); - assertThat(mStore.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); switchUser(USER2_ID); - assertThat(mStore.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); - assertThat(mStore.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); } } diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java index f262733bb882..f16cf35bfb34 100644 --- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java @@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -31,7 +32,6 @@ import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; import android.Manifest; -import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; @@ -46,13 +46,15 @@ import android.location.IGnssNavigationMessageListener; import android.location.IGnssStatusListener; import android.location.INetInitiatedListener; import android.location.Location; +import android.location.LocationManagerInternal; import android.os.Handler; import android.os.IBinder; import android.os.IInterface; import android.os.Message; import android.os.RemoteException; -import com.android.server.LocationManagerService; +import com.android.server.LocalServices; +import com.android.server.location.AppForegroundHelper; import com.android.server.location.GnssBatchingProvider; import com.android.server.location.GnssCapabilitiesProvider; import com.android.server.location.GnssLocationProvider; @@ -63,7 +65,9 @@ import com.android.server.location.GnssNavigationMessageProvider; import com.android.server.location.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative; import com.android.server.location.GnssStatusListenerHelper; import com.android.server.location.LocationUsageLogger; +import com.android.server.location.SettingsHelper; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.AdditionalMatchers; @@ -93,18 +97,20 @@ public class GnssManagerServiceTest { @Mock private GnssMeasurementCorrectionsProvider mMockGnssMeasurementCorrectionsProvider; @Mock - private INetInitiatedListener mMockNetInitiatedListener; + private INetInitiatedListener mNetInitiatedListener; private GnssMeasurementsProvider mTestGnssMeasurementsProvider; private GnssStatusListenerHelper mTestGnssStatusProvider; private GnssNavigationMessageProvider mTestGnssNavigationMessageProvider; // Managers and services @Mock - private AppOpsManager mMockAppOpsManager; + private AppOpsManager mAppOpsManager; @Mock - private ActivityManager mMockActivityManager; + private SettingsHelper mSettingsHelper; @Mock - private LocationManagerService mMockLocationManagerService; + private AppForegroundHelper mAppForegroundHelper; + @Mock + private LocationManagerInternal mLocationManagerInternal; // Context and handler @Mock @@ -113,25 +119,23 @@ public class GnssManagerServiceTest { private Context mMockContext; // Class under test - private com.android.server.location.gnss.GnssManagerService mGnssManagerService; + private GnssManagerService mGnssManagerService; @Before public void setUp() { MockitoAnnotations.initMocks(this); GnssLocationProvider.setIsSupportedForTest(true); - // Set up mock context when(mMockContext.getSystemServiceName(AppOpsManager.class)).thenReturn( Context.APP_OPS_SERVICE); - when(mMockContext.getSystemServiceName(ActivityManager.class)).thenReturn( - Context.ACTIVITY_SERVICE); when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn( - mMockAppOpsManager); - when(mMockContext.getSystemService( - eq(Context.ACTIVITY_SERVICE))).thenReturn( - mMockActivityManager); + mAppOpsManager); enableLocationPermissions(); + when(mAppForegroundHelper.isAppForeground(anyInt())).thenReturn(true); + + LocalServices.addService(LocationManagerInternal.class, mLocationManagerInternal); + // Mock Handler will execute posted runnables immediately when(mMockHandler.sendMessageAtTime(any(Message.class), anyLong())).thenAnswer( (InvocationOnMock invocation) -> { @@ -164,15 +168,22 @@ public class GnssManagerServiceTest { when(mMockGnssLocationProvider.getGnssNavigationMessageProvider()).thenReturn( mTestGnssNavigationMessageProvider); when(mMockGnssLocationProvider.getNetInitiatedListener()).thenReturn( - mMockNetInitiatedListener); + mNetInitiatedListener); // Setup GnssBatching provider when(mMockGnssBatchingProvider.start(anyLong(), anyBoolean())).thenReturn(true); when(mMockGnssBatchingProvider.stop()).thenReturn(true); // Create GnssManagerService - mGnssManagerService = new GnssManagerService(mMockLocationManagerService, mMockContext, - mMockGnssLocationProvider, new LocationUsageLogger()); + mGnssManagerService = new GnssManagerService(mMockContext, mSettingsHelper, + mAppForegroundHelper, new LocationUsageLogger(), + mMockGnssLocationProvider); + mGnssManagerService.onSystemReady(); + } + + @After + public void tearDown() { + LocalServices.removeServiceForTest(LocationManagerInternal.class); } private void overrideAsBinder(IInterface mockListener) { @@ -225,7 +236,7 @@ public class GnssManagerServiceTest { PackageManager.PERMISSION_GRANTED); // AppOpsManager will return true if OP_FINE_LOCATION is checked - when(mMockAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenAnswer( + when(mAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenAnswer( (InvocationOnMock invocation) -> { int code = (int) (invocation.getArguments()[0]); if (code == AppOpsManager.OP_FINE_LOCATION) { @@ -237,11 +248,11 @@ public class GnssManagerServiceTest { private void disableLocationPermissions() { Mockito.doThrow(new SecurityException()).when( - mMockContext).enforceCallingPermission(anyString(), anyString()); + mMockContext).enforceCallingPermission(anyString(), nullable(String.class)); Mockito.doThrow(new SecurityException()).when( mMockContext).checkPermission(anyString(), anyInt(), anyInt()); - when(mMockAppOpsManager.checkOp(anyInt(), anyInt(), + when(mAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ERRORED); } @@ -733,14 +744,12 @@ public class GnssManagerServiceTest { @Test public void sendNiResponseWithPermissionsTest() throws RemoteException { - when(mMockNetInitiatedListener.sendNiResponse(anyInt(), anyInt())).thenReturn(true); - int notifId = 0; int userResponse = 0; enableLocationPermissions(); - assertThat(mGnssManagerService.sendNiResponse(notifId, userResponse)).isEqualTo(true); + mGnssManagerService.sendNiResponse(notifId, userResponse); - verify(mMockNetInitiatedListener, times(1)).sendNiResponse(notifId, userResponse); + verify(mNetInitiatedListener, times(1)).sendNiResponse(notifId, userResponse); } } diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java index 33ad5e8beea3..1dd7539420ac 100644 --- a/telephony/java/android/telephony/CallForwardingInfo.java +++ b/telephony/java/android/telephony/CallForwardingInfo.java @@ -15,7 +15,6 @@ */ package android.telephony; - import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -25,6 +24,8 @@ import android.os.Parcelable; import android.telephony.Annotation.CallForwardingReason; import android.telephony.Annotation.CallForwardingStatus; +import com.android.telephony.Rlog; + import java.util.Objects; /** |