Log BAL and full screen intent to statsd.
Test: atest StatusBarNotificationActivityStarterTest Test: atest ActivityStarterTests Bug: 261910877 Change-Id: I4fdfbe80ea0c368a4809e5613e5f9c3a8369e2a3
This commit is contained in:
@@ -27,6 +27,7 @@ import android.app.PendingIntent;
|
|||||||
import android.app.TaskStackBuilder;
|
import android.app.TaskStackBuilder;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -45,6 +46,7 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
import com.android.internal.jank.InteractionJankMonitor;
|
import com.android.internal.jank.InteractionJankMonitor;
|
||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.internal.statusbar.NotificationVisibility;
|
import com.android.internal.statusbar.NotificationVisibility;
|
||||||
|
import com.android.internal.util.FrameworkStatsLog;
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.systemui.ActivityIntentHelper;
|
import com.android.systemui.ActivityIntentHelper;
|
||||||
import com.android.systemui.EventLogTags;
|
import com.android.systemui.EventLogTags;
|
||||||
@@ -74,12 +76,14 @@ import com.android.systemui.statusbar.policy.HeadsUpUtil;
|
|||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.wmshell.BubblesManager;
|
import com.android.systemui.wmshell.BubblesManager;
|
||||||
|
|
||||||
|
import dagger.Lazy;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.Lazy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status bar implementation of {@link NotificationActivityStarter}.
|
* Status bar implementation of {@link NotificationActivityStarter}.
|
||||||
@@ -572,16 +576,29 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
});
|
});
|
||||||
|
|
||||||
// not immersive & a fullscreen alert should be shown
|
// not immersive & a fullscreen alert should be shown
|
||||||
final PendingIntent fullscreenIntent =
|
final PendingIntent fullScreenIntent =
|
||||||
entry.getSbn().getNotification().fullScreenIntent;
|
entry.getSbn().getNotification().fullScreenIntent;
|
||||||
mLogger.logSendingFullScreenIntent(entry, fullscreenIntent);
|
mLogger.logSendingFullScreenIntent(entry, fullScreenIntent);
|
||||||
try {
|
try {
|
||||||
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
|
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
|
||||||
entry.getKey());
|
entry.getKey());
|
||||||
mCentralSurfaces.wakeUpForFullScreenIntent();
|
mCentralSurfaces.wakeUpForFullScreenIntent();
|
||||||
fullscreenIntent.send();
|
fullScreenIntent.send();
|
||||||
entry.notifyFullScreenIntentLaunched();
|
entry.notifyFullScreenIntentLaunched();
|
||||||
mMetricsLogger.count("note_fullscreen", 1);
|
mMetricsLogger.count("note_fullscreen", 1);
|
||||||
|
|
||||||
|
String activityName;
|
||||||
|
List<ResolveInfo> resolveInfos = fullScreenIntent.queryIntentComponents(0);
|
||||||
|
if (resolveInfos.size() > 0 && resolveInfos.get(0) != null
|
||||||
|
&& resolveInfos.get(0).activityInfo != null
|
||||||
|
&& resolveInfos.get(0).activityInfo.name != null) {
|
||||||
|
activityName = resolveInfos.get(0).activityInfo.name;
|
||||||
|
} else {
|
||||||
|
activityName = "";
|
||||||
|
}
|
||||||
|
FrameworkStatsLog.write(FrameworkStatsLog.FULL_SCREEN_INTENT_LAUNCHED,
|
||||||
|
fullScreenIntent.getCreatorUid(),
|
||||||
|
activityName);
|
||||||
} catch (PendingIntent.CanceledException e) {
|
} catch (PendingIntent.CanceledException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ package com.android.systemui.statusbar.phone;
|
|||||||
|
|
||||||
import static android.service.notification.NotificationListenerService.REASON_CLICK;
|
import static android.service.notification.NotificationListenerService.REASON_CLICK;
|
||||||
|
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||||
|
|
||||||
import static org.mockito.AdditionalAnswers.answerVoid;
|
import static org.mockito.AdditionalAnswers.answerVoid;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
@@ -28,7 +31,6 @@ import static org.mockito.Mockito.atLeastOnce;
|
|||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -38,6 +40,8 @@ import android.app.KeyguardManager;
|
|||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -51,6 +55,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
import com.android.internal.jank.InteractionJankMonitor;
|
import com.android.internal.jank.InteractionJankMonitor;
|
||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.internal.statusbar.NotificationVisibility;
|
import com.android.internal.statusbar.NotificationVisibility;
|
||||||
|
import com.android.internal.util.FrameworkStatsLog;
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.systemui.ActivityIntentHelper;
|
import com.android.systemui.ActivityIntentHelper;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
@@ -90,9 +95,12 @@ import org.mockito.InOrder;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.mockito.MockitoSession;
|
||||||
|
import org.mockito.quality.Strictness;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -398,4 +406,40 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
// THEN display should try wake up for the full screen intent
|
// THEN display should try wake up for the full screen intent
|
||||||
verify(mCentralSurfaces).wakeUpForFullScreenIntent();
|
verify(mCentralSurfaces).wakeUpForFullScreenIntent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnFullScreenIntentWhenDozing_logToStatsd() {
|
||||||
|
final int kTestUid = 12345;
|
||||||
|
final String kTestActivityName = "TestActivity";
|
||||||
|
// GIVEN entry that can has a full screen intent that can show
|
||||||
|
PendingIntent mockFullScreenIntent = mock(PendingIntent.class);
|
||||||
|
when(mockFullScreenIntent.getCreatorUid()).thenReturn(kTestUid);
|
||||||
|
ResolveInfo resolveInfo = new ResolveInfo();
|
||||||
|
resolveInfo.activityInfo = new ActivityInfo();
|
||||||
|
resolveInfo.activityInfo.name = kTestActivityName;
|
||||||
|
when(mockFullScreenIntent.queryIntentComponents(anyInt()))
|
||||||
|
.thenReturn(Arrays.asList(resolveInfo));
|
||||||
|
Notification.Builder nb = new Notification.Builder(mContext, "a")
|
||||||
|
.setContentTitle("foo")
|
||||||
|
.setSmallIcon(android.R.drawable.sym_def_app_icon)
|
||||||
|
.setFullScreenIntent(mockFullScreenIntent, true);
|
||||||
|
StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0,
|
||||||
|
"tag" + System.currentTimeMillis(), 0, 0,
|
||||||
|
nb.build(), new UserHandle(0), null, 0);
|
||||||
|
NotificationEntry entry = mock(NotificationEntry.class);
|
||||||
|
when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH);
|
||||||
|
when(entry.getSbn()).thenReturn(sbn);
|
||||||
|
MockitoSession mockingSession = mockitoSession()
|
||||||
|
.mockStatic(FrameworkStatsLog.class)
|
||||||
|
.strictness(Strictness.LENIENT)
|
||||||
|
.startMocking();
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
mNotificationActivityStarter.launchFullScreenIntent(entry);
|
||||||
|
|
||||||
|
// THEN the full screen intent should be logged to statsd.
|
||||||
|
verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.FULL_SCREEN_INTENT_LAUNCHED,
|
||||||
|
kTestUid, kTestActivityName));
|
||||||
|
mockingSession.finishMocking();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import android.util.ArraySet;
|
|||||||
import android.util.DebugUtils;
|
import android.util.DebugUtils;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.util.FrameworkStatsLog;
|
||||||
import com.android.server.am.PendingIntentRecord;
|
import com.android.server.am.PendingIntentRecord;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@@ -176,22 +177,24 @@ public class BackgroundActivityStartController {
|
|||||||
if (callingUid == Process.ROOT_UID
|
if (callingUid == Process.ROOT_UID
|
||||||
|| callingAppId == Process.SYSTEM_UID
|
|| callingAppId == Process.SYSTEM_UID
|
||||||
|| callingAppId == Process.NFC_UID) {
|
|| callingAppId == Process.NFC_UID) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
|
||||||
BAL_ALLOW_ALLOWLISTED_UID, "Important callingUid");
|
callingUid, realCallingUid, intent, "Important callingUid");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always allow home application to start activities.
|
// Always allow home application to start activities.
|
||||||
if (isHomeApp(callingUid, callingPackage)) {
|
if (isHomeApp(callingUid, callingPackage)) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||||
BAL_ALLOW_ALLOWLISTED_COMPONENT, "Home app");
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
|
"Home app");
|
||||||
}
|
}
|
||||||
|
|
||||||
// IME should always be allowed to start activity, like IME settings.
|
// IME should always be allowed to start activity, like IME settings.
|
||||||
final WindowState imeWindow =
|
final WindowState imeWindow =
|
||||||
mService.mRootWindowContainer.getCurrentInputMethodWindow();
|
mService.mRootWindowContainer.getCurrentInputMethodWindow();
|
||||||
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
|
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||||
BAL_ALLOW_ALLOWLISTED_COMPONENT, "Active ime");
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
|
"Active ime");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,8 +221,8 @@ public class BackgroundActivityStartController {
|
|||||||
&& callingUidHasAnyVisibleWindow)
|
&& callingUidHasAnyVisibleWindow)
|
||||||
|| isCallingUidPersistentSystemProcess;
|
|| isCallingUidPersistentSystemProcess;
|
||||||
if (useCallingUidState && allowCallingUidStartActivity) {
|
if (useCallingUidState && allowCallingUidStartActivity) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_VISIBLE_WINDOW,
|
||||||
BAL_ALLOW_VISIBLE_WINDOW,
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
"callingUidHasAnyVisibleWindow = "
|
"callingUidHasAnyVisibleWindow = "
|
||||||
+ callingUid
|
+ callingUid
|
||||||
+ ", isCallingUidPersistentSystemProcess = "
|
+ ", isCallingUidPersistentSystemProcess = "
|
||||||
@@ -254,8 +257,8 @@ public class BackgroundActivityStartController {
|
|||||||
Process.getAppUidForSdkSandboxUid(UserHandle.getAppId(realCallingUid));
|
Process.getAppUidForSdkSandboxUid(UserHandle.getAppId(realCallingUid));
|
||||||
|
|
||||||
if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
|
if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false, realCallingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_SDK_SANDBOX,
|
||||||
BAL_ALLOW_SDK_SANDBOX,
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
"uid in SDK sandbox has visible (non-toast) window");
|
"uid in SDK sandbox has visible (non-toast) window");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,16 +279,16 @@ public class BackgroundActivityStartController {
|
|||||||
-1,
|
-1,
|
||||||
true)
|
true)
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||||
BAL_ALLOW_PENDING_INTENT,
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
"realCallingUid has BAL permission. realCallingUid: " + realCallingUid);
|
"realCallingUid has BAL permission. realCallingUid: " + realCallingUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't abort if the realCallingUid has a visible window
|
// don't abort if the realCallingUid has a visible window
|
||||||
// TODO(b/171459802): We should check appSwitchAllowed also
|
// TODO(b/171459802): We should check appSwitchAllowed also
|
||||||
if (realCallingUidHasAnyVisibleWindow) {
|
if (realCallingUidHasAnyVisibleWindow) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||||
callingUid, BAL_ALLOW_PENDING_INTENT,
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
"realCallingUid has visible (non-toast) window. realCallingUid: "
|
"realCallingUid has visible (non-toast) window. realCallingUid: "
|
||||||
+ realCallingUid);
|
+ realCallingUid);
|
||||||
}
|
}
|
||||||
@@ -293,9 +296,8 @@ public class BackgroundActivityStartController {
|
|||||||
// wasn't allowed to start an activity
|
// wasn't allowed to start an activity
|
||||||
if (isRealCallingUidPersistentSystemProcess
|
if (isRealCallingUidPersistentSystemProcess
|
||||||
&& backgroundStartPrivileges.allowsBackgroundActivityStarts()) {
|
&& backgroundStartPrivileges.allowsBackgroundActivityStarts()) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||||
callingUid,
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
BAL_ALLOW_PENDING_INTENT,
|
|
||||||
"realCallingUid is persistent system process AND intent "
|
"realCallingUid is persistent system process AND intent "
|
||||||
+ "sender allowed (allowBackgroundActivityStart = true). "
|
+ "sender allowed (allowBackgroundActivityStart = true). "
|
||||||
+ "realCallingUid: " + realCallingUid);
|
+ "realCallingUid: " + realCallingUid);
|
||||||
@@ -303,8 +305,9 @@ public class BackgroundActivityStartController {
|
|||||||
// don't abort if the realCallingUid is an associated companion app
|
// don't abort if the realCallingUid is an associated companion app
|
||||||
if (mService.isAssociatedCompanionApp(
|
if (mService.isAssociatedCompanionApp(
|
||||||
UserHandle.getUserId(realCallingUid), realCallingUid)) {
|
UserHandle.getUserId(realCallingUid), realCallingUid)) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||||
BAL_ALLOW_PENDING_INTENT, "realCallingUid is a companion app. "
|
/*background*/ false, callingUid, realCallingUid, intent,
|
||||||
|
"realCallingUid is a companion app. "
|
||||||
+ "realCallingUid: " + realCallingUid);
|
+ "realCallingUid: " + realCallingUid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,25 +315,28 @@ public class BackgroundActivityStartController {
|
|||||||
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
|
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
|
||||||
if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
|
if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
|
||||||
callingPid, callingUid) == PERMISSION_GRANTED) {
|
callingPid, callingUid) == PERMISSION_GRANTED) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_PERMISSION,
|
||||||
BAL_ALLOW_PERMISSION,
|
/*background*/ true, callingUid, realCallingUid, intent,
|
||||||
"START_ACTIVITIES_FROM_BACKGROUND permission granted");
|
"START_ACTIVITIES_FROM_BACKGROUND permission granted");
|
||||||
}
|
}
|
||||||
// don't abort if the caller has the same uid as the recents component
|
// don't abort if the caller has the same uid as the recents component
|
||||||
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
|
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||||
BAL_ALLOW_ALLOWLISTED_COMPONENT, "Recents Component");
|
/*background*/ true, callingUid, realCallingUid,
|
||||||
|
intent, "Recents Component");
|
||||||
}
|
}
|
||||||
// don't abort if the callingUid is the device owner
|
// don't abort if the callingUid is the device owner
|
||||||
if (mService.isDeviceOwner(callingUid)) {
|
if (mService.isDeviceOwner(callingUid)) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||||
BAL_ALLOW_ALLOWLISTED_COMPONENT, "Device Owner");
|
/*background*/ true, callingUid, realCallingUid,
|
||||||
|
intent, "Device Owner");
|
||||||
}
|
}
|
||||||
// don't abort if the callingUid has companion device
|
// don't abort if the callingUid has companion device
|
||||||
final int callingUserId = UserHandle.getUserId(callingUid);
|
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||||
if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
|
if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||||
BAL_ALLOW_ALLOWLISTED_COMPONENT, "Companion App");
|
/*background*/ true, callingUid, realCallingUid,
|
||||||
|
intent, "Companion App");
|
||||||
}
|
}
|
||||||
// don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
|
// don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
|
||||||
if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
|
if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
|
||||||
@@ -339,8 +345,9 @@ public class BackgroundActivityStartController {
|
|||||||
"Background activity start for "
|
"Background activity start for "
|
||||||
+ callingPackage
|
+ callingPackage
|
||||||
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
|
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_SAW_PERMISSION,
|
||||||
BAL_ALLOW_SAW_PERMISSION, "SYSTEM_ALERT_WINDOW permission is granted");
|
/*background*/ true, callingUid, realCallingUid,
|
||||||
|
intent, "SYSTEM_ALERT_WINDOW permission is granted");
|
||||||
}
|
}
|
||||||
// don't abort if the callingUid and callingPackage have the
|
// don't abort if the callingUid and callingPackage have the
|
||||||
// OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop
|
// OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop
|
||||||
@@ -349,8 +356,8 @@ public class BackgroundActivityStartController {
|
|||||||
callingUid,
|
callingUid,
|
||||||
callingPackage)
|
callingPackage)
|
||||||
== AppOpsManager.MODE_ALLOWED) {
|
== AppOpsManager.MODE_ALLOWED) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
|
return logStartAllowedAndReturnCode(BAL_ALLOW_PERMISSION,
|
||||||
BAL_ALLOW_PERMISSION,
|
/*background*/ true, callingUid, realCallingUid, intent,
|
||||||
"OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
|
"OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,7 +376,8 @@ public class BackgroundActivityStartController {
|
|||||||
@BalCode int balAllowedForCaller = callerApp
|
@BalCode int balAllowedForCaller = callerApp
|
||||||
.areBackgroundActivityStartsAllowed(appSwitchState);
|
.areBackgroundActivityStartsAllowed(appSwitchState);
|
||||||
if (balAllowedForCaller != BAL_BLOCK) {
|
if (balAllowedForCaller != BAL_BLOCK) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, balAllowedForCaller,
|
return logStartAllowedAndReturnCode(balAllowedForCaller,
|
||||||
|
/*background*/ true, callingUid, realCallingUid, intent,
|
||||||
"callerApp process (pid = " + callerApp.getPid()
|
"callerApp process (pid = " + callerApp.getPid()
|
||||||
+ ", uid = " + callerAppUid + ") is allowed");
|
+ ", uid = " + callerAppUid + ") is allowed");
|
||||||
}
|
}
|
||||||
@@ -382,7 +390,8 @@ public class BackgroundActivityStartController {
|
|||||||
int balAllowedForUid = proc.areBackgroundActivityStartsAllowed(appSwitchState);
|
int balAllowedForUid = proc.areBackgroundActivityStartsAllowed(appSwitchState);
|
||||||
if (proc != callerApp
|
if (proc != callerApp
|
||||||
&& balAllowedForUid != BAL_BLOCK) {
|
&& balAllowedForUid != BAL_BLOCK) {
|
||||||
return logStartAllowedAndReturnCode(/*background*/ true, balAllowedForUid,
|
return logStartAllowedAndReturnCode(balAllowedForUid,
|
||||||
|
/*background*/ true, callingUid, realCallingUid, intent,
|
||||||
"process" + proc.getPid()
|
"process" + proc.getPid()
|
||||||
+ " from uid " + callerAppUid + " is allowed");
|
+ " from uid " + callerAppUid + " is allowed");
|
||||||
}
|
}
|
||||||
@@ -448,27 +457,21 @@ public class BackgroundActivityStartController {
|
|||||||
return BAL_BLOCK;
|
return BAL_BLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int logStartAllowedAndReturnCode(boolean background, int callingUid, int code,
|
static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
|
||||||
String msg) {
|
int callingUid, int realCallingUid, Intent intent, int pid, String msg) {
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
return logStartAllowedAndReturnCode(code, background, callingUid, realCallingUid, intent,
|
||||||
return logStartAllowedAndReturnCode(background, code,
|
DEBUG_ACTIVITY_STARTS ? ("[Process(" + pid + ")]" + msg) : "");
|
||||||
msg, "callingUid: " + callingUid);
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int logStartAllowedAndReturnCode(boolean background, int code,
|
static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
|
||||||
String... msg) {
|
int callingUid, int realCallingUid, Intent intent, String msg) {
|
||||||
|
statsLogBalAllowed(code, callingUid, realCallingUid, intent);
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
if (DEBUG_ACTIVITY_STARTS) {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
if (background) {
|
if (background) {
|
||||||
builder.append("Background ");
|
builder.append("Background ");
|
||||||
}
|
}
|
||||||
builder.append("Activity start allowed: ");
|
builder.append("Activity start allowed: " + msg + ". callingUid: " + callingUid + ". ");
|
||||||
for (int i = 0; i < msg.length; i++) {
|
|
||||||
builder.append(msg[i]);
|
|
||||||
builder.append(". ");
|
|
||||||
}
|
|
||||||
builder.append("BAL Code: ");
|
builder.append("BAL Code: ");
|
||||||
builder.append(code);
|
builder.append(code);
|
||||||
Slog.d(TAG, builder.toString());
|
Slog.d(TAG, builder.toString());
|
||||||
@@ -482,4 +485,27 @@ public class BackgroundActivityStartController {
|
|||||||
/* name= */ "system_exempt_from_activity_bg_start_restriction_enabled",
|
/* name= */ "system_exempt_from_activity_bg_start_restriction_enabled",
|
||||||
/* defaultValue= */ true);
|
/* defaultValue= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void statsLogBalAllowed(
|
||||||
|
@BalCode int code, int callingUid, int realCallingUid, Intent intent) {
|
||||||
|
if (code == BAL_ALLOW_PENDING_INTENT
|
||||||
|
&& (callingUid == Process.SYSTEM_UID || realCallingUid == Process.SYSTEM_UID)) {
|
||||||
|
String activityName =
|
||||||
|
intent != null ? intent.getComponent().flattenToShortString() : "";
|
||||||
|
FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||||
|
activityName,
|
||||||
|
code,
|
||||||
|
callingUid,
|
||||||
|
realCallingUid);
|
||||||
|
}
|
||||||
|
if (code == BAL_ALLOW_PERMISSION || code == BAL_ALLOW_FOREGROUND
|
||||||
|
|| code == BAL_ALLOW_SAW_PERMISSION) {
|
||||||
|
// We don't need to know which activity in this case.
|
||||||
|
FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||||
|
/*activityName*/ "",
|
||||||
|
code,
|
||||||
|
callingUid,
|
||||||
|
realCallingUid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,37 +104,29 @@ class BackgroundLaunchProcessController {
|
|||||||
long lastActivityFinishTime) {
|
long lastActivityFinishTime) {
|
||||||
// Allow if the proc is instrumenting with background activity starts privs.
|
// Allow if the proc is instrumenting with background activity starts privs.
|
||||||
if (hasBackgroundActivityStartPrivileges) {
|
if (hasBackgroundActivityStartPrivileges) {
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||||
Slog.d(TAG, "[Process(" + pid
|
BAL_ALLOW_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
|
||||||
+ ")] Activity start allowed: process instrumenting with background "
|
pid, "Activity start allowed: process instrumenting with background "
|
||||||
+ "activity starts privileges");
|
+ "activity starts privileges");
|
||||||
}
|
}
|
||||||
return BAL_ALLOW_PERMISSION;
|
|
||||||
}
|
|
||||||
// Allow if the flag was explicitly set.
|
// Allow if the flag was explicitly set.
|
||||||
if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
|
if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||||
Slog.d(TAG, "[Process(" + pid
|
BAL_ALLOW_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
|
||||||
+ ")] Activity start allowed: process allowed by token");
|
pid, "Activity start allowed: process allowed by token");
|
||||||
}
|
|
||||||
return BAL_ALLOW_PERMISSION;
|
|
||||||
}
|
}
|
||||||
// Allow if the caller is bound by a UID that's currently foreground.
|
// Allow if the caller is bound by a UID that's currently foreground.
|
||||||
if (isBoundByForegroundUid()) {
|
if (isBoundByForegroundUid()) {
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||||
Slog.d(TAG, "[Process(" + pid
|
BAL_ALLOW_VISIBLE_WINDOW, /*background*/ false, uid, uid, /*intent*/ null,
|
||||||
+ ")] Activity start allowed: process bound by foreground uid");
|
pid, "Activity start allowed: process bound by foreground uid");
|
||||||
}
|
|
||||||
return BAL_ALLOW_VISIBLE_WINDOW;
|
|
||||||
}
|
}
|
||||||
// Allow if the caller has an activity in any foreground task.
|
// Allow if the caller has an activity in any foreground task.
|
||||||
if (hasActivityInVisibleTask
|
if (hasActivityInVisibleTask
|
||||||
&& (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
|
&& (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||||
Slog.d(TAG, "[Process(" + pid
|
BAL_ALLOW_FOREGROUND, /*background*/ false, uid, uid, /*intent*/ null,
|
||||||
+ ")] Activity start allowed: process has activity in foreground task");
|
pid, "Activity start allowed: process has activity in foreground task");
|
||||||
}
|
|
||||||
return BAL_ALLOW_FOREGROUND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If app switching is not allowed, we ignore all the start activity grace period
|
// If app switching is not allowed, we ignore all the start activity grace period
|
||||||
@@ -149,13 +141,11 @@ class BackgroundLaunchProcessController {
|
|||||||
// let app to be able to start background activity even it's in grace period.
|
// let app to be able to start background activity even it's in grace period.
|
||||||
if (lastActivityLaunchTime > lastStopAppSwitchesTime
|
if (lastActivityLaunchTime > lastStopAppSwitchesTime
|
||||||
|| lastActivityFinishTime > lastStopAppSwitchesTime) {
|
|| lastActivityFinishTime > lastStopAppSwitchesTime) {
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||||
Slog.d(TAG, "[Process(" + pid
|
BAL_ALLOW_GRACE_PERIOD, /*background*/ true, uid, uid, /*intent*/ null,
|
||||||
+ ")] Activity start allowed: within "
|
pid, "Activity start allowed: within "
|
||||||
+ ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
|
+ ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
|
||||||
}
|
}
|
||||||
return BAL_ALLOW_GRACE_PERIOD;
|
|
||||||
}
|
|
||||||
if (DEBUG_ACTIVITY_STARTS) {
|
if (DEBUG_ACTIVITY_STARTS) {
|
||||||
Slog.d(TAG, "[Process(" + pid + ")] Activity start within "
|
Slog.d(TAG, "[Process(" + pid + ")] Activity start within "
|
||||||
+ ACTIVITY_BG_START_GRACE_PERIOD_MS
|
+ ACTIVITY_BG_START_GRACE_PERIOD_MS
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.wm;
|
package com.android.server.wm;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
|
||||||
import static android.app.Activity.RESULT_CANCELED;
|
import static android.app.Activity.RESULT_CANCELED;
|
||||||
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
|
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
|
||||||
import static android.app.ActivityManager.PROCESS_STATE_TOP;
|
import static android.app.ActivityManager.PROCESS_STATE_TOP;
|
||||||
@@ -43,6 +44,7 @@ import static android.content.pm.ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBE
|
|||||||
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
|
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
|
||||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
|
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
|
||||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
|
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
import static android.os.Process.SYSTEM_UID;
|
import static android.os.Process.SYSTEM_UID;
|
||||||
|
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
|
||||||
@@ -50,6 +52,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
|||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
@@ -77,6 +80,7 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyObject;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.notNull;
|
import static org.mockito.ArgumentMatchers.notNull;
|
||||||
@@ -111,6 +115,8 @@ import android.window.TaskFragmentOrganizerToken;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.compatibility.common.util.DeviceConfigStateHelper;
|
import com.android.compatibility.common.util.DeviceConfigStateHelper;
|
||||||
|
import com.android.internal.util.FrameworkStatsLog;
|
||||||
|
import com.android.server.am.PendingIntentRecord;
|
||||||
import com.android.server.pm.pkg.AndroidPackage;
|
import com.android.server.pm.pkg.AndroidPackage;
|
||||||
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
|
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
|
||||||
import com.android.server.wm.utils.MockTracker;
|
import com.android.server.wm.utils.MockTracker;
|
||||||
@@ -120,6 +126,8 @@ import org.junit.Before;
|
|||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.MockitoSession;
|
||||||
|
import org.mockito.quality.Strictness;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -880,6 +888,64 @@ public class ActivityStarterTests extends WindowTestsBase {
|
|||||||
false, false, false, false, false, false, false);
|
false, false, false, false, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test ensures proper logging for BAL_ALLOW_PERMISSION.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBackgroundActivityStartsAllowed_logging() {
|
||||||
|
doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
|
||||||
|
MockitoSession mockingSession = mockitoSession()
|
||||||
|
.mockStatic(ActivityTaskManagerService.class)
|
||||||
|
.mockStatic(FrameworkStatsLog.class)
|
||||||
|
.strictness(Strictness.LENIENT)
|
||||||
|
.startMocking();
|
||||||
|
doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
|
||||||
|
eq(START_ACTIVITIES_FROM_BACKGROUND),
|
||||||
|
anyInt(), anyInt()));
|
||||||
|
runAndVerifyBackgroundActivityStartsSubtest(
|
||||||
|
"allowed_notAborted", false,
|
||||||
|
UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
|
||||||
|
UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP,
|
||||||
|
false, true, false, false, false, false, false);
|
||||||
|
verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||||
|
"", // activity name
|
||||||
|
BackgroundActivityStartController.BAL_ALLOW_PERMISSION,
|
||||||
|
UNIMPORTANT_UID,
|
||||||
|
UNIMPORTANT_UID2));
|
||||||
|
mockingSession.finishMocking();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test ensures proper logging for BAL_ALLOW_PENDING_INTENT.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBackgroundActivityStartsAllowed_loggingPendingIntentAllowed() {
|
||||||
|
doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
|
||||||
|
MockitoSession mockingSession = mockitoSession()
|
||||||
|
.mockStatic(ActivityTaskManagerService.class)
|
||||||
|
.mockStatic(FrameworkStatsLog.class)
|
||||||
|
.mockStatic(PendingIntentRecord.class)
|
||||||
|
.strictness(Strictness.LENIENT)
|
||||||
|
.startMocking();
|
||||||
|
doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
|
||||||
|
eq(START_ACTIVITIES_FROM_BACKGROUND),
|
||||||
|
anyInt(), anyInt()));
|
||||||
|
doReturn(BackgroundStartPrivileges.allowBackgroundActivityStarts(null)).when(
|
||||||
|
() -> PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(
|
||||||
|
anyObject(), anyInt()));
|
||||||
|
runAndVerifyBackgroundActivityStartsSubtest(
|
||||||
|
"allowed_notAborted", false,
|
||||||
|
UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
|
||||||
|
Process.SYSTEM_UID, true, PROCESS_STATE_BOUND_TOP,
|
||||||
|
false, true, false, false, false, false, false);
|
||||||
|
verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||||
|
DEFAULT_COMPONENT_PACKAGE_NAME + "/" + DEFAULT_COMPONENT_PACKAGE_NAME,
|
||||||
|
BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT,
|
||||||
|
UNIMPORTANT_UID,
|
||||||
|
Process.SYSTEM_UID));
|
||||||
|
mockingSession.finishMocking();
|
||||||
|
}
|
||||||
|
|
||||||
private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
|
private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
|
||||||
int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
|
int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
|
||||||
int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
|
int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
|
||||||
|
|||||||
Reference in New Issue
Block a user