summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java59
-rw-r--r--core/java/android/provider/Settings.java33
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java11
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java8
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java7
-rw-r--r--core/java/com/android/internal/policy/DecorView.java2
-rw-r--r--core/proto/android/providers/settings/secure.proto10
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java41
-rw-r--r--libs/androidfw/PosixUtils.cpp13
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java16
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java33
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java73
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java16
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java22
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java23
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java20
-rw-r--r--services/core/java/com/android/server/wm/DragState.java2
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java131
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java54
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java17
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java21
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyPermissions.java14
43 files changed, 544 insertions, 319 deletions
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index b0b1874107ce..23fbefb73c50 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -17,7 +17,6 @@
package android.content.pm;
import android.Manifest;
-import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -177,8 +176,7 @@ public abstract class RegisteredServicesCache<V> {
mContext.registerReceiver(mUserRemovedReceiver, userFilter);
}
- @VisibleForTesting
- protected void handlePackageEvent(Intent intent, int userId) {
+ private void handlePackageEvent(Intent intent, int userId) {
// Don't regenerate the services map when the package is removed or its
// ASEC container unmounted as a step in replacement. The subsequent
// _ADDED / _AVAILABLE call will regenerate the map in the final state.
@@ -240,9 +238,6 @@ public abstract class RegisteredServicesCache<V> {
public void invalidateCache(int userId) {
synchronized (mServicesLock) {
- if (DEBUG) {
- Slog.d(TAG, "invalidating cache for " + userId + " " + mInterfaceName);
- }
final UserServices<V> user = findOrCreateUserLocked(userId);
user.services = null;
onServicesChangedLocked(userId);
@@ -472,48 +467,34 @@ public abstract class RegisteredServicesCache<V> {
* or null to assume that everything is affected.
* @param userId the user for whom to update the services map.
*/
- private void generateServicesMap(@Nullable int[] changedUids, int userId) {
+ private void generateServicesMap(int[] changedUids, int userId) {
if (DEBUG) {
Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = "
+ Arrays.toString(changedUids));
}
+ final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
+ final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ try {
+ ServiceInfo<V> info = parseServiceInfo(resolveInfo);
+ if (info == null) {
+ Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
+ continue;
+ }
+ serviceInfos.add(info);
+ } catch (XmlPullParserException | IOException e) {
+ Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
+ }
+ }
+
synchronized (mServicesLock) {
final UserServices<V> user = findOrCreateUserLocked(userId);
- final boolean cacheInvalid = user.services == null;
- if (cacheInvalid) {
+ final boolean firstScan = user.services == null;
+ if (firstScan) {
user.services = Maps.newHashMap();
}
- final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
- final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
-
- for (ResolveInfo resolveInfo : resolveInfos) {
- try {
- // when changedUids == null, we want to do a rescan of everything, this means
- // it's the initial scan, and containsUid will trivially return true
- // when changedUids != null, we got here because a package changed, but
- // invalidateCache could have been called (thus user.services == null), and we
- // should query from PackageManager again
- if (!cacheInvalid
- && !containsUid(
- changedUids, resolveInfo.serviceInfo.applicationInfo.uid)) {
- if (DEBUG) {
- Slog.d(TAG, "Skipping parseServiceInfo for " + resolveInfo);
- }
- continue;
- }
- ServiceInfo<V> info = parseServiceInfo(resolveInfo);
- if (info == null) {
- Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
- continue;
- }
- serviceInfos.add(info);
- } catch (XmlPullParserException | IOException e) {
- Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
- }
- }
-
StringBuilder changes = new StringBuilder();
boolean changed = false;
for (ServiceInfo<V> info : serviceInfos) {
@@ -534,7 +515,7 @@ public abstract class RegisteredServicesCache<V> {
changed = true;
user.services.put(info.type, info);
user.persistentServices.put(info.type, info.uid);
- if (!(user.mPersistentServicesFileDidNotExist && cacheInvalid)) {
+ if (!(user.mPersistentServicesFileDidNotExist && firstScan)) {
notifyListener(info.type, userId, false /* removed */);
}
} else if (previousUid == info.uid) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6f0669b15dad..bf8b0066cb64 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7764,6 +7764,12 @@ public final class Settings {
*/
public static final String SKIP_GESTURE_COUNT = "skip_gesture_count";
+ /**
+ * Count of non-gesture interaction.
+ * @hide
+ */
+ public static final String SKIP_TOUCH_COUNT = "skip_touch_count";
+
private static final Validator SKIP_GESTURE_COUNT_VALIDATOR =
NON_NEGATIVE_INTEGER_VALIDATOR;
@@ -7808,11 +7814,22 @@ public final class Settings {
public static final String SILENCE_CALL_GESTURE_COUNT = "silence_call_gesture_count";
/**
- * Count of successful silence notification gestures.
+ * Count of non-gesture interaction.
+ * @hide
+ */
+ public static final String SILENCE_ALARMS_TOUCH_COUNT = "silence_alarms_touch_count";
+
+ /**
+ * Count of non-gesture interaction.
+ * @hide
+ */
+ public static final String SILENCE_TIMER_TOUCH_COUNT = "silence_timer_touch_count";
+
+ /**
+ * Count of non-gesture interaction.
* @hide
*/
- public static final String SILENCE_NOTIFICATION_GESTURE_COUNT =
- "silence_notification_gesture_count";
+ public static final String SILENCE_CALL_TOUCH_COUNT = "silence_call_touch_count";
private static final Validator SILENCE_GESTURE_COUNT_VALIDATOR =
NON_NEGATIVE_INTEGER_VALIDATOR;
@@ -9036,10 +9053,13 @@ public final class Settings {
NAVIGATION_MODE,
AWARE_ENABLED,
SKIP_GESTURE_COUNT,
+ SKIP_TOUCH_COUNT,
SILENCE_ALARMS_GESTURE_COUNT,
- SILENCE_NOTIFICATION_GESTURE_COUNT,
SILENCE_CALL_GESTURE_COUNT,
SILENCE_TIMER_GESTURE_COUNT,
+ SILENCE_ALARMS_TOUCH_COUNT,
+ SILENCE_CALL_TOUCH_COUNT,
+ SILENCE_TIMER_TOUCH_COUNT,
DARK_MODE_DIALOG_SEEN,
GLOBAL_ACTIONS_PANEL_ENABLED,
AWARE_LOCK_ENABLED
@@ -9227,10 +9247,13 @@ public final class Settings {
VALIDATORS.put(NAVIGATION_MODE, NAVIGATION_MODE_VALIDATOR);
VALIDATORS.put(AWARE_ENABLED, AWARE_ENABLED_VALIDATOR);
VALIDATORS.put(SKIP_GESTURE_COUNT, SKIP_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SKIP_TOUCH_COUNT, SKIP_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(SILENCE_ALARMS_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(SILENCE_TIMER_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
- VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_ALARMS_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_TIMER_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_CALL_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index f9d27bb46592..00206fc38d1d 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1534,7 +1534,11 @@ public class ChooserActivity extends ResolverActivity {
if (driList.get(i).getResolvedComponentName().equals(
resultList.get(j).getTargetComponent())) {
ShortcutManager.ShareShortcutInfo shareShortcutInfo = resultList.get(j);
- ChooserTarget chooserTarget = convertToChooserTarget(shareShortcutInfo);
+ // Incoming results are ordered but without a score. Create a score
+ // based on the index in order to be sorted appropriately when joined
+ // with legacy direct share api results.
+ float score = Math.max(1.0f - (0.05f * j), 0.0f);
+ ChooserTarget chooserTarget = convertToChooserTarget(shareShortcutInfo, score);
chooserTargets.add(chooserTarget);
if (mDirectShareAppTargetCache != null && appTargets != null) {
mDirectShareAppTargetCache.put(chooserTarget, appTargets.get(j));
@@ -1580,7 +1584,8 @@ public class ChooserActivity extends ResolverActivity {
return false;
}
- private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut) {
+ private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut,
+ float score) {
ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
Bundle extras = new Bundle();
extras.putString(Intent.EXTRA_SHORTCUT_ID, shortcutInfo.getId());
@@ -1591,7 +1596,7 @@ public class ChooserActivity extends ResolverActivity {
null,
// The ranking score for this target (0.0-1.0); the system will omit items with low
// scores when there are too many Direct Share items.
- 1.0f,
+ score,
// The name of the component to be launched if this target is chosen.
shareShortcut.getTargetComponent().clone(),
// The extra values here will be merged into the Intent when this target is chosen.
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 6e97076fefdf..55e21a4774d9 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -146,14 +146,6 @@ public final class SystemUiDeviceConfigFlags {
public static final String ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS =
"assist_handles_shown_frequency_threshold_ms";
- // Flag related to clock face
-
- /**
- * (String) Contains the clock plugin service names that are not allow to be shown.
- * Each service name is seperated by a comma(",") in the string.
- */
- public static final String CLOCK_FACE_BLACKLIST = "clock_face_blacklist";
-
/**
* (long) How long, in milliseconds, for teaching behaviors to wait before considering the user
* taught.
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 7ec8309e47de..d28c72f319af 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -188,6 +188,13 @@ public class ZygoteInit {
System.loadLibrary("android");
System.loadLibrary("compiler_rt");
System.loadLibrary("jnigraphics");
+
+ // tolerate missing sfplugin_ccodec which is only present on Codec 2 devices
+ try {
+ System.loadLibrary("sfplugin_ccodec");
+ } catch (Error | RuntimeException e) {
+ Log.w(TAG, "Problem preloading sfplugin_ccodec: " + e);
+ }
}
native private static void nativePreloadAppProcessHALs();
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 6f4f3374ac73..fe66cf9aab7d 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1311,7 +1311,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
return semiTransparentBarColor;
} else if ((flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
return Color.BLACK;
- } else if (scrimTransparent && barColor == Color.TRANSPARENT) {
+ } else if (scrimTransparent && Color.alpha(barColor) == 0) {
boolean light = (sysuiVis & lightSysuiFlag) != 0;
return light ? SCRIM_LIGHT : semiTransparentBarColor;
} else {
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index fed2efaf8a78..61799eefdca6 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -198,11 +198,19 @@ message SecureSettingsProto {
optional SettingProto silence_alarms_count = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto silence_calls_count = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto silence_enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto silence_notification_count = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // del: silence_notification_count = 5
optional SettingProto silence_timer_count = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto skip_count = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto skip_enabled = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ optional SettingProto silence_alarms_touch_count = 9 [ (android.privacy).dest =
+ DEST_AUTOMATIC ];
+ optional SettingProto silence_calls_touch_count = 10 [ (android.privacy).dest =
+ DEST_AUTOMATIC ];
+ optional SettingProto silence_timer_touch_count = 11 [ (android.privacy).dest =
+ DEST_AUTOMATIC ];
+ optional SettingProto skip_touch_count = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Gesture gesture = 74;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 600330c356ed..305c1a6d5657 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3787,9 +3787,11 @@
<integer name="config_stableDeviceDisplayWidth">-1</integer>
<integer name="config_stableDeviceDisplayHeight">-1</integer>
- <!-- Decide whether to display 'No service' on status bar instead of 'Emergency calls only'
- when SIM is unready. -->
- <bool name="config_display_no_service_when_sim_unready">false</bool>
+ <!-- List of countries in which we display 'No service' on status bar
+ instead of 'Emergency calls only' when SIM is unready. -->
+ <string-array translatable="false" name="config_display_no_service_when_sim_unready">
+ <item>"DE"</item>
+ </string-array>
<!-- Class names of device specific services inheriting com.android.server.SystemService. The
classes are instantiated in the order of the array. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 51cd7441ef26..6e03f5e8e018 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3552,7 +3552,7 @@
<java-symbol type="integer" name="config_stableDeviceDisplayWidth" />
<java-symbol type="integer" name="config_stableDeviceDisplayHeight" />
- <java-symbol type="bool" name="config_display_no_service_when_sim_unready" />
+ <java-symbol type="array" name="config_display_no_service_when_sim_unready" />
<java-symbol type="layout" name="slice_grid" />
<java-symbol type="layout" name="slice_message_local" />
diff --git a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
index c8150b12a23b..365e97ded928 100644
--- a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
@@ -16,7 +16,6 @@
package android.content.pm;
-import android.content.Intent;
import android.content.res.Resources;
import android.os.FileUtils;
import android.os.Parcel;
@@ -190,36 +189,6 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
assertEquals(0, cache.getPersistentServicesSize(u1));
}
- /**
- * Check that an optimization to skip a call to PackageManager handles an invalidated cache.
- *
- * We added an optimization in generateServicesMap to only query PackageManager for packages
- * that have been changed, because if a package is unchanged, we have already cached the
- * services info for it, so we can save a query to PackageManager (and save some memory).
- * However, if invalidateCache was called, we cannot optimize, and must do a full query.
- * The initial optimization was buggy because it failed to check for an invalidated cache, and
- * only scanned the changed packages, given in the ACTION_PACKAGE_CHANGED intent (b/122912184).
- */
- public void testParseServiceInfoOptimizationHandlesInvalidatedCache() {
- TestServicesCache cache = new TestServicesCache();
- cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
- cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2));
- assertEquals(2, cache.getAllServicesSize(U0));
-
- // simulate the client of the cache invalidating it
- cache.invalidateCache(U0);
-
- // there should be 0 services (userServices.services == null ) at this point, but we don't
- // call getAllServicesSize since that would force a full scan of packages,
- // instead we trigger a package change in a package that is in the list of services
- Intent intent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
- intent.putExtra(Intent.EXTRA_UID, UID1);
- cache.handlePackageEvent(intent, U0);
-
- // check that the optimization does a full query and caches both services
- assertEquals(2, cache.getAllServicesSize(U0));
- }
-
private static RegisteredServicesCache.ServiceInfo<TestServiceType> newServiceInfo(
TestServiceType type, int uid) {
final ComponentInfo info = new ComponentInfo();
@@ -297,11 +266,6 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
map = new HashMap<>();
mServices.put(userId, map);
}
- // in actual cases, resolveInfo should always have a serviceInfo, since we specifically
- // query for intent services
- resolveInfo.serviceInfo = new android.content.pm.ServiceInfo();
- resolveInfo.serviceInfo.applicationInfo =
- new ApplicationInfo(serviceInfo.componentInfo.applicationInfo);
map.put(resolveInfo, serviceInfo);
}
@@ -340,11 +304,6 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
public void onUserRemoved(int userId) {
super.onUserRemoved(userId);
}
-
- @Override
- public void handlePackageEvent(Intent intent, int userId) {
- super.handlePackageEvent(intent, userId);
- }
}
static class TestSerializer implements XmlSerializerAndParser<TestServiceType> {
diff --git a/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp
index df0dd7ce463d..f1ab1493012a 100644
--- a/libs/androidfw/PosixUtils.cpp
+++ b/libs/androidfw/PosixUtils.cpp
@@ -64,6 +64,9 @@ std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv)
return nullptr;
}
+ auto gid = getgid();
+ auto uid = getuid();
+
char const** argv0 = (char const**)malloc(sizeof(char*) * (argv.size() + 1));
for (size_t i = 0; i < argv.size(); i++) {
argv0[i] = argv[i].c_str();
@@ -75,6 +78,16 @@ std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv)
PLOG(ERROR) << "fork";
return nullptr;
case 0: // child
+ if (setgid(gid) != 0) {
+ PLOG(ERROR) << "setgid";
+ exit(1);
+ }
+
+ if (setuid(uid) != 0) {
+ PLOG(ERROR) << "setuid";
+ exit(1);
+ }
+
close(stdout[0]);
if (dup2(stdout[1], STDOUT_FILENO) == -1) {
abort();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 3cd82dfca6b6..b2c10ec8ea7f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1944,9 +1944,6 @@ class SettingsProtoDumpUtil {
Settings.Secure.SILENCE_GESTURE,
SecureSettingsProto.Gesture.SILENCE_ENABLED);
dumpSetting(s, p,
- Settings.Secure.SILENCE_NOTIFICATION_GESTURE_COUNT,
- SecureSettingsProto.Gesture.SILENCE_NOTIFICATION_COUNT);
- dumpSetting(s, p,
Settings.Secure.SILENCE_TIMER_GESTURE_COUNT,
SecureSettingsProto.Gesture.SILENCE_TIMER_COUNT);
@@ -1956,6 +1953,19 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.Secure.SKIP_GESTURE,
SecureSettingsProto.Gesture.SKIP_ENABLED);
+
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_ALARMS_TOUCH_COUNT,
+ SecureSettingsProto.Gesture.SILENCE_ALARMS_TOUCH_COUNT);
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_CALL_TOUCH_COUNT,
+ SecureSettingsProto.Gesture.SILENCE_CALLS_TOUCH_COUNT);
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_TIMER_TOUCH_COUNT,
+ SecureSettingsProto.Gesture.SILENCE_TIMER_TOUCH_COUNT);
+ dumpSetting(s, p,
+ Settings.Secure.SKIP_TOUCH_COUNT,
+ SecureSettingsProto.Gesture.SKIP_TOUCH_COUNT);
p.end(gestureToken);
dumpSetting(s, p,
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4df824e1cb06..a549870ec780 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -112,6 +112,9 @@
wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast
</string>
+ <!-- The minimum number of tiles to display in QuickSettings -->
+ <integer name="quick_settings_min_num_tiles">6</integer>
+
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f60613ae4a83..7feacb469f81 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2011,7 +2011,7 @@
<string name="drag_to_remove_tiles">Drag here to remove</string>
<!-- Label to indicate to users that additional tiles cannot be removed. [CHAR LIMIT=60] -->
- <string name="drag_to_remove_disabled">You need at least 6 tiles</string>
+ <string name="drag_to_remove_disabled">You need at least <xliff:g id="min_num_tiles" example="6">%1$d</xliff:g> tiles</string>
<!-- Button to edit the tile ordering of quick settings [CHAR LIMIT=60] -->
<string name="qs_edit">Edit</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 9edb54c146df..9e2464ea4fbb 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -15,8 +15,6 @@
*/
package com.android.keyguard.clock;
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLOCK_FACE_BLACKLIST;
-
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
@@ -26,12 +24,9 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.LayoutInflater;
import androidx.annotation.VisibleForTesting;
@@ -47,12 +42,10 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.InjectionInflationController;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -74,8 +67,6 @@ public final class ClockManager {
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private final CurrentUserObservable mCurrentUserObservable;
- private final ArraySet<String> mBlacklistedClockPlugins = new ArraySet<>();
-
/**
* Observe settings changes to know when to switch the clock face.
*/
@@ -164,41 +155,6 @@ public final class ClockManager {
DisplayMetrics dm = res.getDisplayMetrics();
mWidth = dm.widthPixels;
mHeight = dm.heightPixels;
-
- updateBlackList();
- registerDeviceConfigListener();
- }
-
- private void updateBlackList() {
- String blacklist = getBlackListFromConfig();
-
- mBlacklistedClockPlugins.clear();
- if (blacklist != null && !blacklist.isEmpty()) {
- mBlacklistedClockPlugins.addAll(Arrays.asList(blacklist.split(",")));
- }
- }
-
- String getBlackListFromConfig() {
- return DeviceConfig.getString(
- DeviceConfig.NAMESPACE_SYSTEMUI, CLOCK_FACE_BLACKLIST, null);
- }
-
- private void registerDeviceConfigListener() {
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- r -> mMainHandler.post(r),
- properties -> onDeviceConfigPropertiesChanged(properties.getNamespace()));
- }
-
- void onDeviceConfigPropertiesChanged(String namespace) {
- if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(namespace)) {
- Log.e(TAG, "Received update from DeviceConfig for unrelated namespace: "
- + namespace);
- return;
- }
-
- updateBlackList();
- reload();
}
/**
@@ -350,12 +306,10 @@ public final class ClockManager {
}
/**
- * Get information about clock faces which are available and not in blacklist.
+ * Get information about available clock faces.
*/
List<ClockInfo> getInfo() {
- return mClockInfo.stream()
- .filter(info -> !mBlacklistedClockPlugins.contains(info.getId()))
- .collect(Collectors.toList());
+ return mClockInfo;
}
/**
@@ -407,7 +361,7 @@ public final class ClockManager {
if (ClockManager.this.isDocked()) {
final String name = mSettingsWrapper.getDockedClockFace(
mCurrentUserObservable.getCurrentUser().getValue());
- if (name != null && !mBlacklistedClockPlugins.contains(name)) {
+ if (name != null) {
plugin = mClocks.get(name);
if (plugin != null) {
return plugin;
@@ -416,7 +370,7 @@ public final class ClockManager {
}
final String name = mSettingsWrapper.getLockScreenCustomClockFace(
mCurrentUserObservable.getCurrentUser().getValue());
- if (name != null && !mBlacklistedClockPlugins.contains(name)) {
+ if (name != null) {
plugin = mClocks.get(name);
}
return plugin;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 8ed5424cf673..2542abdbef72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -19,6 +19,7 @@ import android.app.AlertDialog.Builder;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -54,7 +55,6 @@ import java.util.ArrayList;
import java.util.List;
public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileStateListener {
- private static final int MIN_NUM_TILES = 6;
private static final long DRAG_LENGTH = 100;
private static final float DRAG_SCALE = 1.2f;
public static final long MOVE_DURATION = 150;
@@ -79,6 +79,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private final ItemTouchHelper mItemTouchHelper;
private final ItemDecoration mDecoration;
private final AccessibilityManager mAccessibilityManager;
+ private final int mMinNumTiles;
private int mEditIndex;
private int mTileDividerIndex;
private boolean mNeedsFocus;
@@ -97,6 +98,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mItemTouchHelper = new ItemTouchHelper(mCallbacks);
mDecoration = new TileItemDecoration(context);
+ mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles);
}
public void setHost(QSTileHost host) {
@@ -247,15 +249,17 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
return;
}
if (holder.getItemViewType() == TYPE_EDIT) {
- final int titleResId;
+ final String titleText;
+ Resources res = mContext.getResources();
if (mCurrentDrag == null) {
- titleResId = R.string.drag_to_add_tiles;
+ titleText = res.getString(R.string.drag_to_add_tiles);
} else if (!canRemoveTiles() && mCurrentDrag.getAdapterPosition() < mEditIndex) {
- titleResId = R.string.drag_to_remove_disabled;
+ titleText = res.getString(R.string.drag_to_remove_disabled, mMinNumTiles);
} else {
- titleResId = R.string.drag_to_remove_tiles;
+ titleText = res.getString(R.string.drag_to_remove_tiles);
}
- ((TextView) holder.itemView.findViewById(android.R.id.title)).setText(titleResId);
+
+ ((TextView) holder.itemView.findViewById(android.R.id.title)).setText(titleText);
return;
}
if (holder.getItemViewType() == TYPE_ACCESSIBLE_DROP) {
@@ -337,7 +341,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
private boolean canRemoveTiles() {
- return mCurrentSpecs.size() > MIN_NUM_TILES;
+ return mCurrentSpecs.size() > mMinNumTiles;
}
private void selectPosition(int position, View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 787cc971e6a1..aeb85748fd1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -16,8 +16,11 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
import android.content.Context;
import android.content.res.Resources;
+import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
import android.util.Log;
@@ -44,6 +47,7 @@ import java.util.List;
import java.util.Stack;
import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Lazy;
@@ -59,6 +63,8 @@ import dagger.Lazy;
public class NotificationViewHierarchyManager implements DynamicPrivacyController.Listener {
private static final String TAG = "NotificationViewHierarchyManager";
+ private final Handler mHandler;
+
//TODO: change this top <Entry, List<Entry>>?
private final HashMap<ExpandableNotificationRow, List<ExpandableNotificationRow>>
mTmpChildOrderMap = new HashMap<>();
@@ -88,9 +94,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
// Used to help track down re-entrant calls to our update methods, which will cause bugs.
private boolean mPerformingUpdate;
+ // Hack to get around re-entrant call in onDynamicPrivacyChanged() until we can track down
+ // the problem.
+ private boolean mIsHandleDynamicPrivacyChangeScheduled;
@Inject
public NotificationViewHierarchyManager(Context context,
+ @Named(MAIN_HANDLER_NAME) Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
@@ -100,6 +110,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
BubbleData bubbleData,
KeyguardBypassController bypassController,
DynamicPrivacyController privacyController) {
+ mHandler = mainHandler;
mLockscreenUserManager = notificationLockscreenUserManager;
mBypassController = bypassController;
mGroupManager = groupManager;
@@ -438,6 +449,20 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
@Override
public void onDynamicPrivacyChanged() {
+ if (mPerformingUpdate) {
+ Log.w(TAG, "onDynamicPrivacyChanged made a re-entrant call");
+ }
+ // This listener can be called from updateNotificationViews() via a convoluted listener
+ // chain, so we post here to prevent a re-entrant call. See b/136186188
+ // TODO: Refactor away the need for this
+ if (!mIsHandleDynamicPrivacyChangeScheduled) {
+ mIsHandleDynamicPrivacyChangeScheduled = true;
+ mHandler.post(this::onHandleDynamicPrivacyChanged);
+ }
+ }
+
+ private void onHandleDynamicPrivacyChanged() {
+ mIsHandleDynamicPrivacyChangeScheduled = false;
updateNotificationViews();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 58e639924f4f..9e3d74b138fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4716,14 +4716,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
return mIntrinsicPadding;
}
- /**
- * @return the y position of the first notification
- */
- @ShadeViewRefactor(RefactorComponent.COORDINATOR)
- public float getNotificationsTopY() {
- return mTopPadding + getStackTranslation();
- }
-
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public boolean shouldDelayChildPressedState() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index ea434fc5b344..49afae7415ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -95,6 +95,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private boolean mPulsing;
private boolean mDozing;
private boolean mDocked;
+ private boolean mBlockUpdates;
private int mIconColor;
private float mDozeAmount;
private boolean mBouncerShowingScrimmed;
@@ -107,8 +108,22 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
new KeyguardMonitor.Callback() {
@Override
public void onKeyguardShowingChanged() {
+ boolean force = false;
+ boolean wasShowing = mKeyguardShowing;
mKeyguardShowing = mKeyguardMonitor.isShowing();
- update();
+ if (!wasShowing && mKeyguardShowing && mBlockUpdates) {
+ mBlockUpdates = false;
+ force = true;
+ }
+ update(force);
+ }
+
+ @Override
+ public void onKeyguardFadingAwayChanged() {
+ if (!mKeyguardMonitor.isKeyguardFadingAway() && mBlockUpdates) {
+ mBlockUpdates = false;
+ update(true /* force */);
+ }
}
};
private final DockManager.DockEventListener mDockEventListener =
@@ -261,7 +276,11 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
mIsFaceUnlockState = state == STATE_SCANNING_FACE;
mLastState = state;
- if (lastState != state || mForceUpdate) {
+ boolean shouldUpdate = lastState != state || mForceUpdate;
+ if (mBlockUpdates && canBlockUpdates()) {
+ shouldUpdate = false;
+ }
+ if (shouldUpdate) {
mForceUpdate = false;
@LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(lastState,
state, mPulsing, mDozing);
@@ -330,6 +349,10 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
return true;
}
+ private boolean canBlockUpdates() {
+ return mKeyguardShowing || mKeyguardMonitor.isKeyguardFadingAway();
+ }
+
private void updateClickability() {
if (mAccessibilityController == null) {
return;
@@ -536,11 +559,17 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
/**
* We need to hide the lock whenever there's a fingerprint unlock, otherwise you'll see the
* icon on top of the black front scrim.
+ * @param wakeAndUnlock are we wake and unlocking
+ * @param isUnlock are we currently unlocking
*/
- public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
if (wakeAndUnlock) {
mWakeAndUnlockRunning = true;
}
+ if (isUnlock && mBypassController.getBypassEnabled() && canBlockUpdates()) {
+ // We don't want the icon to change while we are unlocking
+ mBlockUpdates = true;
+ }
update();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 776cd4d71c94..22e3edb2bbd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -627,7 +627,7 @@ public class NavigationBarView extends FrameLayout implements
if (mOverviewProxyService.isEnabled()) {
// Force disable recents when not in legacy mode
disableRecent |= !QuickStepContract.isLegacyMode(mNavBarMode);
- if (pinningActive) {
+ if (pinningActive && !QuickStepContract.isGesturalMode(mNavBarMode)) {
disableBack = disableHome = false;
}
} else if (pinningActive) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 53ce167542f0..6eeb96813c94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -932,7 +932,7 @@ public class NotificationPanelView extends PanelView implements
protected void flingToHeight(float vel, boolean expand, float target,
float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
mHeadsUpTouchHelper.notifyFling(!expand);
- setClosingWithAlphaFadeout(!expand && getFadeoutAlpha() == 1.0f);
+ setClosingWithAlphaFadeout(!expand && !isOnKeyguard() && getFadeoutAlpha() == 1.0f);
super.flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
}
@@ -2068,8 +2068,11 @@ public class NotificationPanelView extends PanelView implements
}
private float getFadeoutAlpha() {
- float alpha = (getNotificationsTopY() + mNotificationStackScroller.getFirstItemMinHeight())
- / mQsMinExpansionHeight;
+ float alpha;
+ if (mQsMinExpansionHeight == 0) {
+ return 1.0f;
+ }
+ alpha = getExpandedHeight() / mQsMinExpansionHeight;
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
return alpha;
@@ -2127,18 +2130,18 @@ public class NotificationPanelView extends PanelView implements
float alpha;
if (mBarState == StatusBarState.KEYGUARD) {
- // When on Keyguard, we hide the header as soon as the top card of the notification
- // stack scroller is close enough (collision distance) to the bottom of the header.
- alpha = getNotificationsTopY()
+ // When on Keyguard, we hide the header as soon as we expanded close enough to the
+ // header
+ alpha = getExpandedHeight()
/
(mKeyguardStatusBar.getHeight() + mNotificationsHeaderCollideDistance);
} else {
// In SHADE_LOCKED, the top card is already really close to the header. Hide it as
// soon as we start translating the stack.
- alpha = getNotificationsTopY() / mKeyguardStatusBar.getHeight();
+ alpha = getExpandedHeight() / mKeyguardStatusBar.getHeight();
}
- alpha = MathUtils.constrain(alpha, 0, 1);
+ alpha = MathUtils.saturate(alpha);
alpha = (float) Math.pow(alpha, 0.75);
return alpha;
}
@@ -2190,13 +2193,6 @@ public class NotificationPanelView extends PanelView implements
mBigClockContainer.setAlpha(alpha);
}
- private float getNotificationsTopY() {
- if (mNotificationStackScroller.getNotGoneChildCount() == 0) {
- return getExpandedHeight();
- }
- return mNotificationStackScroller.getNotificationsTopY();
- }
-
@Override
protected void onExpandingStarted() {
super.onExpandingStarted();
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 e756d3a997f5..55f61fa8a6a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3834,7 +3834,8 @@ public class StatusBar extends SystemUI implements DemoMode,
public void notifyBiometricAuthModeChanged() {
updateDozing();
updateScrimController();
- mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock());
+ mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock(),
+ mBiometricUnlockController.isBiometricUnlock());
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6dc2c8cab055..462b65f37ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -814,7 +814,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
*/
public boolean shouldSubtleWindowAnimationsForUnlock() {
return mStatusBar.mKeyguardBypassController.getBypassEnabled()
- && mStatusBar.mState == StatusBarState.KEYGUARD;
+ && mStatusBar.mState == StatusBarState.KEYGUARD && !mBouncer.isAnimatingAway();
}
public boolean isGoingToNotificationShade() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 667521bf6588..94054188d769 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -272,10 +272,11 @@ public class StatusBarWindowView extends FrameLayout {
/**
* Called when the biometric authentication mode changes.
* @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
+ * @param isUnlock If the type is {@link BiometricUnlockController#isBiometricUnlock()} ()
*/
- public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
if (mLockIcon != null) {
- mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock);
+ mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock, isUnlock);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 01498e6bd54d..f61b556e22ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -50,5 +50,6 @@ public interface KeyguardMonitor extends CallbackController<Callback> {
interface Callback {
void onKeyguardShowingChanged();
+ default void onKeyguardFadingAwayChanged() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index b53ff0e45cea..68d00708b0d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -141,14 +141,24 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
}
public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
- mKeyguardFadingAway = true;
+ setKeyguardFadingAway(true);
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
}
+ private void setKeyguardFadingAway(boolean keyguardFadingAway) {
+ if (mKeyguardFadingAway != keyguardFadingAway) {
+ mKeyguardFadingAway = keyguardFadingAway;
+ ArrayList<Callback> callbacks = new ArrayList<>(mCallbacks);
+ for (int i = 0; i < callbacks.size(); i++) {
+ callbacks.get(i).onKeyguardFadingAwayChanged();
+ }
+ }
+ }
+
public void notifyKeyguardDoneFading() {
- mKeyguardFadingAway = false;
mKeyguardGoingAway = false;
+ setKeyguardFadingAway(false);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index 6891f562a3c4..3330d1e6d0a8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -20,14 +20,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
-import android.provider.DeviceConfig;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
@@ -52,8 +50,6 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.List;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
// Need to run tests on main looper because LiveData operations such as setData, observe,
@@ -67,7 +63,7 @@ public final class ClockManagerTest extends SysuiTestCase {
private static final int SECONDARY_USER_ID = 11;
private static final Uri SETTINGS_URI = null;
- ClockManager mClockManager;
+ private ClockManager mClockManager;
private ContentObserver mContentObserver;
private DockManagerFake mFakeDockManager;
private MutableLiveData<Integer> mCurrentUser;
@@ -144,33 +140,6 @@ public final class ClockManagerTest extends SysuiTestCase {
}
@Test
- public void getCurrentClock_inBlackList() {
- mClockManager = spy(mClockManager);
- // GIVEN that settings is set to the bubble clock face
- when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(BUBBLE_CLOCK);
- // WHEN settings change event is fired
- mContentObserver.onChange(false, SETTINGS_URI, MAIN_USER_ID);
- // GIVEN that bubble clock is in blacklist
- when(mClockManager.getBlackListFromConfig()).thenReturn(BUBBLE_CLOCK);
- // WHEN device config change of systemui is fired
- mClockManager.onDeviceConfigPropertiesChanged(DeviceConfig.NAMESPACE_SYSTEMUI);
- // THEN the result is null, indicated the current clock should be reset to the default one.
- assertThat(mClockManager.getCurrentClock()).isNull();
- }
-
- @Test
- public void getClockInfo_inBlackList() {
- mClockManager = spy(mClockManager);
- // GIVEN that bubble clock is in blacklist
- when(mClockManager.getBlackListFromConfig()).thenReturn(BUBBLE_CLOCK);
- // WHEN device config change of systemui is fired
- mClockManager.onDeviceConfigPropertiesChanged(DeviceConfig.NAMESPACE_SYSTEMUI);
- // THEN the ClockInfo should not contain bubble clock
- List<ClockInfo> clocks = mClockManager.getClockInfos();
- assertThat(clocks.stream().anyMatch(info -> BUBBLE_CLOCK.equals(info.getId()))).isFalse();
- }
-
- @Test
public void onClockChanged_customClock() {
// GIVEN that settings is set to the bubble clock face
when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(BUBBLE_CLOCK);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 010b85edacdd..58fb53aae7bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -20,12 +20,16 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
@@ -79,13 +83,19 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
@Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private ShadeController mShadeController;
+ private TestableLooper mTestableLooper;
+ private Handler mHandler;
private NotificationViewHierarchyManager mViewHierarchyManager;
private NotificationTestHelper mHelper;
+ private boolean mMadeReentrantCall = false;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- Assert.sMainLooper = TestableLooper.get(this).getLooper();
+ mTestableLooper = TestableLooper.get(this);
+ Assert.sMainLooper = mTestableLooper.getLooper();
+ mHandler = Handler.createAsync(mTestableLooper.getLooper());
+
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
mLockscreenUserManager);
@@ -98,7 +108,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
- mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
+ mHandler, mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
mock(StatusBarStateControllerImpl.class), mEntryManager,
() -> mShadeController, new BubbleData(mContext),
mock(KeyguardBypassController.class),
@@ -215,9 +225,60 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
verify(entry0.getRow(), times(1)).showAppOpsIcons(any());
}
+ @Test
+ public void testReentrantCallsToOnDynamicPrivacyChangedPostForLater() {
+ // GIVEN a ListContainer that will make a re-entrant call to updateNotificationViews()
+ mMadeReentrantCall = false;
+ doAnswer((invocation) -> {
+ if (!mMadeReentrantCall) {
+ mMadeReentrantCall = true;
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ }
+ return null;
+ }).when(mListContainer).setMaxDisplayedNotifications(anyInt());
+
+ // WHEN we call updateNotificationViews()
+ mViewHierarchyManager.updateNotificationViews();
+
+ // THEN onNotificationViewUpdateFinished() is only called once
+ verify(mListContainer).onNotificationViewUpdateFinished();
+
+ // WHEN we drain the looper
+ mTestableLooper.processAllMessages();
+
+ // THEN updateNotificationViews() is called a second time (for the reentrant call)
+ verify(mListContainer, times(2)).onNotificationViewUpdateFinished();
+ }
+
+ @Test
+ public void testMultipleReentrantCallsToOnDynamicPrivacyChangedOnlyPostOnce() {
+ // GIVEN a ListContainer that will make many re-entrant calls to updateNotificationViews()
+ mMadeReentrantCall = false;
+ doAnswer((invocation) -> {
+ if (!mMadeReentrantCall) {
+ mMadeReentrantCall = true;
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ }
+ return null;
+ }).when(mListContainer).setMaxDisplayedNotifications(anyInt());
+
+ // WHEN we call updateNotificationViews() and drain the looper
+ mViewHierarchyManager.updateNotificationViews();
+ verify(mListContainer).onNotificationViewUpdateFinished();
+ clearInvocations(mListContainer);
+ mTestableLooper.processAllMessages();
+
+ // THEN updateNotificationViews() is called only one more time
+ verify(mListContainer).onNotificationViewUpdateFinished();
+ }
+
private class FakeListContainer implements NotificationListContainer {
final LinearLayout mLayout = new LinearLayout(mContext);
final List<View> mRows = Lists.newArrayList();
+ private boolean mMakeReentrantCallDuringSetMaxDisplayedNotifications;
@Override
public void setChildTransferInProgress(boolean childTransferInProgress) {}
@@ -266,7 +327,11 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
}
@Override
- public void setMaxDisplayedNotifications(int maxNotifications) {}
+ public void setMaxDisplayedNotifications(int maxNotifications) {
+ if (mMakeReentrantCallDuringSetMaxDisplayedNotifications) {
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ }
+ }
@Override
public ViewGroup getViewParentForNotification(NotificationEntry entry) {
@@ -301,5 +366,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
return false;
}
+ @Override
+ public void onNotificationViewUpdateFinished() { }
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index e2b59b45e1e6..c2f452932775 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -108,7 +108,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
.replaceWith("?");
private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE);
private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE);
- private static final int MAX_LOW_POWER_STATS_SIZE = 2048;
+ private static final int MAX_LOW_POWER_STATS_SIZE = 4096;
/**
* Replaces the information in the given rpmStats with up-to-date information.
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 42802f6c3cec..d1b5534e3777 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1208,14 +1208,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
- // Traffic occurring on stacked interfaces is usually clatd,
- // which is already accounted against its final egress interface
- // by the kernel. Thus, we only need to collect stacked
- // interface stats at the UID level.
+ // Traffic occurring on stacked interfaces is usually clatd.
+ // UID stats are always counted on the stacked interface and never
+ // on the base interface, because the packets on the base interface
+ // do not actually match application sockets until they are translated.
+ //
+ // Interface stats are more complicated. Packets subject to BPF offload
+ // never appear on the base interface and only appear on the stacked
+ // interface, so to ensure those packets increment interface stats, interface
+ // stats from stacked interfaces must be collected.
final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
for (LinkProperties stackedLink : stackedLinks) {
final String stackedIface = stackedLink.getInterfaceName();
if (stackedIface != null) {
+ if (mUseBpfTrafficStats) {
+ findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident);
+ }
findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident);
if (isMobile) {
mobileIfaces.add(stackedIface);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2052b1570f34..eba4fb63bfc6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2523,11 +2523,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
final int resource;
- if (onWallpaper) {
- resource = R.anim.lock_screen_behind_enter_wallpaper;
- } else if (subtleAnimation) {
+ if (subtleAnimation) {
resource = R.anim.lock_screen_behind_enter_subtle;
- } else {
+ } else if (onWallpaper) {
+ resource = R.anim.lock_screen_behind_enter_wallpaper;
+ } else {
resource = R.anim.lock_screen_behind_enter;
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0faea61b9d60..bc67cb04b5bc 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3162,7 +3162,7 @@ final class ActivityRecord extends ConfigurationContainer {
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
return ensureActivityConfiguration(globalChanges, preserveWindow,
- false /* ignoreStopState */);
+ false /* ignoreVisibility */);
}
/**
@@ -3172,15 +3172,15 @@ final class ActivityRecord extends ConfigurationContainer {
* @param globalChanges The changes to the global configuration.
* @param preserveWindow If the activity window should be preserved on screen if the activity
* is relaunched.
- * @param ignoreStopState If we should try to relaunch the activity even if it is in the stopped
- * state. This is useful for the case where we know the activity will be
- * visible soon and we want to ensure its configuration before we make it
- * visible.
+ * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
+ * (stopped state). This is useful for the case where we know the
+ * activity will be visible soon and we want to ensure its configuration
+ * before we make it visible.
* @return False if the activity was relaunched and true if it wasn't relaunched because we
* can't or the app handles the specific configuration that is changing.
*/
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
- boolean ignoreStopState) {
+ boolean ignoreVisibility) {
final ActivityStack stack = getActivityStack();
if (stack.mConfigWillChange) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
@@ -3196,15 +3196,9 @@ final class ActivityRecord extends ConfigurationContainer {
return true;
}
- if (!ignoreStopState && (mState == STOPPING || mState == STOPPED)) {
+ if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
- "Skipping config check stopped or stopping: " + this);
- return true;
- }
-
- if (!shouldBeVisible()) {
- if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
- "Skipping config check invisible stack: " + this);
+ "Skipping config check invisible: " + this);
return true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index c4e0db46f4da..46f86ee5e9f9 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -164,6 +164,8 @@ import com.android.server.am.AppTimeTracker;
import com.android.server.am.EventLogTags;
import com.android.server.am.PendingIntentRecord;
+import com.google.android.collect.Sets;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -1880,8 +1882,7 @@ class ActivityStack extends ConfigurationContainer {
mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
}
- private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed,
- String reason) {
+ void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId,
System.identityHashCode(r), r.shortComponentName, reason);
@@ -2176,7 +2177,7 @@ class ActivityStack extends ConfigurationContainer {
// sure it matches the current configuration.
if (r != starting && notifyClients) {
r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
- true /* ignoreStopState */);
+ true /* ignoreVisibility */);
}
if (!r.attachedToProcess()) {
@@ -3138,8 +3139,10 @@ class ActivityStack extends ConfigurationContainer {
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
TaskRecord rTask = r.getTaskRecord();
final int taskId = rTask.taskId;
+ final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
// mLaunchTaskBehind tasks get placed at the back of the task stack.
- if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
+ if (!r.mLaunchTaskBehind && allowMoveToFront
+ && (taskForIdLocked(taskId) == null || newTask)) {
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
@@ -3198,7 +3201,9 @@ class ActivityStack extends ConfigurationContainer {
task.setFrontOfTask();
- if (!isHomeOrRecentsStack() || numActivities() > 0) {
+ // The transition animation and starting window are not needed if {@code allowMoveToFront}
+ // is false, because the activity won't be visible.
+ if ((!isHomeOrRecentsStack() || numActivities() > 0) && allowMoveToFront) {
final DisplayContent dc = getDisplay().mDisplayContent;
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: starting " + r);
@@ -4021,6 +4026,14 @@ class ActivityStack extends ConfigurationContainer {
}
getDisplay().mDisplayContent.prepareAppTransition(transit, false);
+ // When finishing the activity pre-emptively take the snapshot before the app window
+ // is marked as hidden and any configuration changes take place
+ if (mWindowManager.mTaskSnapshotController != null) {
+ final ArraySet<Task> tasks = Sets.newArraySet(task.mTask);
+ mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
+ mWindowManager.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(tasks);
+ }
+
// Tell window manager to prepare for this one to be removed.
r.setVisibility(false);
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index c992a69c2ecb..19916bc617f4 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -415,7 +415,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
void sendErrorResult(String message) {
try {
- if (callerApp.hasThread()) {
+ if (callerApp != null && callerApp.hasThread()) {
callerApp.getThread().scheduleCrash(message);
}
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 0a88eef86ea8..eda9d24ef3c5 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2307,12 +2307,12 @@ class ActivityStarter {
// isLockTaskModeViolation fails below.
if (mReuseTask == null) {
+ final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
- mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
- mOptions);
+ mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a70ea607cf26..0f96f99c3348 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1451,9 +1451,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
.execute();
}
+ /**
+ * Start the recents activity to perform the recents animation.
+ *
+ * @param intent The intent to start the recents activity.
+ * @param recentsAnimationRunner Pass {@code null} to only preload the activity.
+ */
@Override
- public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
- IRecentsAnimationRunner recentsAnimationRunner) {
+ public void startRecentsActivity(Intent intent, @Deprecated IAssistDataReceiver unused,
+ @Nullable IRecentsAnimationRunner recentsAnimationRunner) {
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
final int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
@@ -1464,9 +1470,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Start a new recents animation
final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
- getActivityStartController(), mWindowManager, callingPid);
- anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
- recentsUid, assistDataReceiver);
+ getActivityStartController(), mWindowManager, intent, recentsComponent,
+ recentsUid, callingPid);
+ if (recentsAnimationRunner == null) {
+ anim.preloadRecentsActivity();
+ } else {
+ anim.startRecentsActivity(recentsAnimationRunner);
+ }
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 6127303141f4..553b0ffa6999 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -176,6 +176,8 @@ class DragState {
mTransaction.transferTouchFocus(mTransferTouchFromToken, h.token);
mTransferTouchFromToken = null;
+ // syncInputWindows here to ensure the input channel isn't removed before the transfer.
+ mTransaction.syncInputWindows();
mTransaction.apply();
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 434239f6ecf7..bf627ec5680c 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -34,7 +34,6 @@ import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_T
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
import android.app.ActivityOptions;
-import android.app.IAssistDataReceiver;
import android.content.ComponentName;
import android.content.Intent;
import android.os.RemoteException;
@@ -58,7 +57,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
private final ActivityStartController mActivityStartController;
private final WindowManagerService mWindowManager;
private final ActivityDisplay mDefaultDisplay;
+ private final Intent mTargetIntent;
+ private final ComponentName mRecentsComponent;
+ private final int mRecentsUid;
private final int mCallingPid;
+ private final int mUserId;
+ private final int mTargetActivityType;
/**
* The activity which has been launched behind. We need to remember the activity because the
@@ -66,27 +70,90 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
* for the exact activity.
*/
private ActivityRecord mLaunchedTargetActivity;
- private int mTargetActivityType;
// The stack to restore the target stack behind when the animation is finished
private ActivityStack mRestoreTargetBehindStack;
RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor,
ActivityStartController activityStartController, WindowManagerService wm,
- int callingPid) {
+ Intent targetIntent, ComponentName recentsComponent, int recentsUid, int callingPid) {
mService = atm;
mStackSupervisor = stackSupervisor;
mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay();
mActivityStartController = activityStartController;
mWindowManager = wm;
+ mTargetIntent = targetIntent;
+ mRecentsComponent = recentsComponent;
+ mRecentsUid = recentsUid;
mCallingPid = callingPid;
+ mUserId = atm.getCurrentUserId();
+ mTargetActivityType = targetIntent.getComponent() != null
+ && recentsComponent.equals(targetIntent.getComponent())
+ ? ACTIVITY_TYPE_RECENTS
+ : ACTIVITY_TYPE_HOME;
+ }
+
+ /**
+ * Starts the recents activity in background without animation if the record doesn't exist or
+ * the client isn't launched. If the recents activity is already alive, ensure its configuration
+ * is updated to the current one.
+ */
+ void preloadRecentsActivity() {
+ if (DEBUG) Slog.d(TAG, "Preload recents with " + mTargetIntent);
+ ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
+ mTargetActivityType);
+ ActivityRecord targetActivity = getTargetActivity(targetStack);
+ if (targetActivity != null) {
+ if (targetActivity.visible || targetActivity.isTopRunningActivity()) {
+ // The activity is ready.
+ return;
+ }
+ if (targetActivity.attachedToProcess()) {
+ // The activity may be relaunched if it cannot handle the current configuration
+ // changes. The activity will be paused state if it is relaunched, otherwise it
+ // keeps the original stopped state.
+ targetActivity.ensureActivityConfiguration(0 /* globalChanges */,
+ false /* preserveWindow */, true /* ignoreVisibility */);
+ if (DEBUG) Slog.d(TAG, "Updated config=" + targetActivity.getConfiguration());
+ }
+ } else {
+ // Create the activity record. Because the activity is invisible, this doesn't really
+ // start the client.
+ startRecentsActivityInBackground("preloadRecents");
+ targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType);
+ targetActivity = getTargetActivity(targetStack);
+ if (targetActivity == null) {
+ Slog.w(TAG, "Cannot start " + mTargetIntent);
+ return;
+ }
+ }
+
+ if (!targetActivity.attachedToProcess()) {
+ if (DEBUG) Slog.d(TAG, "Real start recents");
+ mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
+ false /* checkConfig */);
+ // Make sure the activity won't be involved in transition.
+ if (targetActivity.mAppWindowToken != null) {
+ targetActivity.mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
+ .appRemovedOrHidden(targetActivity.mAppWindowToken);
+ }
+ }
+
+ // Invisible activity should be stopped. If the recents activity is alive and its doesn't
+ // need to relaunch by current configuration, then it may be already in stopped state.
+ if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING,
+ ActivityStack.ActivityState.STOPPED)) {
+ // Add to stopping instead of stop immediately. So the client has the chance to perform
+ // traversal in non-stopped state (ViewRootImpl.mStopped) that would initialize more
+ // things (e.g. the measure can be done earlier). The actual stop will be performed when
+ // it reports idle.
+ targetStack.addToStopping(targetActivity, true /* scheduleIdle */,
+ true /* idleDelayed */, "preloadRecents");
+ }
}
- void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner,
- ComponentName recentsComponent, int recentsUid,
- @Deprecated IAssistDataReceiver assistDataReceiver) {
- if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + intent
- + " assistDataReceiver=" + assistDataReceiver);
+ void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
+ if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + mTargetIntent);
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
// TODO(multi-display) currently only support recents animation in default display.
@@ -100,15 +167,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
}
// If the activity is associated with the recents stack, then try and get that first
- final int userId = mService.getCurrentUserId();
- mTargetActivityType = intent.getComponent() != null
- && recentsComponent.equals(intent.getComponent())
- ? ACTIVITY_TYPE_RECENTS
- : ACTIVITY_TYPE_HOME;
ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
mTargetActivityType);
- ActivityRecord targetActivity = getTargetActivity(targetStack, intent.getComponent(),
- userId);
+ ActivityRecord targetActivity = getTargetActivity(targetStack);
final boolean hasExistingActivity = targetActivity != null;
if (hasExistingActivity) {
final ActivityDisplay display = targetActivity.getDisplay();
@@ -127,7 +188,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
true /* forceSend */, targetActivity);
}
- mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
+ mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent);
mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true));
@@ -148,23 +209,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
}
} else {
// No recents activity, create the new recents activity bottom most
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchActivityType(mTargetActivityType);
- options.setAvoidMoveToFront();
- intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
-
- mActivityStartController
- .obtainStarter(intent, "startRecentsActivity_noTargetActivity")
- .setCallingUid(recentsUid)
- .setCallingPackage(recentsComponent.getPackageName())
- .setActivityOptions(SafeActivityOptions.fromBundle(options.toBundle()))
- .setMayWait(userId)
- .execute();
+ startRecentsActivityInBackground("startRecentsActivity_noTargetActivity");
// Move the recents activity into place for the animation
targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
mTargetActivityType);
- targetActivity = getTargetActivity(targetStack, intent.getComponent(), userId);
+ targetActivity = getTargetActivity(targetStack);
mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
if (DEBUG) {
Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
@@ -176,7 +226,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// TODO: Maybe wait for app to draw in this particular case?
- if (DEBUG) Slog.d(TAG, "Started intent=" + intent);
+ if (DEBUG) Slog.d(TAG, "Started intent=" + mTargetIntent);
}
// Mark the target activity as launch-behind to bump its visibility for the
@@ -383,6 +433,21 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
}
}
+ private void startRecentsActivityInBackground(String reason) {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchActivityType(mTargetActivityType);
+ options.setAvoidMoveToFront();
+ mTargetIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
+
+ mActivityStartController
+ .obtainStarter(mTargetIntent, reason)
+ .setCallingUid(mRecentsUid)
+ .setCallingPackage(mRecentsComponent.getPackageName())
+ .setActivityOptions(new SafeActivityOptions(options))
+ .setMayWait(mUserId)
+ .execute();
+ }
+
/**
* Called only when the animation should be canceled prior to starting.
*/
@@ -412,15 +477,15 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
* @return the top activity in the {@param targetStack} matching the {@param component}, or just
* the top activity of the top task if no task matches the component.
*/
- private ActivityRecord getTargetActivity(ActivityStack targetStack, ComponentName component,
- int userId) {
+ private ActivityRecord getTargetActivity(ActivityStack targetStack) {
if (targetStack == null) {
return null;
}
for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
final TaskRecord task = targetStack.getChildAt(i);
- if (task.userId == userId && task.getBaseIntent().getComponent().equals(component)) {
+ if (task.userId == mUserId
+ && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent())) {
return task.getTopActivity();
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 4986a6d5bd0d..ecf3acd32d4f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -85,6 +85,7 @@ import org.mockito.invocation.InvocationOnMock;
import java.io.File;
import java.util.List;
+import java.util.function.Consumer;
/**
* A base class to handle common operations in activity related unit tests.
@@ -169,8 +170,12 @@ class ActivityTestsBase {
* Delegates task creation to {@link #TaskBuilder} to avoid the dependency of window hierarchy
* when starting activity in unit tests.
*/
- void mockTaskRecordFactory() {
- final TaskRecord task = new TaskBuilder(mSupervisor).setCreateStack(false).build();
+ void mockTaskRecordFactory(Consumer<TaskBuilder> taskBuilderSetup) {
+ final TaskBuilder taskBuilder = new TaskBuilder(mSupervisor).setCreateStack(false);
+ if (taskBuilderSetup != null) {
+ taskBuilderSetup.accept(taskBuilder);
+ }
+ final TaskRecord task = taskBuilder.build();
final TaskRecordFactory factory = mock(TaskRecordFactory.class);
TaskRecord.setTaskRecordFactory(factory);
doReturn(task).when(factory).create(any() /* service */, anyInt() /* taskId */,
@@ -178,6 +183,10 @@ class ActivityTestsBase {
any() /* voiceInteractor */);
}
+ void mockTaskRecordFactory() {
+ mockTaskRecordFactory(null /* taskBuilderSetup */);
+ }
+
/**
* Builder for creating new activities.
*/
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 1f8b33eb5bb4..9630b7d46e3c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -42,8 +42,11 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.platform.test.annotations.Presubmit;
import android.view.IRecentsAnimationRunner;
@@ -111,6 +114,57 @@ public class RecentsAnimationTest extends ActivityTestsBase {
}
@Test
+ public void testPreloadRecentsActivity() {
+ // Ensure that the fake recent component can be resolved by the recents intent.
+ mockTaskRecordFactory(builder -> builder.setComponent(mRecentsComponent));
+ ActivityInfo aInfo = new ActivityInfo();
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.uid = 10001;
+ aInfo.applicationInfo.targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+ aInfo.packageName = aInfo.applicationInfo.packageName = mRecentsComponent.getPackageName();
+ aInfo.processName = "recents";
+ doReturn(aInfo).when(mSupervisor).resolveActivity(any() /* intent */, any() /* rInfo */,
+ anyInt() /* startFlags */, any() /* profilerInfo */);
+
+ // Assume its process is alive because the caller should be the recents service.
+ WindowProcessController wpc = new WindowProcessController(mService, aInfo.applicationInfo,
+ aInfo.processName, aInfo.applicationInfo.uid, 0 /* userId */,
+ mock(Object.class) /* owner */, mock(WindowProcessListener.class));
+ wpc.setThread(mock(IApplicationThread.class));
+ doReturn(wpc).when(mService).getProcessController(eq(wpc.mName), eq(wpc.mUid));
+
+ Intent recentsIntent = new Intent().setComponent(mRecentsComponent);
+ // Null animation indicates to preload.
+ mService.startRecentsActivity(recentsIntent, null /* assistDataReceiver */,
+ null /* recentsAnimationRunner */);
+
+ ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ ActivityStack recentsStack = display.getStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_RECENTS);
+ assertThat(recentsStack).isNotNull();
+
+ ActivityRecord recentsActivity = recentsStack.getTopActivity();
+ // The activity is started in background so it should be invisible and will be stopped.
+ assertThat(recentsActivity).isNotNull();
+ assertThat(mSupervisor.mStoppingActivities).contains(recentsActivity);
+ assertFalse(recentsActivity.visible);
+
+ // Assume it is stopped to test next use case.
+ recentsActivity.activityStoppedLocked(null /* newIcicle */, null /* newPersistentState */,
+ null /* description */);
+ mSupervisor.mStoppingActivities.remove(recentsActivity);
+
+ spyOn(recentsActivity);
+ // Start when the recents activity exists. It should ensure the configuration.
+ mService.startRecentsActivity(recentsIntent, null /* assistDataReceiver */,
+ null /* recentsAnimationRunner */);
+
+ verify(recentsActivity).ensureActivityConfiguration(anyInt() /* globalChanges */,
+ anyBoolean() /* preserveWindow */, eq(true) /* ignoreVisibility */);
+ assertThat(mSupervisor.mStoppingActivities).contains(recentsActivity);
+ }
+
+ @Test
public void testRestartRecentsActivity() throws Exception {
// Have a recents activity that is not attached to its process (ActivityRecord.app = null).
ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 19f8203f7502..ef967d71cfa0 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -836,6 +836,19 @@ public class CarrierConfigManager {
"carrier_metered_roaming_apn_types_strings";
/**
+ * APN types that are not allowed on cellular
+ * @hide
+ */
+ public static final String KEY_CARRIER_WWAN_DISALLOWED_APN_TYPES_STRING_ARRAY =
+ "carrier_wwan_disallowed_apn_types_string_array";
+
+ /**
+ * APN types that are not allowed on IWLAN
+ * @hide
+ */
+ public static final String KEY_CARRIER_WLAN_DISALLOWED_APN_TYPES_STRING_ARRAY =
+ "carrier_wlan_disallowed_apn_types_string_array";
+ /**
* CDMA carrier ERI (Enhanced Roaming Indicator) file name
* @hide
*/
@@ -3133,6 +3146,10 @@ public class CarrierConfigManager {
new String[]{"default", "mms", "dun", "supl"});
sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
+ sDefaults.putStringArray(KEY_CARRIER_WWAN_DISALLOWED_APN_TYPES_STRING_ARRAY,
+ new String[]{""});
+ sDefaults.putStringArray(KEY_CARRIER_WLAN_DISALLOWED_APN_TYPES_STRING_ARRAY,
+ new String[]{""});
sDefaults.putIntArray(KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY,
new int[]{
4, /* IS95A */
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 4a9b174cedbb..484fd3b17c02 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2121,27 +2121,24 @@ public class SubscriptionManager {
* @hide
*/
@UnsupportedAppUsage
- public static @NonNull int[] getActiveSubscriptionIdList() {
- return getActiveSubscriptionIdList(true);
- }
+ public @NonNull int[] getActiveSubscriptionIdList() {
+ int[] subId = null;
- /**
- * @return a non-null list of subId's that are active.
- *
- * @hide
- */
- public static @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- int[] subId = iSub.getActiveSubIdList(visibleOnly);
- if (subId != null) return subId;
+ subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
}
} catch (RemoteException ex) {
// ignore it
}
- return new int[0];
+ if (subId == null) {
+ subId = new int[0];
+ }
+
+ return subId;
+
}
/**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 5b57c9d7554c..7a0ab9ca6a28 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -605,11 +605,15 @@ public final class TelephonyPermissions {
*/
private static boolean checkCarrierPrivilegeForAnySubId(Context context,
Supplier<ITelephony> telephonySupplier, int uid) {
- int[] activeSubIds = SubscriptionManager.getActiveSubscriptionIdList(/*visibleOnly*/ false);
- for (int activeSubId : activeSubIds) {
- if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return true;
+ SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ int[] activeSubIds = sm.getActiveSubscriptionIdList();
+ if (activeSubIds != null) {
+ for (int activeSubId : activeSubIds) {
+ if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
+ }
}
}
return false;