summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/WorkSource.java2
-rw-r--r--media/java/android/media/session/ISession.aidl2
-rw-r--r--media/java/android/media/session/MediaSession.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardToast.java56
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java58
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java5
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java11
-rw-r--r--services/core/java/com/android/server/media/MediaButtonReceiverHolder.java61
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java15
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java6
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java72
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java147
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java51
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java18
16 files changed, 403 insertions, 142 deletions
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index e899f7729efa..65528e306943 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -128,7 +128,7 @@ public class WorkSource implements Parcelable {
mNames = in.createStringArray();
int numChains = in.readInt();
- if (numChains > 0) {
+ if (numChains >= 0) {
mChains = new ArrayList<>(numChains);
in.readParcelableList(mChains, WorkChain.class.getClassLoader(), android.os.WorkSource.WorkChain.class);
} else {
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index 9bf126b7a875..31fb8d03c4a0 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -35,7 +35,7 @@ interface ISession {
ISessionController getController();
void setFlags(int flags);
void setActive(boolean active);
- void setMediaButtonReceiver(in PendingIntent mbr, String sessionPackageName);
+ void setMediaButtonReceiver(in PendingIntent mbr);
void setMediaButtonBroadcastReceiver(in ComponentName broadcastReceiver);
void setLaunchPendingIntent(in PendingIntent pi);
void destroySession();
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index bc00c404b11e..84ecc06d172f 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -286,7 +286,7 @@ public final class MediaSession {
@Deprecated
public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
try {
- mBinder.setMediaButtonReceiver(mbr, mContext.getPackageName());
+ mBinder.setMediaButtonReceiver(mbr);
} catch (RemoteException e) {
Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
index f526277a0a37..da602caac0dc 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
@@ -16,15 +16,21 @@
package com.android.systemui.clipboardoverlay;
+import static android.content.ClipDescription.CLASSIFICATION_COMPLETE;
+
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN;
+
+import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
+import android.provider.Settings;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -51,6 +57,7 @@ public class ClipboardListener extends CoreStartable
private final DeviceConfigProxy mDeviceConfig;
private final ClipboardOverlayControllerFactory mOverlayFactory;
+ private final ClipboardToast mClipboardToast;
private final ClipboardManager mClipboardManager;
private final UiEventLogger mUiEventLogger;
private ClipboardOverlayController mClipboardOverlayController;
@@ -58,10 +65,11 @@ public class ClipboardListener extends CoreStartable
@Inject
public ClipboardListener(Context context, DeviceConfigProxy deviceConfigProxy,
ClipboardOverlayControllerFactory overlayFactory, ClipboardManager clipboardManager,
- UiEventLogger uiEventLogger) {
+ ClipboardToast clipboardToast,UiEventLogger uiEventLogger) {
super(context);
mDeviceConfig = deviceConfigProxy;
mOverlayFactory = overlayFactory;
+ mClipboardToast = clipboardToast;
mClipboardManager = clipboardManager;
mUiEventLogger = uiEventLogger;
}
@@ -88,6 +96,15 @@ public class ClipboardListener extends CoreStartable
return;
}
+ if (!isUserSetupComplete()) {
+ // just show a toast, user should not access intents from this state
+ if (shouldShowToast(clipData)) {
+ mUiEventLogger.log(CLIPBOARD_TOAST_SHOWN, 0, clipSource);
+ mClipboardToast.showCopiedToast();
+ }
+ return;
+ }
+
if (mClipboardOverlayController == null) {
mClipboardOverlayController = mOverlayFactory.create(mContext);
mUiEventLogger.log(CLIPBOARD_OVERLAY_ENTERED, 0, clipSource);
@@ -116,7 +133,23 @@ public class ClipboardListener extends CoreStartable
return clipData.getDescription().getExtras().getBoolean(EXTRA_SUPPRESS_OVERLAY, false);
}
+ boolean shouldShowToast(ClipData clipData) {
+ if (clipData == null) {
+ return false;
+ } else if (clipData.getDescription().getClassificationStatus() == CLASSIFICATION_COMPLETE) {
+ // only show for classification complete if we aren't already showing a toast, to ignore
+ // the duplicate ClipData with classification
+ return !mClipboardToast.isShowing();
+ }
+ return true;
+ }
+
private static boolean isEmulator() {
return SystemProperties.getBoolean("ro.boot.qemu", false);
}
+
+ private boolean isUserSetupComplete() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java
index a0b2ab99e240..1e7dbe69b3e2 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java
@@ -41,7 +41,9 @@ public enum ClipboardOverlayEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "clipboard overlay tapped outside")
CLIPBOARD_OVERLAY_TAP_OUTSIDE(1077),
@UiEvent(doc = "clipboard overlay dismissed, miscellaneous reason")
- CLIPBOARD_OVERLAY_DISMISSED_OTHER(1078);
+ CLIPBOARD_OVERLAY_DISMISSED_OTHER(1078),
+ @UiEvent(doc = "clipboard toast shown")
+ CLIPBOARD_TOAST_SHOWN(1270);
private final int mId;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardToast.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardToast.java
new file mode 100644
index 000000000000..0ed7d2711c62
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardToast.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.systemui.clipboardoverlay;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import com.android.systemui.R;
+
+import javax.inject.Inject;
+
+/**
+ * Utility class for showing a simple clipboard toast on copy.
+ */
+class ClipboardToast extends Toast.Callback {
+ private final Context mContext;
+ private Toast mCopiedToast;
+
+ @Inject
+ ClipboardToast(Context context) {
+ mContext = context;
+ }
+
+ void showCopiedToast() {
+ if (mCopiedToast != null) {
+ mCopiedToast.cancel();
+ }
+ mCopiedToast = Toast.makeText(mContext,
+ R.string.clipboard_overlay_text_copied, Toast.LENGTH_SHORT);
+ mCopiedToast.show();
+ }
+
+ boolean isShowing() {
+ return mCopiedToast != null;
+ }
+
+ @Override // Toast.Callback
+ public void onToastHidden() {
+ super.onToastHidden();
+ mCopiedToast = null;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
index 91214a85ddd5..86402b3202d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
@@ -18,6 +18,8 @@ package com.android.systemui.clipboardoverlay;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;
+import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -32,6 +34,7 @@ import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.os.PersistableBundle;
import android.provider.DeviceConfig;
+import android.provider.Settings;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -59,6 +62,8 @@ public class ClipboardListenerTest extends SysuiTestCase {
@Mock
private ClipboardOverlayController mOverlayController;
@Mock
+ private ClipboardToast mClipboardToast;
+ @Mock
private UiEventLogger mUiEventLogger;
private DeviceConfigProxyFake mDeviceConfigProxy;
@@ -72,6 +77,7 @@ public class ClipboardListenerTest extends SysuiTestCase {
@Captor
private ArgumentCaptor<String> mStringCaptor;
+ private ClipboardListener mClipboardListener;
@Before
public void setup() {
@@ -79,7 +85,8 @@ public class ClipboardListenerTest extends SysuiTestCase {
when(mClipboardOverlayControllerFactory.create(any())).thenReturn(
mOverlayController);
when(mClipboardManager.hasPrimaryClip()).thenReturn(true);
-
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 1);
mSampleClipData = new ClipData("Test", new String[]{"text/plain"},
new ClipData.Item("Test Item"));
@@ -87,15 +94,17 @@ public class ClipboardListenerTest extends SysuiTestCase {
when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource);
mDeviceConfigProxy = new DeviceConfigProxyFake();
+
+ mClipboardListener = new ClipboardListener(getContext(), mDeviceConfigProxy,
+ mClipboardOverlayControllerFactory, mClipboardManager,mClipboardToast,
+ mUiEventLogger);
}
@Test
public void test_disabled() {
mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
"false", false);
- ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
- mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
- listener.start();
+ mClipboardListener.start();
verifyZeroInteractions(mClipboardManager);
verifyZeroInteractions(mUiEventLogger);
}
@@ -104,9 +113,7 @@ public class ClipboardListenerTest extends SysuiTestCase {
public void test_enabled() {
mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
"true", false);
- ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
- mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
- listener.start();
+ mClipboardListener.start();
verify(mClipboardManager).addPrimaryClipChangedListener(any());
verifyZeroInteractions(mUiEventLogger);
}
@@ -115,10 +122,8 @@ public class ClipboardListenerTest extends SysuiTestCase {
public void test_consecutiveCopies() {
mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
"true", false);
- ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
- mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
- listener.start();
- listener.onPrimaryClipChanged();
+ mClipboardListener.start();
+ mClipboardListener.onPrimaryClipChanged();
verify(mClipboardOverlayControllerFactory).create(any());
@@ -132,14 +137,14 @@ public class ClipboardListenerTest extends SysuiTestCase {
// Should clear the overlay controller
mRunnableCaptor.getValue().run();
- listener.onPrimaryClipChanged();
+ mClipboardListener.onPrimaryClipChanged();
verify(mClipboardOverlayControllerFactory, times(2)).create(any());
// Not calling the runnable here, just change the clip again and verify that the overlay is
// NOT recreated.
- listener.onPrimaryClipChanged();
+ mClipboardListener.onPrimaryClipChanged();
verify(mClipboardOverlayControllerFactory, times(2)).create(any());
}
@@ -169,4 +174,31 @@ public class ClipboardListenerTest extends SysuiTestCase {
assertTrue(ClipboardListener.shouldSuppressOverlay(suppressableClipData,
ClipboardListener.SHELL_PACKAGE, false));
}
+
+ @Test
+ public void test_logging_enterAndReenter() {
+ mClipboardListener.start();
+
+ mClipboardListener.onPrimaryClipChanged();
+ mClipboardListener.onPrimaryClipChanged();
+
+ verify(mUiEventLogger, times(1)).log(
+ ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource);
+ verify(mUiEventLogger, times(1)).log(
+ ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED, 0, mSampleSource);
+ }
+
+ @Test
+ public void test_userSetupIncomplete_showsToast() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0);
+
+ mClipboardListener.start();
+ mClipboardListener.onPrimaryClipChanged();
+
+ verify(mUiEventLogger, times(1)).log(
+ ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN, 0, mSampleSource);
+ verify(mClipboardToast, times(1)).showCopiedToast();
+ verifyZeroInteractions(mClipboardOverlayControllerFactory);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java
index c7c2cd8d7b4b..5e2f6a0f7a70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java
@@ -51,6 +51,8 @@ public class ClipboardOverlayEventTest extends SysuiTestCase {
@Mock
private ClipboardOverlayController mOverlayController;
@Mock
+ private ClipboardToast mClipboardToast;
+ @Mock
private UiEventLogger mUiEventLogger;
private final String mSampleSource = "Example source";
@@ -75,7 +77,8 @@ public class ClipboardOverlayEventTest extends SysuiTestCase {
"true", false);
mClipboardListener = new ClipboardListener(getContext(), deviceConfigProxy,
- mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
+ mClipboardOverlayControllerFactory, mClipboardManager, mClipboardToast,
+ mUiEventLogger);
}
@Test
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 9ccf83996782..4044cceb606b 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -377,16 +377,11 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
resolvedType = key.requestResolvedType;
}
- // Apply any launch flags from the ActivityOptions. This is used only by SystemUI
- // to ensure that we can launch the pending intent with a consistent launch mode even
- // if the provided PendingIntent is immutable (ie. to force an activity to launch into
- // a new task, or to launch multiple instances if supported by the app)
+ // Apply any launch flags from the ActivityOptions. This is to ensure that the caller
+ // can specify a consistent launch mode even if the PendingIntent is immutable
final ActivityOptions opts = ActivityOptions.fromBundle(options);
if (opts != null) {
- // TODO(b/254490217): Move this check into SafeActivityOptions
- if (controller.mAtmInternal.isCallerRecents(Binder.getCallingUid())) {
- finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
- }
+ finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
}
// Extract options before clearing calling identity
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index 9a190316f4eb..c5fb5270f841 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -18,6 +18,7 @@ package com.android.server.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -37,6 +38,7 @@ import android.view.KeyEvent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
import java.util.List;
/**
@@ -102,15 +104,19 @@ final class MediaButtonReceiverHolder {
}
/**
- * Creates a new instance.
+ * Creates a new instance from a {@link PendingIntent}.
+ *
+ * <p>This method assumes the session package name has been validated and effectively belongs to
+ * the media session's owner.
*
- * @param context context
* @param userId userId
- * @param pendingIntent pending intent
- * @return Can be {@code null} if pending intent was null.
+ * @param pendingIntent pending intent that will receive media button events
+ * @param sessionPackageName package name of media session owner
+ * @return {@link MediaButtonReceiverHolder} instance or {@code null} if pending intent was
+ * null.
*/
- public static MediaButtonReceiverHolder create(Context context, int userId,
- PendingIntent pendingIntent, String sessionPackageName) {
+ public static MediaButtonReceiverHolder create(
+ int userId, @Nullable PendingIntent pendingIntent, String sessionPackageName) {
if (pendingIntent == null) {
return null;
}
@@ -312,7 +318,7 @@ final class MediaButtonReceiverHolder {
}
private static ComponentName getComponentName(PendingIntent pendingIntent, int componentType) {
- List<ResolveInfo> resolveInfos = null;
+ List<ResolveInfo> resolveInfos = Collections.emptyList();
switch (componentType) {
case COMPONENT_TYPE_ACTIVITY:
resolveInfos = pendingIntent.queryIntentComponents(
@@ -330,32 +336,37 @@ final class MediaButtonReceiverHolder {
PACKAGE_MANAGER_COMMON_FLAGS | PackageManager.GET_RECEIVERS);
break;
}
- if (resolveInfos != null && !resolveInfos.isEmpty()) {
- return createComponentName(resolveInfos.get(0));
+
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ ComponentInfo componentInfo = getComponentInfo(resolveInfo);
+ if (componentInfo != null && TextUtils.equals(componentInfo.packageName,
+ pendingIntent.getCreatorPackage())
+ && componentInfo.packageName != null && componentInfo.name != null) {
+ return new ComponentName(componentInfo.packageName, componentInfo.name);
+ }
}
+
return null;
}
- private static ComponentName createComponentName(ResolveInfo resolveInfo) {
- if (resolveInfo == null) {
- return null;
- }
- ComponentInfo componentInfo;
+ /**
+ * Retrieves the {@link ComponentInfo} from a {@link ResolveInfo} instance. Similar to {@link
+ * ResolveInfo#getComponentInfo()}, but returns {@code null} if this {@link ResolveInfo} points
+ * to a content provider.
+ *
+ * @param resolveInfo Where to extract the {@link ComponentInfo} from.
+ * @return Either a non-null {@link ResolveInfo#activityInfo} or {@link
+ * ResolveInfo#serviceInfo}. Otherwise {@code null} if {@link ResolveInfo#providerInfo} is
+ * not {@code null}.
+ */
+ private static ComponentInfo getComponentInfo(@NonNull ResolveInfo resolveInfo) {
// Code borrowed from ResolveInfo#getComponentInfo().
if (resolveInfo.activityInfo != null) {
- componentInfo = resolveInfo.activityInfo;
+ return resolveInfo.activityInfo;
} else if (resolveInfo.serviceInfo != null) {
- componentInfo = resolveInfo.serviceInfo;
+ return resolveInfo.serviceInfo;
} else {
- // We're not interested in content provider.
- return null;
- }
- // Code borrowed from ComponentInfo#getComponentName().
- try {
- return new ComponentName(componentInfo.packageName, componentInfo.name);
- } catch (IllegalArgumentException | NullPointerException e) {
- // This may be happen if resolveActivity() end up with matching multiple activities.
- // see PackageManager#resolveActivity().
+ // We're not interested in content providers.
return null;
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 604e8f3949f4..1bd50632ccbf 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -52,6 +52,8 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
@@ -936,8 +938,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
}
@Override
- public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName)
- throws RemoteException {
+ public void setMediaButtonReceiver(PendingIntent pi) throws RemoteException {
final long token = Binder.clearCallingIdentity();
try {
if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
@@ -945,7 +946,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
return;
}
mMediaButtonReceiverHolder =
- MediaButtonReceiverHolder.create(mContext, mUserId, pi, sessionPackageName);
+ MediaButtonReceiverHolder.create(mUserId, pi, mPackageName);
mService.onMediaButtonReceiverChanged(MediaSessionRecord.this);
} finally {
Binder.restoreCallingIdentity(token);
@@ -956,6 +957,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException {
final long token = Binder.clearCallingIdentity();
try {
+ //mPackageName has been verified in MediaSessionService.enforcePackageName().
+ if (receiver != null && !TextUtils.equals(
+ mPackageName, receiver.getPackageName())) {
+ EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging.
+ throw new IllegalArgumentException("receiver does not belong to "
+ + "package name provided to MediaSessionRecord. Pkg = " + mPackageName
+ + ", Receiver Pkg = " + receiver.getPackageName());
+ }
if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
!= 0) {
return;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index b89147ea181a..d08150cf0a56 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -2285,9 +2285,9 @@ public class MediaSessionService extends SystemService implements Monitor {
PendingIntent pi = mCustomMediaKeyDispatcher.getMediaButtonReceiver(keyEvent,
uid, asSystemService);
if (pi != null) {
- mediaButtonReceiverHolder = MediaButtonReceiverHolder.create(mContext,
- mCurrentFullUserRecord.mFullUserId, pi,
- /* sessionPackageName= */ "");
+ mediaButtonReceiverHolder =
+ MediaButtonReceiverHolder.create(
+ mCurrentFullUserRecord.mFullUserId, pi, "");
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ea6a83e7d4cd..e355e2076514 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1952,34 +1952,39 @@ public class NotificationManagerService extends SystemService {
return (haystack & needle) != 0;
}
- public boolean isInLockDownMode() {
- return mIsInLockDownMode;
+ // Return whether the user is in lockdown mode.
+ // If the flag is not set, we assume the user is not in lockdown.
+ public boolean isInLockDownMode(int userId) {
+ return mUserInLockDownMode.get(userId, false);
}
@Override
public synchronized void onStrongAuthRequiredChanged(int userId) {
boolean userInLockDownModeNext = containsFlag(getStrongAuthForUser(userId),
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- mUserInLockDownMode.put(userId, userInLockDownModeNext);
- boolean isInLockDownModeNext = mUserInLockDownMode.indexOfValue(true) != -1;
- if (mIsInLockDownMode == isInLockDownModeNext) {
+ // Nothing happens if the lockdown mode of userId keeps the same.
+ if (userInLockDownModeNext == isInLockDownMode(userId)) {
return;
}
- if (isInLockDownModeNext) {
- cancelNotificationsWhenEnterLockDownMode();
+ // When the lockdown mode is changed, we perform the following steps.
+ // If the userInLockDownModeNext is true, all the function calls to
+ // notifyPostedLocked and notifyRemovedLocked will not be executed.
+ // The cancelNotificationsWhenEnterLockDownMode calls notifyRemovedLocked
+ // and postNotificationsWhenExitLockDownMode calls notifyPostedLocked.
+ // So we shall call cancelNotificationsWhenEnterLockDownMode before
+ // we set mUserInLockDownMode as true.
+ // On the other hand, if the userInLockDownModeNext is false, we shall call
+ // postNotificationsWhenExitLockDownMode after we put false into mUserInLockDownMode
+ if (userInLockDownModeNext) {
+ cancelNotificationsWhenEnterLockDownMode(userId);
}
- // When the mIsInLockDownMode is true, both notifyPostedLocked and
- // notifyRemovedLocked will be dismissed. So we shall call
- // cancelNotificationsWhenEnterLockDownMode before we set mIsInLockDownMode
- // as true and call postNotificationsWhenExitLockDownMode after we set
- // mIsInLockDownMode as false.
- mIsInLockDownMode = isInLockDownModeNext;
+ mUserInLockDownMode.put(userId, userInLockDownModeNext);
- if (!isInLockDownModeNext) {
- postNotificationsWhenExitLockDownMode();
+ if (!userInLockDownModeNext) {
+ postNotificationsWhenExitLockDownMode(userId);
}
}
}
@@ -9625,11 +9630,14 @@ public class NotificationManagerService extends SystemService {
}
}
- private void cancelNotificationsWhenEnterLockDownMode() {
+ private void cancelNotificationsWhenEnterLockDownMode(int userId) {
synchronized (mNotificationLock) {
int numNotifications = mNotificationList.size();
for (int i = 0; i < numNotifications; i++) {
NotificationRecord rec = mNotificationList.get(i);
+ if (rec.getUser().getIdentifier() != userId) {
+ continue;
+ }
mListeners.notifyRemovedLocked(rec, REASON_CANCEL_ALL,
rec.getStats());
}
@@ -9637,14 +9645,23 @@ public class NotificationManagerService extends SystemService {
}
}
- private void postNotificationsWhenExitLockDownMode() {
+ private void postNotificationsWhenExitLockDownMode(int userId) {
synchronized (mNotificationLock) {
int numNotifications = mNotificationList.size();
+ // Set the delay to spread out the burst of notifications.
+ long delay = 0;
for (int i = 0; i < numNotifications; i++) {
NotificationRecord rec = mNotificationList.get(i);
- mListeners.notifyPostedLocked(rec, rec);
+ if (rec.getUser().getIdentifier() != userId) {
+ continue;
+ }
+ mHandler.postDelayed(() -> {
+ synchronized (mNotificationLock) {
+ mListeners.notifyPostedLocked(rec, rec);
+ }
+ }, delay);
+ delay += 20;
}
-
}
}
@@ -9823,12 +9840,15 @@ public class NotificationManagerService extends SystemService {
* notifications visible to the given listener.
*/
@GuardedBy("mNotificationLock")
- private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
+ NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
final int N = mNotificationList.size();
final ArrayList<NotificationListenerService.Ranking> rankings = new ArrayList<>();
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
+ if (isInLockDownMode(record.getUser().getIdentifier())) {
+ continue;
+ }
if (!isVisibleToListener(record.getSbn(), record.getNotificationType(), info)) {
continue;
}
@@ -9870,8 +9890,8 @@ public class NotificationManagerService extends SystemService {
rankings.toArray(new NotificationListenerService.Ranking[0]));
}
- boolean isInLockDownMode() {
- return mStrongAuthTracker.isInLockDownMode();
+ boolean isInLockDownMode(int userId) {
+ return mStrongAuthTracker.isInLockDownMode(userId);
}
boolean hasCompanionDevice(ManagedServiceInfo info) {
@@ -10927,7 +10947,7 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
boolean notifyAllListeners) {
- if (isInLockDownMode()) {
+ if (isInLockDownMode(r.getUser().getIdentifier())) {
return;
}
@@ -11028,7 +11048,7 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
public void notifyRemovedLocked(NotificationRecord r, int reason,
NotificationStats notificationStats) {
- if (isInLockDownMode()) {
+ if (isInLockDownMode(r.getUser().getIdentifier())) {
return;
}
@@ -11077,10 +11097,6 @@ public class NotificationManagerService extends SystemService {
*/
@GuardedBy("mNotificationLock")
public void notifyRankingUpdateLocked(List<NotificationRecord> changedHiddenNotifications) {
- if (isInLockDownMode()) {
- return;
- }
-
boolean isHiddenRankingUpdate = changedHiddenNotifications != null
&& changedHiddenNotifications.size() > 0;
// TODO (b/73052211): if the ranking update changed the notification type,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index 76d4059eb436..0f6606f74ae9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -398,63 +398,112 @@ public class NotificationListenersTest extends UiServiceTestCase {
@Test
public void testNotifyPostedLockedInLockdownMode() {
- NotificationRecord r = mock(NotificationRecord.class);
- NotificationRecord old = mock(NotificationRecord.class);
-
- // before the lockdown mode
- when(mNm.isInLockDownMode()).thenReturn(false);
- mListeners.notifyPostedLocked(r, old, true);
- mListeners.notifyPostedLocked(r, old, false);
- verify(r, atLeast(2)).getSbn();
-
- // in the lockdown mode
- reset(r);
- reset(old);
- when(mNm.isInLockDownMode()).thenReturn(true);
- mListeners.notifyPostedLocked(r, old, true);
- mListeners.notifyPostedLocked(r, old, false);
- verify(r, never()).getSbn();
- }
-
- @Test
- public void testnotifyRankingUpdateLockedInLockdownMode() {
- List chn = mock(List.class);
-
- // before the lockdown mode
- when(mNm.isInLockDownMode()).thenReturn(false);
- mListeners.notifyRankingUpdateLocked(chn);
- verify(chn, atLeast(1)).size();
-
- // in the lockdown mode
- reset(chn);
- when(mNm.isInLockDownMode()).thenReturn(true);
- mListeners.notifyRankingUpdateLocked(chn);
- verify(chn, never()).size();
+ NotificationRecord r0 = mock(NotificationRecord.class);
+ NotificationRecord old0 = mock(NotificationRecord.class);
+ UserHandle uh0 = mock(UserHandle.class);
+
+ NotificationRecord r1 = mock(NotificationRecord.class);
+ NotificationRecord old1 = mock(NotificationRecord.class);
+ UserHandle uh1 = mock(UserHandle.class);
+
+ // Neither user0 and user1 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(false);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+
+ mListeners.notifyPostedLocked(r0, old0, true);
+ mListeners.notifyPostedLocked(r0, old0, false);
+ verify(r0, atLeast(2)).getSbn();
+
+ mListeners.notifyPostedLocked(r1, old1, true);
+ mListeners.notifyPostedLocked(r1, old1, false);
+ verify(r1, atLeast(2)).getSbn();
+
+ // Reset
+ reset(r0);
+ reset(old0);
+ reset(r1);
+ reset(old1);
+
+ // Only user 0 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(true);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+
+ mListeners.notifyPostedLocked(r0, old0, true);
+ mListeners.notifyPostedLocked(r0, old0, false);
+ verify(r0, never()).getSbn();
+
+ mListeners.notifyPostedLocked(r1, old1, true);
+ mListeners.notifyPostedLocked(r1, old1, false);
+ verify(r1, atLeast(2)).getSbn();
}
@Test
public void testNotifyRemovedLockedInLockdownMode() throws NoSuchFieldException {
- NotificationRecord r = mock(NotificationRecord.class);
- NotificationStats rs = mock(NotificationStats.class);
+ NotificationRecord r0 = mock(NotificationRecord.class);
+ NotificationStats rs0 = mock(NotificationStats.class);
+ UserHandle uh0 = mock(UserHandle.class);
+
+ NotificationRecord r1 = mock(NotificationRecord.class);
+ NotificationStats rs1 = mock(NotificationStats.class);
+ UserHandle uh1 = mock(UserHandle.class);
+
StatusBarNotification sbn = mock(StatusBarNotification.class);
FieldSetter.setField(mNm,
NotificationManagerService.class.getDeclaredField("mHandler"),
mock(NotificationManagerService.WorkerHandler.class));
- // before the lockdown mode
- when(mNm.isInLockDownMode()).thenReturn(false);
- when(r.getSbn()).thenReturn(sbn);
- mListeners.notifyRemovedLocked(r, 0, rs);
- mListeners.notifyRemovedLocked(r, 0, rs);
- verify(r, atLeast(2)).getSbn();
-
- // in the lockdown mode
- reset(r);
- reset(rs);
- when(mNm.isInLockDownMode()).thenReturn(true);
- when(r.getSbn()).thenReturn(sbn);
- mListeners.notifyRemovedLocked(r, 0, rs);
- mListeners.notifyRemovedLocked(r, 0, rs);
- verify(r, never()).getSbn();
+ // Neither user0 and user1 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(false);
+ when(r0.getSbn()).thenReturn(sbn);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+ when(r1.getSbn()).thenReturn(sbn);
+
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
+ verify(r0, atLeast(2)).getSbn();
+
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ verify(r1, atLeast(2)).getSbn();
+
+ // Reset
+ reset(r0);
+ reset(rs0);
+ reset(r1);
+ reset(rs1);
+
+ // Only user 0 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(true);
+ when(r0.getSbn()).thenReturn(sbn);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+ when(r1.getSbn()).thenReturn(sbn);
+
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
+ verify(r0, never()).getSbn();
+
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ verify(r1, atLeast(2)).getSbn();
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 60f94f3ec32c..0c190b8556c0 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -170,6 +170,7 @@ import android.service.notification.Adjustment;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.NotificationListenerFilter;
import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationRankingUpdate;
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenPolicy;
@@ -9680,10 +9681,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
- assertTrue(mStrongAuthTracker.isInLockDownMode());
- mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+ assertTrue(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
+ mStrongAuthTracker.setGetStrongAuthForUserReturnValue(mContext.getUserId());
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
- assertFalse(mStrongAuthTracker.isInLockDownMode());
+ assertFalse(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
}
@Test
@@ -9699,8 +9700,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// when entering the lockdown mode, cancel the 2 notifications.
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
- assertTrue(mStrongAuthTracker.isInLockDownMode());
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertTrue(mStrongAuthTracker.isInLockDownMode(0));
// the notifyRemovedLocked function is called twice due to REASON_CANCEL_ALL.
ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
@@ -9709,10 +9710,46 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// exit lockdown mode.
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
- mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertFalse(mStrongAuthTracker.isInLockDownMode(0));
// the notifyPostedLocked function is called twice.
- verify(mListeners, times(2)).notifyPostedLocked(any(), any());
+ verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong());
+ //verify(mListeners, times(2)).notifyPostedLocked(any(), any());
+ }
+
+ @Test
+ public void testMakeRankingUpdateLockedInLockDownMode() {
+ // post 2 notifications from a same package
+ NotificationRecord pkgA = new NotificationRecord(mContext,
+ generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
+ mService.addNotification(pkgA);
+ NotificationRecord pkgB = new NotificationRecord(mContext,
+ generateSbn("a", 1000, 9, 1), mTestNotificationChannel);
+ mService.addNotification(pkgB);
+
+ mService.setIsVisibleToListenerReturnValue(true);
+ NotificationRankingUpdate nru = mService.makeRankingUpdateLocked(null);
+ assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
+
+ // when only user 0 entering the lockdown mode, its notification will be suppressed.
+ mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
+ STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertTrue(mStrongAuthTracker.isInLockDownMode(0));
+ assertFalse(mStrongAuthTracker.isInLockDownMode(1));
+
+ nru = mService.makeRankingUpdateLocked(null);
+ assertEquals(1, nru.getRankingMap().getOrderedKeys().length);
+
+ // User 0 exits lockdown mode. Its notification will be resumed.
+ mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertFalse(mStrongAuthTracker.isInLockDownMode(0));
+ assertFalse(mStrongAuthTracker.isInLockDownMode(1));
+
+ nru = mService.makeRankingUpdateLocked(null);
+ assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
index 21ca37f4d238..61a6985d473e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
@@ -19,10 +19,12 @@ package com.android.server.notification;
import android.companion.ICompanionDeviceManager;
import android.content.ComponentName;
import android.content.Context;
+import android.service.notification.StatusBarNotification;
import androidx.annotation.Nullable;
import com.android.internal.logging.InstanceIdSequence;
+import com.android.server.notification.ManagedServices.ManagedServiceInfo;
import java.util.HashSet;
import java.util.Set;
@@ -38,6 +40,9 @@ public class TestableNotificationManagerService extends NotificationManagerServi
@Nullable
NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
+ @Nullable
+ Boolean mIsVisibleToListenerReturnValue = null;
+
TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
InstanceIdSequence notificationInstanceIdSequence) {
super(context, logger, notificationInstanceIdSequence);
@@ -126,6 +131,19 @@ public class TestableNotificationManagerService extends NotificationManagerServi
mShowReviewPermissionsNotification = setting;
}
+ protected void setIsVisibleToListenerReturnValue(boolean value) {
+ mIsVisibleToListenerReturnValue = value;
+ }
+
+ @Override
+ boolean isVisibleToListener(StatusBarNotification sbn, int notificationType,
+ ManagedServiceInfo listener) {
+ if (mIsVisibleToListenerReturnValue != null) {
+ return mIsVisibleToListenerReturnValue;
+ }
+ return super.isVisibleToListener(sbn, notificationType, listener);
+ }
+
public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
private int mGetStrongAuthForUserReturnValue = 0;
StrongAuthTrackerFake(Context context) {