Merge "[Unfold transition] Take over only physical display changes" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 7f261d4..1b5c953 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -12606,6 +12606,7 @@
method public boolean isStagedSessionApplied();
method public boolean isStagedSessionFailed();
method public boolean isStagedSessionReady();
+ method @FlaggedApi("android.content.pm.archiving") public boolean isUnarchival();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
field public static final int INVALID_ID = -1; // 0xffffffff
@@ -13296,6 +13297,7 @@
method @NonNull public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
method @IntRange(from=0xffffffff) public long getLongVersion();
method public String getName();
+ method @FlaggedApi("android.content.pm.sdk_lib_independence") @NonNull public java.util.List<android.content.pm.VersionedPackage> getOptionalDependentPackages();
method public int getType();
method @Deprecated @IntRange(from=0xffffffff) public int getVersion();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index e7803fb..d395b8c 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -136,6 +136,7 @@
package android.content.pm {
public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+ method @FlaggedApi("android.content.pm.sdk_lib_independence") @NonNull public java.util.List<android.content.pm.SharedLibraryInfo> getOptionalSharedLibraryInfos();
method @NonNull public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraryInfos();
field public static final int HIDDEN_API_ENFORCEMENT_DEFAULT = -1; // 0xffffffff
field public static final int HIDDEN_API_ENFORCEMENT_DISABLED = 0; // 0x0
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 16a80e9..3713380 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -19,6 +19,7 @@
import static android.os.Build.VERSION_CODES.DONUT;
import android.Manifest;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1065,11 +1066,25 @@
* PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
* the structure.
*
+ * NOTE: the list also contains the result of {@link #getOptionalSharedLibraryInfos}.
+ *
* {@hide}
*/
+ @Nullable
public List<SharedLibraryInfo> sharedLibraryInfos;
/**
+ * List of all shared libraries this application is optionally linked against.
+ * This field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
+ * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
+ * the structure.
+ *
+ * @hide
+ */
+ @Nullable
+ public List<SharedLibraryInfo> optionalSharedLibraryInfos;
+
+ /**
* Full path to the default directory assigned to the package for its
* persistent data.
*/
@@ -1937,6 +1952,7 @@
seInfoUser = orig.seInfoUser;
sharedLibraryFiles = orig.sharedLibraryFiles;
sharedLibraryInfos = orig.sharedLibraryInfos;
+ optionalSharedLibraryInfos = orig.optionalSharedLibraryInfos;
dataDir = orig.dataDir;
deviceProtectedDataDir = orig.deviceProtectedDataDir;
credentialProtectedDataDir = orig.credentialProtectedDataDir;
@@ -2029,6 +2045,7 @@
dest.writeString8(seInfoUser);
dest.writeString8Array(sharedLibraryFiles);
dest.writeTypedList(sharedLibraryInfos);
+ dest.writeTypedList(optionalSharedLibraryInfos);
dest.writeString8(dataDir);
dest.writeString8(deviceProtectedDataDir);
dest.writeString8(credentialProtectedDataDir);
@@ -2129,6 +2146,7 @@
seInfoUser = source.readString8();
sharedLibraryFiles = source.createString8Array();
sharedLibraryInfos = source.createTypedArrayList(SharedLibraryInfo.CREATOR);
+ optionalSharedLibraryInfos = source.createTypedArrayList(SharedLibraryInfo.CREATOR);
dataDir = source.readString8();
deviceProtectedDataDir = source.readString8();
credentialProtectedDataDir = source.readString8();
@@ -2760,6 +2778,8 @@
* list will only be set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
* PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving the structure.
*
+ * NOTE: the list also contains the result of {@link #getOptionalSharedLibraryInfos}.
+ *
* @hide
*/
@NonNull
@@ -2772,6 +2792,23 @@
}
/**
+ * List of all shared libraries this application is optionally linked against. This
+ * list will only be set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
+ * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving the structure.
+ *
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @FlaggedApi(Flags.FLAG_SDK_LIB_INDEPENDENCE)
+ public List<SharedLibraryInfo> getOptionalSharedLibraryInfos() {
+ if (optionalSharedLibraryInfos == null) {
+ return Collections.EMPTY_LIST;
+ }
+ return optionalSharedLibraryInfos;
+ }
+
+ /**
* Gets the trusted host certificate digests of apps that are allowed to embed activities of
* this application. The digests are computed using the SHA-256 digest algorithm.
* @see android.R.attr#knownActivityEmbeddingCerts
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 6f7299a..a97de63 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -65,6 +65,8 @@
in UserHandle user);
LauncherUserInfo getLauncherUserInfo(in UserHandle user);
List<String> getPreInstalledSystemPackages(in UserHandle user);
+ IntentSender getAppMarketActivityIntent(String callingPackage, String packageName,
+ in UserHandle user);
void showAppDetailsAsUser(in IApplicationThread caller, String callingPackage,
String callingFeatureId, in ComponentName component, in Rect sourceBounds,
in Bundle opts, in UserHandle user);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index ccc8f09..1d2b1af 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -799,6 +799,55 @@
}
}
+
+ /**
+ * Returns an intent sender which can be used to start the App Market activity (Installer
+ * Activity).
+ * This method is primarily used to get an intent sender which starts App Market activity for
+ * another profile, if the caller is not otherwise allowed to start activity in that profile.
+ *
+ * <p>When packageName is set, intent sender to start the App Market Activity which installed
+ * the package in calling user will be returned, but for the profile passed.
+ *
+ * <p>When packageName is not set, intent sender to launch the default App Market Activity for
+ * the profile will be returned. In case there are multiple App Market Activities available for
+ * the profile, IntentPicker will be started, allowing user to choose the preferred activity.
+ *
+ * <p>The method will fall back to the behaviour of not having the packageName set, in case:
+ * <ul>
+ * <li>No activity for the packageName is found in calling user-space.</li>
+ * <li>The App Market Activity which installed the package in calling user-space is not
+ * present.</li>
+ * <li>The App Market Activity which installed the package in calling user-space is not
+ * present in the profile passed.</li>
+ * </ul>
+ * </p>
+ *
+ *
+ *
+ * @param packageName the package for which intent sender to launch App Market Activity is
+ * required.
+ * @param user the profile for which intent sender to launch App Market Activity is required.
+ * @return {@link IntentSender} object which launches the App Market Activity, null in case
+ * there is no such activity.
+ * @hide
+ */
+ @Nullable
+ @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+ public IntentSender getAppMarketActivityIntent(@Nullable String packageName,
+ @NonNull UserHandle user) {
+ if (DEBUG) {
+ Log.i(TAG, "getAppMarketActivityIntent for package: " + packageName
+ + " user: " + user);
+ }
+ try {
+ return mService.getAppMarketActivityIntent(mContext.getPackageName(),
+ packageName, user);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
/**
* Returns the list of the system packages that are installed at user creation.
*
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index e395127..0e131b4 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -4381,6 +4381,17 @@
return pendingUserActionReason;
}
+ /**
+ * Returns true if the session is an unarchival.
+ *
+ * @see PackageInstaller#requestUnarchive
+ */
+ @FlaggedApi(Flags.FLAG_ARCHIVING)
+ public boolean isUnarchival() {
+ return (installFlags & PackageManager.INSTALL_UNARCHIVE) != 0;
+ }
+
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a5d16f2..82a8c11 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1517,6 +1517,7 @@
INSTALL_REQUEST_UPDATE_OWNERSHIP,
INSTALL_IGNORE_DEXOPT_PROFILE,
INSTALL_UNARCHIVE_DRAFT,
+ INSTALL_UNARCHIVE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -1764,13 +1765,22 @@
* If set, then the session is a draft session created for an upcoming unarchival by its
* installer.
*
- * @see PackageInstaller#requestUnarchive(String)
+ * @see PackageInstaller#requestUnarchive
*
* @hide
*/
public static final int INSTALL_UNARCHIVE_DRAFT = 1 << 29;
/**
+ * If set, then the {@link PackageInstaller.Session} is an unarchival.
+ *
+ * @see PackageInstaller#requestUnarchive
+ *
+ * @hide
+ */
+ public static final int INSTALL_UNARCHIVE = 1 << 30;
+
+ /**
* Flag parameter for {@link #installPackage} to force a non-staged update of an APEX. This is
* a development-only feature and should not be used on end user devices.
*
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 25ba725..5acebf5 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -23,6 +24,7 @@
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Pair;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -99,20 +101,22 @@
private final boolean mIsNative;
private final VersionedPackage mDeclaringPackage;
private final List<VersionedPackage> mDependentPackages;
+
+ private final List<VersionedPackage> mOptionalDependentPackages;
private List<SharedLibraryInfo> mDependencies;
/**
* Creates a new instance.
*
- * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of jars of
- * this shared library. Null for builtin library.
- * @param name The lib name.
- * @param version The lib version if not builtin.
- * @param type The lib type.
- * @param declaringPackage The package that declares the library.
+ * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of
+ * jars of
+ * this shared library. Null for builtin library.
+ * @param name The lib name.
+ * @param version The lib version if not builtin.
+ * @param type The lib type.
+ * @param declaringPackage The package that declares the library.
* @param dependentPackages The packages that depend on the library.
- * @param isNative indicate if this shared lib is a native lib or not (i.e. java)
- *
+ * @param isNative indicate if this shared lib is a native lib or not (i.e. java)
* @hide
*/
public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
@@ -129,6 +133,58 @@
mDependentPackages = dependentPackages;
mDependencies = dependencies;
mIsNative = isNative;
+ mOptionalDependentPackages = null;
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of jars of
+ * this shared library. Null for builtin library.
+ * @param name The lib name.
+ * @param version The lib version if not builtin.
+ * @param type The lib type.
+ * @param declaringPackage The package that declares the library.
+ * @param isNative indicate if this shared lib is a native lib or not (i.e. java)
+ * @param allDependentPackages All packages that depend on the library (including the optional
+ * sdk libraries).
+ *
+ * @hide
+ */
+ public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
+ String name, long version, int type,
+ VersionedPackage declaringPackage,
+ List<SharedLibraryInfo> dependencies, boolean isNative,
+ Pair<List<VersionedPackage>, List<Boolean>> allDependentPackages) {
+ mPath = path;
+ mPackageName = packageName;
+ mCodePaths = codePaths;
+ mName = name;
+ mVersion = version;
+ mType = type;
+ mDeclaringPackage = declaringPackage;
+ mDependencies = dependencies;
+ mIsNative = isNative;
+
+ var allDependents = allDependentPackages.first;
+ var usesLibOptional = allDependentPackages.second;
+ mDependentPackages = allDependents;
+ List<VersionedPackage> optionalDependents = null;
+ if (mType == SharedLibraryInfo.TYPE_SDK_PACKAGE
+ && Flags.sdkLibIndependence() && allDependents != null
+ && usesLibOptional != null
+ && allDependents.size() == usesLibOptional.size()) {
+ for (int k = 0; k < allDependents.size(); k++) {
+ VersionedPackage versionedPackage = allDependents.get(k);
+ if (usesLibOptional.get(k)) {
+ if (optionalDependents == null) {
+ optionalDependents = new ArrayList<>();
+ }
+ optionalDependents.add(versionedPackage);
+ }
+ }
+ }
+ mOptionalDependentPackages = optionalDependents;
}
private SharedLibraryInfo(Parcel parcel) {
@@ -148,6 +204,8 @@
parcel.readArrayList(null, android.content.pm.VersionedPackage.class);
mDependencies = parcel.createTypedArrayList(SharedLibraryInfo.CREATOR);
mIsNative = parcel.readBoolean();
+ mOptionalDependentPackages = parcel.readParcelableList(new ArrayList<>(),
+ VersionedPackage.class.getClassLoader(), VersionedPackage.class);
}
/**
@@ -324,6 +382,8 @@
/**
* Gets the packages that depend on the library.
*
+ * NOTE: the list also contains the result of {@link #getOptionalDependentPackages}.
+ *
* @return The dependent packages.
*/
public @NonNull List<VersionedPackage> getDependentPackages() {
@@ -333,6 +393,19 @@
return mDependentPackages;
}
+ /**
+ * Gets the packages that optionally depend on the library.
+ *
+ * @return The dependent packages.
+ */
+ @FlaggedApi(Flags.FLAG_SDK_LIB_INDEPENDENCE)
+ public @NonNull List<VersionedPackage> getOptionalDependentPackages() {
+ if (mOptionalDependentPackages == null) {
+ return Collections.emptyList();
+ }
+ return mOptionalDependentPackages;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -362,6 +435,7 @@
parcel.writeList(mDependentPackages);
parcel.writeTypedList(mDependencies);
parcel.writeBoolean(mIsNative);
+ parcel.writeParcelableList(mOptionalDependentPackages, flags);
}
private static String typeToString(int type) {
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index a26b311..facb244 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -61,6 +61,13 @@
}
flag {
+ name: "refactor_get_current_user"
+ namespace: "systemui"
+ description: "KeyguardUpdateMonitor.getCurrentUser() was providing outdated results."
+ bug: "305984787"
+}
+
+flag {
name: "notification_throttle_hun"
namespace: "systemui"
description: "During notification avalanche, throttle HUNs showing in fast succession."
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 33dd3d9..edf9648 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -35,7 +35,7 @@
import static android.view.WindowManager.TransitionOldType;
import static android.view.WindowManager.TransitionType;
-import static com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER;
+import static com.android.systemui.Flags.refactorGetCurrentUser;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -609,7 +609,7 @@
public void setCurrentUser(int userId) {
trace("Deprecated/NOT USED: setCurrentUser userId=" + userId);
checkPermission();
- if (!mFlags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+ if (!refactorGetCurrentUser()) {
mKeyguardViewMediator.setCurrentUser(userId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 57f3b70..d7a1906 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -38,7 +38,7 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER;
+import static com.android.systemui.Flags.refactorGetCurrentUser;
import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -617,7 +617,7 @@
public void onUserSwitching(int userId) {
if (DEBUG) Log.d(TAG, String.format("onUserSwitching %d", userId));
synchronized (KeyguardViewMediator.this) {
- if (mFeatureFlags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+ if (refactorGetCurrentUser()) {
notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId));
}
resetKeyguardDonePendingLocked();
@@ -1502,7 +1502,7 @@
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- if (!mFeatureFlags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+ if (!refactorGetCurrentUser()) {
KeyguardUpdateMonitor.setCurrentUser(mUserTracker.getUserId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
index 3ed05aa..0fb4b43 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
@@ -2,9 +2,8 @@
import android.annotation.UserIdInt
import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.Flags.refactorGetCurrentUser
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER
import com.android.systemui.user.data.repository.UserRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -12,12 +11,7 @@
/** Encapsulates business logic to interact the selected user */
@SysUISingleton
-class SelectedUserInteractor
-@Inject
-constructor(
- private val repository: UserRepository,
- private val flags: FeatureFlagsClassic,
-) {
+class SelectedUserInteractor @Inject constructor(private val repository: UserRepository) {
/** Flow providing the ID of the currently selected user. */
val selectedUser = repository.selectedUserInfo.map { it.id }.distinctUntilChanged()
@@ -34,7 +28,7 @@
@UserIdInt
@JvmOverloads
fun getSelectedUserId(bypassFlag: Boolean = false): Int {
- return if (bypassFlag || flags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+ return if (bypassFlag || refactorGetCurrentUser()) {
repository.getSelectedUserInfo().id
} else {
KeyguardUpdateMonitor.getCurrentUser()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 4ef18cf..b38c9ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -24,6 +24,7 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import static com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER;
import static com.android.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION;
import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT;
import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE;
@@ -266,7 +267,7 @@
mSceneContainerFlags);
mFeatureFlags = new FakeFeatureFlags();
mFeatureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false);
- mFeatureFlags.set(Flags.REFACTOR_GETCURRENTUSER, true);
+ mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER);
DejankUtils.setImmediate(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
index 8dea57c..8e81185 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
@@ -20,8 +20,6 @@
import androidx.test.filters.SmallTest
import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -46,11 +44,7 @@
class FromPrimaryBouncerTransitionInteractorTest : KeyguardTransitionInteractorTestCase() {
private lateinit var underTest: FromPrimaryBouncerTransitionInteractor
- private val mSelectedUserInteractor =
- SelectedUserInteractor(
- FakeUserRepository(),
- FakeFeatureFlagsClassic().apply { set(Flags.REFACTOR_GETCURRENTUSER, true) }
- )
+ private val mSelectedUserInteractor = SelectedUserInteractor(FakeUserRepository())
// Override the fromPrimaryBouncerTransitionInteractor provider from the superclass so our
// underTest interactor is provided to any classes that need it.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
index 60fe7d2..140e919 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
@@ -2,9 +2,8 @@
import android.content.pm.UserInfo
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER
import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
import com.android.systemui.user.data.repository.FakeUserRepository
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.runBlocking
@@ -24,15 +23,12 @@
@Before
fun setUp() {
userRepository.setUserInfos(USER_INFOS)
- underTest =
- SelectedUserInteractor(
- userRepository,
- FakeFeatureFlagsClassic().apply { set(Flags.REFACTOR_GETCURRENTUSER, true) }
- )
+ underTest = SelectedUserInteractor(userRepository)
}
@Test
fun getSelectedUserIdReturnsId() {
+ mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER)
runBlocking { userRepository.setSelectedUserInfo(USER_INFOS[0]) }
val actualId = underTest.getSelectedUserId()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
index 3d8ae1e..3cabf0c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
@@ -27,8 +27,6 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -57,12 +55,6 @@
keyguardRepository: FakeKeyguardRepository = FakeKeyguardRepository(),
bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
keyguardUpdateMonitor: KeyguardUpdateMonitor = mock(KeyguardUpdateMonitor::class.java),
- featureFlags: FakeFeatureFlagsClassic =
- FakeFeatureFlagsClassic().apply {
- set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, true)
- set(Flags.FULL_SCREEN_USER_SWITCHER, false)
- set(Flags.REFACTOR_GETCURRENTUSER, true)
- },
powerRepository: FakePowerRepository = FakePowerRepository(),
userRepository: FakeUserRepository = FakeUserRepository(),
): WithDependencies {
@@ -98,8 +90,7 @@
PowerInteractorFactory.create(
repository = powerRepository,
)
- val selectedUserInteractor =
- SelectedUserInteractor(repository = userRepository, flags = featureFlags)
+ val selectedUserInteractor = SelectedUserInteractor(repository = userRepository)
return WithDependencies(
trustRepository = trustRepository,
keyguardRepository = keyguardRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index d78bcb9..0b41926 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -387,7 +387,7 @@
}
fun selectedUserInteractor(): SelectedUserInteractor {
- return SelectedUserInteractor(userRepository, featureFlags)
+ return SelectedUserInteractor(userRepository)
}
fun bouncerActionButtonInteractor(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt
index 427f92a..89672f1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt
@@ -16,9 +16,7 @@
package com.android.systemui.user.domain.interactor
-import com.android.systemui.flags.featureFlagsClassic
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.user.data.repository.userRepository
-val Kosmos.selectedUserInteractor by
- Kosmos.Fixture { SelectedUserInteractor(userRepository, featureFlagsClassic) }
+val Kosmos.selectedUserInteractor by Kosmos.Fixture { SelectedUserInteractor(userRepository) }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index c440a64..16e043c 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -6499,10 +6499,12 @@
nextEnabledImes).getId();
// Reset enabled IMEs.
- settings.putEnabledInputMethodsStr("");
- nextEnabledImes.forEach(
- imi -> settings.appendAndPutEnabledInputMethodLocked(
- imi.getId()));
+ final String[] nextEnabledImeIds = new String[nextEnabledImes.size()];
+ for (int i = 0; i < nextEnabledImeIds.length; ++i) {
+ nextEnabledImeIds[i] = nextEnabledImes.get(i).getId();
+ }
+ settings.putEnabledInputMethodsStr(InputMethodUtils.concatEnabledImeIds(
+ settings.getEnabledInputMethodsStr(), nextEnabledImeIds));
// Reset selected IME.
settings.putSelectedInputMethod(nextIme);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index 2128356..773293f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -33,6 +33,7 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.IntArray;
import android.util.Pair;
import android.util.Printer;
@@ -50,6 +51,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.StringJoiner;
+import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -952,24 +955,64 @@
final String enabledInputMethodsStr = TextUtils.nullIfEmpty(
SecureSettingsWrapper.getString(Settings.Secure.ENABLED_INPUT_METHODS, null,
userId));
- if (enabledInputMethodsStr == null) {
- return List.of();
+ final ArrayList<String> result = new ArrayList<>();
+ splitEnabledImeStr(enabledInputMethodsStr, result::add);
+ return result;
+ }
+
+ /**
+ * Split enabled IME string ({@link Settings.Secure#ENABLED_INPUT_METHODS}) into IME IDs.
+ *
+ * @param text a text formatted with {@link Settings.Secure#ENABLED_INPUT_METHODS}.
+ * @param consumer {@link Consumer} called back when a new IME ID is found.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ static void splitEnabledImeStr(@Nullable String text, @NonNull Consumer<String> consumer) {
+ if (TextUtils.isEmpty(text)) {
+ return;
}
final TextUtils.SimpleStringSplitter inputMethodSplitter =
new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATOR);
final TextUtils.SimpleStringSplitter subtypeSplitter =
new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR);
- inputMethodSplitter.setString(enabledInputMethodsStr);
- final ArrayList<String> result = new ArrayList<>();
+ inputMethodSplitter.setString(text);
while (inputMethodSplitter.hasNext()) {
String nextImsStr = inputMethodSplitter.next();
subtypeSplitter.setString(nextImsStr);
if (subtypeSplitter.hasNext()) {
// The first element is ime id.
- result.add(subtypeSplitter.next());
+ consumer.accept(subtypeSplitter.next());
}
}
- return result;
+ }
+
+ /**
+ * Concat given IME IDs with an existing enabled IME
+ * ({@link Settings.Secure#ENABLED_INPUT_METHODS}).
+ *
+ * @param existingEnabledImeId an existing {@link Settings.Secure#ENABLED_INPUT_METHODS} to
+ * which {@code imeIDs} will be added.
+ * @param imeIds an array of IME IDs to be added. For IME IDs that are already seen in
+ * {@code existingEnabledImeId} will be skipped.
+ * @return a new enabled IME ID string that can be stored in
+ * {@link Settings.Secure#ENABLED_INPUT_METHODS}.
+ */
+ @NonNull
+ static String concatEnabledImeIds(@NonNull String existingEnabledImeId,
+ @NonNull String... imeIds) {
+ final ArraySet<String> alreadyEnabledIds = new ArraySet<>();
+ final StringJoiner joiner = new StringJoiner(Character.toString(INPUT_METHOD_SEPARATOR));
+ if (!TextUtils.isEmpty(existingEnabledImeId)) {
+ splitEnabledImeStr(existingEnabledImeId, alreadyEnabledIds::add);
+ joiner.add(existingEnabledImeId);
+ }
+ for (String id : imeIds) {
+ if (!alreadyEnabledIds.contains(id)) {
+ joiner.add(id);
+ alreadyEnabledIds.add(id);
+ }
+ }
+ return joiner.toString();
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
index b12180b..4b8de4e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -19,6 +19,7 @@
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
+import android.service.notification.DeviceEffectsApplier;
import java.util.Set;
@@ -54,4 +55,22 @@
void cleanupHistoryFiles();
void removeBitmaps();
+
+ /**
+ * Sets the {@link DeviceEffectsApplier} that will be used to apply the different
+ * {@link android.service.notification.ZenDeviceEffects} that are relevant for the platform
+ * when {@link android.service.notification.ZenModeConfig.ZenRule} instances are activated and
+ * deactivated.
+ *
+ * <p>This method is optional and needs only be called if the platform supports non-standard
+ * effects (i.e. any that are not <em>public APIs</em> in
+ * {@link android.service.notification.ZenDeviceEffects}, or if they must be applied in a
+ * non-standard fashion. If not used, a {@link DefaultDeviceEffectsApplier} will be invoked,
+ * which should be sufficient for most devices.
+ *
+ * <p>If this method is called, it <em>must</em> be during system startup and <em>before</em>
+ * the {@link com.android.server.SystemService#PHASE_THIRD_PARTY_APPS_CAN_START} boot phase.
+ * Otherwise an {@link IllegalStateException} will be thrown.
+ */
+ void setDeviceEffectsApplier(DeviceEffectsApplier applier);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 66a9740..e7ae610 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -251,6 +251,7 @@
import android.service.notification.Adjustment;
import android.service.notification.Condition;
import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.DeviceEffectsApplier;
import android.service.notification.IConditionProvider;
import android.service.notification.INotificationListener;
import android.service.notification.IStatusBarNotificationHolder;
@@ -6964,6 +6965,18 @@
}
}
}
+
+ @Override
+ public void setDeviceEffectsApplier(DeviceEffectsApplier applier) {
+ if (!android.app.Flags.modesApi()) {
+ return;
+ }
+ if (mZenModeHelper == null) {
+ throw new IllegalStateException("ZenModeHelper is not yet ready!");
+ }
+ // This can also throw IllegalStateException if called too late.
+ mZenModeHelper.setDeviceEffectsApplier(applier);
+ }
};
private static boolean isBigPictureWithBitmapOrIcon(Notification n) {
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index abfd571..744c946 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -3864,19 +3864,15 @@
} finally {
Binder.restoreCallingIdentity(identity);
}
-
- var usingSharedLibraryPair =
- getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId);
SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getPath(),
libInfo.getPackageName(), libInfo.getAllCodePaths(),
libInfo.getName(), libInfo.getLongVersion(),
libInfo.getType(), declaringPackage,
- usingSharedLibraryPair.first,
(libInfo.getDependencies() == null
? null
: new ArrayList<>(libInfo.getDependencies())),
- libInfo.isNative());
-
+ libInfo.isNative(),
+ getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId));
if (result == null) {
result = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index ba66377..127bf49 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -822,7 +822,7 @@
return new LauncherActivityInfoInternal(
activityInfo,
new IncrementalStatesInfo(
- false /* isLoading */, 1 /* progress */, 0 /* loadingCompletedTime */),
+ false /* isLoading */, 0 /* progress */, 0 /* loadingCompletedTime */),
user);
}
@@ -1599,6 +1599,33 @@
}
@Override
+ public @Nullable IntentSender getAppMarketActivityIntent(@NonNull String callingPackage,
+ @Nullable String packageName, @NonNull UserHandle user) {
+ // Only system launchers, which have access to recents should have access to this API.
+ // TODO(b/303803157): Update access control for this API to default Launcher app.
+ if (!mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
+ throw new SecurityException("Caller is not the recents app");
+ }
+ if (!canAccessProfile(user.getIdentifier(),
+ "Can't access AppMarketActivity for another user")) {
+ return null;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO(b/316118005): Add code to launch the app installer for the packageName.
+ Intent appMarketIntent = new Intent(Intent.ACTION_MAIN);
+ appMarketIntent.addCategory(Intent.CATEGORY_APP_MARKET);
+ final PendingIntent pi = PendingIntent.getActivityAsUser(
+ mContext, /* requestCode */ 0, appMarketIntent, PendingIntent.FLAG_ONE_SHOT
+ | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT,
+ /* options */ null, user);
+ return pi == null ? null : pi.getIntentSender();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, ComponentName component, Rect sourceBounds,
Bundle opts, UserHandle user) throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 7d6dd62..2942bbb 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -821,6 +821,18 @@
params.installFlags &= ~PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
}
+ params.installFlags &= ~PackageManager.INSTALL_UNARCHIVE;
+ if (Flags.archiving() && params.appPackageName != null) {
+ PackageStateInternal ps = mPm.snapshotComputer().getPackageStateInternal(
+ params.appPackageName, SYSTEM_UID);
+ if (ps != null
+ && PackageArchiver.isArchived(ps.getUserStateOrDefault(userId))
+ && PackageArchiver.getResponsibleInstallerPackage(ps)
+ .equals(requestedInstallerPackageName)) {
+ params.installFlags |= PackageManager.INSTALL_UNARCHIVE;
+ }
+ }
+
if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0
&& !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)
&& (snapshot.getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM)
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index fa54f0b..d0fe964 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -28,6 +28,7 @@
import android.content.pm.FallbackCategoryProvider;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.Flags;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
@@ -474,7 +475,34 @@
}
info.sharedLibraryFiles = usesLibraryFiles.isEmpty()
? null : usesLibraryFiles.toArray(new String[0]);
- info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+
+
+ if (!Flags.sdkLibIndependence()) {
+ info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+ info.optionalSharedLibraryInfos = null;
+ } else {
+ // sharedLibraryInfos contains all shared libraries that the app depends on (including
+ // the optional sdk libraries)
+ info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+ String[] libsNames = pkgSetting.getUsesSdkLibraries();
+ boolean[] libsOptional = pkgSetting.getUsesSdkLibrariesOptional();
+ List<SharedLibraryInfo> optionalSdkLibraries = null;
+ if (!ArrayUtils.isEmpty(libsOptional) && !ArrayUtils.isEmpty(libsNames)
+ && libsNames.length == libsOptional.length) {
+ for (SharedLibraryInfo info1 : usesLibraryInfos) {
+ if (info1.getType() == SharedLibraryInfo.TYPE_SDK_PACKAGE) {
+ int index = ArrayUtils.indexOf(libsNames, info1.getName());
+ if (index >= 0 && libsOptional[index]) {
+ if (optionalSdkLibraries == null) {
+ optionalSdkLibraries = new ArrayList<>();
+ }
+ optionalSdkLibraries.add(info1);
+ }
+ }
+ }
+ }
+ info.optionalSharedLibraryInfos = optionalSdkLibraries;
+ }
if (info.category == ApplicationInfo.CATEGORY_UNDEFINED) {
info.category = pkgSetting.getCategoryOverride();
}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index b396cf4..3d0b389 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -45,7 +45,9 @@
import android.app.PropertyInvalidatedCache;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
+import android.content.pm.Flags;
import android.content.pm.PackageManager;
+import android.content.pm.SharedLibraryInfo;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.UserInfo;
import android.os.BaseBundle;
@@ -54,6 +56,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -67,6 +70,7 @@
import com.android.internal.pm.parsing.pkg.ParsedPackage;
import com.android.permission.persistence.RuntimePermissionsPersistence;
import com.android.server.LocalServices;
+import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.ArchiveState;
@@ -85,6 +89,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -109,6 +114,9 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PackageManagerSettingsTests {
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final String PACKAGE_NAME_1 = "com.android.app1";
private static final String PACKAGE_NAME_2 = "com.android.app2";
private static final String PACKAGE_NAME_3 = "com.android.app3";
@@ -140,6 +148,7 @@
public void setup() {
// Disable binder caches in this process.
PropertyInvalidatedCache.disableForTestMode();
+
}
@Before
@@ -161,6 +170,107 @@
deleteFolder(InstrumentationRegistry.getContext().getFilesDir());
}
+ @Test
+ public void testApplicationInfoForUseSdkOptionalEnabled() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_SDK_LIB_INDEPENDENCE);
+
+ // Create basic information for SDK lib
+ final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
+ ps1.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
+ .setUid(ps1.getAppId())
+ .setSystem(true)
+ .hideAsFinal());
+ ps1.setUsesSdkLibraries(new String[] { "com.example.sdk.one" });
+ ps1.setUsesSdkLibrariesVersionsMajor(new long[] { 12 });
+ ps1.setUsesSdkLibrariesOptional(new boolean[] {true});
+ ps1.addUsesLibraryInfo(new SharedLibraryInfo("path1",
+ "packageName1",
+ Collections.emptyList(),
+ "com.example.sdk.one",
+ 12 /*version*/,
+ SharedLibraryInfo.TYPE_SDK_PACKAGE,
+ null /*declaringPackage*/,
+ null /*dependentPackages*/,
+ null /*dependencies*/,
+ false /*isNative*/));
+ ps1.addUsesLibraryInfo(new SharedLibraryInfo("path11",
+ "packageName11",
+ Collections.emptyList(),
+ "com.example.sdk.oneone",
+ 1212 /*version*/,
+ SharedLibraryInfo.TYPE_STATIC,
+ null /*declaringPackage*/,
+ null /*dependentPackages*/,
+ null /*dependencies*/,
+ false /*isNative*/));
+ ApplicationInfo appInfo1 = PackageInfoUtils.generateApplicationInfo(ps1.getAndroidPackage(),
+ 0 /*flags*/, ps1.getUserStateOrDefault(0), 0 /*userId*/,
+ ps1);
+ assertThat(appInfo1, notNullValue());
+ assertThat(appInfo1.sharedLibraryInfos, notNullValue());
+ assertThat(appInfo1.optionalSharedLibraryInfos, notNullValue());
+ assertEquals(appInfo1.sharedLibraryInfos.get(0).getName(), "com.example.sdk.one");
+ assertEquals(appInfo1.optionalSharedLibraryInfos.get(0).getName(), "com.example.sdk.one");
+
+ final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
+ ps2.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_2).hideAsParsed())
+ .setUid(ps2.getAppId())
+ .setSystem(true)
+ .hideAsFinal());
+ ps2.setUsesSdkLibraries(new String[] { "com.example.sdk.two" });
+ ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 });
+ ps2.setUsesSdkLibrariesOptional(new boolean[] {false});
+ ps2.addUsesLibraryInfo(new SharedLibraryInfo("path2",
+ "packageName2",
+ Collections.emptyList(),
+ "com.example.sdk.two",
+ 34 /*version*/,
+ SharedLibraryInfo.TYPE_SDK_PACKAGE,
+ null /*declaringPackage*/,
+ null /*dependentPackages*/,
+ null /*dependencies*/,
+ false /*isNative*/));
+ ApplicationInfo appInfo2 = PackageInfoUtils.generateApplicationInfo(ps2.getAndroidPackage(),
+ 0 /*flags*/, ps2.getUserStateOrDefault(0), 0 /*userId*/,
+ ps2);
+ assertThat(appInfo2, notNullValue());
+ assertThat(appInfo2.sharedLibraryInfos, notNullValue());
+ assertThat(appInfo2.optionalSharedLibraryInfos, nullValue());
+ assertEquals(appInfo2.sharedLibraryInfos.get(0).getName(), "com.example.sdk.two");
+ }
+
+ @Test
+ public void testApplicationInfoForUseSdkOptionalDisabled() throws Exception {
+ mSetFlagsRule.disableFlags(Flags.FLAG_SDK_LIB_INDEPENDENCE);
+
+ // Create basic information for SDK lib
+ final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
+ ps1.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
+ .setUid(ps1.getAppId())
+ .setSystem(true)
+ .hideAsFinal());
+ ps1.setUsesSdkLibraries(new String[] { "com.example.sdk.one" });
+ ps1.setUsesSdkLibrariesVersionsMajor(new long[] { 12 });
+ ps1.setUsesSdkLibrariesOptional(new boolean[] {true});
+ ps1.addUsesLibraryInfo(new SharedLibraryInfo("path1",
+ "packageName1",
+ Collections.emptyList(),
+ "com.example.sdk.one",
+ 12 /*version*/,
+ SharedLibraryInfo.TYPE_SDK_PACKAGE,
+ null /*declaringPackage*/,
+ null /*dependentPackages*/,
+ null /*dependencies*/,
+ false /*isNative*/));
+ ApplicationInfo appInfo1 = PackageInfoUtils.generateApplicationInfo(ps1.getAndroidPackage(),
+ 0 /*flags*/, ps1.getUserStateOrDefault(0), 0 /*userId*/,
+ ps1);
+ assertThat(appInfo1, notNullValue());
+ assertThat(appInfo1.sharedLibraryInfos, notNullValue());
+ assertThat(appInfo1.optionalSharedLibraryInfos, nullValue());
+ assertEquals(appInfo1.sharedLibraryInfos.get(0).getName(), "com.example.sdk.one");
+ }
+
/** make sure our initialized KeySetManagerService metadata matches packages.xml */
@Test
public void testReadKeySetSettings() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
index fb78574..0d25faf 100644
--- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
@@ -60,6 +60,8 @@
import com.android.internal.inputmethod.StartInputFlags;
+import com.google.common.truth.Truth;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -1336,6 +1338,54 @@
}
}
+ private static void verifySplitEnabledImeStr(@NonNull String enabledImeStr,
+ @NonNull String... expected) {
+ final ArrayList<String> actual = new ArrayList<>();
+ InputMethodUtils.splitEnabledImeStr(enabledImeStr, actual::add);
+ if (expected.length == 0) {
+ Truth.assertThat(actual).isEmpty();
+ } else {
+ Truth.assertThat(actual).containsExactlyElementsIn(expected);
+ }
+ }
+
+ @Test
+ public void testSplitEnabledImeStr() {
+ verifySplitEnabledImeStr("");
+ verifySplitEnabledImeStr("com.android/.ime1", "com.android/.ime1");
+ verifySplitEnabledImeStr("com.android/.ime1;1;2;3", "com.android/.ime1");
+ verifySplitEnabledImeStr("com.android/.ime1;1;2;3:com.android/.ime2",
+ "com.android/.ime1", "com.android/.ime2");
+ verifySplitEnabledImeStr("com.android/.ime1:com.android/.ime2",
+ "com.android/.ime1", "com.android/.ime2");
+ verifySplitEnabledImeStr("com.android/.ime1:com.android/.ime2:com.android/.ime3",
+ "com.android/.ime1", "com.android/.ime2", "com.android/.ime3");
+ verifySplitEnabledImeStr("com.android/.ime1;1:com.android/.ime2;1:com.android/.ime3;1",
+ "com.android/.ime1", "com.android/.ime2", "com.android/.ime3");
+ }
+
+ @Test
+ public void testConcatEnabledImeIds() {
+ Truth.assertThat(InputMethodUtils.concatEnabledImeIds("")).isEmpty();
+ Truth.assertThat(InputMethodUtils.concatEnabledImeIds("", "com.android/.ime1"))
+ .isEqualTo("com.android/.ime1");
+ Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+ "com.android/.ime1", "com.android/.ime1"))
+ .isEqualTo("com.android/.ime1");
+ Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+ "com.android/.ime1", "com.android/.ime2"))
+ .isEqualTo("com.android/.ime1:com.android/.ime2");
+ Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+ "com.android/.ime1", "com.android/.ime2", "com.android/.ime3"))
+ .isEqualTo("com.android/.ime1:com.android/.ime2:com.android/.ime3");
+ Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+ "com.android/.ime1:com.android/.ime2", "com.android/.ime1"))
+ .isEqualTo("com.android/.ime1:com.android/.ime2");
+ Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+ "com.android/.ime1:com.android/.ime2", "com.android/.ime3"))
+ .isEqualTo("com.android/.ime1:com.android/.ime2:com.android/.ime3");
+ }
+
@Test
public void updateEnabledImeStringTest() {
// No change cases
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 14b551a..776189e 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -219,6 +219,7 @@
import android.provider.Settings;
import android.service.notification.Adjustment;
import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.DeviceEffectsApplier;
import android.service.notification.NotificationListenerFilter;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
@@ -635,6 +636,10 @@
}
private void initNMS() throws Exception {
+ initNMS(SystemService.PHASE_BOOT_COMPLETED);
+ }
+
+ private void initNMS(int upToBootPhase) throws Exception {
mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
mNotificationInstanceIdSequence);
@@ -662,13 +667,21 @@
mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager,
mPowerManager, mPostNotificationTrackerFactory);
+
// Return first true for RoleObserver main-thread check
when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
- mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
+
+ if (upToBootPhase >= SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
+ }
+
Mockito.reset(mHistoryManager);
verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
- mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
- verify(mHistoryManager).onBootPhaseAppsCanStart();
+
+ if (upToBootPhase >= SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
+ verify(mHistoryManager).onBootPhaseAppsCanStart();
+ }
// TODO b/291907312: remove feature flag
if (Flags.refactorAttentionHelper()) {
@@ -914,7 +927,9 @@
mTestNotificationChannel.setAllowBubbles(channelEnabled);
}
- private void setUpPrefsForHistory(int uid, boolean globalEnabled) {
+ private void setUpPrefsForHistory(int uid, boolean globalEnabled) throws Exception {
+ initNMS(SystemService.PHASE_ACTIVITY_MANAGER_READY);
+
// Sets NOTIFICATION_HISTORY_ENABLED setting for calling process uid
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.NOTIFICATION_HISTORY_ENABLED, globalEnabled ? 1 : 0, uid);
@@ -10090,7 +10105,7 @@
}
@Test
- public void testHandleOnPackageRemoved_ClearsHistory() throws RemoteException {
+ public void testHandleOnPackageRemoved_ClearsHistory() throws Exception {
// Enables Notification History setting
setUpPrefsForHistory(mUid, true /* =enabled */);
@@ -13209,6 +13224,34 @@
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void setDeviceEffectsApplier_succeeds() throws Exception {
+ initNMS(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+ mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class));
+ // No exception!
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void setDeviceEffectsApplier_tooLate_throws() throws Exception {
+ initNMS(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+
+ assertThrows(IllegalStateException.class, () ->
+ mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class)));
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void setDeviceEffectsApplier_calledTwice_throws() throws Exception {
+ initNMS(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+ mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class));
+ assertThrows(IllegalStateException.class, () ->
+ mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class)));
+ }
+
+ @Test
@EnableCompatChanges(NotificationManagerService.MANAGE_GLOBAL_ZEN_VIA_IMPLICIT_RULES)
public void setNotificationPolicy_mappedToImplicitRule() throws RemoteException {
mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);