diff options
210 files changed, 3414 insertions, 1668 deletions
diff --git a/api/current.txt b/api/current.txt index 7c13dc1293c1..6f9f57bc7f02 100644 --- a/api/current.txt +++ b/api/current.txt @@ -41053,6 +41053,7 @@ package android.service.autofill { method public int getType(); field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2 field public static final int TYPE_CONTEXT_COMMITTED = 4; // 0x4 + field public static final int TYPE_DATASETS_SHOWN = 5; // 0x5 field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1 field public static final int TYPE_DATASET_SELECTED = 0; // 0x0 field public static final int TYPE_SAVE_SHOWN = 3; // 0x3 @@ -52435,6 +52436,7 @@ package android.view.accessibility { method public int getId(); method public int getLayer(); method public android.view.accessibility.AccessibilityWindowInfo getParent(); + method public void getRegionInScreen(@NonNull android.graphics.Region); method public android.view.accessibility.AccessibilityNodeInfo getRoot(); method @Nullable public CharSequence getTitle(); method public int getType(); diff --git a/api/removed.txt b/api/removed.txt index 7b1d241fdd6a..b075f9ef3e51 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -73,10 +73,6 @@ package android.app.usage { package android.content { - public class ClipData implements android.os.Parcelable { - method @Deprecated public void addItem(android.content.ClipData.Item, android.content.ContentResolver); - } - public abstract class Context { method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int); method public abstract java.io.File getSharedPreferencesPath(String); diff --git a/api/system-current.txt b/api/system-current.txt index 48804b6be72a..eef6b3f98e61 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5179,7 +5179,8 @@ package android.os { method @NonNull public static java.io.File getOdmDirectory(); method @NonNull public static java.io.File getOemDirectory(); method @NonNull public static java.io.File getProductDirectory(); - method @NonNull public static java.io.File getProductServicesDirectory(); + method @Deprecated @NonNull public static java.io.File getProductServicesDirectory(); + method @NonNull public static java.io.File getSystemExtDirectory(); method @NonNull public static java.io.File getVendorDirectory(); } diff --git a/api/test-current.txt b/api/test-current.txt index 050ec520059c..d2179d3f4262 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -54,6 +54,7 @@ package android.app { method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getPackageImportance(String); method public long getTotalRam(); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int); + method public static boolean isHighEndGfx(); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener); method public static void resumeAppSwitches() throws android.os.RemoteException; method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int); @@ -3492,11 +3493,6 @@ package android.view.inputmethod { method public boolean isInputMethodPickerShown(); } - public class InputMethodSystemProperty { - ctor public InputMethodSystemProperty(); - field public static final boolean MULTI_CLIENT_IME_ENABLED; - } - } package android.view.inspector { diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index 680ccfc57ddf..76b905d8985f 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -64,6 +64,10 @@ public class Bmgr { private static final String BMGR_NOT_RUNNING_ERR = "Error: Could not access the Backup Manager. Is the system running?"; + private static final String BMGR_NOT_ACTIVATED_FOR_USER = + "Error: Backup Manager is not activated for user "; + private static final String BMGR_ERR_NO_RESTORESESSION_FOR_USER = + "Error: Could not get restore session for user "; private static final String TRANSPORT_NOT_RUNNING_ERR = "Error: Could not access the backup transport. Is the system running?"; private static final String PM_NOT_RUNNING_ERR = @@ -190,15 +194,19 @@ public class Bmgr { showUsage(); } - boolean isBackupActive(@UserIdInt int userId) { + private void handleRemoteException(RemoteException e) { + System.err.println(e.toString()); + System.err.println(BMGR_NOT_RUNNING_ERR); + } + + private boolean isBackupActive(@UserIdInt int userId) { try { if (!mBmgr.isBackupServiceActive(userId)) { - System.err.println(BMGR_NOT_RUNNING_ERR); + System.err.println(BMGR_NOT_ACTIVATED_FOR_USER + userId); return false; } } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); return false; } @@ -214,8 +222,7 @@ public class Bmgr { System.out.println("Backup Manager currently " + activatedToString(mBmgr.isBackupServiceActive(userId))); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -230,8 +237,7 @@ public class Bmgr { System.out.println("Backup Manager currently " + enableToString(isEnabled)); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -250,8 +256,7 @@ public class Bmgr { showUsage(); return; } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -259,8 +264,7 @@ public class Bmgr { try { mBmgr.backupNowForUser(userId); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -274,8 +278,7 @@ public class Bmgr { try { mBmgr.dataChangedForUser(userId, pkg); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -292,8 +295,7 @@ public class Bmgr { mBmgr.fullTransportBackupForUser( userId, allPkgs.toArray(new String[allPkgs.size()])); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } } @@ -421,8 +423,7 @@ public class Bmgr { try { filteredPackages = mBmgr.filterAppsEligibleForBackupForUser(userId, packages); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } backupNowPackages(userId, Arrays.asList(filteredPackages), nonIncrementalBackup, monitorState); @@ -455,8 +456,7 @@ public class Bmgr { System.err.println("Unable to run backup"); } } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -506,8 +506,7 @@ public class Bmgr { try { mBmgr.cancelBackupsForUser(userId); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } return; } @@ -537,8 +536,7 @@ public class Bmgr { } } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -569,8 +567,7 @@ public class Bmgr { } }); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); return; } @@ -598,8 +595,7 @@ public class Bmgr { mBmgr.clearBackupDataForUser(userId, transport, pkg); System.out.println("Wiped backup data for " + pkg + " on " + transport); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -632,8 +628,7 @@ public class Bmgr { observer.waitForCompletion(30*1000L); System.out.println("Initialization result: " + observer.result); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -648,7 +643,7 @@ public class Bmgr { try { mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null); if (mRestore == null) { - System.err.println(BMGR_NOT_RUNNING_ERR); + System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId); return; } @@ -658,8 +653,7 @@ public class Bmgr { mRestore.endRestoreSession(); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -686,8 +680,7 @@ public class Bmgr { System.out.println(pad + t); } } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -805,7 +798,7 @@ public class Bmgr { boolean didRestore = false; mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null); if (mRestore == null) { - System.err.println(BMGR_NOT_RUNNING_ERR); + System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId); return; } RestoreSet[] sets = null; @@ -851,8 +844,7 @@ public class Bmgr { System.out.println("done"); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -865,8 +857,7 @@ public class Bmgr { } } } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } @@ -886,8 +877,7 @@ public class Bmgr { + " for user " + userId); } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(BMGR_NOT_RUNNING_ERR); + handleRemoteException(e); } } diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp index 31bd612cc2c7..c1f86544070e 100644 --- a/cmds/bootanimation/Android.bp +++ b/cmds/bootanimation/Android.bp @@ -79,7 +79,6 @@ cc_library_shared { "libEGL", "libGLESv1_CM", "libgui", - "libtinyalsa", ], product_variables: { diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp index cfac5f31e2e6..0b349e10a118 100644 --- a/cmds/idmap2/idmap2/Scan.cpp +++ b/cmds/idmap2/idmap2/Scan.cpp @@ -103,6 +103,7 @@ std::vector<std::string> PoliciesForPath(const std::string& apk_path) { {"/oem/", kPolicyOem}, {"/product/", kPolicyProduct}, {"/system/", kPolicySystem}, + {"/system_ext/", kPolicySystem}, {"/vendor/", kPolicyVendor}, }; diff --git a/config/preloaded-classes b/config/preloaded-classes index b4fd031bf5a2..03e3b82c75f7 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -2696,6 +2696,7 @@ android.os.-$$Lambda$ThreadLocalWorkSource$IP9vRFCDG5YwbWbXAEGHH52B9IE android.os.-$$Lambda$Trace$2zLZ-Lc2kAXsVjw_nLYeNhqmGq0 android.os.-$$Lambda$q1UvBdLgHRZVzc68BxdksTmbuCw android.os.AsyncResult +android.os.AsyncTask android.os.AsyncTask$1 android.os.AsyncTask$2 android.os.AsyncTask$3 diff --git a/config/preloaded-classes-blacklist b/config/preloaded-classes-blacklist index b5f995088977..f05edee9c42d 100644 --- a/config/preloaded-classes-blacklist +++ b/config/preloaded-classes-blacklist @@ -1,6 +1,5 @@ android.content.AsyncTaskLoader$LoadTask android.net.ConnectivityThread$Singleton -android.os.AsyncTask android.os.FileObserver android.speech.tts.TextToSpeech$Connection$SetupConnectionAsyncTask android.widget.Magnifier diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 17368b789645..cb99a3aa11c6 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -925,7 +925,7 @@ public class ActivityManager { * (which tends to consume a lot more RAM). * @hide */ - @UnsupportedAppUsage + @TestApi static public boolean isHighEndGfx() { return !isLowRamDeviceStatic() && !RoSystemProperties.CONFIG_AVOID_GFX_ACCEL @@ -1822,7 +1822,8 @@ public class ActivityManager { * @hide */ public static class TaskSnapshot implements Parcelable { - + // Identifier of this snapshot + private final long mId; // Top activity in task when snapshot was taken private final ComponentName mTopActivityComponent; private final GraphicBuffer mSnapshot; @@ -1841,10 +1842,12 @@ public class ActivityManager { // Must be one of the named color spaces, otherwise, always use SRGB color space. private final ColorSpace mColorSpace; - public TaskSnapshot(@NonNull ComponentName topActivityComponent, GraphicBuffer snapshot, + public TaskSnapshot(long id, + @NonNull ComponentName topActivityComponent, GraphicBuffer snapshot, @NonNull ColorSpace colorSpace, int orientation, Rect contentInsets, boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode, int systemUiVisibility, boolean isTranslucent) { + mId = id; mTopActivityComponent = topActivityComponent; mSnapshot = snapshot; mColorSpace = colorSpace.getId() < 0 @@ -1860,6 +1863,7 @@ public class ActivityManager { } private TaskSnapshot(Parcel source) { + mId = source.readLong(); mTopActivityComponent = ComponentName.readFromParcel(source); mSnapshot = source.readParcelable(null /* classLoader */); int colorSpaceId = source.readInt(); @@ -1877,6 +1881,13 @@ public class ActivityManager { } /** + * @return Identifier of this snapshot. + */ + public long getId() { + return mId; + } + + /** * @return The top activity component for the task at the point this snapshot was taken. */ public ComponentName getTopActivityComponent() { @@ -1970,6 +1981,7 @@ public class ActivityManager { @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mId); ComponentName.writeToParcel(mTopActivityComponent, dest); dest.writeParcelable(mSnapshot, 0); dest.writeInt(mColorSpace.getId()); @@ -1988,6 +2000,7 @@ public class ActivityManager { final int width = mSnapshot != null ? mSnapshot.getWidth() : 0; final int height = mSnapshot != null ? mSnapshot.getHeight() : 0; return "TaskSnapshot{" + + " mId=" + mId + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString() + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")" + " mColorSpace=" + mColorSpace.toString() diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index f8e6ae50d765..69e71185f228 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -26,6 +26,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ActivityPresentationInfo; import android.content.pm.ApplicationInfo; import android.content.pm.UserInfo; +import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.TransactionTooLargeException; @@ -52,6 +53,12 @@ public abstract class ActivityManagerInternal { */ public abstract String checkContentProviderAccess(String authority, int userId); + /** + * Verify that calling UID has access to the given provider. + */ + public abstract int checkContentProviderUriPermission(Uri uri, int userId, + int callingUid, int modeFlags); + // Called by the power manager. public abstract void onWakefulnessChanged(int wakefulness); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index d741b610a0e2..2b4d4f8bc6eb 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -791,6 +791,8 @@ public final class ActivityThread extends ClientTransactionHandler { @Nullable ContentCaptureOptions contentCaptureOptions; + long[] disabledCompatChanges; + @Override public String toString() { return "AppBindData{appInfo=" + appInfo + "}"; @@ -1003,7 +1005,7 @@ public final class ActivityThread extends ClientTransactionHandler { boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map services, Bundle coreSettings, String buildSerial, AutofillOptions autofillOptions, - ContentCaptureOptions contentCaptureOptions) { + ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) { if (services != null) { if (false) { // Test code to make sure the app could see the passed-in services. @@ -1051,6 +1053,7 @@ public final class ActivityThread extends ClientTransactionHandler { data.buildSerial = buildSerial; data.autofillOptions = autofillOptions; data.contentCaptureOptions = contentCaptureOptions; + data.disabledCompatChanges = disabledCompatChanges; sendMessage(H.BIND_APPLICATION, data); } @@ -6144,10 +6147,10 @@ public final class ActivityThread extends ClientTransactionHandler { if (data.trackAllocation) { DdmVmInternal.enableRecentAllocations(true); } - // Note when this process has started. Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); + AppCompatCallbacks.install(data.disabledCompatChanges); mBoundApplication = data; mConfiguration = new Configuration(data.config); mCompatConfiguration = new Configuration(data.config); diff --git a/core/java/android/app/AppCompatCallbacks.java b/core/java/android/app/AppCompatCallbacks.java new file mode 100644 index 000000000000..17697dba9ccd --- /dev/null +++ b/core/java/android/app/AppCompatCallbacks.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.compat.Compatibility; +import android.os.Process; +import android.util.Log; + +import java.util.Arrays; + +/** + * App process implementation of the {@link Compatibility} API. + * + * @hide + */ +public final class AppCompatCallbacks extends Compatibility.Callbacks { + + private static final String TAG = "Compatibility"; + + private final long[] mDisabledChanges; + + /** + * Install this class into the current process. + * + * @param disabledChanges Set of compatibility changes that are disabled for this process. + */ + public static void install(long[] disabledChanges) { + Compatibility.setCallbacks(new AppCompatCallbacks(disabledChanges)); + } + + private AppCompatCallbacks(long[] disabledChanges) { + mDisabledChanges = Arrays.copyOf(disabledChanges, disabledChanges.length); + Arrays.sort(mDisabledChanges); + } + + protected void reportChange(long changeId) { + Log.d(TAG, "Compat change reported: " + changeId + "; UID " + Process.myUid()); + // TODO log via StatsLog + } + + protected boolean isChangeEnabled(long changeId) { + if (Arrays.binarySearch(mDisabledChanges, changeId) < 0) { + // Not present in the disabled array + reportChange(changeId); + return true; + } + return false; + } + +} diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 416aaa37f064..0478ac89fbbb 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -635,7 +635,7 @@ public class ApplicationPackageManager extends PackageManager { @Override public boolean isPermissionRevokedByPolicy(String permName, String pkgName) { try { - return mPM.isPermissionRevokedByPolicy(permName, pkgName, getUserId()); + return mPermissionManager.isPermissionRevokedByPolicy(permName, pkgName, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -795,10 +795,11 @@ public class ApplicationPackageManager extends PackageManager { @Override @UnsupportedAppUsage - public boolean shouldShowRequestPermissionRationale(String permission) { + public boolean shouldShowRequestPermissionRationale(String permName) { try { - return mPM.shouldShowRequestPermissionRationale(permission, - mContext.getPackageName(), getUserId()); + final String packageName = mContext.getPackageName(); + return mPermissionManager + .shouldShowRequestPermissionRationale(permName, packageName, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2049,7 +2050,7 @@ public class ApplicationPackageManager extends PackageManager { @Override public String getDefaultBrowserPackageNameAsUser(int userId) { try { - return mPM.getDefaultBrowserPackageName(userId); + return mPermissionManager.getDefaultBrowser(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2058,7 +2059,7 @@ public class ApplicationPackageManager extends PackageManager { @Override public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) { try { - return mPM.setDefaultBrowserPackageName(packageName, userId); + return mPermissionManager.setDefaultBrowser(packageName, userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 66c438393bd6..cfa065ba5bc9 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -73,7 +73,7 @@ oneway interface IApplicationThread { boolean restrictedBackupMode, boolean persistent, in Configuration config, in CompatibilityInfo compatInfo, in Map services, in Bundle coreSettings, in String buildSerial, in AutofillOptions autofillOptions, - in ContentCaptureOptions contentCaptureOptions); + in ContentCaptureOptions contentCaptureOptions, in long[] disabledCompatChanges); void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs); void scheduleExit(); void scheduleServiceArgs(IBinder token, in ParceledListSlice args); diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index 88e2c220bb8d..fdef2a143fc4 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -892,12 +892,6 @@ public class ClipData implements Parcelable { mItems.add(item); } - /** @removed use #addItem(ContentResolver, Item) instead */ - @Deprecated - public void addItem(Item item, ContentResolver resolver) { - addItem(resolver, item); - } - /** * Add a new Item to the overall ClipData container. * <p> Unlike {@link #addItem(Item)}, this method will update the list of available MIME types diff --git a/core/java/android/content/ContentInterface.java b/core/java/android/content/ContentInterface.java index d41d8d9cc1e2..197de9711296 100644 --- a/core/java/android/content/ContentInterface.java +++ b/core/java/android/content/ContentInterface.java @@ -56,6 +56,9 @@ public interface ContentInterface { public boolean refresh(@NonNull Uri uri, @Nullable Bundle args, @Nullable CancellationSignal cancellationSignal) throws RemoteException; + public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) + throws RemoteException; + public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues) throws RemoteException; diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 7cdd2683905f..3c799915b871 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -28,6 +28,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.app.AppOpsManager; +import android.content.pm.PackageManager; import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.res.AssetFileDescriptor; @@ -582,6 +583,22 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } } + @Override + public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) { + uri = validateIncomingUri(uri); + uri = maybeGetUriWithoutUserId(uri); + Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission"); + final String original = setCallingPackage(callingPkg); + try { + return mInterface.checkUriPermission(uri, uid, modeFlags); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } finally { + setCallingPackage(original); + Trace.traceEnd(TRACE_TAG_DATABASE); + } + } + private void enforceFilePermission(String callingPkg, Uri uri, String mode, IBinder callerToken) throws FileNotFoundException, SecurityException { if (mode != null && mode.indexOf('w') != -1) { @@ -1416,6 +1433,12 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall return false; } + /** {@hide} */ + @Override + public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) { + return PackageManager.PERMISSION_DENIED; + } + /** * @hide * Implementation when a caller has performed an insert on the content diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java index 93bf5188705c..8a4330ec0ede 100644 --- a/core/java/android/content/ContentProviderClient.java +++ b/core/java/android/content/ContentProviderClient.java @@ -307,6 +307,25 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { } } + /** {@hide} */ + @Override + public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) + throws RemoteException { + Preconditions.checkNotNull(uri, "uri"); + + beforeRemote(); + try { + return mContentProvider.checkUriPermission(mPackageName, uri, uid, modeFlags); + } catch (DeadObjectException e) { + if (!mStable) { + mContentResolver.unstableProviderDied(mContentProvider); + } + throw e; + } finally { + afterRemote(); + } + } + /** See {@link ContentProvider#insert ContentProvider.insert} */ @Override public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues) diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index 994833866f40..cd735d4b10a3 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -363,6 +363,19 @@ abstract public class ContentProviderNative extends Binder implements IContentPr reply.writeInt(out ? 0 : -1); return true; } + + case CHECK_URI_PERMISSION_TRANSACTION: { + data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); + Uri uri = Uri.CREATOR.createFromParcel(data); + int uid = data.readInt(); + int modeFlags = data.readInt(); + + int out = checkUriPermission(callingPkg, uri, uid, modeFlags); + reply.writeNoException(); + reply.writeInt(out); + return true; + } } } catch (Exception e) { DatabaseUtils.writeExceptionToParcel(reply, e); @@ -800,6 +813,29 @@ final class ContentProviderProxy implements IContentProvider } } + @Override + public int checkUriPermission(String callingPkg, Uri url, int uid, int modeFlags) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + try { + data.writeInterfaceToken(IContentProvider.descriptor); + + data.writeString(callingPkg); + url.writeToParcel(data, 0); + data.writeInt(uid); + data.writeInt(modeFlags); + + mRemote.transact(IContentProvider.CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0); + + DatabaseUtils.readExceptionFromParcel(reply); + return reply.readInt(); + } finally { + data.recycle(); + reply.recycle(); + } + } + @UnsupportedAppUsage private IBinder mRemote; } diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 0a1bc85202ff..9c863591f16f 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -31,6 +31,7 @@ import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.UriGrantsManager; +import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; @@ -1146,6 +1147,24 @@ public abstract class ContentResolver implements ContentInterface { } } + /** {@hide} */ + @Override + public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) { + Preconditions.checkNotNull(uri, "uri"); + + try { + if (mWrapped != null) return mWrapped.checkUriPermission(uri, uid, modeFlags); + } catch (RemoteException e) { + return PackageManager.PERMISSION_DENIED; + } + + try (ContentProviderClient client = acquireUnstableContentProviderClient(uri)) { + return client.checkUriPermission(uri, uid, modeFlags); + } catch (RemoteException e) { + return PackageManager.PERMISSION_DENIED; + } + } + /** * Open a stream on to the content associated with a content URI. If there * is no data associated with the URI, FileNotFoundException is thrown. diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java index 0427c2f52415..fade0ab6bb5c 100644 --- a/core/java/android/content/IContentProvider.java +++ b/core/java/android/content/IContentProvider.java @@ -16,6 +16,7 @@ package android.content; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.content.res.AssetFileDescriptor; @@ -82,6 +83,9 @@ public interface IContentProvider extends IInterface { public Bundle call(String callingPkg, String authority, String method, @Nullable String arg, @Nullable Bundle extras) throws RemoteException; + public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) + throws RemoteException; + public ICancellationSignal createCancellationSignal() throws RemoteException; public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException; @@ -116,4 +120,5 @@ public interface IContentProvider extends IInterface { static final int CANONICALIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 24; static final int UNCANONICALIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 25; static final int REFRESH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 26; + static final int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 27; } diff --git a/core/java/android/content/LoggingContentInterface.java b/core/java/android/content/LoggingContentInterface.java index 83c0c9112387..1df1c4faf2fe 100644 --- a/core/java/android/content/LoggingContentInterface.java +++ b/core/java/android/content/LoggingContentInterface.java @@ -165,6 +165,19 @@ public class LoggingContentInterface implements ContentInterface { } @Override + public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) + throws RemoteException { + try (Logger l = new Logger("checkUriPermission", uri, uid, modeFlags)) { + try { + return l.setResult(delegate.checkUriPermission(uri, uid, modeFlags)); + } catch (Exception res) { + l.setResult(res); + throw res; + } + } + } + + @Override public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues) throws RemoteException { try (Logger l = new Logger("insert", uri, initialValues)) { diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index f75cd236eb36..d0a61eb38141 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -614,10 +614,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * Value for {@link #privateFlags}: whether this app is pre-installed on the - * google partition of the system image. + * system_ext partition of the system image. * @hide */ - public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21; + public static final int PRIVATE_FLAG_SYSTEM_EXT = 1 << 21; /** * Indicates whether this package requires access to non-SDK APIs. @@ -713,7 +713,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { PRIVATE_FLAG_USE_EMBEDDED_DEX, PRIVATE_FLAG_PRIVILEGED, PRIVATE_FLAG_PRODUCT, - PRIVATE_FLAG_PRODUCT_SERVICES, + PRIVATE_FLAG_SYSTEM_EXT, PRIVATE_FLAG_PROFILEABLE_BY_SHELL, PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY, @@ -2046,8 +2046,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } /** @hide */ - public boolean isProductServices() { - return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0; + public boolean isSystemExt() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0; } /** @hide */ diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 904bd1682f9a..c6beee2f898a 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -94,8 +94,6 @@ interface IPackageManager { @UnsupportedAppUsage ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId); - boolean shouldShowRequestPermissionRationale(String permName, - String packageName, int userId); boolean isProtectedBroadcast(String actionName); @@ -594,18 +592,12 @@ interface IPackageManager { ParceledListSlice getIntentFilterVerifications(String packageName); ParceledListSlice getAllIntentFilters(String packageName); - boolean setDefaultBrowserPackageName(String packageName, int userId); - String getDefaultBrowserPackageName(int userId); - VerifierDeviceIdentity getVerifierDeviceIdentity(); boolean isFirstBoot(); boolean isOnlyCoreApps(); boolean isDeviceUpgrading(); - void setPermissionEnforced(String permission, boolean enforced); - boolean isPermissionEnforced(String permission); - /** Reflects current DeviceStorageMonitorService state */ @UnsupportedAppUsage boolean isStorageLow(); @@ -629,17 +621,6 @@ interface IPackageManager { boolean isPackageSignedByKeySet(String packageName, in KeySet ks); boolean isPackageSignedByKeySetExactly(String packageName, in KeySet ks); - void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId); - void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId); - void grantDefaultPermissionsToEnabledTelephonyDataServices( - in String[] packageNames, int userId); - void revokeDefaultPermissionsFromDisabledTelephonyDataServices( - in String[] packageNames, int userId); - void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId); - void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId); - - boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId); - @UnsupportedAppUsage String getPermissionControllerPackageName(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b845a37b0342..4d8a0c46508e 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3571,7 +3571,7 @@ public abstract class PackageManager { /** * Retrieve all of the information we know about a particular permission. * - * @param permissionName The fully qualified name (i.e. com.google.permission.LOGIN) + * @param permName The fully qualified name (i.e. com.google.permission.LOGIN) * of the permission you are interested in. * @param flags Additional option flags to modify the data returned. * @return Returns a {@link PermissionInfo} containing information about the @@ -3579,7 +3579,7 @@ public abstract class PackageManager { * @throws NameNotFoundException if a package with the given name cannot be * found on the system. */ - public abstract PermissionInfo getPermissionInfo(@NonNull String permissionName, + public abstract PermissionInfo getPermissionInfo(@NonNull String permName, @PermissionInfoFlags int flags) throws NameNotFoundException; /** @@ -3620,7 +3620,7 @@ public abstract class PackageManager { * Retrieve all of the information we know about a particular group of * permissions. * - * @param permissionName The fully qualified name (i.e. + * @param permName The fully qualified name (i.e. * com.google.permission_group.APPS) of the permission you are * interested in. * @param flags Additional option flags to modify the data returned. @@ -3630,7 +3630,7 @@ public abstract class PackageManager { * found on the system. */ @NonNull - public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String permissionName, + public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String permName, @PermissionGroupInfoFlags int flags) throws NameNotFoundException; /** @@ -3858,7 +3858,7 @@ public abstract class PackageManager { * Check whether a particular package has been granted a particular * permission. * - * @param permissionName The name of the permission you are checking for. + * @param permName The name of the permission you are checking for. * @param packageName The name of the package you are checking against. * * @return If the package has the permission, PERMISSION_GRANTED is @@ -3870,7 +3870,7 @@ public abstract class PackageManager { */ @CheckResult @PermissionResult - public abstract int checkPermission(@NonNull String permissionName, + public abstract int checkPermission(@NonNull String permName, @NonNull String packageName); /** @@ -3880,13 +3880,13 @@ public abstract class PackageManager { * permissions, hence the only way for an app to get such a permission * is by a policy change. * - * @param permissionName The name of the permission you are checking for. + * @param permName The name of the permission you are checking for. * @param packageName The name of the package you are checking against. * * @return Whether the permission is restricted by policy. */ @CheckResult - public abstract boolean isPermissionRevokedByPolicy(@NonNull String permissionName, + public abstract boolean isPermissionRevokedByPolicy(@NonNull String permName, @NonNull String packageName); /** @@ -3949,14 +3949,14 @@ public abstract class PackageManager { * -- you are only allowed to remove permissions that you are allowed * to add. * - * @param permissionName The name of the permission to remove. + * @param permName The name of the permission to remove. * * @throws SecurityException if you are not allowed to remove the * given permission name. * * @see #addPermission(PermissionInfo) */ - public abstract void removePermission(@NonNull String permissionName); + public abstract void removePermission(@NonNull String permName); /** * Permission flags set when granting or revoking a permission. @@ -3998,7 +3998,7 @@ public abstract class PackageManager { * </p> * * @param packageName The package to which to grant the permission. - * @param permissionName The permission name to grant. + * @param permName The permission name to grant. * @param user The user for which to grant the permission. * * @see #revokeRuntimePermission(String, String, android.os.UserHandle) @@ -4009,7 +4009,7 @@ public abstract class PackageManager { @SystemApi @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String packageName, - @NonNull String permissionName, @NonNull UserHandle user); + @NonNull String permName, @NonNull UserHandle user); /** * Revoke a runtime permission that was previously granted by {@link @@ -4025,7 +4025,7 @@ public abstract class PackageManager { * </p> * * @param packageName The package from which to revoke the permission. - * @param permissionName The permission name to revoke. + * @param permName The permission name to revoke. * @param user The user for which to revoke the permission. * * @see #grantRuntimePermission(String, String, android.os.UserHandle) @@ -4036,12 +4036,12 @@ public abstract class PackageManager { @SystemApi @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String packageName, - @NonNull String permissionName, @NonNull UserHandle user); + @NonNull String permName, @NonNull UserHandle user); /** * Gets the state flags associated with a permission. * - * @param permissionName The permission for which to get the flags. + * @param permName The permission for which to get the flags. * @param packageName The package name for which to get the flags. * @param user The user for which to get permission flags. * @return The permission flags. @@ -4056,14 +4056,14 @@ public abstract class PackageManager { android.Manifest.permission.GET_RUNTIME_PERMISSIONS }) @PermissionFlags - public abstract int getPermissionFlags(@NonNull String permissionName, + public abstract int getPermissionFlags(@NonNull String permName, @NonNull String packageName, @NonNull UserHandle user); /** * Updates the flags associated with a permission by replacing the flags in * the specified mask with the provided flag values. * - * @param permissionName The permission for which to update the flags. + * @param permName The permission for which to update the flags. * @param packageName The package name for which to update the flags. * @param flagMask The flags which to replace. * @param flagValues The flags with which to replace. @@ -4077,7 +4077,7 @@ public abstract class PackageManager { android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS }) - public abstract void updatePermissionFlags(@NonNull String permissionName, + public abstract void updatePermissionFlags(@NonNull String permName, @NonNull String packageName, @PermissionFlags int flagMask, @PermissionFlags int flagValues, @NonNull UserHandle user); @@ -4164,7 +4164,7 @@ public abstract class PackageManager { * provided ones. * * @param packageName The app for which to get whitelisted permissions. - * @param permission The whitelisted permission to add. + * @param permName The whitelisted permission to add. * @param whitelistFlags The whitelists to which to add. Passing multiple flags * updates all specified whitelists. * @return Whether the permission was added to the whitelist. @@ -4180,7 +4180,7 @@ public abstract class PackageManager { @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, conditional = true) public boolean addWhitelistedRestrictedPermission(@NonNull String packageName, - @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) { + @NonNull String permName, @PermissionWhitelistFlags int whitelistFlags) { return false; } @@ -4218,7 +4218,7 @@ public abstract class PackageManager { * provided ones. * * @param packageName The app for which to get whitelisted permissions. - * @param permission The whitelisted permission to remove. + * @param permName The whitelisted permission to remove. * @param whitelistFlags The whitelists from which to remove. Passing multiple flags * updates all specified whitelists. * @return Whether the permission was removed from the whitelist. @@ -4234,7 +4234,7 @@ public abstract class PackageManager { @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, conditional = true) public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName, - @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) { + @NonNull String permName, @PermissionWhitelistFlags int whitelistFlags) { return false; } @@ -4244,13 +4244,13 @@ public abstract class PackageManager { * which the permission is requested does not clearly communicate to the user * what would be the benefit from grating this permission. * - * @param permissionName A permission your app wants to request. + * @param permName A permission your app wants to request. * @return Whether you can show permission rationale UI. * * @hide */ @UnsupportedAppUsage - public abstract boolean shouldShowRequestPermissionRationale(@NonNull String permissionName); + public abstract boolean shouldShowRequestPermissionRationale(@NonNull String permName); /** * Returns an {@link android.content.Intent} suitable for passing to diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index e21d4c41811c..2f198acde06d 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -84,139 +84,6 @@ public abstract class PackageManagerInternal { } /** - * Provider for package names. - */ - public interface PackagesProvider { - - /** - * Gets the packages for a given user. - * @param userId The user id. - * @return The package names. - */ - public String[] getPackages(int userId); - } - - /** - * Provider for package names. - */ - public interface SyncAdapterPackagesProvider { - - /** - * Gets the sync adapter packages for given authority and user. - * @param authority The authority. - * @param userId The user id. - * @return The package names. - */ - public String[] getPackages(String authority, int userId); - } - - /** - * Provider for default browser - */ - public interface DefaultBrowserProvider { - - /** - * Get the package name of the default browser. - * - * @param userId the user id - * - * @return the package name of the default browser, or {@code null} if none - */ - @Nullable - String getDefaultBrowser(@UserIdInt int userId); - - /** - * Set the package name of the default browser. - * - * @param packageName package name of the default browser, or {@code null} to remove - * @param userId the user id - * - * @return whether the default browser was successfully set. - */ - boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId); - - /** - * Set the package name of the default browser asynchronously. - * - * @param packageName package name of the default browser, or {@code null} to remove - * @param userId the user id - */ - void setDefaultBrowserAsync(@Nullable String packageName, @UserIdInt int userId); - } - - /** - * Provider for default dialer - */ - public interface DefaultDialerProvider { - - /** - * Get the package name of the default dialer. - * - * @param userId the user id - * - * @return the package name of the default dialer, or {@code null} if none - */ - @Nullable - String getDefaultDialer(@UserIdInt int userId); - } - - /** - * Provider for default home - */ - public interface DefaultHomeProvider { - - /** - * Get the package name of the default home. - * - * @param userId the user id - * - * @return the package name of the default home, or {@code null} if none - */ - @Nullable - String getDefaultHome(@UserIdInt int userId); - - /** - * Set the package name of the default home. - * - * @param packageName package name of the default home, or {@code null} to remove - * @param userId the user id - * @param callback the callback made after the default home as been updated - */ - void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId, - @NonNull Consumer<Boolean> callback); - } - - /** - * Sets the location provider packages provider. - * @param provider The packages provider. - */ - public abstract void setLocationPackagesProvider(PackagesProvider provider); - - /** - * Set the location extra packages provider. - * @param provider The packages provider. - */ - public abstract void setLocationExtraPackagesProvider(PackagesProvider provider); - - /** - * Sets the voice interaction packages provider. - * @param provider The packages provider. - */ - public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider); - - /** - * Sets the Use Open Wifi packages provider. - * @param provider The packages provider. - */ - public abstract void setUseOpenWifiAppPackagesProvider(PackagesProvider provider); - - /** - * Sets the sync adapter packages provider. - * @param provider The provider. - */ - public abstract void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider); - - /** * Called when the package for the default SMS handler changed * * @param packageName the new sms package @@ -233,14 +100,6 @@ public abstract class PackageManagerInternal { public void onDefaultSimCallManagerAppChanged(String packageName, int userId) {} /** - * Requests granting of the default permissions to the current default Use Open Wifi app. - * @param packageName The default use open wifi package name. - * @param userId The user for which to grant the permissions. - */ - public abstract void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, - int userId); - - /** * Sets a list of apps to keep in PM's internal data structures and as APKs even if no user has * currently installed it. The apps are not preloaded. * @param packageList List of package names to keep cached. @@ -697,7 +556,15 @@ public abstract class PackageManagerInternal { * @see #canAccessInstantApps */ public abstract boolean filterAppAccess( - @Nullable PackageParser.Package pkg, int callingUid, int userId); + @NonNull PackageParser.Package pkg, int callingUid, int userId); + + /** + * Returns whether or not access to the application should be filtered. + * + * @see #filterAppAccess(android.content.pm.PackageParser.Package, int, int) + */ + public abstract boolean filterAppAccess( + @NonNull String packageName, int callingUid, int userId); /** Returns whether the given package was signed by the platform */ public abstract boolean isPlatformSigned(String pkg); @@ -872,27 +739,6 @@ public abstract class PackageManagerInternal { public abstract String removeLegacyDefaultBrowserPackageName(int userId); /** - * Sets the default browser provider. - * - * @param provider the provider - */ - public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider); - - /** - * Sets the default dialer provider. - * - * @param provider the provider - */ - public abstract void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider); - - /** - * Sets the default home provider. - * - * @param provider the provider - */ - public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider); - - /** * Returns {@code true} if given {@code packageName} is an apex package. */ public abstract boolean isApexPackage(String packageName); @@ -910,15 +756,6 @@ public abstract class PackageManagerInternal { IntentSender intentSender); /** - * Whether default permission grants have been performed for a user - * since the device booted. - * - * @param userId The user id. - * @return true if default permissions - */ - public abstract boolean wereDefaultPermissionsGrantedSinceBoot(int userId); - - /** * Get fingerprint of build that updated the runtime permissions for a user. * * @param userId The user to update @@ -960,4 +797,10 @@ public abstract class PackageManagerInternal { */ public abstract boolean isCallerInstallerOfRecord( @NonNull PackageParser.Package pkg, int callingUid); + + /** Returns whether or not default runtime permissions are granted for the given user */ + public abstract boolean areDefaultRuntimePermissionsGranted(@UserIdInt int userId); + + /** Sets the enforcement of reading external storage */ + public abstract void setReadExternalStorageEnforced(boolean enforced); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index a74c34ff4a88..e690a7fd783b 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -254,6 +254,8 @@ public class PackageParser { /** @hide */ public static final String APK_FILE_EXTENSION = ".apk"; + /** @hide */ + public static final String APEX_FILE_EXTENSION = ".apex"; /** @hide */ public static class NewPermissionInfo { @@ -6897,8 +6899,8 @@ public class PackageParser { } /** @hide */ - public boolean isProductServices() { - return applicationInfo.isProductServices(); + public boolean isSystemExt() { + return applicationInfo.isSystemExt(); } /** @hide */ diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index 2b1b32ed3df2..30d87f4a490b 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -19,10 +19,11 @@ package android.content.pm; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; +import com.android.internal.os.RoSystemProperties; + /** * Per-user information. * @hide @@ -232,7 +233,9 @@ public class UserInfo implements Parcelable { if (isManagedProfile() || isGuest() || isRestricted()) { return false; } - if (UserManager.isSplitSystemUser()) { + boolean splitOrHeadlessSystemUser = UserManager.isSplitSystemUser() + || RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER; + if (splitOrHeadlessSystemUser) { return id != UserHandle.USER_SYSTEM; } else { return id == UserHandle.USER_SYSTEM; diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index a99a0b5a7a90..f3b7553577ca 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -32,8 +32,8 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; /** - * CompatibilityInfo class keeps the information about compatibility mode that the application is - * running under. + * CompatibilityInfo class keeps the information about the screen compatibility mode that the + * application is running under. * * {@hide} */ diff --git a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl index d22e7e295b77..62d727c080e3 100644 --- a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl +++ b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl @@ -22,5 +22,5 @@ import android.hardware.biometrics.BiometricSourceType; * @hide */ oneway interface IBiometricEnabledOnKeyguardCallback { - void onChanged(in BiometricSourceType type, boolean enabled); + void onChanged(in BiometricSourceType type, boolean enabled, int userId); }
\ No newline at end of file diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 9f4118e83e47..b3125d89a1a7 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -1191,7 +1191,7 @@ public class Build { ArrayList<Partition> partitions = new ArrayList(); String[] names = new String[] { - "bootimage", "odm", "product", "product_services", Partition.PARTITION_NAME_SYSTEM, + "bootimage", "odm", "product", "system_ext", Partition.PARTITION_NAME_SYSTEM, "vendor" }; for (String name : names) { diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 0ee9a1192a5f..3462d1f56b67 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -54,7 +54,7 @@ public class Environment { private static final String ENV_ODM_ROOT = "ODM_ROOT"; private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT"; private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT"; - private static final String ENV_PRODUCT_SERVICES_ROOT = "PRODUCT_SERVICES_ROOT"; + private static final String ENV_SYSTEM_EXT_ROOT = "SYSTEM_EXT_ROOT"; /** {@hide} */ public static final String DIR_ANDROID = "Android"; @@ -77,8 +77,8 @@ public class Environment { private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm"); private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product"); - private static final File DIR_PRODUCT_SERVICES_ROOT = getDirectory(ENV_PRODUCT_SERVICES_ROOT, - "/product_services"); + private static final File DIR_SYSTEM_EXT_ROOT = getDirectory(ENV_SYSTEM_EXT_ROOT, + "/system_ext"); @UnsupportedAppUsage private static UserEnvironment sCurrentUser; @@ -222,11 +222,26 @@ public class Environment { * Return root directory of the "product_services" partition holding middleware * services if any. If present, the partition is mounted read-only. * + * @deprecated This directory is not guaranteed to exist. + * Its name is changed to "system_ext" because the partition's purpose is changed. + * {@link #getSystemExtDirectory()} * @hide */ @SystemApi + @Deprecated public static @NonNull File getProductServicesDirectory() { - return DIR_PRODUCT_SERVICES_ROOT; + return getDirectory("PRODUCT_SERVICES_ROOT", "/product_services"); + } + + /** + * Return root directory of the "system_ext" partition holding system partition's extension + * If present, the partition is mounted read-only. + * + * @hide + */ + @SystemApi + public static @NonNull File getSystemExtDirectory() { + return DIR_SYSTEM_EXT_ROOT; } /** diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl index d31cee0a1dac..9fa5f1647431 100644 --- a/core/java/android/permission/IPermissionManager.aidl +++ b/core/java/android/permission/IPermissionManager.aidl @@ -70,4 +70,31 @@ interface IPermissionManager { void revokeRuntimePermission(String packageName, String permName, int userId); void resetRuntimePermissions(); + + boolean setDefaultBrowser(String packageName, int userId); + + String getDefaultBrowser(int userId); + + void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId); + + void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId); + + void grantDefaultPermissionsToEnabledTelephonyDataServices( + in String[] packageNames, int userId); + + void revokeDefaultPermissionsFromDisabledTelephonyDataServices( + in String[] packageNames, int userId); + + void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId); + + void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId); + + void setPermissionEnforced(String permName, boolean enforced); + + boolean isPermissionEnforced(String permName); + + boolean shouldShowRequestPermissionRationale(String permName, + String packageName, int userId); + + boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId); } diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java index c65e773283cb..1cd2d62ce55f 100644 --- a/core/java/android/service/autofill/FillEventHistory.java +++ b/core/java/android/service/autofill/FillEventHistory.java @@ -224,13 +224,21 @@ public final class FillEventHistory implements Parcelable { */ public static final int TYPE_CONTEXT_COMMITTED = 4; + /** + * A dataset selector was shown. + * + * <p>This event is fired whenever the autofill UI was presented to the user.</p> + */ + public static final int TYPE_DATASETS_SHOWN = 5; + /** @hide */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_DATASET_SELECTED, TYPE_DATASET_AUTHENTICATION_SELECTED, TYPE_AUTHENTICATION_SELECTED, TYPE_SAVE_SHOWN, - TYPE_CONTEXT_COMMITTED + TYPE_CONTEXT_COMMITTED, + TYPE_DATASETS_SHOWN }) @Retention(RetentionPolicy.SOURCE) @interface EventIds{} @@ -473,7 +481,7 @@ public final class FillEventHistory implements Parcelable { @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds, @Nullable AutofillId[] detectedFieldIds, @Nullable FieldClassification[] detectedFieldClassifications) { - mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_CONTEXT_COMMITTED, + mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN, "eventType"); mDatasetId = datasetId; mClientState = clientState; diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 4bfd1387bef4..f73f28a943c3 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -308,7 +308,7 @@ interface IWindowSession { /** * Called when the system gesture exclusion has changed. */ - void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects); + oneway void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects); /** * Request the server to call setInputWindowInfo on a given Surface, and return diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java index abf5e3f47e45..57dfc62b4f8f 100644 --- a/core/java/android/view/WindowInfo.java +++ b/core/java/android/view/WindowInfo.java @@ -16,7 +16,7 @@ package android.view; -import android.graphics.Rect; +import android.graphics.Region; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -44,7 +44,7 @@ public class WindowInfo implements Parcelable { public IBinder parentToken; public IBinder activityToken; public boolean focused; - public final Rect boundsInScreen = new Rect(); + public Region regionInScreen = new Region(); public List<IBinder> childTokens; public CharSequence title; public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID; @@ -73,7 +73,7 @@ public class WindowInfo implements Parcelable { window.parentToken = other.parentToken; window.activityToken = other.activityToken; window.focused = other.focused; - window.boundsInScreen.set(other.boundsInScreen); + window.regionInScreen.set(other.regionInScreen); window.title = other.title; window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor; window.inPictureInPicture = other.inPictureInPicture; @@ -109,7 +109,7 @@ public class WindowInfo implements Parcelable { parcel.writeStrongBinder(parentToken); parcel.writeStrongBinder(activityToken); parcel.writeInt(focused ? 1 : 0); - boundsInScreen.writeToParcel(parcel, flags); + regionInScreen.writeToParcel(parcel, flags); parcel.writeCharSequence(title); parcel.writeLong(accessibilityIdOfAnchor); parcel.writeInt(inPictureInPicture ? 1 : 0); @@ -132,7 +132,8 @@ public class WindowInfo implements Parcelable { builder.append(", type=").append(type); builder.append(", layer=").append(layer); builder.append(", token=").append(token); - builder.append(", bounds=").append(boundsInScreen); + builder.append(", region=").append(regionInScreen); + builder.append(", bounds=").append(regionInScreen.getBounds()); builder.append(", parent=").append(parentToken); builder.append(", focused=").append(focused); builder.append(", children=").append(childTokens); @@ -151,7 +152,7 @@ public class WindowInfo implements Parcelable { parentToken = parcel.readStrongBinder(); activityToken = parcel.readStrongBinder(); focused = (parcel.readInt() == 1); - boundsInScreen.readFromParcel(parcel); + regionInScreen = Region.CREATOR.createFromParcel(parcel); title = parcel.readCharSequence(); accessibilityIdOfAnchor = parcel.readLong(); inPictureInPicture = (parcel.readInt() == 1); @@ -174,7 +175,7 @@ public class WindowInfo implements Parcelable { parentToken = null; activityToken = null; focused = false; - boundsInScreen.setEmpty(); + regionInScreen.setEmpty(); if (childTokens != null) { childTokens.clear(); } diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index 985effbb9423..fd09a87aaa70 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -622,6 +622,10 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par /** * Change type for {@link #TYPE_WINDOWS_CHANGED} event: * The window's bounds changed. + * <p> + * Starting in {@link android.os.Build.VERSION_CODES#R R}, this event implies the window's + * region changed. It's also possible that region changed but bounds doesn't. + * </p> */ public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008; diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java index ea61ef86c1b1..6a3af3478449 100644 --- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java +++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java @@ -16,9 +16,11 @@ package android.view.accessibility; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.graphics.Rect; +import android.graphics.Region; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -107,7 +109,7 @@ public final class AccessibilityWindowInfo implements Parcelable { private int mBooleanProperties; private int mId = UNDEFINED_WINDOW_ID; private int mParentId = UNDEFINED_WINDOW_ID; - private final Rect mBoundsInScreen = new Rect(); + private Region mRegionInScreen = new Region(); private LongArray mChildIds; private CharSequence mTitle; private long mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID; @@ -305,23 +307,33 @@ public final class AccessibilityWindowInfo implements Parcelable { } /** - * Gets the bounds of this window in the screen. + * Gets the touchable region of this window in the screen. * - * @param outBounds The out window bounds. + * @param outRegion The out window region. */ - public void getBoundsInScreen(Rect outBounds) { - outBounds.set(mBoundsInScreen); + public void getRegionInScreen(@NonNull Region outRegion) { + outRegion.set(mRegionInScreen); } /** - * Sets the bounds of this window in the screen. + * Sets the touchable region of this window in the screen. * - * @param bounds The out window bounds. + * @param region The window region. * * @hide */ - public void setBoundsInScreen(Rect bounds) { - mBoundsInScreen.set(bounds); + public void setRegionInScreen(Region region) { + mRegionInScreen.set(region); + } + + /** + * Gets the bounds of this window in the screen. This is equivalent to get the bounds of the + * Region from {@link #getRegionInScreen(Region)}. + * + * @param outBounds The out window bounds. + */ + public void getBoundsInScreen(Rect outBounds) { + outBounds.set(mRegionInScreen.getBounds()); } /** @@ -522,7 +534,7 @@ public final class AccessibilityWindowInfo implements Parcelable { parcel.writeInt(mBooleanProperties); parcel.writeInt(mId); parcel.writeInt(mParentId); - mBoundsInScreen.writeToParcel(parcel, flags); + mRegionInScreen.writeToParcel(parcel, flags); parcel.writeCharSequence(mTitle); parcel.writeLong(mAnchorId); @@ -552,7 +564,7 @@ public final class AccessibilityWindowInfo implements Parcelable { mBooleanProperties = other.mBooleanProperties; mId = other.mId; mParentId = other.mParentId; - mBoundsInScreen.set(other.mBoundsInScreen); + mRegionInScreen.set(other.mRegionInScreen); mTitle = other.mTitle; mAnchorId = other.mAnchorId; @@ -574,7 +586,7 @@ public final class AccessibilityWindowInfo implements Parcelable { mBooleanProperties = parcel.readInt(); mId = parcel.readInt(); mParentId = parcel.readInt(); - mBoundsInScreen.readFromParcel(parcel); + mRegionInScreen = Region.CREATOR.createFromParcel(parcel); mTitle = parcel.readCharSequence(); mAnchorId = parcel.readLong(); @@ -621,7 +633,8 @@ public final class AccessibilityWindowInfo implements Parcelable { builder.append(", id=").append(mId); builder.append(", type=").append(typeToString(mType)); builder.append(", layer=").append(mLayer); - builder.append(", bounds=").append(mBoundsInScreen); + builder.append(", region=").append(mRegionInScreen); + builder.append(", bounds=").append(mRegionInScreen.getBounds()); builder.append(", focused=").append(isFocused()); builder.append(", active=").append(isActive()); builder.append(", pictureInPicture=").append(isInPictureInPictureMode()); @@ -661,7 +674,7 @@ public final class AccessibilityWindowInfo implements Parcelable { mBooleanProperties = 0; mId = UNDEFINED_WINDOW_ID; mParentId = UNDEFINED_WINDOW_ID; - mBoundsInScreen.setEmpty(); + mRegionInScreen.setEmpty(); mChildIds = null; mConnectionId = UNDEFINED_WINDOW_ID; mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID; @@ -716,7 +729,6 @@ public final class AccessibilityWindowInfo implements Parcelable { } } - /** * Reports how this window differs from a possibly different state of the same window. The * argument must have the same id and type as neither of those properties may change. @@ -739,8 +751,7 @@ public final class AccessibilityWindowInfo implements Parcelable { if (!TextUtils.equals(mTitle, other.mTitle)) { changes |= AccessibilityEvent.WINDOWS_CHANGE_TITLE; } - - if (!mBoundsInScreen.equals(other.mBoundsInScreen)) { + if (!mRegionInScreen.equals(other.mRegionInScreen)) { changes |= AccessibilityEvent.WINDOWS_CHANGE_BOUNDS; } if (mLayer != other.mLayer) { diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/core/java/android/view/inputmethod/InputMethodSystemProperty.java index 0689806bf832..e20c2fdc8074 100644 --- a/core/java/android/view/inputmethod/InputMethodSystemProperty.java +++ b/core/java/android/view/inputmethod/InputMethodSystemProperty.java @@ -17,7 +17,6 @@ package android.view.inputmethod; import android.annotation.Nullable; -import android.annotation.TestApi; import android.content.ComponentName; import android.os.Build; import android.os.SystemProperties; @@ -27,7 +26,6 @@ import android.os.SystemProperties; * * @hide */ -@TestApi public class InputMethodSystemProperty { /** * System property key for the production use. The value must be either empty or a valid @@ -78,6 +76,5 @@ public class InputMethodSystemProperty { * * @hide */ - @TestApi public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null); } diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java index 8136cfc09733..d6862f0188ce 100644 --- a/core/java/com/android/internal/infra/ServiceConnector.java +++ b/core/java/com/android/internal/infra/ServiceConnector.java @@ -228,7 +228,7 @@ public interface ServiceConnector<I extends IInterface> { private final int mUserId; private final @Nullable Function<IBinder, I> mBinderAsInterface; - private I mService = null; + private volatile I mService = null; private boolean mBinding = false; private boolean mUnbinding = false; @@ -506,11 +506,12 @@ public interface ServiceConnector<I extends IInterface> { void unbindJobThread() { cancelTimeout(); - boolean wasBound = isBound(); + I service = mService; + boolean wasBound = service != null; if (wasBound) { - onServiceConnectionStatusChanged(mService, false); + onServiceConnectionStatusChanged(service, false); mContext.unbindService(mServiceConnection); - mService.asBinder().unlinkToDeath(this, 0); + service.asBinder().unlinkToDeath(this, 0); mService = null; } mBinding = false; @@ -543,7 +544,7 @@ public interface ServiceConnector<I extends IInterface> { } @Override - public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) { + public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder binder) { if (mUnbinding) { Log.i(LOG_TAG, "Ignoring onServiceConnected due to ongoing unbinding: " + this); return; @@ -551,14 +552,15 @@ public interface ServiceConnector<I extends IInterface> { if (DEBUG) { logTrace(); } - mService = binderAsInterface(service); + I service = binderAsInterface(binder); + mService = service; mBinding = false; try { - service.linkToDeath(ServiceConnector.Impl.this, 0); + binder.linkToDeath(ServiceConnector.Impl.this, 0); } catch (RemoteException e) { Log.e(LOG_TAG, "onServiceConnected " + name + ": ", e); } - onServiceConnectionStatusChanged(mService, true); + onServiceConnectionStatusChanged(service, true); processQueue(); } @@ -568,8 +570,11 @@ public interface ServiceConnector<I extends IInterface> { logTrace(); } mBinding = true; - onServiceConnectionStatusChanged(mService, false); - mService = null; + I service = mService; + if (service != null) { + onServiceConnectionStatusChanged(service, false); + mService = null; + } } @Override diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index fe66cf9aab7d..480ff4d528f0 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -983,14 +983,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind @Override public void setBackgroundDrawable(Drawable background) { - - // TODO: This should route through setWindowBackground, but late in the release to make this - // change. - if (mOriginalBackgroundDrawable != background) { - mOriginalBackgroundDrawable = background; - updateBackgroundDrawable(); - drawableChanged(); - } + setWindowBackground(background); } public void setWindowFrame(Drawable drawable) { diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index 9fc79cb606e6..364278d1a09e 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -194,9 +194,8 @@ public class SystemConfig { final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>(); final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>(); - final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppPermissions = new ArrayMap<>(); - final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppDenyPermissions = - new ArrayMap<>(); + final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>(); + final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>(); final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>(); @@ -321,12 +320,20 @@ public class SystemConfig { return mProductPrivAppDenyPermissions.get(packageName); } - public ArraySet<String> getProductServicesPrivAppPermissions(String packageName) { - return mProductServicesPrivAppPermissions.get(packageName); + /** + * Read from "permission" tags in /system_ext/etc/permissions/*.xml + * @return Set of privileged permissions that are explicitly granted. + */ + public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) { + return mSystemExtPrivAppPermissions.get(packageName); } - public ArraySet<String> getProductServicesPrivAppDenyPermissions(String packageName) { - return mProductServicesPrivAppDenyPermissions.get(packageName); + /** + * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml + * @return Set of privileged permissions that are explicitly denied. + */ + public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) { + return mSystemExtPrivAppDenyPermissions.get(packageName); } public Map<String, Boolean> getOemPermissions(String packageName) { @@ -398,11 +405,11 @@ public class SystemConfig { readPermissions(Environment.buildPath( Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL); - // Allow /product_services to customize all system configs + // Allow /system_ext to customize all system configs readPermissions(Environment.buildPath( - Environment.getProductServicesDirectory(), "etc", "sysconfig"), ALLOW_ALL); + Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL); readPermissions(Environment.buildPath( - Environment.getProductServicesDirectory(), "etc", "permissions"), ALLOW_ALL); + Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL); } void readPermissions(File libraryDir, int permissionFlag) { @@ -848,7 +855,7 @@ public class SystemConfig { } break; case "privapp-permissions": { if (allowPrivappPermissions) { - // privapp permissions from system, vendor, product and product_services + // privapp permissions from system, vendor, product and system_ext // partitions are stored separately. This is to prevent xml files in // the vendor partition from granting permissions to priv apps in the // system partition and vice versa. @@ -858,17 +865,17 @@ public class SystemConfig { Environment.getOdmDirectory().toPath() + "/"); boolean product = permFile.toPath().startsWith( Environment.getProductDirectory().toPath() + "/"); - boolean productServices = permFile.toPath().startsWith( - Environment.getProductServicesDirectory().toPath() + "/"); + boolean systemExt = permFile.toPath().startsWith( + Environment.getSystemExtDirectory().toPath() + "/"); if (vendor) { readPrivAppPermissions(parser, mVendorPrivAppPermissions, mVendorPrivAppDenyPermissions); } else if (product) { readPrivAppPermissions(parser, mProductPrivAppPermissions, mProductPrivAppDenyPermissions); - } else if (productServices) { - readPrivAppPermissions(parser, mProductServicesPrivAppPermissions, - mProductServicesPrivAppDenyPermissions); + } else if (systemExt) { + readPrivAppPermissions(parser, mSystemExtPrivAppPermissions, + mSystemExtPrivAppDenyPermissions); } else { readPrivAppPermissions(parser, mPrivAppPermissions, mPrivAppDenyPermissions); diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h index 6934d26cdc78..06e31a1518ca 100644 --- a/core/jni/android/graphics/Bitmap.h +++ b/core/jni/android/graphics/Bitmap.h @@ -18,8 +18,9 @@ #include <jni.h> #include <android/bitmap.h> -#include <SkBitmap.h> -#include <SkImageInfo.h> + +class SkBitmap; +struct SkImageInfo; namespace android { @@ -34,8 +35,8 @@ enum BitmapCreateFlags { }; jobject createBitmap(JNIEnv* env, Bitmap* bitmap, - int bitmapCreateFlags, jbyteArray ninePatchChunk = NULL, - jobject ninePatchInsets = NULL, int density = -1); + int bitmapCreateFlags, jbyteArray ninePatchChunk = nullptr, + jobject ninePatchInsets = nullptr, int density = -1); void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap); diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp index 55abc932cff2..58c5871aba28 100644 --- a/core/jni/android/opengl/util.cpp +++ b/core/jni/android/opengl/util.cpp @@ -16,7 +16,6 @@ #include "jni.h" #include <nativehelper/JNIHelp.h> -#include "GraphicsJNI.h" #include <math.h> #include <stdio.h> @@ -33,6 +32,7 @@ #include <SkBitmap.h> #include "core_jni_helpers.h" +#include "android/graphics/Bitmap.h" #undef LOG_TAG #define LOG_TAG "OpenGLUtil" @@ -43,6 +43,10 @@ namespace android { +static void doThrowIAE(JNIEnv* env, const char* msg = nullptr) { + jniThrowException(env, "java/lang/IllegalArgumentException", msg); +} + static inline void mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) { pDest[0] = pM[0 + 4 * 0] * x + pM[0 + 4 * 1] * y + pM[0 + 4 * 2] * z + pM[0 + 4 * 3] * w; @@ -706,7 +710,7 @@ static jint util_getInternalFormat(JNIEnv *env, jclass clazz, jlong bitmapPtr) { SkBitmap nativeBitmap; - bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap); + bitmap::toSkBitmap(bitmapPtr, &nativeBitmap); return getInternalFormat(nativeBitmap.colorType()); } @@ -714,7 +718,7 @@ static jint util_getType(JNIEnv *env, jclass clazz, jlong bitmapPtr) { SkBitmap nativeBitmap; - bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap); + bitmap::toSkBitmap(bitmapPtr, &nativeBitmap); return getType(nativeBitmap.colorType()); } @@ -723,7 +727,7 @@ static jint util_texImage2D(JNIEnv *env, jclass clazz, jlong bitmapPtr, jint type, jint border) { SkBitmap bitmap; - bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); + bitmap::toSkBitmap(bitmapPtr, &bitmap); SkColorType colorType = bitmap.colorType(); if (internalformat < 0) { internalformat = getInternalFormat(colorType); @@ -751,7 +755,7 @@ static jint util_texSubImage2D(JNIEnv *env, jclass clazz, jlong bitmapPtr, jint format, jint type) { SkBitmap bitmap; - bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); + bitmap::toSkBitmap(bitmapPtr, &bitmap); SkColorType colorType = bitmap.colorType(); int internalFormat = getInternalFormat(colorType); if (format < 0) { diff --git a/core/jni/android_app_ActivityThread.cpp b/core/jni/android_app_ActivityThread.cpp index 93f2525eb29d..3a0814875531 100644 --- a/core/jni/android_app_ActivityThread.cpp +++ b/core/jni/android_app_ActivityThread.cpp @@ -15,7 +15,6 @@ */ #include "jni.h" -#include "GraphicsJNI.h" #include <nativehelper/JNIHelp.h> #include <minikin/Layout.h> diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h index aa75dd0c7e32..4aaa0a78c276 100644 --- a/core/jni/android_nio_utils.h +++ b/core/jni/android_nio_utils.h @@ -17,7 +17,7 @@ #ifndef _ANDROID_NIO_UTILS_H_ #define _ANDROID_NIO_UTILS_H_ -#include <android_runtime/AndroidRuntime.h> +#include <nativehelper/JNIHelp.h> namespace android { @@ -68,12 +68,12 @@ private: AutoBufferPointer() = delete; AutoBufferPointer(AutoBufferPointer&) = delete; AutoBufferPointer& operator=(AutoBufferPointer&) = delete; - static void* operator new(std::size_t); - static void* operator new[](std::size_t); - static void* operator new(std::size_t, void*); - static void* operator new[](std::size_t, void*); - static void operator delete(void*, std::size_t); - static void operator delete[](void*, std::size_t); + static void* operator new(size_t); + static void* operator new[](size_t); + static void* operator new(size_t, void*); + static void* operator new[](size_t, void*); + static void operator delete(void*, size_t); + static void operator delete[](void*, size_t); }; } /* namespace android */ diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index d6d939183a0d..bf4ffc7e42e0 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -161,7 +161,7 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) { } // Generic idmap parameters - const char* argv[10]; + const char* argv[11]; int argc = 0; struct stat st; @@ -193,8 +193,8 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) { argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR; } - if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) { - argv[argc++] = AssetManager::PRODUCT_SERVICES_OVERLAY_DIR; + if (stat(AssetManager::SYSTEM_EXT_OVERLAY_DIR, &st) == 0) { + argv[argc++] = AssetManager::SYSTEM_EXT_OVERLAY_DIR; } if (stat(AssetManager::ODM_OVERLAY_DIR, &st) == 0) { @@ -235,8 +235,8 @@ static jobjectArray NativeCreateIdmapsForStaticOverlaysTargetingAndroid(JNIEnv* input_dirs.push_back(AssetManager::PRODUCT_OVERLAY_DIR); } - if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) { - input_dirs.push_back(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR); + if (stat(AssetManager::SYSTEM_EXT_OVERLAY_DIR, &st) == 0) { + input_dirs.push_back(AssetManager::SYSTEM_EXT_OVERLAY_DIR); } if (stat(AssetManager::ODM_OVERLAY_DIR, &st) == 0) { diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index c9eac79ef9b6..ca32b0051bf5 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -17,7 +17,6 @@ #define LOG_TAG "OpenGLRenderer" #include "jni.h" -#include "GraphicsJNI.h" #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 78dd1aa85ae0..a5792293e4bd 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -21,10 +21,10 @@ #include "android_util_Binder.h" #include "android_hardware_input_InputWindowHandle.h" #include "android/graphics/Bitmap.h" -#include "android/graphics/GraphicsJNI.h" #include "android/graphics/Region.h" #include "core_jni_helpers.h" +#include <android_runtime/AndroidRuntime.h> #include <android-base/chrono_utils.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedUtfChars.h> @@ -50,6 +50,14 @@ namespace android { +static void doThrowNPE(JNIEnv* env) { + jniThrowNullPointerException(env, NULL); +} + +static void doThrowIAE(JNIEnv* env, const char* msg = nullptr) { + jniThrowException(env, "java/lang/IllegalArgumentException", msg); +} + static const char* const OutOfResourcesException = "android/view/Surface$OutOfResourcesException"; diff --git a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp index d20bae232656..d629d63cd2c4 100644 --- a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp +++ b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#include "jni.h" #include <nativehelper/JNIHelp.h> +#include <utils/LightRefBase.h> #include "core_jni_helpers.h" namespace android { diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp index 940ac22193b3..5aea8485d0c1 100644 --- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp @@ -30,10 +30,6 @@ #include <gui/GLConsumer.h> #include <gui/Surface.h> -#include <GraphicsJNI.h> -#include <SkBitmap.h> -#include <SkPixelRef.h> - #include <ui/ANativeObjectBase.h> namespace android { diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp index e5d6393530e4..ea4b25267512 100644 --- a/core/jni/fd_utils.cpp +++ b/core/jni/fd_utils.cpp @@ -100,8 +100,8 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/"; static const char* kSystemProductOverlayDir = "/system/product/overlay/"; static const char* kProductOverlayDir = "/product/overlay"; - static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/"; - static const char* kProductServicesOverlayDir = "/product_services/overlay"; + static const char* kSystemSystemExtOverlayDir = "/system/system_ext/overlay/"; + static const char* kSystemExtOverlayDir = "/system_ext/overlay"; static const char* kSystemOdmOverlayDir = "/system/odm/overlay"; static const char* kOdmOverlayDir = "/odm/overlay"; static const char* kSystemOemOverlayDir = "/system/oem/overlay"; @@ -113,8 +113,8 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { || android::base::StartsWith(path, kVendorOverlayDir) || android::base::StartsWith(path, kSystemProductOverlayDir) || android::base::StartsWith(path, kProductOverlayDir) - || android::base::StartsWith(path, kSystemProductServicesOverlayDir) - || android::base::StartsWith(path, kProductServicesOverlayDir) + || android::base::StartsWith(path, kSystemSystemExtOverlayDir) + || android::base::StartsWith(path, kSystemExtOverlayDir) || android::base::StartsWith(path, kSystemOdmOverlayDir) || android::base::StartsWith(path, kOdmOverlayDir) || android::base::StartsWith(path, kSystemOemOverlayDir) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ebf5b9306c4a..40acebc40abd 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4981,6 +4981,7 @@ <service android:name="com.android.server.autofill.AutofillCompatAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" + android:visibleToInstantApps="true" android:exported="true"> <meta-data android:name="android.accessibilityservice" diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index bc7e3b7e9058..3b1275354d1f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1115,6 +1115,22 @@ regularly selected color mode will be used if this value is negative. --> <integer name="config_accessibilityColorMode">-1</integer> + <!-- The following two arrays specify which color space to use for display composition when a + certain color mode is active. + Composition color spaces are defined in android.view.Display.COLOR_MODE_xxx, and color + modes are defined in ColorDisplayManager.COLOR_MODE_xxx and + ColorDisplayManager.VENDOR_COLOR_MODE_xxx. + The color space COLOR_MODE_DEFAULT (0) lets the system select the most appropriate + composition color space for currently displayed content. Other values (e.g., + COLOR_MODE_SRGB) override system selection; these other color spaces must be supported by + the device for for display composition. + If a color mode does not have a corresponding color space specified in this array, the + currently set composition color space will not be modified.--> + <integer-array name="config_displayCompositionColorModes"> + </integer-array> + <integer-array name="config_displayCompositionColorSpaces"> + </integer-array> + <!-- Indicate whether to allow the device to suspend when the screen is off due to the proximity sensor. This resource should only be set to true if the sensor HAL correctly handles the proximity sensor as a wake-up source. @@ -4133,8 +4149,27 @@ for higher refresh rates to be automatically used out of the box --> <integer name="config_defaultPeakRefreshRate">60</integer> - <!-- The default brightness threshold that allows to switch to higher refresh rate --> - <integer name="config_brightnessThresholdOfPeakRefreshRate">-1</integer> + <!-- The display uses different gamma curves for different refresh rates. It's hard for panel + vendor to tune the curves to have exact same brightness for different refresh rate. So + flicker could be observed at switch time. The issue is worse at the gamma lower end. + In addition, human eyes are more sensitive to the flicker at darker environment. + To prevent flicker, we only support higher refresh rates if the display brightness is above + a threshold. And the darker environment could have higher threshold. + For example, no higher refresh rate if + display brightness <= disp0 && ambient brightness <= amb0 + || display brightness <= disp1 && ambient brightness <= amb1 --> + <integer-array translatable="false" name="config_brightnessThresholdsOfPeakRefreshRate"> + <!-- + <item>disp0</item> + <item>disp1</item> + --> + </integer-array> + <integer-array translatable="false" name="config_ambientThresholdsOfPeakRefreshRate"> + <!-- + <item>amb0</item> + <item>amb1</item> + --> + </integer-array> <!-- The type of the light sensor to be used by the display framework for things like auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b3b1b9fc01f2..c49092effd9b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3196,6 +3196,8 @@ <java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficientsNative" /> <java-symbol type="array" name="config_availableColorModes" /> <java-symbol type="integer" name="config_accessibilityColorMode" /> + <java-symbol type="array" name="config_displayCompositionColorModes" /> + <java-symbol type="array" name="config_displayCompositionColorSpaces" /> <java-symbol type="bool" name="config_displayWhiteBalanceAvailable" /> <java-symbol type="bool" name="config_displayWhiteBalanceEnabledDefault" /> <java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureMin" /> @@ -3793,7 +3795,8 @@ <!-- For high refresh rate displays --> <java-symbol type="integer" name="config_defaultPeakRefreshRate" /> - <java-symbol type="integer" name="config_brightnessThresholdOfPeakRefreshRate" /> + <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" /> + <java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" /> <!-- For Auto-Brightness --> <java-symbol type="string" name="config_displayLightSensorType" /> diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index d2b18cb0bcb8..51da0c871c4d 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -416,7 +416,8 @@ public class TransactionParcelTests { IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1, boolean b2, boolean b3, Configuration configuration, CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1, - AutofillOptions ao, ContentCaptureOptions co) throws RemoteException { + AutofillOptions ao, ContentCaptureOptions co, long[] disableCompatChanges) + throws RemoteException { } @Override diff --git a/core/tests/coretests/src/android/view/WindowInfoTest.java b/core/tests/coretests/src/android/view/WindowInfoTest.java index 037a0d9a1207..05e8bd8b6cab 100644 --- a/core/tests/coretests/src/android/view/WindowInfoTest.java +++ b/core/tests/coretests/src/android/view/WindowInfoTest.java @@ -91,7 +91,7 @@ public class WindowInfoTest { assertFalse(w.focused); assertFalse(w.inPictureInPicture); assertFalse(w.hasFlagWatchOutsideTouch); - assertTrue(w.boundsInScreen.isEmpty()); + assertTrue(w.regionInScreen.isEmpty()); } @SmallTest @@ -114,7 +114,7 @@ public class WindowInfoTest { equality &= w1.childTokens.equals(w2.childTokens); equality &= w1.parentToken == w2.parentToken; equality &= w1.activityToken == w2.activityToken; - equality &= w1.boundsInScreen.equals(w2.boundsInScreen); + equality &= w1.regionInScreen.equals(w2.regionInScreen); return equality; } @@ -132,6 +132,6 @@ public class WindowInfoTest { windowInfo.focused = true; windowInfo.inPictureInPicture = true; windowInfo.hasFlagWatchOutsideTouch = true; - windowInfo.boundsInScreen.set(0, 0, 1080, 1080); + windowInfo.regionInScreen.set(0, 0, 1080, 1080); } } diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java index aadfcbc84f76..abee1da2ed7a 100644 --- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java +++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java @@ -71,7 +71,7 @@ import com.android.internal.R; import com.android.internal.accessibility.AccessibilityShortcutController.FrameworkObjectProvider; import com.android.internal.util.test.FakeSettingsProvider; -import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -136,6 +136,7 @@ public class AccessibilityShortcutControllerTest { mContentResolver = new MockContentResolver(mContext); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); + FakeSettingsProvider.clearSettingsProvider(); when(mContext.getContentResolver()).thenReturn(mContentResolver); when(mAccessibilityManagerService.getInstalledAccessibilityServiceList(anyInt())) @@ -193,8 +194,9 @@ public class AccessibilityShortcutControllerTest { when(mTextToSpeech.getVoice()).thenReturn(mVoice); } - @After - public void tearDown() { + @AfterClass + public static void cleanUpSettingsProvider() { + FakeSettingsProvider.clearSettingsProvider(); } @Test diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java new file mode 100644 index 000000000000..f66717e9066c --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.policy; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.frameworks.coretests.R; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +public class DecorViewTest { + + private Context mContext; + private DecorView mDecorView; + + @Before + public void setUp() { + mContext = InstrumentationRegistry.getInstrumentation().getContext(); + PhoneWindow phoneWindow = new PhoneWindow(mContext); + mDecorView = (DecorView) phoneWindow.getDecorView(); + } + + @Test + public void setBackgroundDrawableSameAsSetWindowBackground() { + Drawable bitmapDrawable = mContext.getResources() + .getDrawable(R.drawable.test16x12, mContext.getTheme()); + int w = 16; + int h = 12; + Bitmap expectedBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + + mDecorView.setWindowBackground(bitmapDrawable); + Canvas testCanvas = new Canvas(expectedBitmap); + mDecorView.draw(testCanvas); + testCanvas.release(); + + Drawable expectedBackground = mDecorView.getBackground(); + + mDecorView.setBackgroundDrawable(bitmapDrawable); + Bitmap resultBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas resCanvas = new Canvas(resultBitmap); + mDecorView.draw(resCanvas); + resCanvas.release(); + + // Check that the drawable is the same. + assertThat(mDecorView.getBackground()).isEqualTo(expectedBackground); + assertThat(mDecorView.getBackground()).isEqualTo(bitmapDrawable); + + // Check that canvas is the same. + int[] expPixels = new int[w * h]; + int[] resPixels = new int[w * h]; + resultBitmap.getPixels(resPixels, 0, w, 0, 0, w, h); + expectedBitmap.getPixels(expPixels, 0, w, 0, 0, w, h); + assertThat(Arrays.toString(expPixels)).isEqualTo(Arrays.toString(resPixels)); + } +} diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 4755cb866310..f7c83371f79c 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -74,7 +74,7 @@ const char* AssetManager::RESOURCES_FILENAME = "resources.arsc"; const char* AssetManager::IDMAP_BIN = "/system/bin/idmap"; const char* AssetManager::VENDOR_OVERLAY_DIR = "/vendor/overlay"; const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay"; -const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay"; +const char* AssetManager::SYSTEM_EXT_OVERLAY_DIR = "/system_ext/overlay"; const char* AssetManager::ODM_OVERLAY_DIR = "/odm/overlay"; const char* AssetManager::OEM_OVERLAY_DIR = "/oem/overlay"; const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme"; @@ -575,7 +575,7 @@ bool AssetManager::appendPathToResTable(asset_path& ap, bool appAsLib) const { mZipSet.setZipResourceTableAsset(ap.path, ass); } } - + if (nextEntryIdx == 0 && ass != NULL) { // If this is the first resource table in the asset // manager, then we are going to cache it so that we diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h index 66fba26b7289..ce0985b38986 100644 --- a/libs/androidfw/include/androidfw/AssetManager.h +++ b/libs/androidfw/include/androidfw/AssetManager.h @@ -61,7 +61,7 @@ public: static const char* IDMAP_BIN; static const char* VENDOR_OVERLAY_DIR; static const char* PRODUCT_OVERLAY_DIR; - static const char* PRODUCT_SERVICES_OVERLAY_DIR; + static const char* SYSTEM_EXT_OVERLAY_DIR; static const char* ODM_OVERLAY_DIR; static const char* OEM_OVERLAY_DIR; /* diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 7269bcad3d7a..16ec877002f7 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -29,7 +29,6 @@ #include "SkPaint.h" #include "SkPath.h" #include "SkRect.h" -#include "SkTDArray.h" #include "SkTemplates.h" #include <vector> diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index e50428b2ee62..40fbdffaf90a 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -16,6 +16,8 @@ #include "RenderProxy.h" +#include <gui/Surface.h> + #include "DeferredLayerUpdater.h" #include "DisplayList.h" #include "Properties.h" diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index a0f08cbd26f9..c3eb6ede9bf2 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -19,7 +19,6 @@ #include <SkBitmap.h> #include <cutils/compiler.h> -#include <gui/Surface.h> #include <utils/Functor.h> #include "../FrameMetricsObserver.h" @@ -30,6 +29,7 @@ namespace android { class GraphicBuffer; +class Surface; namespace uirenderer { diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h index 5fa860a20916..5717bb3afe5b 100644 --- a/libs/hwui/renderthread/VulkanSurface.h +++ b/libs/hwui/renderthread/VulkanSurface.h @@ -17,6 +17,7 @@ #include <system/graphics.h> #include <system/window.h> +#include <ui/BufferQueueDefs.h> #include <vulkan/vulkan.h> #include <SkRefCnt.h> diff --git a/media/Android.bp b/media/Android.bp index 4f9671f9936b..29064adf8a01 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -33,6 +33,8 @@ java_library { "framework_media_annotation", "android_system_stubs_current", ], + + plugins: ["java_api_finder"], } filegroup { diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java index f13a64c1520b..5dcbb05184fe 100644 --- a/media/java/android/media/MediaRoute2Info.java +++ b/media/java/android/media/MediaRoute2Info.java @@ -23,6 +23,9 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.Objects; /** @@ -53,6 +56,8 @@ public final class MediaRoute2Info implements Parcelable { final String mDescription; @Nullable final String mClientPackageName; + @NonNull + final List<String> mSupportedCategories; @Nullable final Bundle mExtras; @@ -62,6 +67,7 @@ public final class MediaRoute2Info implements Parcelable { mName = builder.mName; mDescription = builder.mDescription; mClientPackageName = builder.mClientPackageName; + mSupportedCategories = builder.mSupportedCategories; mExtras = builder.mExtras; } @@ -71,6 +77,7 @@ public final class MediaRoute2Info implements Parcelable { mName = in.readString(); mDescription = in.readString(); mClientPackageName = in.readString(); + mSupportedCategories = in.createStringArrayList(); mExtras = in.readBundle(); } @@ -103,13 +110,14 @@ public final class MediaRoute2Info implements Parcelable { && Objects.equals(mName, other.mName) && Objects.equals(mDescription, other.mDescription) && Objects.equals(mClientPackageName, other.mClientPackageName) + && Objects.equals(mSupportedCategories, other.mSupportedCategories) //TODO: This will be evaluated as false in most cases. Try not to. && Objects.equals(mExtras, other.mExtras); } @Override public int hashCode() { - return Objects.hash(mId, mName, mDescription); + return Objects.hash(mId, mName, mDescription, mSupportedCategories); } @NonNull @@ -146,11 +154,38 @@ public final class MediaRoute2Info implements Parcelable { return mClientPackageName; } + /** + * Gets the supported categories of the route. + */ + @NonNull + public List<String> getSupportedCategories() { + return mSupportedCategories; + } + @Nullable public Bundle getExtras() { return mExtras; } + //TODO: Move this if we re-define control category / selector things. + /** + * Returns true if the route supports at least one of the specified control categories + * + * @param controlCategories the list of control categories to consider + * @return true if the route supports at least one category + */ + public boolean supportsControlCategory(@NonNull Collection<String> controlCategories) { + Objects.requireNonNull(controlCategories, "control categories must not be null"); + for (String controlCategory : controlCategories) { + for (String supportedCategory : getSupportedCategories()) { + if (TextUtils.equals(controlCategory, supportedCategory)) { + return true; + } + } + } + return false; + } + @Override public int describeContents() { return 0; @@ -163,6 +198,7 @@ public final class MediaRoute2Info implements Parcelable { dest.writeString(mName); dest.writeString(mDescription); dest.writeString(mClientPackageName); + dest.writeStringList(mSupportedCategories); dest.writeBundle(mExtras); } @@ -187,6 +223,7 @@ public final class MediaRoute2Info implements Parcelable { String mName; String mDescription; String mClientPackageName; + List<String> mSupportedCategories; Bundle mExtras; public Builder(@NonNull String id, @NonNull String name) { @@ -198,6 +235,7 @@ public final class MediaRoute2Info implements Parcelable { } setId(id); setName(name); + mSupportedCategories = new ArrayList<>(); } public Builder(@NonNull MediaRoute2Info routeInfo) { @@ -212,6 +250,7 @@ public final class MediaRoute2Info implements Parcelable { setName(routeInfo.mName); mDescription = routeInfo.mDescription; setClientPackageName(routeInfo.mClientPackageName); + setSupportedCategories(routeInfo.mSupportedCategories); if (routeInfo.mExtras != null) { mExtras = new Bundle(routeInfo.mExtras); } @@ -273,6 +312,39 @@ public final class MediaRoute2Info implements Parcelable { } /** + * Sets the supported categories of the route. + */ + @NonNull + public Builder setSupportedCategories(@NonNull Collection<String> categories) { + mSupportedCategories = new ArrayList<>(); + return addSupportedCategories(categories); + } + + /** + * Adds supported categories for the route. + */ + @NonNull + public Builder addSupportedCategories(@NonNull Collection<String> categories) { + Objects.requireNonNull(categories, "categories must not be null"); + for (String category: categories) { + addSupportedCategory(category); + } + return this; + } + + /** + * Add a supported category for the route. + */ + @NonNull + public Builder addSupportedCategory(@NonNull String category) { + if (TextUtils.isEmpty(category)) { + throw new IllegalArgumentException("category must not be null or empty"); + } + mSupportedCategories.add(category); + return this; + } + + /** * Sets a bundle of extras for the route. */ @NonNull diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 5fc37a579d92..85105e069aaa 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -38,6 +38,8 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; @@ -66,6 +68,8 @@ public class MediaRouter2Manager { List<MediaRoute2ProviderInfo> mProviders = Collections.emptyList(); @NonNull List<MediaRoute2Info> mRoutes = Collections.emptyList(); + @NonNull + ConcurrentMap<String, List<String>> mControlCategoryMap = new ConcurrentHashMap<>(); /** * Gets an instance of media router manager that controls media route of other applications. @@ -160,6 +164,8 @@ public class MediaRouter2Manager { return -1; } + //TODO: Use cache not to create array. For now, it's unclear when to purge the cache. + //Do this when we finalize how to set control categories. /** * Gets available routes for an application. * @@ -167,8 +173,17 @@ public class MediaRouter2Manager { */ @NonNull public List<MediaRoute2Info> getAvailableRoutes(@NonNull String packageName) { - //TODO: filter irrelevant routes. - return Collections.unmodifiableList(mRoutes); + List<String> controlCategories = mControlCategoryMap.get(packageName); + if (controlCategories == null) { + return Collections.emptyList(); + } + List<MediaRoute2Info> routes = new ArrayList<>(); + for (MediaRoute2Info route : mRoutes) { + if (route.supportsControlCategory(controlCategories)) { + routes.add(route); + } + } + return routes; } /** @@ -310,11 +325,8 @@ public class MediaRouter2Manager { } } - void notifyControlCategoriesChanged(String packageName, List<String> categories) { - for (CallbackRecord record : mCallbacks) { - record.mExecutor.execute( - () -> record.mCallback.onControlCategoriesChanged(packageName, categories)); - } + void updateControlCategories(String packageName, List<String> categories) { + mControlCategoryMap.put(packageName, categories); } /** @@ -346,15 +358,6 @@ public class MediaRouter2Manager { public void onRouteSelected(@NonNull String packageName, @Nullable MediaRoute2Info route) {} /** - * Called when the control categories of an application is changed. - * - * @param packageName the package name of the app that changed control categories - * @param categories the changed categories - */ - public void onControlCategoriesChanged(@NonNull String packageName, - @NonNull List<String> categories) {} - - /** * Called when the list of routes are changed. * A client may refresh available routes for each application. */ @@ -389,7 +392,7 @@ public class MediaRouter2Manager { @Override public void notifyControlCategoriesChanged(String packageName, List<String> categories) { - mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyControlCategoriesChanged, + mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updateControlCategories, MediaRouter2Manager.this, packageName, categories)); } diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java index 2cdc6a8101d7..1267aa88a939 100644 --- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java +++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java @@ -32,19 +32,35 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService public static final String ROUTE_NAME1 = "Sample Route 1"; public static final String ROUTE_ID2 = "route_id2"; public static final String ROUTE_NAME2 = "Sample Route 2"; + + public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category"; + public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route"; + public static final String ACTION_REMOVE_ROUTE = "com.android.mediarouteprovider.action_remove_route"; + public static final String CATEGORY_SAMPLE = + "com.android.mediarouteprovider.CATEGORY_SAMPLE"; + public static final String CATEGORY_SPECIAL = + "com.android.mediarouteprovider.CATEGORY_SPECIAL"; + Map<String, MediaRoute2Info> mRoutes = new HashMap<>(); private void initializeRoutes() { MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1) + .addSupportedCategory(CATEGORY_SAMPLE) .build(); MediaRoute2Info route2 = new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2) + .addSupportedCategory(CATEGORY_SAMPLE) .build(); - + MediaRoute2Info routeSpecial = + new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_CATEGORY, ROUTE_NAME_SPECIAL_CATEGORY) + .addSupportedCategory(CATEGORY_SAMPLE) + .addSupportedCategory(CATEGORY_SPECIAL) + .build(); mRoutes.put(route1.getId(), route1); mRoutes.put(route2.getId(), route2); + mRoutes.put(routeSpecial.getId(), routeSpecial); } @Override diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java index 03b43e215c25..4282a5bcea01 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java @@ -58,9 +58,18 @@ public class MediaRouterManagerTest { public static final String ROUTE_NAME1 = "Sample Route 1"; public static final String ROUTE_ID2 = "route_id2"; public static final String ROUTE_NAME2 = "Sample Route 2"; + + public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category"; + public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route"; + public static final String ACTION_REMOVE_ROUTE = "com.android.mediarouteprovider.action_remove_route"; + public static final String CATEGORY_SAMPLE = + "com.android.mediarouteprovider.CATEGORY_SAMPLE"; + public static final String CATEGORY_SPECIAL = + "com.android.mediarouteprovider.CATEGORY_SPECIAL"; + private static final int TIMEOUT_MS = 5000; private Context mContext; @@ -69,12 +78,13 @@ public class MediaRouterManagerTest { private Executor mExecutor; private String mPackageName; - private static final List<String> TEST_CONTROL_CATEGORIES = new ArrayList(); - private static final String CONTROL_CATEGORY_1 = "android.media.mediarouter.MEDIA1"; - private static final String CONTROL_CATEGORY_2 = "android.media.mediarouter.MEDIA2"; + private static final List<String> CONTROL_CATEGORIES_ALL = new ArrayList(); + private static final List<String> CONTROL_CATEGORIES_SPECIAL = new ArrayList(); static { - TEST_CONTROL_CATEGORIES.add(CONTROL_CATEGORY_1); - TEST_CONTROL_CATEGORIES.add(CONTROL_CATEGORY_2); + CONTROL_CATEGORIES_ALL.add(CATEGORY_SAMPLE); + CONTROL_CATEGORIES_ALL.add(CATEGORY_SPECIAL); + + CONTROL_CATEGORIES_SPECIAL.add(CATEGORY_SPECIAL); } @Before @@ -125,7 +135,7 @@ public class MediaRouterManagerTest { // (Control requests shouldn't be used in this way.) InstrumentationRegistry.getInstrumentation().runOnMainSync( (Runnable) () -> { - mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback); + mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, mockRouterCallback); mRouter.sendControlRequest( new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2).build(), new Intent(ACTION_REMOVE_ROUTE)); @@ -138,8 +148,11 @@ public class MediaRouterManagerTest { mManager.removeCallback(mockCallback); } + /** + * Tests if we get proper routes for application that has special control category. + */ @Test - public void controlCategoryTest() throws Exception { + public void testControlCategory() throws Exception { MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class); mManager.addCallback(mExecutor, mockCallback); @@ -147,12 +160,19 @@ public class MediaRouterManagerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync( () -> { - mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback); + mRouter.addCallback(CONTROL_CATEGORIES_SPECIAL, + mExecutor, mockRouterCallback); mRouter.removeCallback(mockRouterCallback); } ); - verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce()) - .onControlCategoriesChanged(mPackageName, TEST_CONTROL_CATEGORIES); + verify(mockCallback, timeout(TIMEOUT_MS)) + .onRouteListChanged(argThat(routes -> routes.size() > 0)); + + Map<String, MediaRoute2Info> routes = + createRouteMap(mManager.getAvailableRoutes(mPackageName)); + + Assert.assertEquals(1, routes.size()); + Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY)); mManager.removeCallback(mockCallback); } @@ -164,7 +184,7 @@ public class MediaRouterManagerTest { MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class); InstrumentationRegistry.getInstrumentation().runOnMainSync( () -> { - mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback); + mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, mockRouterCallback); } ); @@ -197,10 +217,10 @@ public class MediaRouterManagerTest { mManager.removeCallback(managerCallback); } - @Test /** * Tests selecting and unselecting routes of a single provider. */ + @Test public void testSingleProviderSelect() { MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class); MediaRouter2.Callback routerCallback = mock(MediaRouter2.Callback.class); @@ -208,7 +228,7 @@ public class MediaRouterManagerTest { mManager.addCallback(mExecutor, managerCallback); InstrumentationRegistry.getInstrumentation().runOnMainSync( () -> { - mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, routerCallback); + mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, routerCallback); } ); verify(managerCallback, timeout(TIMEOUT_MS)) @@ -218,7 +238,8 @@ public class MediaRouterManagerTest { createRouteMap(mManager.getAvailableRoutes(mPackageName)); mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1)); - verify(managerCallback, timeout(TIMEOUT_MS)) + verify(managerCallback, timeout(TIMEOUT_MS) + ) .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID1, routeInfo.getId()) && TextUtils.equals(routeInfo.getClientPackageName(), mPackageName))); diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java index fc5e791ff7c5..c0dcbbcf30d4 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java @@ -70,13 +70,9 @@ public class CarNavigationButton extends com.android.keyguard.AlphaOptimizedImag R.styleable.CarNavigationButton_unselectedAlpha, mUnselectedAlpha); mSelectedIconResourceId = typedArray.getResourceId( R.styleable.CarNavigationButton_selectedIcon, mIconResourceId); + mIconResourceId = typedArray.getResourceId( + R.styleable.CarNavigationButton_icon, 0); typedArray.recycle(); - - // ImageView attrs - TypedArray a = context.obtainStyledAttributes( - attrs, com.android.internal.R.styleable.ImageView); - mIconResourceId = a.getResourceId(com.android.internal.R.styleable.ImageView_src, 0); - a.recycle(); } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index a452baeac5c1..b1f979708615 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -1073,9 +1073,10 @@ public class CarStatusBar extends StatusBar implements // shade is visible to the user. When the notification shade is completely open then // alpha value will be 1. float alpha = (float) height / mNotificationView.getHeight(); - Drawable background = mNotificationView.getBackground(); + Drawable background = mNotificationView.getBackground().mutate(); background.setAlpha((int) (alpha * 255)); + mNotificationView.setBackground(background); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java index 9a41f1d6a2b1..9672fea1cc19 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java @@ -663,7 +663,8 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText()); removeExistingRestrictedSpans(sb); if (disabled) { - final int disabledColor = context.getColor(R.color.disabled_text_color); + final int disabledColor = Utils.getDisabled(context, + textView.getCurrentTextColor()); sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setCompoundDrawables(null, null, getRestrictedPadlock(context), null); diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index d32e85f01962..eb5ca46b0d33 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -218,6 +218,13 @@ public class Utils { return list.getDefaultColor(); } + /** + * This method computes disabled color from normal color + * + * @param context + * @param inputColor normal color. + * @return disabled color. + */ @ColorInt public static int getDisabled(Context context, int inputColor) { return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor); diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/ColorUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/ColorUtil.java new file mode 100644 index 000000000000..c54b471135d1 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/utils/ColorUtil.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.utils; + +import android.content.Context; +import android.content.res.TypedArray; + +/** Utility class for getting color attribute **/ +public class ColorUtil { + + /** + * Returns android:disabledAlpha value in context + */ + public static float getDisabledAlpha(Context context) { + final TypedArray ta = context.obtainStyledAttributes( + new int[]{android.R.attr.disabledAlpha}); + final float alpha = ta.getFloat(0, 0); + ta.recycle(); + return alpha; + } +} diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index 9d398b5b69a1..b11df4890e98 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -16,7 +16,6 @@ package com.android.providers.settings; -import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.backup.BackupAgentHelper; import android.app.backup.BackupDataInput; @@ -41,6 +40,7 @@ import android.util.ArraySet; import android.util.BackupUtils; import android.util.Log; +import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; import java.io.BufferedOutputStream; @@ -586,15 +586,15 @@ public class SettingsBackupAgent extends BackupAgentHelper { final String[] whitelist; Map<String, Validator> validators = null; if (contentUri.equals(Settings.Secure.CONTENT_URI)) { - whitelist = concat(Settings.Secure.SETTINGS_TO_BACKUP, + whitelist = ArrayUtils.concatElements(String.class, Settings.Secure.SETTINGS_TO_BACKUP, Settings.Secure.LEGACY_RESTORE_SETTINGS); validators = Settings.Secure.VALIDATORS; } else if (contentUri.equals(Settings.System.CONTENT_URI)) { - whitelist = concat(Settings.System.SETTINGS_TO_BACKUP, + whitelist = ArrayUtils.concatElements(String.class, Settings.System.SETTINGS_TO_BACKUP, Settings.System.LEGACY_RESTORE_SETTINGS); validators = Settings.System.VALIDATORS; } else if (contentUri.equals(Settings.Global.CONTENT_URI)) { - whitelist = concat(Settings.Global.SETTINGS_TO_BACKUP, + whitelist = ArrayUtils.concatElements(String.class, Settings.Global.SETTINGS_TO_BACKUP, Settings.Global.LEGACY_RESTORE_SETTINGS); validators = Settings.Global.VALIDATORS; } else { @@ -672,18 +672,6 @@ public class SettingsBackupAgent extends BackupAgentHelper { return (validator != null) && validator.validate(value); } - private final String[] concat(String[] first, @Nullable String[] second) { - if (second == null || second.length == 0) { - return first; - } - final int firstLen = first.length; - final int secondLen = second.length; - String[] both = new String[firstLen + secondLen]; - System.arraycopy(first, 0, both, 0, firstLen); - System.arraycopy(second, 0, both, firstLen, secondLen); - return both; - } - /** * Restores the owner info enabled and other settings in LockSettings. * diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index 28d5402bf707..52ec1f0bb330 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -30,7 +30,7 @@ import java.io.PrintWriter; */ @ProvidesInterface(version = FalsingManager.VERSION) public interface FalsingManager { - int VERSION = 1; + int VERSION = 2; void onSucccessfulUnlock(); @@ -103,4 +103,6 @@ public interface FalsingManager { void onTouchEvent(MotionEvent ev, int width, int height); void dump(PrintWriter pw); + + void cleanup(); } diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml index c560d7e8f126..e687cdfac356 100644 --- a/packages/SystemUI/res/layout/biometric_dialog.xml +++ b/packages/SystemUI/res/layout/biometric_dialog.xml @@ -55,7 +55,8 @@ android:id="@+id/left_space" android:layout_weight="1" android:layout_width="0dp" - android:layout_height="match_parent"/> + android:layout_height="match_parent" + android:contentDescription="@string/biometric_dialog_empty_space_description"/> <LinearLayout android:id="@+id/dialog" @@ -177,7 +178,8 @@ android:id="@+id/right_space" android:layout_weight="1" android:layout_width="0dp" - android:layout_height="match_parent" /> + android:layout_height="match_parent" + android:contentDescription="@string/biometric_dialog_empty_space_description"/> </LinearLayout> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 7fc2066c7176..21c2c6b879f8 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -46,6 +46,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" + android:paddingStart="@dimen/keyguard_indication_text_padding" + android:paddingEnd="@dimen/keyguard_indication_text_padding" android:textAppearance="@style/TextAppearance.Keyguard.BottomArea" android:visibility="gone" /> @@ -54,6 +56,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" + android:paddingStart="@dimen/keyguard_indication_text_padding" + android:paddingEnd="@dimen/keyguard_indication_text_padding" android:textAppearance="@style/TextAppearance.Keyguard.BottomArea" android:accessibilityLiveRegion="polite" /> diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml index ced26c95dfd9..49b87f31d3ab 100644 --- a/packages/SystemUI/res/values/attrs_car.xml +++ b/packages/SystemUI/res/values/attrs_car.xml @@ -62,6 +62,8 @@ <attr name="unselectedAlpha" /> <!-- icon to be rendered when in selected state --> <attr name="selectedIcon" /> + <!-- icon to be rendered (drawable) --> + <attr name="icon"/> </declare-styleable> <!-- Custom attributes to configure hvac values --> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 7c2413039ae4..861187fded15 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -154,12 +154,8 @@ <!-- The number of milliseconds before the heads up notification accepts touches. --> <integer name="touch_acceptance_delay">700</integer> - <!-- The number of milliseconds before the ambient notification auto-dismisses. This will - override the default pulse length. --> - <integer name="heads_up_notification_decay_dozing">10000</integer> - <!-- The number of milliseconds to extend ambient pulse by when prompted (e.g. on touch) --> - <integer name="ambient_notification_extension_time">6000</integer> + <integer name="ambient_notification_extension_time">10000</integer> <!-- In multi-window, determines whether the stack where recents lives should grow from the smallest position when being launched. --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index f4970d073741..62089e9a6c19 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -183,6 +183,9 @@ <!-- The padding on the bottom of the notifications on the keyguard --> <dimen name="keyguard_indication_bottom_padding">12sp</dimen> + <!-- The padding at start and end of indication text shown on AOD --> + <dimen name="keyguard_indication_text_padding">16dp</dimen> + <!-- Shadows under the clock, date and other keyguard text fields --> <dimen name="keyguard_shadow_radius">5</dimen> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java index 98a8110209e6..98b7e2484478 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java @@ -38,6 +38,7 @@ public class ThumbnailData { public int windowingMode; public int systemUiVisibility; public float scale; + public long snapshotId; public ThumbnailData() { thumbnail = null; @@ -49,6 +50,7 @@ public class ThumbnailData { isTranslucent = false; windowingMode = WINDOWING_MODE_UNDEFINED; systemUiVisibility = 0; + snapshotId = 0; } public ThumbnailData(TaskSnapshot snapshot) { @@ -61,5 +63,6 @@ public class ThumbnailData { isTranslucent = snapshot.isTranslucent(); windowingMode = snapshot.getWindowingMode(); systemUiVisibility = snapshot.getSystemUiVisibility(); + snapshotId = snapshot.getId(); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 69630c4e90e8..4ad262fee520 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -237,6 +237,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe MIN_DRAG_SIZE, getResources().getDisplayMetrics()) && !mUpdateMonitor.isFaceDetectionRunning()) { mUpdateMonitor.requestFaceAuth(); + mCallback.userActivity(); showMessage(null, null); } } @@ -512,7 +513,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe case SimPuk: // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId); - if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled( + if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled( KeyguardUpdateMonitor.getCurrentUser())) { finish = true; eventSubtype = BOUNCER_DISMISS_SIM; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 2eb93d3a6075..fd618b05f348 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -377,14 +377,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } }; - private boolean mFaceSettingEnabledForUser; + private SparseBooleanArray mFaceSettingEnabledForUser = new SparseBooleanArray(); private BiometricManager mBiometricManager; private IBiometricEnabledOnKeyguardCallback mBiometricEnabledCallback = new IBiometricEnabledOnKeyguardCallback.Stub() { @Override - public void onChanged(BiometricSourceType type, boolean enabled) throws RemoteException { + public void onChanged(BiometricSourceType type, boolean enabled, int userId) + throws RemoteException { if (type == BiometricSourceType.FACE) { - mFaceSettingEnabledForUser = enabled; + mFaceSettingEnabledForUser.put(userId, enabled); updateFaceListeningState(); } } @@ -1711,7 +1712,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant()) && !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer - && !mKeyguardGoingAway && mFaceSettingEnabledForUser && !mLockIconPressed + && !mKeyguardGoingAway && mFaceSettingEnabledForUser.get(user) && !mLockIconPressed && strongAuthAllowsScanning && mIsPrimaryUser && !mSecureCameraLaunched; } @@ -1783,13 +1784,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } /** - * If face hardware is available and user has enrolled. Not considering encryption or - * lockdown state. + * If face hardware is available, user has enrolled and enabled auth via setting. + * Not considering encryption or lock down state. */ public boolean isUnlockWithFacePossible(int userId) { return mFaceManager != null && mFaceManager.isHardwareDetected() && !isFaceDisabled(userId) - && mFaceManager.hasEnrolledTemplates(userId); + && mFaceManager.hasEnrolledTemplates(userId) + && mFaceSettingEnabledForUser.get(userId); } private void stopListeningForFingerprint() { @@ -2657,7 +2659,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { pw.println(" possible=" + isUnlockWithFacePossible(userId)); pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags)); pw.println(" trustManaged=" + getUserTrustIsManaged(userId)); - pw.println(" enabledByUser=" + mFaceSettingEnabledForUser); + pw.println(" enabledByUser=" + mFaceSettingEnabledForUser.get(userId)); pw.println(" mSecureCameraLaunched=" + mSecureCameraLaunched); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java index 0041b0c9a469..ea175edf0be1 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java @@ -239,4 +239,8 @@ public class FalsingManagerFake implements FalsingManager { public void dump(PrintWriter pw) { } + + @Override + public void cleanup() { + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java index 67dfdcac4b22..fba0d5005db4 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java @@ -168,6 +168,7 @@ public class FalsingManagerImpl implements FalsingManager { .append("enabled=").append(isEnabled() ? 1 : 0) .append(" mScreenOn=").append(mScreenOn ? 1 : 0) .append(" mState=").append(StatusBarState.toShortString(mState)) + .append(" mShowingAod=").append(mShowingAod ? 1 : 0) .toString() ); } @@ -550,6 +551,14 @@ public class FalsingManagerImpl implements FalsingManager { pw.println(); } + @Override + public void cleanup() { + mSensorManager.unregisterListener(mSensorEventListener); + mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); + Dependency.get(StatusBarStateController.class).removeCallback(mStatusBarStateListener); + KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mKeyguardUpdateCallback); + } + public Uri reportRejectedTouch() { if (mDataCollector.isEnabled()) { return mDataCollector.reportRejectedTouch(); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index 3cc8ec9afbb2..8210951e1f96 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -65,6 +65,7 @@ public class FalsingManagerProxy implements FalsingManager { public void onPluginConnected(FalsingPlugin plugin, Context context) { FalsingManager pluginFalsingManager = plugin.getFalsingManager(context); if (pluginFalsingManager != null) { + mInternalFalsingManager.cleanup(); mInternalFalsingManager = pluginFalsingManager; } } @@ -290,4 +291,9 @@ public class FalsingManagerProxy implements FalsingManager { public void dump(PrintWriter pw) { mInternalFalsingManager.dump(pw); } + + @Override + public void cleanup() { + mInternalFalsingManager.cleanup(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java index 00f35aa4276c..cee01a4d3048 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java @@ -324,6 +324,11 @@ public class BrightLineFalsingManager implements FalsingManager { public void dump(PrintWriter printWriter) { } + @Override + public void cleanup() { + unregisterSensors(); + } + static void logDebug(String msg) { logDebug(msg, null); } diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java index 0e93f42a3554..d3e8b3d3236e 100644 --- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java +++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java @@ -77,7 +77,7 @@ public class SysuiColorExtractor extends ColorExtractor implements Dumpable, protected void extractWallpaperColors() { super.extractWallpaperColors(); // mTonal is final but this method will be invoked by the base class during its ctor. - if (mTonal == null) { + if (mTonal == null || mNeutralColorsLock == null) { return; } mTonal.applyFallback(mLockColors == null ? mSystemColors : mLockColors, mNeutralColorsLock); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index 537c09ed3199..1bc7e635f9ed 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -30,6 +30,7 @@ import com.android.systemui.R; import com.android.systemui.SystemUIApplication; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.AsyncSensorManager; import com.android.systemui.util.wakelock.DelayedWakeLock; @@ -70,7 +71,7 @@ public class DozeFactory { new DozeScreenState(wrappedService, handler, params, wakeLock), createDozeScreenBrightness(context, wrappedService, sensorManager, host, params, handler), - new DozeWallpaperState(context), + new DozeWallpaperState(context, getBiometricUnlockController(dozeService)), new DozeDockHandler(context, machine, host, config, handler, dockManager), new DozeAuthRemover(dozeService) }); @@ -108,4 +109,10 @@ public class DozeFactory { final SystemUIApplication app = (SystemUIApplication) appCandidate; return app.getComponent(DozeHost.class); } + + public static BiometricUnlockController getBiometricUnlockController(DozeService service) { + Application appCandidate = service.getApplication(); + final SystemUIApplication app = (SystemUIApplication) appCandidate; + return app.getComponent(BiometricUnlockController.class); + } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index 3c9d4a9704a0..ae6dac59b2f5 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -50,9 +50,23 @@ public interface DozeHost { */ void onSlpiTap(float x, float y); + /** + * Artificially dim down the the display by changing scrim opacities. + * @param scrimOpacity opacity from 0 to 1. + */ default void setAodDimmingScrim(float scrimOpacity) {} + + /** + * Sets the actual display brightness. + * @param value from 0 to 255. + */ void setDozeScreenBrightness(int value); + /** + * Makes scrims black and changes animation durations. + */ + default void prepareForGentleWakeUp() {} + void onIgnoreTouchWhilePulsing(boolean ignore); /** diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 5be097c457dc..38ee2fed136d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -82,7 +82,10 @@ public class DozeScreenState implements DozeMachine.Part { boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState); boolean pulseEnding = oldState == DozeMachine.State.DOZE_PULSE_DONE && newState == DozeMachine.State.DOZE_AOD; - if (messagePending || oldState == DozeMachine.State.INITIALIZED || pulseEnding) { + boolean turningOn = (oldState == DozeMachine.State.DOZE_AOD_PAUSED + || oldState == DozeMachine.State.DOZE) && newState == DozeMachine.State.DOZE_AOD; + boolean justInitialized = oldState == DozeMachine.State.INITIALIZED; + if (messagePending || justInitialized || pulseEnding || turningOn) { // During initialization, we hide the navigation bar. That is however only applied after // a traversal; setting the screen state here is immediate however, so it can happen // that the screen turns on again before the navigation bar is hidden. To work around @@ -91,7 +94,7 @@ public class DozeScreenState implements DozeMachine.Part { // Delay screen state transitions even longer while animations are running. boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD - && mParameters.shouldControlScreenOff(); + && mParameters.shouldControlScreenOff() && !turningOn; if (shouldDelayTransition) { mWakeLock.setAcquired(true); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index cf04b7f192e4..6918501bfb9f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -198,7 +198,10 @@ public class DozeSensors { updateListening(); } - private void updateListening() { + /** + * Registers/unregisters sensors based on internal state. + */ + public void updateListening() { boolean anyListening = false; for (TriggerSensor s : mSensors) { // We don't want to be listening while we're PAUSED (prox sensor is covered) @@ -231,7 +234,7 @@ public class DozeSensors { public void onUserSwitched() { for (TriggerSensor s : mSensors) { - s.updateListener(); + s.updateListening(); } } @@ -246,7 +249,7 @@ public class DozeSensors { return; } for (TriggerSensor s : mSensors) { - s.updateListener(); + s.updateListening(); } } }; @@ -409,22 +412,22 @@ public class DozeSensors { public void setListening(boolean listen) { if (mRequested == listen) return; mRequested = listen; - updateListener(); + updateListening(); } public void setDisabled(boolean disabled) { if (mDisabled == disabled) return; mDisabled = disabled; - updateListener(); + updateListening(); } public void ignoreSetting(boolean ignored) { if (mIgnoresSetting == ignored) return; mIgnoresSetting = ignored; - updateListener(); + updateListening(); } - public void updateListener() { + public void updateListening() { if (!mConfigured || mSensor == null) return; if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting) && !mRegistered) { @@ -480,7 +483,7 @@ public class DozeSensors { mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY, event.values); if (!mRegistered) { - updateListener(); // reregister, this sensor only fires once + updateListening(); // reregister, this sensor only fires once } })); } @@ -541,7 +544,7 @@ public class DozeSensors { } @Override - public void updateListener() { + public void updateListening() { if (!mConfigured) return; AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager; if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 97b08d5a12a6..8ef01e8d608e 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -201,7 +201,7 @@ public class DozeTriggers implements DozeMachine.Part { // Let's prepare the display to wake-up by drawing black. // This will cover the hardware wake-up sequence, where the display // becomes black for a few frames. - mDozeHost.setAodDimmingScrim(255f); + mDozeHost.setAodDimmingScrim(1f); } mMachine.wakeUp(); } @@ -314,6 +314,9 @@ public class DozeTriggers implements DozeMachine.Part { break; case DOZE_PULSE_DONE: mDozeSensors.requestTemporaryDisable(); + // A pulse will temporarily disable sensors that require a touch screen. + // Let's make sure that they are re-enabled when the pulse is over. + mDozeSensors.updateListening(); break; case FINISH: mBroadcastReceiver.unregister(mContext); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 51e96d2eecad..e877d4446c63 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -130,6 +130,7 @@ public class DozeUi implements DozeMachine.Part { break; case DOZE: case DOZE_AOD_PAUSED: + mHost.prepareForGentleWakeUp(); unscheduleTimeTick(); break; case DOZE_REQUEST_PULSE: diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java index 1b3cd881b949..35c8b741381c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java @@ -24,6 +24,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; +import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; import java.io.PrintWriter; @@ -38,18 +39,22 @@ public class DozeWallpaperState implements DozeMachine.Part { private final IWallpaperManager mWallpaperManagerService; private final DozeParameters mDozeParameters; + private final BiometricUnlockController mBiometricUnlockController; private boolean mIsAmbientMode; - public DozeWallpaperState(Context context) { + public DozeWallpaperState(Context context, + BiometricUnlockController biometricUnlockController) { this(IWallpaperManager.Stub.asInterface( ServiceManager.getService(Context.WALLPAPER_SERVICE)), + biometricUnlockController, DozeParameters.getInstance(context)); } @VisibleForTesting DozeWallpaperState(IWallpaperManager wallpaperManagerService, - DozeParameters parameters) { + BiometricUnlockController biometricUnlockController, DozeParameters parameters) { mWallpaperManagerService = wallpaperManagerService; + mBiometricUnlockController = biometricUnlockController; mDozeParameters = parameters; } @@ -76,7 +81,9 @@ public class DozeWallpaperState implements DozeMachine.Part { } else { boolean wakingUpFromPulse = oldState == DozeMachine.State.DOZE_PULSING && newState == DozeMachine.State.FINISH; - animated = !mDozeParameters.getDisplayNeedsBlanking() || wakingUpFromPulse; + boolean fastDisplay = !mDozeParameters.getDisplayNeedsBlanking(); + animated = (fastDisplay && !mBiometricUnlockController.unlockedByWakeAndUnlock()) + || wakingUpFromPulse; } if (isAmbientMode != mIsAmbientMode) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java index cc1170f7409b..b444fa50a253 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java @@ -83,6 +83,11 @@ public class SectionHeaderView extends ActivatableNotificationView { bindContents(); } + @Override + public boolean isTransparent() { + return true; + } + /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */ void onUiModeChanged() { updateBackgroundColors(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 01e2b28600db..7655056ea60b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -159,15 +159,13 @@ public class StackScrollAlgorithm { float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding() + ambientState.getStackTranslation() + ambientState.getExpandAnimationTopChange() : 0; - float previousNotificationEnd = 0; - float previousNotificationStart = 0; + float clipStart = 0; int childCount = algorithmState.visibleChildren.size(); for (int i = 0; i < childCount; i++) { ExpandableView child = algorithmState.visibleChildren.get(i); ExpandableViewState state = child.getViewState(); if (!child.mustStayOnScreen() || state.headsUpIsVisible) { - previousNotificationEnd = Math.max(drawStart, previousNotificationEnd); - previousNotificationStart = Math.max(drawStart, previousNotificationStart); + clipStart = Math.max(drawStart, clipStart); } float newYTranslation = state.yTranslation; float newHeight = state.height; @@ -175,10 +173,10 @@ public class StackScrollAlgorithm { boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && ((ExpandableNotificationRow) child).isPinned(); if (mClipNotificationScrollToTop - && !state.inShelf && newYTranslation < previousNotificationEnd - && (!isHeadsUp || ambientState.isShadeExpanded())) { + && (!state.inShelf || isHeadsUp) + && newYTranslation < clipStart) { // The previous view is overlapping on top, clip! - float overlapAmount = previousNotificationEnd - newYTranslation; + float overlapAmount = clipStart - newYTranslation; state.clipTopAmount = (int) overlapAmount; } else { state.clipTopAmount = 0; @@ -187,8 +185,7 @@ public class StackScrollAlgorithm { if (!child.isTransparent()) { // Only update the previous values if we are not transparent, // otherwise we would clip to a transparent view. - previousNotificationEnd = newNotificationEnd; - previousNotificationStart = newYTranslation; + clipStart = Math.max(clipStart, isHeadsUp ? newYTranslation : newNotificationEnd); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index bc7174d33b13..94cd2cdaa9d3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -141,6 +141,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { private BiometricSourceType mPendingAuthenticatedBioSourceType = null; private boolean mPendingShowBouncer; private boolean mHasScreenTurnedOnSinceAuthenticating; + private boolean mFadedAwayAfterWakeAndUnlock; private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); @@ -260,6 +261,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated( biometricSourceType); if (unlockAllowed) { + mKeyguardViewMediator.userActivity(); startWakeAndUnlock(biometricSourceType); } else { Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller"); @@ -367,6 +369,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { @Override public void onStartedGoingToSleep(int why) { resetMode(); + mFadedAwayAfterWakeAndUnlock = false; mPendingAuthenticatedUserId = -1; mPendingAuthenticatedBioSourceType = null; } @@ -466,8 +469,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { } if (mStatusBarKeyguardViewManager.isShowing()) { if (mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing() && unlockingAllowed) { - return bypass && !mKeyguardBypassController.canPlaySubtleWindowAnimations() - ? MODE_UNLOCK_COLLAPSING : MODE_UNLOCK_FADING; + if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) { + return MODE_UNLOCK_FADING; + } else { + return MODE_DISMISS_BOUNCER; + } } else if (unlockingAllowed) { return bypass ? MODE_UNLOCK_FADING : MODE_NONE; } else { @@ -509,6 +515,9 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { } public void finishKeyguardFadingAway() { + if (isWakeAndUnlock()) { + mFadedAwayAfterWakeAndUnlock = true; + } resetMode(); } @@ -559,6 +568,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { } /** + * Successful authentication with fingerprint, face, or iris that wakes up the device. + * This will return {@code true} even after the keyguard fades away. + */ + public boolean unlockedByWakeAndUnlock() { + return isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock; + } + + /** * Successful authentication with fingerprint, face, or iris when the screen was either * on or off. */ @@ -567,6 +584,13 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { } /** + * Successful authentication with fingerprint, face, or iris when the lockscreen fades away + */ + public boolean isUnlockFading() { + return mMode == MODE_UNLOCK_FADING; + } + + /** * Translates biometric source type for logging purpose. */ private int toSubtype(BiometricSourceType biometricSourceType) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index cbaf85c511dd..680e52223178 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -72,8 +72,6 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private NotificationGroupManager mGroupManager; private VisualStabilityManager mVisualStabilityManager; private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; - @VisibleForTesting - int mAutoDismissNotificationDecayDozing; private boolean mReleaseOnExpandFinish; private int mStatusBarHeight; @@ -120,8 +118,6 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, KeyguardBypassController bypassController) { super(context); Resources resources = mContext.getResources(); - mAutoDismissNotificationDecayDozing = resources.getInteger( - R.integer.heads_up_notification_decay_dozing); mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time); mAutoHeadsUpNotificationDecay = resources.getInteger( R.integer.auto_heads_up_notification_decay); @@ -612,9 +608,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, } private int getDecayDuration() { - if (mStatusBarStateController.isDozing()) { - return mAutoDismissNotificationDecayDozing; - } else if (isAutoHeadsUp()) { + if (isAutoHeadsUp()) { return getRecommendedHeadsUpTimeoutMs(mAutoHeadsUpNotificationDecay); } else { return getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index c88b22bbbced..0aec2b12fa92 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -167,4 +167,8 @@ class KeyguardBypassController { pw.print(" qSExpanded: "); pw.println(qSExpanded) pw.print(" bouncerShowing: "); pw.println(bouncerShowing) } + + companion object { + const val BYPASS_PANEL_FADE_DURATION = 67 + } } 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 49afae7415ae..1360a084207b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -102,6 +102,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange private boolean mWakeAndUnlockRunning; private boolean mKeyguardShowing; private boolean mShowingLaunchAffordance; + private boolean mKeyguardJustShown; private boolean mUpdatePending; private final KeyguardMonitor.Callback mKeyguardMonitorCallback = @@ -115,6 +116,9 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange mBlockUpdates = false; force = true; } + if (!wasShowing && mKeyguardShowing) { + mKeyguardJustShown = true; + } update(force); } @@ -273,8 +277,10 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange int state = getState(); int lastState = mLastState; + boolean keyguardJustShown = mKeyguardJustShown; mIsFaceUnlockState = state == STATE_SCANNING_FACE; mLastState = state; + mKeyguardJustShown = false; boolean shouldUpdate = lastState != state || mForceUpdate; if (mBlockUpdates && canBlockUpdates()) { @@ -283,7 +289,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange if (shouldUpdate) { mForceUpdate = false; @LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(lastState, - state, mPulsing, mDozing); + state, mPulsing, mDozing, keyguardJustShown); boolean isAnim = lockAnimIndex != -1; int iconRes = isAnim ? getThemedAnimationResId(lockAnimIndex) : getIconForState(state); @@ -412,7 +418,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange } private static int getAnimationIndexForTransition(int oldState, int newState, boolean pulsing, - boolean dozing) { + boolean dozing, boolean keyguardJustShown) { // Never animate when screen is off if (dozing && !pulsing) { @@ -423,7 +429,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange return ERROR; } else if (oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN) { return UNLOCK; - } else if (oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED) { + } else if (oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED && !keyguardJustShown) { return LOCK; } else if (newState == STATE_SCANNING_FACE) { return SCANNING; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java index 0bbfbefb7883..195870bde25a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java @@ -464,7 +464,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) { return false; } - if (!mHeadsUpManager.isAlerting(entry.key)) { + if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.key)) { return false; } return (sbn.getNotification().fullScreenIntent != null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 3f38c049a977..1aec5e4d0b1d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -487,6 +487,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } /** + * Set front scrim to black, cancelling animations, in order to prepare to fade them + * away once the display turns on. + */ + public void prepareForGentleWakeUp() { + if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) { + mCurrentInFrontAlpha = 1f; + mAnimateChange = false; + updateScrims(); + mAnimateChange = true; + mAnimationDuration = ANIMATION_DURATION_LONG; + } + } + + /** * If the lock screen sensor is active. */ public void setWakeLockScreenSensorActive(boolean active) { @@ -932,6 +946,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } } + public void setUnlockIsFading(boolean unlockFading) { + for (ScrimState state : ScrimState.values()) { + state.setUnlockIsFading(unlockFading); + } + } + public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) { for (ScrimState state : ScrimState.values()) { state.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index d152ecd8b930..763e0d70469b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -147,7 +147,9 @@ public enum ScrimState { public void prepare(ScrimState previousState) { mCurrentBehindAlpha = 0; mCurrentInFrontAlpha = 0; - mAnimationDuration = StatusBar.FADE_KEYGUARD_DURATION; + mAnimationDuration = mUnlockIsFading + ? KeyguardBypassController.BYPASS_PANEL_FADE_DURATION + : StatusBar.FADE_KEYGUARD_DURATION; mAnimateChange = !mLaunchingAffordanceWithPreview; if (previousState == ScrimState.AOD) { @@ -198,6 +200,7 @@ public enum ScrimState { boolean mHasBackdrop; boolean mLaunchingAffordanceWithPreview; boolean mWakeLockScreenSensorActive; + boolean mUnlockIsFading; ScrimState(int index) { mIndex = index; @@ -285,4 +288,8 @@ public enum ScrimState { public void setWakeLockScreenSensorActive(boolean active) { mWakeLockScreenSensorActive = active; } + + public void setUnlockIsFading(boolean unlockIsFading) { + mUnlockIsFading = unlockIsFading; + } }
\ No newline at end of file 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 40ebe583b021..f8e6aa3b844f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1229,6 +1229,7 @@ public class StatusBar extends SystemUI implements DemoMode, mDozeScrimController, keyguardViewMediator, mScrimController, this, UnlockMethodCache.getInstance(mContext), new Handler(), mKeyguardUpdateMonitor, mKeyguardBypassController); + putComponent(BiometricUnlockController.class, mBiometricUnlockController); mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, getBouncerContainer(), mNotificationPanel, mBiometricUnlockController, mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller, @@ -3839,6 +3840,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void notifyBiometricAuthModeChanged() { updateDozing(); + mScrimController.setUnlockIsFading(mBiometricUnlockController.isUnlockFading()); updateScrimController(); mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock(), mBiometricUnlockController.isBiometricUnlock()); @@ -3850,7 +3852,8 @@ public class StatusBar extends SystemUI implements DemoMode, // We don't want to end up in KEYGUARD state when we're unlocking with // fingerprint from doze. We should cross fade directly from black. - boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock(); + boolean unlocking = mBiometricUnlockController.isWakeAndUnlock() + || mKeyguardMonitor.isKeyguardFadingAway(); // Do not animate the scrim expansion when triggered by the fingerprint sensor. mScrimController.setExpansionAffectsAlpha( @@ -3875,9 +3878,9 @@ public class StatusBar extends SystemUI implements DemoMode, } else if (isPulsing()) { mScrimController.transitionTo(ScrimState.PULSING, mDozeScrimController.getScrimCallback()); - } else if (mDozing && !wakeAndUnlocking) { + } else if (mDozing && !unlocking) { mScrimController.transitionTo(ScrimState.AOD); - } else if (mIsKeyguard && !wakeAndUnlocking) { + } else if (mIsKeyguard && !unlocking) { mScrimController.transitionTo(ScrimState.KEYGUARD); } else if (mBubbleController.isStackExpanded()) { mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED); @@ -4118,6 +4121,11 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController.setAodFrontScrimAlpha(scrimOpacity); } + @Override + public void prepareForGentleWakeUp() { + mScrimController.prepareForGentleWakeUp(); + } + private void dispatchTap(View view, float x, float y) { long now = SystemClock.elapsedRealtime(); dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN); 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 65be7089ff08..5ce1329d5a89 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -85,7 +85,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb // make everything a bit slower to bridge a gap until the user is unlocked and home screen has // dranw its first frame. private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000; - private static final long BYPASS_PANEL_FADE_DURATION = 67; private static String TAG = "StatusBarKeyguardViewManager"; @@ -270,7 +269,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb boolean keyguardWithoutQs = mStatusBarStateController.getState() == StatusBarState.KEYGUARD && !mNotificationPanelView.isQsExpanded(); boolean lockVisible = (mBouncer.isShowing() || keyguardWithoutQs) - && !mBouncer.isAnimatingAway(); + && !mBouncer.isAnimatingAway() && !mKeyguardMonitor.isKeyguardFadingAway(); if (mLastLockVisible != lockVisible) { mLastLockVisible = lockVisible; @@ -279,8 +278,14 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb AppearAnimationUtils.DEFAULT_APPEAR_DURATION /* duration */, 0 /* delay */); } else { + final long duration; + if (needsBypassFading()) { + duration = KeyguardBypassController.BYPASS_PANEL_FADE_DURATION; + } else { + duration = AppearAnimationUtils.DEFAULT_APPEAR_DURATION / 2; + } CrossFadeHelper.fadeOut(mLockIconContainer, - AppearAnimationUtils.DEFAULT_APPEAR_DURATION / 2 /* duration */, + duration /* duration */, 0 /* delay */, null /* runnable */); } } @@ -567,7 +572,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (needsBypassFading()) { ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView, mNotificationContainer, - BYPASS_PANEL_FADE_DURATION, + KeyguardBypassController.BYPASS_PANEL_FADE_DURATION, () -> { mStatusBar.hideKeyguard(); onKeyguardFadedAway(); @@ -583,7 +588,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (needsBypassFading()) { ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView, mNotificationContainer, - BYPASS_PANEL_FADE_DURATION, + KeyguardBypassController.BYPASS_PANEL_FADE_DURATION, () -> { mStatusBar.hideKeyguard(); }); @@ -602,6 +607,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mBiometricUnlockController.finishKeyguardFadingAway(); } } + updateLockIcon(); updateStates(); mStatusBarWindowController.setKeyguardShowing(false); mViewMediatorCallback.keyguardGone(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java index f36c56f60965..a71fcdbd9914 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java @@ -107,6 +107,9 @@ public class UnlockMethodCache { mListeners.remove(listener); } + /** + * If there are faces enrolled and user enabled face auth on keyguard. + */ public boolean isUnlockingWithFacePossible() { return mIsUnlockingWithFacePossible; } @@ -119,15 +122,16 @@ public class UnlockMethodCache { || (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked); boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user); boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user); - boolean hasEnrolledFaces = mKeyguardUpdateMonitor.isUnlockWithFacePossible(user); - boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer || - trustManaged != mTrustManaged || mIsUnlockingWithFacePossible != hasEnrolledFaces; + boolean isUnlockingWithFacePossible = mKeyguardUpdateMonitor.isUnlockWithFacePossible(user); + boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer + || trustManaged != mTrustManaged + || mIsUnlockingWithFacePossible != isUnlockingWithFacePossible; if (changed || updateAlways) { mSecure = secure; mCanSkipBouncer = canSkipBouncer; mTrusted = trusted; mTrustManaged = trustManaged; - mIsUnlockingWithFacePossible = hasEnrolledFaces; + mIsUnlockingWithFacePossible = isUnlockingWithFacePossible; notifyListeners(); } Trace.endSection(); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index bdc6341bde91..db6177a63f96 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -103,7 +103,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { when(context.getPackageManager()).thenReturn(mPackageManager); doAnswer(invocation -> { IBiometricEnabledOnKeyguardCallback callback = invocation.getArgument(0); - callback.onChanged(BiometricSourceType.FACE, true /* enabled */); + callback.onChanged(BiometricSourceType.FACE, true /* enabled */, + KeyguardUpdateMonitor.getCurrentUser()); return null; }).when(mBiometricManager).registerEnabledOnKeyguardCallback(any()); when(mFaceManager.isHardwareDetected()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java index 2d6ae2629ce4..2ed0970ce44b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.utils.hardware.FakeSensorManager; import org.mockito.Answers; import org.mockito.MockSettings; @@ -39,6 +40,7 @@ public class DozeConfigurationUtil { when(params.getPickupPerformsProxCheck()).thenReturn(true); when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class)); when(params.doubleTapReportsTouchCoordinates()).thenReturn(false); + when(params.getDisplayNeedsBlanking()).thenReturn(false); doneHolder[0] = true; return params; @@ -52,11 +54,17 @@ public class DozeConfigurationUtil { when(config.pickupGestureEnabled(anyInt())).thenReturn(false); when(config.pulseOnNotificationEnabled(anyInt())).thenReturn(true); when(config.alwaysOnEnabled(anyInt())).thenReturn(false); + when(config.enabled(anyInt())).thenReturn(true); + when(config.getWakeLockScreenDebounce()).thenReturn(0L); when(config.doubleTapSensorType()).thenReturn(null); when(config.tapSensorType()).thenReturn(null); when(config.longPressSensorType()).thenReturn(null); + when(config.tapGestureEnabled(anyInt())).thenReturn(true); + when(config.tapSensorAvailable()).thenReturn(true); + when(config.tapSensorType()).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE); + when(config.dozePickupSensorAvailable()).thenReturn(false); when(config.wakeScreenGestureAvailable()).thenReturn(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 6979fd811817..eb8ef09d0635 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -19,6 +19,7 @@ package com.android.systemui.doze; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -27,18 +28,17 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.AlarmManager; -import android.app.Instrumentation; +import android.hardware.Sensor; import android.hardware.display.AmbientDisplayConfiguration; import android.os.Handler; import android.os.Looper; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; -import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.dock.DockManagerFake; +import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.wakelock.WakeLock; import com.android.systemui.util.wakelock.WakeLockFake; @@ -46,14 +46,12 @@ import com.android.systemui.utils.hardware.FakeSensorManager; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @SmallTest -@Ignore("failing") @RunWith(AndroidTestingRunner.class) -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) public class DozeTriggersTest extends SysuiTestCase { private DozeTriggers mTriggers; private DozeMachine mMachine; @@ -61,10 +59,10 @@ public class DozeTriggersTest extends SysuiTestCase { private AmbientDisplayConfiguration mConfig; private DozeParameters mParameters; private FakeSensorManager mSensors; + private Sensor mTapSensor; private WakeLock mWakeLock; - private Instrumentation mInstrumentation; private AlarmManager mAlarmManager; - private DockManagerFake mDockManagerFake; + private DockManager mDockManagerFake; @BeforeClass public static void setupSuite() { @@ -74,15 +72,15 @@ public class DozeTriggersTest extends SysuiTestCase { @Before public void setUp() throws Exception { - mInstrumentation = InstrumentationRegistry.getInstrumentation(); mMachine = mock(DozeMachine.class); mAlarmManager = mock(AlarmManager.class); - mHost = new DozeHostFake(); + mHost = spy(new DozeHostFake()); mConfig = DozeConfigurationUtil.createMockConfig(); mParameters = DozeConfigurationUtil.createMockParameters(); - mSensors = new FakeSensorManager(mContext); + mSensors = spy(new FakeSensorManager(mContext)); + mTapSensor = mSensors.getFakeTapSensor().getSensor(); mWakeLock = new WakeLockFake(); - mDockManagerFake = spy(new DockManagerFake()); + mDockManagerFake = mock(DockManager.class); mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, mConfig, mParameters, mSensors, Handler.createAsync(Looper.myLooper()), mWakeLock, true, @@ -95,29 +93,45 @@ public class DozeTriggersTest extends SysuiTestCase { mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED); mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE); + clearInvocations(mMachine); mHost.callback.onNotificationAlerted(); - mSensors.getMockProximitySensor().sendProximityResult(false); /* Near */ verify(mMachine, never()).requestState(any()); verify(mMachine, never()).requestPulse(anyInt()); mHost.callback.onNotificationAlerted(); - mSensors.getMockProximitySensor().sendProximityResult(true); /* Far */ verify(mMachine).requestPulse(anyInt()); } @Test + public void testTransitionTo_disablesAndEnablesTouchSensors() { + when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE); + + mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE); + verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor)); + + clearInvocations(mSensors); + mTriggers.transitionTo(DozeMachine.State.DOZE, + DozeMachine.State.DOZE_REQUEST_PULSE); + mTriggers.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE, + DozeMachine.State.DOZE_PULSING); + verify(mSensors).cancelTriggerSensor(any(), eq(mTapSensor)); + + clearInvocations(mSensors); + mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE); + verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor)); + } + + @Test public void testDockEventListener_registerAndUnregister() { mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED); - verify(mDockManagerFake).addListener(any()); mTriggers.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.FINISH); - verify(mDockManagerFake).removeListener(any()); } @@ -128,7 +142,6 @@ public class DozeTriggersTest extends SysuiTestCase { mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP, false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */, null /* rawValues */); - verify(mMachine, never()).wakeUp(); } @@ -142,7 +155,7 @@ public class DozeTriggersTest extends SysuiTestCase { false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */, null /* rawValues */); - verify(mHost).setAodDimmingScrim(eq(255)); + verify(mHost).setAodDimmingScrim(eq(1f)); verify(mMachine).wakeUp(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java index 87ae85f6d302..f07edf331f13 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java @@ -18,6 +18,7 @@ package com.android.systemui.doze; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,6 +30,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; +import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; import org.junit.Before; @@ -44,12 +46,14 @@ public class DozeWallpaperStateTest extends SysuiTestCase { private DozeWallpaperState mDozeWallpaperState; @Mock IWallpaperManager mIWallpaperManager; + @Mock BiometricUnlockController mBiometricUnlockController; @Mock DozeParameters mDozeParameters; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mDozeParameters); + mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mBiometricUnlockController, + mDozeParameters); } @Test @@ -102,6 +106,20 @@ public class DozeWallpaperStateTest extends SysuiTestCase { } @Test + public void testDoesNotAnimate_whenWakeAndUnlock() throws RemoteException { + // Pre-conditions + when(mDozeParameters.getAlwaysOn()).thenReturn(true); + when(mBiometricUnlockController.unlockedByWakeAndUnlock()).thenReturn(true); + + mDozeWallpaperState.transitionTo(DozeMachine.State.UNINITIALIZED, + DozeMachine.State.DOZE_AOD); + clearInvocations(mIWallpaperManager); + + mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, DozeMachine.State.FINISH); + verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(0L)); + } + + @Test public void testTransitionTo_requestPulseIsAmbientMode() throws RemoteException { mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.DOZE_REQUEST_PULSE); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java index 5c1f473360b2..881cc3915880 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java @@ -64,7 +64,7 @@ public class AlertingNotificationManagerTest extends SysuiTestCase { protected static final int TEST_AUTO_DISMISS_TIME = 500; // Number of notifications to use in tests requiring multiple notifications private static final int TEST_NUM_NOTIFICATIONS = 4; - protected static final int TEST_TIMEOUT_TIME = 10000; + protected static final int TEST_TIMEOUT_TIME = 15000; protected final Runnable TEST_TIMEOUT_RUNNABLE = () -> mTimedOut = true; private AlertingNotificationManager mAlertingNotificationManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index a99dc7fb6924..7d9920db36a4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; @@ -192,6 +194,34 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { } @Test + public void onBiometricAuthenticated_whenBypassOnBouncer_dismissBouncer() { + reset(mKeyguardBypassController); + when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true); + when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true); + when(mKeyguardBypassController.onBiometricAuthenticated(any())).thenReturn(true); + when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true); + mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, + BiometricSourceType.FACE); + + verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false)); + assertThat(mBiometricUnlockController.getMode()) + .isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER); + } + + @Test + public void onBiometricAuthenticated_whenBypassOnBouncer_respectsCanPlaySubtleAnim() { + when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true); + when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true); + when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true); + mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, + BiometricSourceType.FACE); + + verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false)); + assertThat(mBiometricUnlockController.getMode()) + .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING); + } + + @Test public void onBiometricAuthenticated_whenFaceAndPulsing_dontDismissKeyguard() { reset(mUpdateMonitor); reset(mStatusBarKeyguardViewManager); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java index f8b9e6879dcf..48934da9fb37 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java @@ -70,7 +70,6 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { setUp(statusBarWindowView, groupManager, bar, vsManager); mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME; mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME; - mAutoDismissNotificationDecayDozing = TEST_AUTO_DISMISS_TIME; } } @@ -134,13 +133,11 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { @Test public void testExtendHeadsUp() { - when(mStatusBarStateController.isDozing()).thenReturn(true); mHeadsUpManager.showNotification(mEntry); Runnable pastNormalTimeRunnable = () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.key); mTestHandler.postDelayed(pastNormalTimeRunnable, - mHeadsUpManager.mAutoDismissNotificationDecayDozing + - mHeadsUpManager.mExtensionTime / 2); + TEST_AUTO_DISMISS_TIME + mHeadsUpManager.mExtensionTime / 2); mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_TIMEOUT_TIME); mHeadsUpManager.extendHeadsUp(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java index a4ae166d0675..29b8ab600caf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java @@ -40,18 +40,23 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import javax.annotation.Nullable; + /** * Rudimentary fake for SensorManager * - * Currently only supports the proximity sensor. + * Currently only supports proximity, light and tap sensors. * * Note that this class ignores the "Handler" argument, so the test is responsible for calling the * listener on the right thread. */ public class FakeSensorManager extends SensorManager { + public static final String TAP_SENSOR_TYPE = "tapSensorType"; + private final MockProximitySensor mMockProximitySensor; private final FakeGenericSensor mFakeLightSensor; + private final FakeGenericSensor mFakeTapSensor; private final FakeGenericSensor[] mSensors; public FakeSensorManager(Context context) throws Exception { @@ -59,12 +64,13 @@ public class FakeSensorManager extends SensorManager { .getDefaultSensor(Sensor.TYPE_PROXIMITY); if (proxSensor == null) { // No prox? Let's create a fake one! - proxSensor = createSensor(Sensor.TYPE_PROXIMITY); + proxSensor = createSensor(Sensor.TYPE_PROXIMITY, null); } mSensors = new FakeGenericSensor[]{ mMockProximitySensor = new MockProximitySensor(proxSensor), - mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT)), + mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT, null)), + mFakeTapSensor = new FakeGenericSensor(createSensor(99, TAP_SENSOR_TYPE)) }; } @@ -76,6 +82,10 @@ public class FakeSensorManager extends SensorManager { return mFakeLightSensor; } + public FakeGenericSensor getFakeTapSensor() { + return mFakeTapSensor; + } + @Override public Sensor getDefaultSensor(int type) { Sensor s = super.getDefaultSensor(type); @@ -160,13 +170,13 @@ public class FakeSensorManager extends SensorManager { @Override protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) { - return false; + return true; } @Override protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable) { - return false; + return true; } @Override @@ -185,12 +195,15 @@ public class FakeSensorManager extends SensorManager { return false; } - private Sensor createSensor(int type) throws Exception { + private Sensor createSensor(int type, @Nullable String stringType) throws Exception { Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor(); constr.setAccessible(true); Sensor sensor = constr.newInstance(); setSensorType(sensor, type); + if (stringType != null) { + setSensorField(sensor, "mStringType", stringType); + } setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type); setSensorField(sensor, "mVendor", "Mock Vendor"); setSensorField(sensor, "mVersion", 1); diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto index 381d9834fa87..821db860dd96 100644 --- a/proto/src/task_snapshot.proto +++ b/proto/src/task_snapshot.proto @@ -33,4 +33,5 @@ bool is_translucent = 9; string top_activity_component = 10; float scale = 11; - }
\ No newline at end of file + int64 id = 12; + } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java index 841527261e29..1dea2f2dd954 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java @@ -23,7 +23,6 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.NonNull; import android.annotation.Nullable; -import android.graphics.Rect; import android.graphics.Region; import android.os.Binder; import android.os.Handler; @@ -277,7 +276,7 @@ public class AccessibilityWindowManager } else if (!oldWindow.activityToken.equals(newWindow.activityToken)) { return true; } - if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) { + if (!oldWindow.regionInScreen.equals(newWindow.regionInScreen)) { return true; } if (oldWindow.childTokens != null && newWindow.childTokens != null @@ -755,20 +754,20 @@ public class AccessibilityWindowManager boolean windowInteractiveRegionChanged = false; final int windowCount = mWindows.size(); - final Rect currentWindowBounds = new Rect(); + final Region currentWindowRegions = new Region(); for (int i = windowCount - 1; i >= 0; i--) { AccessibilityWindowInfo currentWindow = mWindows.get(i); if (windowInteractiveRegion == null) { if (currentWindow.getId() == windowId) { - currentWindow.getBoundsInScreen(currentWindowBounds); - outRegion.set(currentWindowBounds); + currentWindow.getRegionInScreen(currentWindowRegions); + outRegion.set(currentWindowRegions); windowInteractiveRegion = outRegion; continue; } } else if (currentWindow.getType() != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) { - currentWindow.getBoundsInScreen(currentWindowBounds); - if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) { + currentWindow.getRegionInScreen(currentWindowRegions); + if (windowInteractiveRegion.op(currentWindowRegions, Region.Op.DIFFERENCE)) { windowInteractiveRegionChanged = true; } } @@ -1115,7 +1114,7 @@ public class AccessibilityWindowManager reportedWindow.setType(getTypeForWindowManagerWindowType(window.type)); reportedWindow.setLayer(window.layer); reportedWindow.setFocused(window.focused); - reportedWindow.setBoundsInScreen(window.boundsInScreen); + reportedWindow.setRegionInScreen(window.regionInScreen); reportedWindow.setTitle(window.title); reportedWindow.setAnchorId(window.accessibilityIdOfAnchor); reportedWindow.setPictureInPicture(window.inPictureInPicture); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index aada96771324..1e1e07d32588 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -769,6 +769,19 @@ final class AutofillManagerServiceImpl } /** + * Updates the last fill response when a dataset is shown. + */ + void logDatasetShown(int sessionId, @Nullable Bundle clientState) { + synchronized (mLock) { + if (isValidEventLocked("logDatasetShown", sessionId)) { + mEventHistory.addEvent( + new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null, + null, null, null, null, null)); + } + } + } + + /** * Updates the last fill response when an autofill context is committed. */ @GuardedBy("mLock") diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 988db6a87100..46c2a85d0691 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -2497,6 +2497,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mService.getServicePackageName(), mComponentName, serviceLabel, serviceIcon, this, id, mCompatMode); + mService.logDatasetShown(id, mClientState); + synchronized (mLock) { if (mUiShownTime == 0) { // Log first time UI is shown. diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 8df25b5a6465..d5a7c818bfb2 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -194,6 +194,11 @@ public class BackupManagerService { } } + boolean isAbleToServeUser(int userId) { + return getServiceUsers().get(UserHandle.USER_SYSTEM) != null + && getServiceUsers().get(userId) != null; + } + /** * Returns a lst of users currently unlocked that have a * {@link UserBackupManagerService} registered. diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java index 53bbac4d41fe..f4b66456c27b 100644 --- a/services/backup/java/com/android/server/backup/Trampoline.java +++ b/services/backup/java/com/android/server/backup/Trampoline.java @@ -202,11 +202,10 @@ public class Trampoline extends IBackupManager.Stub { } } - // A user is ready for a backup if it's unlocked and is not suppressed by a device - // admin (device owner or profile owner). + // This method should not perform any I/O (e.g. do not call isBackupActivatedForUser), + // it's used in multiple places where I/O waits would cause system lock-ups. private boolean isUserReadyForBackup(int userId) { - return mService != null && mService.getServiceUsers().get(userId) != null - && isBackupActivatedForUser(userId); + return mService != null && mService.isAbleToServeUser(userId); } /** diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java index 18ee7a488998..18c38dc9efdb 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java +++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java @@ -128,7 +128,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba private static final String TAG = "PFTBT"; - private UserBackupManagerService backupManagerService; + private UserBackupManagerService mUserBackupManagerService; private final Object mCancelLock = new Object(); ArrayList<PackageInfo> mPackages; @@ -159,7 +159,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba @Nullable IBackupManagerMonitor monitor, @Nullable OnTaskFinishedListener listener, boolean userInitiated) { super(observer); - this.backupManagerService = backupManagerService; + this.mUserBackupManagerService = backupManagerService; mTransportClient = transportClient; mUpdateSchedule = updateSchedule; mLatch = latch; @@ -252,16 +252,16 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba } private void registerTask() { - synchronized (backupManagerService.getCurrentOpLock()) { + synchronized (mUserBackupManagerService.getCurrentOpLock()) { Slog.d(TAG, "backupmanager pftbt token=" + Integer.toHexString(mCurrentOpToken)); - backupManagerService.getCurrentOperations().put( + mUserBackupManagerService.getCurrentOperations().put( mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP)); } } public void unregisterTask() { - backupManagerService.removeOperation(mCurrentOpToken); + mUserBackupManagerService.removeOperation(mCurrentOpToken); } @Override @@ -288,7 +288,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba mCancelAll = true; if (mIsDoingBackup) { - backupManagerService.handleCancel(mBackupRunnerOpToken, cancelAll); + mUserBackupManagerService.handleCancel(mBackupRunnerOpToken, cancelAll); try { // If we're running a backup we should be connected to a transport IBackupTransport transport = @@ -320,16 +320,17 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba int backupRunStatus = BackupManager.SUCCESS; try { - if (!backupManagerService.isEnabled() || !backupManagerService.isSetupComplete()) { + if (!mUserBackupManagerService.isEnabled() + || !mUserBackupManagerService.isSetupComplete()) { // Backups are globally disabled, so don't proceed. if (DEBUG) { - Slog.i(TAG, "full backup requested but enabled=" + backupManagerService + Slog.i(TAG, "full backup requested but enabled=" + mUserBackupManagerService .isEnabled() - + " setupComplete=" + backupManagerService.isSetupComplete() + + " setupComplete=" + mUserBackupManagerService.isSetupComplete() + "; ignoring"); } int monitoringEvent; - if (backupManagerService.isSetupComplete()) { + if (mUserBackupManagerService.isSetupComplete()) { monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED; } else { monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED; @@ -532,7 +533,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba // Roll this package to the end of the backup queue if we're // in a queue-driven mode (regardless of success/failure) if (mUpdateSchedule) { - backupManagerService.enqueueFullBackup(packageName, System.currentTimeMillis()); + mUserBackupManagerService.enqueueFullBackup( + packageName, System.currentTimeMillis()); } if (backupPackageStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) { @@ -549,7 +551,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba // from the preflight pass. If we got as far as preflight, we now need // to tear down the target process. if (mBackupRunner != null) { - backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); + mUserBackupManagerService.tearDownAgentAndKill( + currentPackage.applicationInfo); } // ... and continue looping. } else if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) { @@ -561,7 +564,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba EventLog.writeEvent(EventLogTags.FULL_BACKUP_QUOTA_EXCEEDED, packageName); } - backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); + mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); // Do nothing, clean up, and continue looping. } else if (backupPackageStatus == BackupTransport.AGENT_ERROR) { BackupObserverUtils @@ -569,7 +572,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba BackupManager.ERROR_AGENT_FAILURE); Slog.w(TAG, "Application failure for package: " + packageName); EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName); - backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); + mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); // Do nothing, clean up, and continue looping. } else if (backupPackageStatus == BackupManager.ERROR_BACKUP_CANCELLED) { BackupObserverUtils @@ -578,7 +581,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba Slog.w(TAG, "Backup cancelled. package=" + packageName + ", cancelAll=" + mCancelAll); EventLog.writeEvent(EventLogTags.FULL_BACKUP_CANCELLED, packageName); - backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); + mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); // Do nothing, clean up, and continue looping. } else if (backupPackageStatus != BackupTransport.TRANSPORT_OK) { BackupObserverUtils @@ -588,7 +591,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE); // Abort entire backup pass. backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED; - backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); + mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); return; } else { // Success! @@ -596,14 +599,14 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba .sendBackupOnPackageResult(mBackupObserver, packageName, BackupManager.SUCCESS); EventLog.writeEvent(EventLogTags.FULL_BACKUP_SUCCESS, packageName); - backupManagerService.logBackupComplete(packageName); + mUserBackupManagerService.logBackupComplete(packageName); } cleanUpPipes(transportPipes); cleanUpPipes(enginePipes); if (currentPackage.applicationInfo != null) { Slog.i(TAG, "Unbinding agent in " + packageName); try { - backupManagerService.getActivityManager().unbindBackupAgent( + mUserBackupManagerService.getActivityManager().unbindBackupAgent( currentPackage.applicationInfo); } catch (RemoteException e) { /* can't happen; activity manager is local */ } } @@ -639,8 +642,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba mJob.finishBackupPass(mUserId); } - synchronized (backupManagerService.getQueueLock()) { - backupManagerService.setRunningFullBackupTask(null); + synchronized (mUserBackupManagerService.getQueueLock()) { + mUserBackupManagerService.setRunningFullBackupTask(null); } mListener.onFinished("PFTBT.run()"); @@ -650,11 +653,11 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba // Now that we're actually done with schedule-driven work, reschedule // the next pass based on the new queue state. if (mUpdateSchedule) { - backupManagerService.scheduleNextFullBackupJob(backoff); + mUserBackupManagerService.scheduleNextFullBackupJob(backoff); } Slog.i(TAG, "Full data backup pass finished."); - backupManagerService.getWakelock().release(); + mUserBackupManagerService.getWakelock().release(); } } @@ -709,13 +712,13 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba long fullBackupAgentTimeoutMillis = mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis(); try { - backupManagerService.prepareOperationTimeout( + mUserBackupManagerService.prepareOperationTimeout( mCurrentOpToken, fullBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT); if (MORE_DEBUG) { Slog.d(TAG, "Preflighting full payload of " + pkg.packageName); } agent.doMeasureFullBackup(mQuota, mCurrentOpToken, - backupManagerService.getBackupManagerBinder(), mTransportFlags); + mUserBackupManagerService.getBackupManagerBinder(), mTransportFlags); // Now wait to get our result back. If this backstop timeout is reached without // the latch being thrown, flow will continue as though a result or "normal" @@ -765,7 +768,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba } mResult.set(result); mLatch.countDown(); - backupManagerService.removeOperation(mCurrentOpToken); + mUserBackupManagerService.removeOperation(mCurrentOpToken); } @Override @@ -775,7 +778,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba } mResult.set(BackupTransport.AGENT_ERROR); mLatch.countDown(); - backupManagerService.removeOperation(mCurrentOpToken); + mUserBackupManagerService.removeOperation(mCurrentOpToken); } @Override @@ -812,7 +815,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba mOutput = ParcelFileDescriptor.dup(output.getFileDescriptor()); mTarget = target; mCurrentOpToken = currentOpToken; - mEphemeralToken = backupManagerService.generateRandomIntegerToken(); + mEphemeralToken = mUserBackupManagerService.generateRandomIntegerToken(); mPreflight = new SinglePackageBackupPreflight( transportClient, quota, mEphemeralToken, transportFlags); mPreflightLatch = new CountDownLatch(1); @@ -825,23 +828,32 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba } void registerTask() { - synchronized (backupManagerService.getCurrentOpLock()) { - backupManagerService.getCurrentOperations().put( + synchronized (mUserBackupManagerService.getCurrentOpLock()) { + mUserBackupManagerService.getCurrentOperations().put( mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP_WAIT)); } } void unregisterTask() { - synchronized (backupManagerService.getCurrentOpLock()) { - backupManagerService.getCurrentOperations().remove(mCurrentOpToken); + synchronized (mUserBackupManagerService.getCurrentOpLock()) { + mUserBackupManagerService.getCurrentOperations().remove(mCurrentOpToken); } } @Override public void run() { FileOutputStream out = new FileOutputStream(mOutput.getFileDescriptor()); - mEngine = new FullBackupEngine(backupManagerService, out, mPreflight, mTarget, false, - this, mQuota, mCurrentOpToken, mTransportFlags); + mEngine = + new FullBackupEngine( + mUserBackupManagerService, + out, + mPreflight, + mTarget, + false, + this, + mQuota, + mCurrentOpToken, + mTransportFlags); try { try { if (!mIsCancelled) { @@ -928,13 +940,13 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null); mIsCancelled = true; // Cancel tasks spun off by this task. - backupManagerService.handleCancel(mEphemeralToken, cancelAll); - backupManagerService.tearDownAgentAndKill(mTarget.applicationInfo); + mUserBackupManagerService.handleCancel(mEphemeralToken, cancelAll); + mUserBackupManagerService.tearDownAgentAndKill(mTarget.applicationInfo); // Free up everyone waiting on this task and its children. mPreflightLatch.countDown(); mBackupLatch.countDown(); // We are done with this operation. - backupManagerService.removeOperation(mCurrentOpToken); + mUserBackupManagerService.removeOperation(mCurrentOpToken); } } } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 930cf9efdb1a..5089ee0ace57 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -42,7 +42,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.content.res.Resources; @@ -121,6 +120,7 @@ import com.android.server.location.LocationRequestStatistics.PackageStatistics; import com.android.server.location.MockProvider; import com.android.server.location.PassiveProvider; import com.android.server.location.RemoteListenerHelper; +import com.android.server.pm.permission.PermissionManagerServiceInternal; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; @@ -282,12 +282,12 @@ public class LocationManagerService extends ILocationManager.Stub { // Let the package manager query which are the default location // providers as they get certain permissions granted by default. - PackageManagerInternal packageManagerInternal = LocalServices.getService( - PackageManagerInternal.class); - packageManagerInternal.setLocationPackagesProvider( + PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService( + PermissionManagerServiceInternal.class); + permissionManagerInternal.setLocationPackagesProvider( userId -> mContext.getResources().getStringArray( com.android.internal.R.array.config_locationProviderPackageNames)); - packageManagerInternal.setLocationExtraPackagesProvider( + permissionManagerInternal.setLocationExtraPackagesProvider( userId -> mContext.getResources().getStringArray( com.android.internal.R.array.config_locationExtraPackageNames)); diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 80d7ac931111..df5005eed66b 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -26,7 +26,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.database.ContentObserver; import android.location.LocationManager; import android.net.INetworkRecommendationProvider; @@ -54,15 +53,14 @@ import android.provider.Settings.Global; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.IntArray; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; import com.android.internal.os.TransferPipe; -import com.android.internal.telephony.SmsApplication; import com.android.internal.util.DumpUtils; +import com.android.server.pm.permission.PermissionManagerServiceInternal; import java.io.FileDescriptor; import java.io.IOException; @@ -294,7 +292,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { String useOpenWifiPackage = Global.getString(mContext.getContentResolver(), Global.USE_OPEN_WIFI_PACKAGE); if (!TextUtils.isEmpty(useOpenWifiPackage)) { - LocalServices.getService(PackageManagerInternal.class) + LocalServices.getService(PermissionManagerServiceInternal.class) .grantDefaultPermissionsToDefaultUseOpenWifiApp(useOpenWifiPackage, userId); } @@ -306,17 +304,14 @@ public class NetworkScoreService extends INetworkScoreService.Stub { false /*notifyForDescendants*/, mUseOpenWifiPackageObserver); // Set a callback for the package manager to query the use open wifi app. - LocalServices.getService(PackageManagerInternal.class).setUseOpenWifiAppPackagesProvider( - new PackageManagerInternal.PackagesProvider() { - @Override - public String[] getPackages(int userId) { - String useOpenWifiPackage = Global.getString(mContext.getContentResolver(), - Global.USE_OPEN_WIFI_PACKAGE); - if (!TextUtils.isEmpty(useOpenWifiPackage)) { - return new String[]{useOpenWifiPackage}; - } - return null; + LocalServices.getService(PermissionManagerServiceInternal.class) + .setUseOpenWifiAppPackagesProvider((userId) -> { + String useOpenWifiPackage = Global.getString(mContext.getContentResolver(), + Global.USE_OPEN_WIFI_PACKAGE); + if (!TextUtils.isEmpty(useOpenWifiPackage)) { + return new String[]{useOpenWifiPackage}; } + return null; }); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index adb0909f46b8..ff8c3e954460 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -347,6 +347,7 @@ import com.android.server.ThreadPriorityBooster; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto; import com.android.server.appop.AppOpsService; +import com.android.server.compat.CompatConfig; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.firewall.IntentFirewall; import com.android.server.job.JobSchedulerInternal; @@ -392,7 +393,9 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -5027,6 +5030,7 @@ public class ActivityManagerService extends IActivityManager.Stub bindApplicationTimeMillis = SystemClock.elapsedRealtime(); mAtmInternal.preBindApplication(app.getWindowProcessController()); final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); + long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info); if (app.isolatedEntryPoint != null) { // This is an isolated process which should just call an entry point instead of // being bound to an application. @@ -5042,7 +5046,8 @@ public class ActivityManagerService extends IActivityManager.Stub new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), - buildSerial, autofillOptions, contentCaptureOptions); + buildSerial, autofillOptions, contentCaptureOptions, + disabledCompatChanges); } else { thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode, @@ -5051,7 +5056,8 @@ public class ActivityManagerService extends IActivityManager.Stub new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), - buildSerial, autofillOptions, contentCaptureOptions); + buildSerial, autofillOptions, contentCaptureOptions, + disabledCompatChanges); } if (profilerInfo != null) { profilerInfo.closeFd(); @@ -7706,6 +7712,34 @@ public class ActivityManagerService extends IActivityManager.Stub return null; } + int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) { + final String name = uri.getAuthority(); + final long ident = Binder.clearCallingIdentity(); + ContentProviderHolder holder = null; + try { + holder = getContentProviderExternalUnchecked(name, null, callingUid, + "*checkContentProviderUriPermission*", userId); + if (holder != null) { + return holder.provider.checkUriPermission(null, uri, callingUid, modeFlags); + } + } catch (RemoteException e) { + Log.w(TAG, "Content provider dead retrieving " + uri, e); + return PackageManager.PERMISSION_DENIED; + } catch (Exception e) { + Log.w(TAG, "Exception while determining type of " + uri, e); + return PackageManager.PERMISSION_DENIED; + } finally { + try { + if (holder != null) { + removeContentProviderExternalUnchecked(name, null, userId); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + return PackageManager.PERMISSION_DENIED; + } + private boolean canClearIdentity(int callingPid, int callingUid, int userId) { if (UserHandle.getUserId(callingUid) == userId) { return true; @@ -17826,6 +17860,35 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public int checkContentProviderUriPermission(Uri uri, int userId, + int callingUid, int modeFlags) { + // We can find ourselves needing to check Uri permissions while + // already holding the WM lock, which means reaching back here for + // the AM lock would cause an inversion. The WM team has requested + // that we use the strategy below instead of shifting where Uri + // grants are calculated. + + // Since we could also arrive here while holding the AM lock, we + // can't always delegate the call through the handler, and we need + // to delicately dance between the deadlocks. + if (Thread.currentThread().holdsLock(ActivityManagerService.this)) { + return ActivityManagerService.this.checkContentProviderUriPermission(uri, + userId, callingUid, modeFlags); + } else { + final CompletableFuture<Integer> res = new CompletableFuture<>(); + mHandler.post(() -> { + res.complete(ActivityManagerService.this.checkContentProviderUriPermission(uri, + userId, callingUid, modeFlags)); + }); + try { + return res.get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + } + + @Override public void onWakefulnessChanged(int wakefulness) { ActivityManagerService.this.onWakefulnessChanged(wakefulness); } diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags index 421b75586224..cf0de061185f 100644 --- a/services/core/java/com/android/server/am/EventLogTags.logtags +++ b/services/core/java/com/android/server/am/EventLogTags.logtags @@ -146,4 +146,7 @@ option java_package com.android.server.am 30065 am_on_top_resumed_lost_called (Token|1|5),(Component Name|3),(Reason|3) # An activity been add into stopping list -30066 am_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
\ No newline at end of file +30066 am_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3) + +# Keyguard status changed ++30067 am_set_keyguard_shown (keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(Reason|3)
\ No newline at end of file diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index df6f73b914a8..bd3cd5439b32 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -521,8 +521,8 @@ public class BiometricService extends SystemService { List<EnabledOnKeyguardCallback> callbacks = mEnabledOnKeyguardCallbacks; for (int i = 0; i < callbacks.size(); i++) { callbacks.get(i).notify(BiometricSourceType.FACE, - mFaceEnabledOnKeyguard.getOrDefault(userId, - DEFAULT_KEYGUARD_ENABLED)); + mFaceEnabledOnKeyguard.getOrDefault(userId, DEFAULT_KEYGUARD_ENABLED), + userId); } } } @@ -540,9 +540,9 @@ public class BiometricService extends SystemService { } } - void notify(BiometricSourceType sourceType, boolean enabled) { + void notify(BiometricSourceType sourceType, boolean enabled, int userId) { try { - mCallback.onChanged(sourceType, enabled); + mCallback.onChanged(sourceType, enabled, userId); } catch (DeadObjectException e) { Slog.w(TAG, "Death while invoking notify", e); mEnabledOnKeyguardCallbacks.remove(this); @@ -796,7 +796,8 @@ public class BiometricService extends SystemService { mEnabledOnKeyguardCallbacks.add(new EnabledOnKeyguardCallback(callback)); try { callback.onChanged(BiometricSourceType.FACE, - mSettingObserver.getFaceEnabledOnKeyguard()); + mSettingObserver.getFaceEnabledOnKeyguard(), + UserHandle.getCallingUserId()); } catch (RemoteException e) { Slog.w(TAG, "Remote exception", e); } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 7824a0ac3194..3e1817bd14ff 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -40,7 +40,6 @@ import android.content.SyncInfo; import android.content.SyncRequest; import android.content.SyncStatusInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.content.pm.ProviderInfo; import android.database.IContentObserver; import android.database.sqlite.SQLiteException; @@ -71,6 +70,7 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.pm.permission.PermissionManagerServiceInternal; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -280,15 +280,11 @@ public final class ContentService extends IContentService.Stub { // Let the package manager query for the sync adapters for a given authority // as we grant default permissions to sync adapters for specific authorities. - PackageManagerInternal packageManagerInternal = LocalServices.getService( - PackageManagerInternal.class); - packageManagerInternal.setSyncAdapterPackagesprovider( - new PackageManagerInternal.SyncAdapterPackagesProvider() { - @Override - public String[] getPackages(String authority, int userId) { - return getSyncAdapterPackagesForAuthorityAsUser(authority, userId); - } - }); + final PermissionManagerServiceInternal permissionManagerInternal = + LocalServices.getService(PermissionManagerServiceInternal.class); + permissionManagerInternal.setSyncAdapterPackagesProvider((authority, userId) -> { + return getSyncAdapterPackagesForAuthorityAsUser(authority, userId); + }); final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 99341d1c96ae..4f33ebb035da 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -303,6 +303,8 @@ public final class DisplayManagerService extends SystemService { private final Spline mMinimumBrightnessSpline; private final ColorSpace mWideColorSpace; + private SensorManager mSensorManager; + public DisplayManagerService(Context context) { this(context, new Injector()); } @@ -430,7 +432,7 @@ public final class DisplayManagerService extends SystemService { } mDisplayModeDirector.setListener(new AllowedDisplayModeObserver()); - mDisplayModeDirector.start(); + mDisplayModeDirector.start(mSensorManager); mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); } @@ -2358,6 +2360,7 @@ public final class DisplayManagerService extends SystemService { }; mDisplayPowerController = new DisplayPowerController( mContext, callbacks, handler, sensorManager, blanker); + mSensorManager = sensorManager; } mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION); diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 14bd2d8150da..78a48dac6fb5 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -18,26 +18,41 @@ package com.android.server.display; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.display.DisplayManager; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; + import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.UserHandle; +import android.os.PowerManager; +import android.os.SystemClock; import android.provider.Settings; +import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import com.android.internal.R; +import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory; +import com.android.server.display.whitebalance.AmbientFilter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Objects; /** @@ -74,7 +89,7 @@ public class DisplayModeDirector { private final AppRequestObserver mAppRequestObserver; private final SettingsObserver mSettingsObserver; private final DisplayObserver mDisplayObserver; - + private final BrightnessObserver mBrightnessObserver; private Listener mListener; @@ -87,6 +102,8 @@ public class DisplayModeDirector { mAppRequestObserver = new AppRequestObserver(); mSettingsObserver = new SettingsObserver(context, handler); mDisplayObserver = new DisplayObserver(context, handler); + mBrightnessObserver = new BrightnessObserver(context, handler); + } /** @@ -96,15 +113,17 @@ public class DisplayModeDirector { * This has to be deferred because the object may be constructed before the rest of the system * is ready. */ - public void start() { + public void start(SensorManager sensorManager) { mSettingsObserver.observe(); mDisplayObserver.observe(); mSettingsObserver.observe(); + mBrightnessObserver.observe(sensorManager); synchronized (mLock) { // We may have a listener already registered before the call to start, so go ahead and // notify them to pick up our newly initialized state. notifyAllowedModesChangedLocked(); } + } /** @@ -315,6 +334,7 @@ public class DisplayModeDirector { } mSettingsObserver.dumpLocked(pw); mAppRequestObserver.dumpLocked(pw); + mBrightnessObserver.dumpLocked(pw); } } @@ -486,20 +506,15 @@ public class DisplayModeDirector { Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE); private final Uri mLowPowerModeSetting = Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE); - private final Uri mBrightnessSetting = - Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); private final Context mContext; private final float mDefaultPeakRefreshRate; - private final int mBrightnessThreshold; SettingsObserver(@NonNull Context context, @NonNull Handler handler) { super(handler); mContext = context; mDefaultPeakRefreshRate = (float) context.getResources().getInteger( R.integer.config_defaultPeakRefreshRate); - mBrightnessThreshold = context.getResources().getInteger( - R.integer.config_brightnessThresholdOfPeakRefreshRate); } public void observe() { @@ -508,14 +523,9 @@ public class DisplayModeDirector { UserHandle.USER_SYSTEM); cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM); - if (mBrightnessThreshold >= 0) { - cr.registerContentObserver(mBrightnessSetting, false /*notifyDescendants*/, this, - UserHandle.USER_SYSTEM); - } synchronized (mLock) { updateRefreshRateSettingLocked(); updateLowPowerModeSettingLocked(); - updateBrightnessSettingLocked(); } } @@ -526,8 +536,6 @@ public class DisplayModeDirector { updateRefreshRateSettingLocked(); } else if (mLowPowerModeSetting.equals(uri)) { updateLowPowerModeSettingLocked(); - } else if (mBrightnessThreshold >=0 && mBrightnessSetting.equals(uri)) { - updateBrightnessSettingLocked(); } } } @@ -542,6 +550,7 @@ public class DisplayModeDirector { vote = null; } updateVoteLocked(Vote.PRIORITY_LOW_POWER_MODE, vote); + mBrightnessObserver.onLowPowerModeEnabled(inLowPowerMode); } private void updateRefreshRateSettingLocked() { @@ -549,23 +558,7 @@ public class DisplayModeDirector { Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate); Vote vote = Vote.forRefreshRates(0f, peakRefreshRate); updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote); - } - - private void updateBrightnessSettingLocked() { - int brightness = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.SCREEN_BRIGHTNESS, -1); - - if (brightness < 0) { - return; - } - - final Vote vote; - if (brightness <= mBrightnessThreshold) { - vote = Vote.forRefreshRates(0f, 60f); - } else { - vote = null; - } - updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote); + mBrightnessObserver.onPeakRefreshRateEnabled(peakRefreshRate > 60f); } public void dumpLocked(PrintWriter pw) { @@ -715,4 +708,240 @@ public class DisplayModeDirector { } } } + + /** + * This class manages brightness threshold for switching between 60 hz and higher refresh rate. + * See more information at the definition of + * {@link R.array#config_brightnessThresholdsOfPeakRefreshRate} and + * {@link R.array#config_ambientThresholdsOfPeakRefreshRate}. + */ + private class BrightnessObserver extends ContentObserver { + private final Uri mDisplayBrightnessSetting = + Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); + + private final static int LIGHT_SENSOR_RATE_MS = 250; + private final int[] mDisplayBrightnessThresholds; + private final int[] mAmbientBrightnessThresholds; + // valid threshold if any item from the array >= 0 + private boolean mShouldObserveDisplayChange; + private boolean mShouldObserveAmbientChange; + + private SensorManager mSensorManager; + private Sensor mLightSensor; + // Take it as low brightness before valid sensor data comes + private float mAmbientLux = -1.0f; + private AmbientFilter mAmbientFilter; + + private final Context mContext; + private ScreenStateReceiver mScreenStateReceiver; + + // Enable light sensor only when screen is on, peak refresh rate enabled and low power mode + // off. After initialization, these states will be updated from the same handler thread. + private boolean mScreenOn = false; + private boolean mPeakRefreshRateEnabled = false; + private boolean mLowPowerModeEnabled = false; + + BrightnessObserver(Context context, Handler handler) { + super(handler); + mContext = context; + mDisplayBrightnessThresholds = context.getResources().getIntArray( + R.array.config_brightnessThresholdsOfPeakRefreshRate); + mAmbientBrightnessThresholds = context.getResources().getIntArray( + R.array.config_ambientThresholdsOfPeakRefreshRate); + if (mDisplayBrightnessThresholds.length != mAmbientBrightnessThresholds.length) { + throw new RuntimeException("display brightness threshold array and ambient " + + "brightness threshold array have different length"); + } + + mShouldObserveDisplayChange = checkShouldObserve(mDisplayBrightnessThresholds); + mShouldObserveAmbientChange = checkShouldObserve(mAmbientBrightnessThresholds); + } + + public void observe(SensorManager sensorManager) { + if (mShouldObserveDisplayChange) { + final ContentResolver cr = mContext.getContentResolver(); + cr.registerContentObserver(mDisplayBrightnessSetting, + false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM); + } + + if (mShouldObserveAmbientChange) { + Resources resources = mContext.getResources(); + String lightSensorType = resources.getString( + com.android.internal.R.string.config_displayLightSensorType); + + Sensor lightSensor = null; + if (!TextUtils.isEmpty(lightSensorType)) { + List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL); + for (int i = 0; i < sensors.size(); i++) { + Sensor sensor = sensors.get(i); + if (lightSensorType.equals(sensor.getStringType())) { + lightSensor = sensor; + break; + } + } + } + + if (lightSensor == null) { + lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); + } + + if (lightSensor != null) { + final Resources res = mContext.getResources(); + + mAmbientFilter = DisplayWhiteBalanceFactory.createBrightnessFilter(res); + mSensorManager = sensorManager; + mLightSensor = lightSensor; + + // Intent.ACTION_SCREEN_ON is not sticky. Check current screen status. + if (mContext.getSystemService(PowerManager.class).isInteractive()) { + onScreenOn(true); + } + mScreenStateReceiver = new ScreenStateReceiver(mContext); + } + } + + if (mShouldObserveDisplayChange || mShouldObserveAmbientChange) { + synchronized (mLock) { + onBrightnessChangedLocked(); + } + } + } + + public void onPeakRefreshRateEnabled(boolean b) { + if (mShouldObserveAmbientChange && mPeakRefreshRateEnabled != b) { + mPeakRefreshRateEnabled = b; + updateSensorStatus(); + } + } + + public void onLowPowerModeEnabled(boolean b) { + if (mShouldObserveAmbientChange && mLowPowerModeEnabled != b) { + mLowPowerModeEnabled = b; + updateSensorStatus(); + } + } + + public void dumpLocked(PrintWriter pw) { + pw.println(" BrightnessObserver"); + + for (int d: mDisplayBrightnessThresholds) { + pw.println(" mDisplayBrightnessThreshold: " + d); + } + + for (int d: mAmbientBrightnessThresholds) { + pw.println(" mAmbientBrightnessThreshold: " + d); + } + } + + @Override + public void onChange(boolean selfChange, Uri uri, int userId) { + synchronized (mLock) { + onBrightnessChangedLocked(); + } + } + + /** + * Checks to see if at least one value is positive, in which case it is necessary to listen + * to value changes. + */ + private boolean checkShouldObserve(int[] a) { + for (int d: a) { + if (d >= 0) { + return true; + } + } + + return false; + } + + private void onBrightnessChangedLocked() { + int brightness = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS, -1); + + Vote vote = null; + for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) { + int disp = mDisplayBrightnessThresholds[i]; + int ambi = mAmbientBrightnessThresholds[i]; + + if (disp >= 0 && ambi >= 0) { + if (brightness <= disp && mAmbientLux <= ambi) { + vote = Vote.forRefreshRates(0f, 60f); + } + } else if (disp >= 0) { + if (brightness <= disp) { + vote = Vote.forRefreshRates(0f, 60f); + } + } else if (ambi >= 0) { + if (mAmbientLux <= ambi) { + vote = Vote.forRefreshRates(0f, 60f); + } + } + + if (vote != null) { + break; + } + } + + if (DEBUG) { + Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " + mAmbientLux + + (vote != null ? " 60hz only" : " no refresh rate limit")); + } + updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote); + } + + private void onScreenOn(boolean on) { + // Not check mShouldObserveAmbientChange because Screen status receiver is registered + // only when it is true. + if (mScreenOn != on) { + mScreenOn = on; + updateSensorStatus(); + } + } + + private void updateSensorStatus() { + if (mSensorManager == null || mLightSensorListener == null) { + return; + } + + if (mScreenOn && !mLowPowerModeEnabled && mPeakRefreshRateEnabled) { + mSensorManager.registerListener(mLightSensorListener, + mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler); + } else { + mSensorManager.unregisterListener(mLightSensorListener); + } + } + + private final SensorEventListener mLightSensorListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + long now = SystemClock.uptimeMillis(); + mAmbientFilter.addValue(now, event.values[0]); + mAmbientLux = mAmbientFilter.getEstimate(now); + + synchronized (mLock) { + onBrightnessChangedLocked(); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // Not used. + } + }; + + private final class ScreenStateReceiver extends BroadcastReceiver { + public ScreenStateReceiver(Context context) { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(Intent.ACTION_SCREEN_ON); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + context.registerReceiver(this, filter, null, mHandler); + } + + @Override + public void onReceive(Context context, Intent intent) { + onScreenOn(Intent.ACTION_SCREEN_ON.equals(intent.getAction())); + } + } + } } diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java index 2e5aafe0da72..7fb5b191a9b0 100644 --- a/services/core/java/com/android/server/display/color/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java @@ -63,6 +63,8 @@ import android.provider.Settings.Secure; import android.provider.Settings.System; import android.util.MathUtils; import android.util.Slog; +import android.util.SparseIntArray; +import android.view.Display; import android.view.SurfaceControl; import android.view.accessibility.AccessibilityManager; import android.view.animation.AnimationUtils; @@ -171,6 +173,11 @@ public final class ColorDisplayService extends SystemService { private NightDisplayAutoMode mNightDisplayAutoMode; + /** + * Map of color modes -> display composition colorspace + */ + private SparseIntArray mColorModeCompositionColorSpaces = null; + public ColorDisplayService(Context context) { super(context); mHandler = new TintHandler(DisplayThread.get().getLooper()); @@ -267,6 +274,30 @@ public final class ColorDisplayService extends SystemService { return Secure.getIntForUser(cr, Secure.USER_SETUP_COMPLETE, 0, userHandle) == 1; } + private void setUpDisplayCompositionColorSpaces(Resources res) { + mColorModeCompositionColorSpaces = null; + + final int[] colorModes = res.getIntArray(R.array.config_displayCompositionColorModes); + if (colorModes == null) { + return; + } + + final int[] compSpaces = res.getIntArray(R.array.config_displayCompositionColorSpaces); + if (compSpaces == null) { + return; + } + + if (colorModes.length != compSpaces.length) { + Slog.e(TAG, "Number of composition color spaces doesn't match specified color modes"); + return; + } + + mColorModeCompositionColorSpaces = new SparseIntArray(colorModes.length); + for (int i = 0; i < colorModes.length; i++) { + mColorModeCompositionColorSpaces.put(colorModes[i], compSpaces[i]); + } + } + private void setUp() { Slog.d(TAG, "setUp: currentUser=" + mCurrentUser); @@ -359,6 +390,8 @@ public final class ColorDisplayService extends SystemService { onAccessibilityInversionChanged(); onAccessibilityDaltonizerChanged(); + setUpDisplayCompositionColorSpaces(getContext().getResources()); + // Set the color mode, if valid, and immediately apply the updated tint matrix based on the // existing activated state. This ensures consistency of tint across the color mode change. onDisplayColorModeChanged(getColorModeInternal()); @@ -450,6 +483,14 @@ public final class ColorDisplayService extends SystemService { } } + private int getCompositionColorSpace(int mode) { + if (mColorModeCompositionColorSpaces == null) { + return Display.COLOR_MODE_INVALID; + } + + return mColorModeCompositionColorSpaces.get(mode, Display.COLOR_MODE_INVALID); + } + private void onDisplayColorModeChanged(int mode) { if (mode == NOT_SET) { return; @@ -470,7 +511,8 @@ public final class ColorDisplayService extends SystemService { // DisplayTransformManager.needsLinearColorMatrix(), therefore it is dependent // on the state of DisplayTransformManager. final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); - dtm.setColorMode(mode, mNightDisplayTintController.getMatrix()); + dtm.setColorMode(mode, mNightDisplayTintController.getMatrix(), + getCompositionColorSpace(mode)); if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) { updateDisplayWhiteBalanceStatus(); diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java index 5ff45a97706e..d5706a59b987 100644 --- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java +++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java @@ -26,6 +26,7 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.util.Slog; import android.util.SparseArray; +import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -77,6 +78,8 @@ public class DisplayTransformManager { @VisibleForTesting static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation"; @VisibleForTesting + static final String PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE = "persist.sys.sf.color_mode"; + @VisibleForTesting static final String PERSISTENT_PROPERTY_DISPLAY_COLOR = "persist.sys.sf.native_mode"; private static final float COLOR_SATURATION_NATURAL = 1.0f; @@ -251,23 +254,24 @@ public class DisplayTransformManager { /** * Sets color mode and updates night display transform values. */ - public boolean setColorMode(int colorMode, float[] nightDisplayMatrix) { + public boolean setColorMode(int colorMode, float[] nightDisplayMatrix, + int compositionColorMode) { if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) { applySaturation(COLOR_SATURATION_NATURAL); - setDisplayColor(DISPLAY_COLOR_MANAGED); + setDisplayColor(DISPLAY_COLOR_MANAGED, compositionColorMode); } else if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) { applySaturation(COLOR_SATURATION_BOOSTED); - setDisplayColor(DISPLAY_COLOR_MANAGED); + setDisplayColor(DISPLAY_COLOR_MANAGED, compositionColorMode); } else if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) { applySaturation(COLOR_SATURATION_NATURAL); - setDisplayColor(DISPLAY_COLOR_UNMANAGED); + setDisplayColor(DISPLAY_COLOR_UNMANAGED, compositionColorMode); } else if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) { applySaturation(COLOR_SATURATION_NATURAL); - setDisplayColor(DISPLAY_COLOR_ENHANCED); + setDisplayColor(DISPLAY_COLOR_ENHANCED, compositionColorMode); } else if (colorMode >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN && colorMode <= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX) { applySaturation(COLOR_SATURATION_NATURAL); - setDisplayColor(colorMode); + setDisplayColor(colorMode, compositionColorMode); } setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, nightDisplayMatrix); @@ -323,13 +327,21 @@ public class DisplayTransformManager { /** * Toggles native mode on/off in SurfaceFlinger. */ - private void setDisplayColor(int color) { + private void setDisplayColor(int color, int compositionColorMode) { SystemProperties.set(PERSISTENT_PROPERTY_DISPLAY_COLOR, Integer.toString(color)); + if (compositionColorMode != Display.COLOR_MODE_INVALID) { + SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE, + Integer.toString(compositionColorMode)); + } + final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER); if (flinger != null) { final Parcel data = Parcel.obtain(); data.writeInterfaceToken("android.ui.ISurfaceComposer"); data.writeInt(color); + if (compositionColorMode != Display.COLOR_MODE_INVALID) { + data.writeInt(compositionColorMode); + } try { flinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0); } catch (RemoteException ex) { diff --git a/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java b/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java index 123cd73a3ff3..35808974b9e4 100644 --- a/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java +++ b/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java @@ -36,7 +36,7 @@ import java.util.Arrays; * - {@link WeightedMovingAverageAmbientFilter} * A weighted average prioritising recent changes. */ -abstract class AmbientFilter { +abstract public class AmbientFilter { protected static final boolean DEBUG = false; // Enable for verbose logs. @@ -156,8 +156,7 @@ abstract class AmbientFilter { /** * A weighted average prioritising recent changes. */ - @VisibleForTesting - public static class WeightedMovingAverageAmbientFilter extends AmbientFilter { + static class WeightedMovingAverageAmbientFilter extends AmbientFilter { // How long the latest ambient value change is predicted to last. private static final int PREDICTION_TIME = 100; // Milliseconds diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java index 4df7d6b14f25..bf0a1d16219d 100644 --- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java +++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java @@ -115,8 +115,7 @@ public class DisplayWhiteBalanceFactory { * Creates a BrightnessFilter which functions as a weighted moving average buffer for recent * brightness values. */ - @VisibleForTesting - static AmbientFilter createBrightnessFilter(Resources resources) { + public static AmbientFilter createBrightnessFilter(Resources resources) { final int horizon = resources.getInteger( com.android.internal.R.integer.config_displayWhiteBalanceBrightnessFilterHorizon); final float intercept = getFloat(resources, @@ -129,7 +128,6 @@ public class DisplayWhiteBalanceFactory { + "expected config_displayWhiteBalanceBrightnessFilterIntercept"); } - /** * Creates an ambient color sensor instance to redirect sensor data to callbacks. */ diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 01936c9159dd..12137fe8d841 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -32,16 +32,15 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.Message; import android.os.RemoteException; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; -import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.function.pooled.PooledLambda; import java.io.PrintWriter; import java.lang.ref.WeakReference; @@ -204,13 +203,15 @@ class MediaRouter2ServiceImpl { UserRecord oldUser = mUserRecords.get(oldUserId); if (oldUser != null) { - oldUser.mHandler.sendEmptyMessage(MediaRouterService.UserHandler.MSG_STOP); + oldUser.mHandler.sendMessage( + obtainMessage(UserHandler::stop, oldUser.mHandler)); disposeUserIfNeededLocked(oldUser); // since no longer current user } UserRecord newUser = mUserRecords.get(userId); if (newUser != null) { - newUser.mHandler.sendEmptyMessage(MediaRouterService.UserHandler.MSG_START); + newUser.mHandler.sendMessage( + obtainMessage(UserHandler::start, newUser.mHandler)); } } } @@ -296,8 +297,9 @@ class MediaRouter2ServiceImpl { if (clientRecord != null) { clientRecord.mControlCategories = categories; - clientRecord.mUserRecord.mHandler.obtainMessage( - UserHandler.MSG_UPDATE_CLIENT_USAGE, clientRecord).sendToTarget(); + clientRecord.mUserRecord.mHandler.sendMessage( + obtainMessage(UserHandler::updateClientUsage, + clientRecord.mUserRecord.mHandler, clientRecord)); } } @@ -307,9 +309,9 @@ class MediaRouter2ServiceImpl { ClientRecord clientRecord = mAllClientRecords.get(binder); if (clientRecord != null) { - Pair<MediaRoute2Info, Intent> obj = new Pair<>(route, request); - clientRecord.mUserRecord.mHandler.obtainMessage( - UserHandler.MSG_SEND_CONTROL_REQUEST, obj).sendToTarget(); + clientRecord.mUserRecord.mHandler.sendMessage( + obtainMessage(UserHandler::sendControlRequest, + clientRecord.mUserRecord.mHandler, route, request)); } } @@ -346,8 +348,9 @@ class MediaRouter2ServiceImpl { final int count = userRecord.mClientRecords.size(); for (int i = 0; i < count; i++) { ClientRecord clientRecord = userRecord.mClientRecords.get(i); - clientRecord.mUserRecord.mHandler.obtainMessage( - UserHandler.MSG_UPDATE_CLIENT_USAGE, clientRecord).sendToTarget(); + clientRecord.mUserRecord.mHandler.sendMessage( + obtainMessage(UserHandler::updateClientUsage, + clientRecord.mUserRecord.mHandler, clientRecord)); } } } @@ -381,7 +384,8 @@ class MediaRouter2ServiceImpl { Slog.d(TAG, userRecord + ": Initialized"); } if (userRecord.mUserId == mCurrentUserId) { - userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START); + userRecord.mHandler.sendMessage( + obtainMessage(UserHandler::start, userRecord.mHandler)); } } @@ -497,13 +501,6 @@ class MediaRouter2ServiceImpl { MediaRoute2ProviderWatcher.Callback, MediaRoute2ProviderProxy.Callback { - //TODO: Use PooledLambda instead. - static final int MSG_START = 1; - static final int MSG_STOP = 2; - - static final int MSG_UPDATE_CLIENT_USAGE = 11; - static final int MSG_SEND_CONTROL_REQUEST = 12; - private final WeakReference<MediaRouter2ServiceImpl> mServiceRef; private final UserRecord mUserRecord; private final MediaRoute2ProviderWatcher mWatcher; @@ -524,28 +521,6 @@ class MediaRouter2ServiceImpl { this, mUserRecord.mUserId); } - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_START: { - start(); - break; - } - case MSG_STOP: { - stop(); - break; - } - case MSG_UPDATE_CLIENT_USAGE: { - updateClientUsage((ClientRecord) msg.obj); - break; - } - case MSG_SEND_CONTROL_REQUEST: { - Pair<MediaRoute2Info, Intent> obj = (Pair<MediaRoute2Info, Intent>) msg.obj; - sendControlRequest(obj.first, obj.second); - } - } - } - private void start() { if (!mRunning) { mRunning = true; @@ -613,7 +588,7 @@ class MediaRouter2ServiceImpl { private void scheduleUpdateManagerState() { if (!mManagerStateUpdateScheduled) { mManagerStateUpdateScheduled = true; - post(this::updateManagerState); + sendMessage(PooledLambda.obtainMessage(UserHandler::updateManagerState, this)); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 07fd3228dec2..d30895efbdc3 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -401,7 +401,7 @@ public class NotificationManagerService extends SystemService { // for enabling and disabling notification pulse behavior boolean mScreenOn = true; - protected boolean mInCall = false; + protected boolean mInCallStateOffHook = false; boolean mNotificationPulseEnabled; private Uri mInCallNotificationUri; @@ -1299,7 +1299,7 @@ public class NotificationManagerService extends SystemService { mScreenOn = false; updateNotificationPulse(); } else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { - mInCall = TelephonyManager.EXTRA_STATE_OFFHOOK + mInCallStateOffHook = TelephonyManager.EXTRA_STATE_OFFHOOK .equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE)); updateNotificationPulse(); } else if (action.equals(Intent.ACTION_USER_STOPPED)) { @@ -5824,7 +5824,7 @@ public class NotificationManagerService extends SystemService { } if (DBG) Slog.v(TAG, "Interrupting!"); if (hasValidSound) { - if (mInCall) { + if (isInCall()) { playInCallNotification(); beep = true; } else { @@ -5838,7 +5838,7 @@ public class NotificationManagerService extends SystemService { final boolean ringerModeSilent = mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT; - if (!mInCall && hasValidVibrate && !ringerModeSilent) { + if (!isInCall() && hasValidVibrate && !ringerModeSilent) { buzz = playVibration(record, vibration, hasValidSound); if(buzz) { mVibrateNotificationKey = key; @@ -5926,7 +5926,7 @@ public class NotificationManagerService extends SystemService { return false; } // not if in call or the screen's on - if (mInCall || mScreenOn) { + if (isInCall() || mScreenOn) { return false; } @@ -7027,7 +7027,7 @@ public class NotificationManagerService extends SystemService { } // Don't flash while we are in a call or screen is on - if (ledNotification == null || mInCall || mScreenOn) { + if (ledNotification == null || isInCall() || mScreenOn) { mNotificationLight.turnOff(); } else { NotificationRecord.Light light = ledNotification.getLight(); @@ -7495,6 +7495,18 @@ public class NotificationManagerService extends SystemService { } } + private boolean isInCall() { + if (mInCallStateOffHook) { + return true; + } + int audioMode = mAudioManager.getMode(); + if (audioMode == AudioManager.MODE_IN_CALL + || audioMode == AudioManager.MODE_IN_COMMUNICATION) { + return true; + } + return false; + } + public class NotificationAssistants extends ManagedServices { static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants"; diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java new file mode 100644 index 000000000000..55fbcb4344cf --- /dev/null +++ b/services/core/java/com/android/server/om/IdmapDaemon.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.om; + +import static android.content.Context.IDMAP_SERVICE; + +import static com.android.server.om.OverlayManagerService.DEBUG; +import static com.android.server.om.OverlayManagerService.TAG; + +import android.os.IBinder; +import android.os.IIdmap2; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.util.Slog; + +import com.android.server.IoThread; + +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * To prevent idmap2d from continuously running, the idmap daemon will terminate after 10 + * seconds without a transaction. + **/ +class IdmapDaemon { + // The amount of time in milliseconds to wait after a transaction to the idmap service is made + // before stopping the service. + private static final int SERVICE_TIMEOUT_MS = 10000; + + // The amount of time in milliseconds to wait when attempting to connect to idmap service. + private static final int SERVICE_CONNECT_TIMEOUT_MS = 5000; + + private static final Object IDMAP_TOKEN = new Object(); + private static final String IDMAP_DAEMON = "idmap2d"; + + private static IdmapDaemon sInstance; + private volatile IIdmap2 mService; + private final AtomicInteger mOpenedCount = new AtomicInteger(); + + /** + * An {@link AutoCloseable} connection to the idmap service. When the connection is closed or + * finalized, the idmap service will be stopped after a period of time unless another connection + * to the service is open. + **/ + private class Connection implements AutoCloseable { + private boolean mOpened = true; + + private Connection() { + synchronized (IDMAP_TOKEN) { + mOpenedCount.incrementAndGet(); + } + } + + @Override + public void close() { + synchronized (IDMAP_TOKEN) { + if (!mOpened) { + return; + } + + mOpened = false; + if (mOpenedCount.decrementAndGet() != 0) { + // Only post the callback to stop the service if the service does not have an + // open connection. + return; + } + + IoThread.getHandler().postDelayed(() -> { + synchronized (IDMAP_TOKEN) { + // Only stop the service if the service does not have an open connection. + if (mService == null || mOpenedCount.get() != 0) { + return; + } + + stopIdmapService(); + mService = null; + } + }, IDMAP_TOKEN, SERVICE_TIMEOUT_MS); + } + } + } + + static IdmapDaemon getInstance() { + if (sInstance == null) { + sInstance = new IdmapDaemon(); + } + return sInstance; + } + + String createIdmap(String targetPath, String overlayPath, int policies, boolean enforce, + int userId) throws Exception { + try (Connection connection = connect()) { + return mService.createIdmap(targetPath, overlayPath, policies, enforce, userId); + } + } + + boolean removeIdmap(String overlayPath, int userId) throws Exception { + try (Connection connection = connect()) { + return mService.removeIdmap(overlayPath, userId); + } + } + + boolean verifyIdmap(String overlayPath, int policies, boolean enforce, int userId) + throws Exception { + try (Connection connection = connect()) { + return mService.verifyIdmap(overlayPath, policies, enforce, userId); + } + } + + String getIdmapPath(String overlayPath, int userId) throws Exception { + try (Connection connection = connect()) { + return mService.getIdmapPath(overlayPath, userId); + } + } + + static void startIdmapService() { + SystemProperties.set("ctl.start", IDMAP_DAEMON); + } + + static void stopIdmapService() { + SystemProperties.set("ctl.stop", IDMAP_DAEMON); + } + + private Connection connect() throws Exception { + synchronized (IDMAP_TOKEN) { + IoThread.getHandler().removeCallbacksAndMessages(IDMAP_TOKEN); + if (mService != null) { + // Not enough time has passed to stop the idmap service. Reuse the existing + // interface. + return new Connection(); + } + + // Start the idmap service if it is not currently running. + startIdmapService(); + + // Block until the service is found. + FutureTask<IBinder> bindIdmap = new FutureTask<>(() -> { + IBinder binder = null; + while (binder == null) { + try { + binder = ServiceManager.getService(IDMAP_SERVICE); + Thread.sleep(100); + } catch (Exception e) { + Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not retrieved; " + + e.getMessage()); + } + } + return binder; + }); + + IBinder binder; + try { + IoThread.getHandler().postAtFrontOfQueue(bindIdmap); + binder = bindIdmap.get(SERVICE_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (Exception rethrow) { + Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not found;"); + throw rethrow; + } + + try { + binder.linkToDeath(() -> { + Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died"); + }, 0); + } catch (RemoteException rethrow) { + Slog.e(TAG, "service '" + IDMAP_SERVICE + "' failed to be bound"); + throw rethrow; + } + + mService = IIdmap2.Stub.asInterface(binder); + if (DEBUG) { + Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected"); + } + + return new Connection(); + } + } +} diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index b604aa87f8f3..288ef0e618b6 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -16,9 +16,6 @@ package com.android.server.om; -import static android.content.Context.IDMAP_SERVICE; -import static android.text.format.DateUtils.SECOND_IN_MILLIS; - import static com.android.server.om.OverlayManagerService.DEBUG; import static com.android.server.om.OverlayManagerService.TAG; @@ -27,15 +24,11 @@ import android.content.om.OverlayInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.os.Build.VERSION_CODES; -import android.os.IBinder; import android.os.IIdmap2; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.util.Slog; -import com.android.internal.os.BackgroundThread; import com.android.server.om.OverlayManagerServiceImpl.PackageManagerHelper; import com.android.server.pm.Installer; @@ -51,11 +44,6 @@ import java.io.File; */ class IdmapManager { private static final boolean FEATURE_FLAG_IDMAP2 = true; - - private final Installer mInstaller; - private final PackageManagerHelper mPackageManager; - private IIdmap2 mIdmap2Service; - private static final boolean VENDOR_IS_Q_OR_LATER; static { final String value = SystemProperties.get("ro.vndk.version", "29"); @@ -70,12 +58,14 @@ class IdmapManager { VENDOR_IS_Q_OR_LATER = isQOrLater; } + private final Installer mInstaller; + private final PackageManagerHelper mPackageManager; + private final IdmapDaemon mIdmapDaemon; + IdmapManager(final Installer installer, final PackageManagerHelper packageManager) { mInstaller = installer; mPackageManager = packageManager; - if (FEATURE_FLAG_IDMAP2) { - connectToIdmap2d(); - } + mIdmapDaemon = IdmapDaemon.getInstance(); } boolean createIdmap(@NonNull final PackageInfo targetPackage, @@ -91,11 +81,11 @@ class IdmapManager { if (FEATURE_FLAG_IDMAP2) { int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId); boolean enforce = enforceOverlayable(overlayPackage); - if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) { + if (mIdmapDaemon.verifyIdmap(overlayPath, policies, enforce, userId)) { return true; } - return mIdmap2Service.createIdmap(targetPath, overlayPath, policies, enforce, - userId) != null; + return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies, + enforce, userId) != null; } else { mInstaller.idmap(targetPath, overlayPath, sharedGid); return true; @@ -113,7 +103,7 @@ class IdmapManager { } try { if (FEATURE_FLAG_IDMAP2) { - return mIdmap2Service.removeIdmap(oi.baseCodePath, userId); + return mIdmapDaemon.removeIdmap(oi.baseCodePath, userId); } else { mInstaller.removeIdmap(oi.baseCodePath); return true; @@ -137,7 +127,7 @@ class IdmapManager { final int userId) { if (FEATURE_FLAG_IDMAP2) { try { - return mIdmap2Service.getIdmapPath(overlayPackagePath, userId); + return mIdmapDaemon.getIdmapPath(overlayPackagePath, userId); } catch (Exception e) { Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": " + e.getMessage()); @@ -151,35 +141,6 @@ class IdmapManager { } } - private void connectToIdmap2d() { - IBinder binder = ServiceManager.getService(IDMAP_SERVICE); - if (binder != null) { - try { - binder.linkToDeath(new IBinder.DeathRecipient() { - @Override - public void binderDied() { - Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died; reconnecting..."); - connectToIdmap2d(); - } - - }, 0); - } catch (RemoteException e) { - binder = null; - } - } - if (binder != null) { - mIdmap2Service = IIdmap2.Stub.asInterface(binder); - if (DEBUG) { - Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected"); - } - } else { - Slog.w(TAG, "service '" + IDMAP_SERVICE + "' not found; trying again..."); - BackgroundThread.getHandler().postDelayed(() -> { - connectToIdmap2d(); - }, SECOND_IN_MILLIS); - } - } - /** * Checks if overlayable and policies should be enforced on the specified overlay for backwards * compatibility with pre-Q overlays. @@ -237,14 +198,9 @@ class IdmapManager { return fulfilledPolicies | IIdmap2.POLICY_OEM_PARTITION; } - // Check partitions for which there exists no policy so overlays on these partitions will - // not fulfill the system policy. - if (ai.isProductServices()) { - return fulfilledPolicies; - } - + // System_ext partition (/system_ext) is considered as system // Check this last since every partition except for data is scanned as system in the PMS. - if (ai.isSystemApp()) { + if (ai.isSystemApp() || ai.isSystemExt()) { return fulfilledPolicies | IIdmap2.POLICY_SYSTEM_PARTITION; } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index da69986cd59f..ce951816d3a6 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -262,6 +262,7 @@ public final class OverlayManagerService extends SystemService { initIfNeeded(); onSwitchUser(UserHandle.USER_SYSTEM); + IdmapDaemon.stopIdmapService(); publishBinderService(Context.OVERLAY_SERVICE, mService); publishLocalService(OverlayManagerService.class, this); diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 9094e1bf4c5a..e5a2e777a796 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -376,12 +376,12 @@ public class OtaDexoptService extends IOtaDexopt.Stub { continue; } - // If the path is in /system, /vendor, /product or /product_services, ignore. It will + // If the path is in /system, /vendor, /product or /system_ext, ignore. It will // have been ota-dexopted into /data/ota and moved into the dalvik-cache already. if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor") || pkg.codePath.startsWith("/product") - || pkg.codePath.startsWith("/product_services")) { + || pkg.codePath.startsWith("/system_ext")) { continue; } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 6f9a918d105c..4eddb9301a69 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STOR import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SPLIT; +import static android.content.pm.PackageParser.APEX_FILE_EXTENSION; import static android.content.pm.PackageParser.APK_FILE_EXTENSION; import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDONLY; @@ -1484,7 +1485,29 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "Too many files for apex install"); } - mResolvedBaseFile = addedFiles[0]; + try { + resolveStageDirLocked(); + } catch (IOException e) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to resolve stage location", e); + } + + File addedFile = addedFiles[0]; // there is only one file + + // Ensure file name has proper suffix + final String sourceName = addedFile.getName(); + final String targetName = sourceName.endsWith(APEX_FILE_EXTENSION) + ? sourceName + : sourceName + APEX_FILE_EXTENSION; + if (!FileUtils.isValidExtFilename(targetName)) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Invalid filename: " + targetName); + } + + final File targetFile = new File(mResolvedStageDir, targetName); + resolveAndStageFile(addedFile, targetFile); + + mResolvedBaseFile = targetFile; } /** diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8660d191960c..6a672c3961e5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -311,7 +311,6 @@ import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.PackageDexUsage; import com.android.server.pm.dex.ViewCompiler; import com.android.server.pm.permission.BasePermission; -import com.android.server.pm.permission.DefaultPermissionGrantPolicy; import com.android.server.pm.permission.PermissionManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.pm.permission.PermissionsState; @@ -472,7 +471,7 @@ public class PackageManagerService extends IPackageManager.Stub static final int SCAN_AS_OEM = 1 << 19; static final int SCAN_AS_VENDOR = 1 << 20; static final int SCAN_AS_PRODUCT = 1 << 21; - static final int SCAN_AS_PRODUCT_SERVICES = 1 << 22; + static final int SCAN_AS_SYSTEM_EXT = 1 << 22; static final int SCAN_AS_ODM = 1 << 23; @IntDef(flag = true, prefix = { "SCAN_" }, value = { @@ -584,7 +583,7 @@ public class PackageManagerService extends IPackageManager.Stub private static final String PRODUCT_OVERLAY_DIR = "/product/overlay"; - private static final String PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay"; + private static final String SYSTEM_EXT_OVERLAY_DIR = "/system_ext/overlay"; private static final String ODM_OVERLAY_DIR = "/odm/overlay"; @@ -948,8 +947,6 @@ public class PackageManagerService extends IPackageManager.Stub final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates = new SparseArray<>(); - // TODO remove this and go through mPermissonManager directly - final DefaultPermissionGrantPolicy mDefaultPermissionPolicy; // Internal interface for permission manager private final PermissionManagerServiceInternal mPermissionManager; // Public interface for permission manager @@ -992,15 +989,6 @@ public class PackageManagerService extends IPackageManager.Stub void receiveVerificationResponse(int verificationId); } - @GuardedBy("mPackages") - private PackageManagerInternal.DefaultBrowserProvider mDefaultBrowserProvider; - - @GuardedBy("mPackages") - private PackageManagerInternal.DefaultDialerProvider mDefaultDialerProvider; - - @GuardedBy("mPackages") - private PackageManagerInternal.DefaultHomeProvider mDefaultHomeProvider; - private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> { private Context mContext; private ComponentName mIntentFilterVerifierComponent; @@ -1966,7 +1954,7 @@ public class PackageManagerService extends IPackageManager.Stub final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting.getInstallReason(userId) != PackageManager.INSTALL_REASON_DEVICE_RESTORE) { - setDefaultBrowserAsyncLPw(null, userId); + mPermissionManager.setDefaultBrowser(null, true, true, userId); } } } @@ -2348,7 +2336,6 @@ public class PackageManagerService extends IPackageManager.Stub mPackages /*externalLock*/); mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr"); - mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy(); mSettings = new Settings(Environment.getDataDirectory(), mPermissionManager.getPermissionSettings(), mPackages); } @@ -2540,7 +2527,7 @@ public class PackageManagerService extends IPackageManager.Stub scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE; } - // Collect vendor/product/product_services overlay packages. (Do this before scanning + // Collect vendor/product/system_ext overlay packages. (Do this before scanning // any apps.) // For security and version matching reason, only consider overlay packages if they // reside in the right directory. @@ -2558,12 +2545,12 @@ public class PackageManagerService extends IPackageManager.Stub | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT, 0); - scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR), + scanDirTracedLI(new File(SYSTEM_EXT_OVERLAY_DIR), mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM - | SCAN_AS_PRODUCT_SERVICES, + | SCAN_AS_SYSTEM_EXT, 0); scanDirTracedLI(new File(ODM_OVERLAY_DIR), mDefParseFlags @@ -2721,37 +2708,37 @@ public class PackageManagerService extends IPackageManager.Stub | SCAN_AS_PRODUCT, 0); - // Collected privileged /product_services packages. - File privilegedProductServicesAppDir = - new File(Environment.getProductServicesDirectory(), "priv-app"); + // Collected privileged /system_ext packages. + File privilegedSystemExtAppDir = + new File(Environment.getSystemExtDirectory(), "priv-app"); try { - privilegedProductServicesAppDir = - privilegedProductServicesAppDir.getCanonicalFile(); + privilegedSystemExtAppDir = + privilegedSystemExtAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } - scanDirTracedLI(privilegedProductServicesAppDir, + scanDirTracedLI(privilegedSystemExtAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM - | SCAN_AS_PRODUCT_SERVICES + | SCAN_AS_SYSTEM_EXT | SCAN_AS_PRIVILEGED, 0); - // Collect ordinary /product_services packages. - File productServicesAppDir = new File(Environment.getProductServicesDirectory(), "app"); + // Collect ordinary /system_ext packages. + File systemExtAppDir = new File(Environment.getSystemExtDirectory(), "app"); try { - productServicesAppDir = productServicesAppDir.getCanonicalFile(); + systemExtAppDir = systemExtAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } - scanDirTracedLI(productServicesAppDir, + scanDirTracedLI(systemExtAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM - | SCAN_AS_PRODUCT_SERVICES, + | SCAN_AS_SYSTEM_EXT, 0); // Prune any system packages that no longer exist. @@ -2981,23 +2968,23 @@ public class PackageManagerService extends IPackageManager.Stub scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT; - } else if (FileUtils.contains(privilegedProductServicesAppDir, scanFile)) { + } else if (FileUtils.contains(privilegedSystemExtAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM - | SCAN_AS_PRODUCT_SERVICES + | SCAN_AS_SYSTEM_EXT | SCAN_AS_PRIVILEGED; - } else if (FileUtils.contains(productServicesAppDir, scanFile)) { + } else if (FileUtils.contains(systemExtAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM - | SCAN_AS_PRODUCT_SERVICES; + | SCAN_AS_SYSTEM_EXT; } else { Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile); continue; @@ -5499,40 +5486,6 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId) { - if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, - "isPermissionRevokedByPolicy for user " + userId); - } - - if (checkPermission(permission, packageName, userId) - == PackageManager.PERMISSION_GRANTED) { - return false; - } - - final int callingUid = Binder.getCallingUid(); - if (getInstantAppPackageName(callingUid) != null) { - if (!isCallerSameApp(packageName, callingUid)) { - return false; - } - } else { - if (isInstantApp(packageName, userId)) { - return false; - } - } - - final long identity = Binder.clearCallingIdentity(); - try { - final int flags = mPermissionManager - .getPermissionFlags(permission, packageName, Binder.getCallingUid(), userId); - return (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0; - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override public String getPermissionControllerPackageName() { synchronized (mPackages) { return mRequiredPermissionControllerPackage; @@ -5588,46 +5541,6 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public boolean shouldShowRequestPermissionRationale(String permName, - String packageName, int userId) { - if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, - "canShowRequestPermissionRationale for user " + userId); - } - - final int uid = getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId); - if (UserHandle.getAppId(getCallingUid()) != UserHandle.getAppId(uid)) { - return false; - } - - if (checkPermission(permName, packageName, userId) - == PackageManager.PERMISSION_GRANTED) { - return false; - } - - final int flags; - - final long identity = Binder.clearCallingIdentity(); - try { - flags = mPermissionManager - .getPermissionFlags(permName, packageName, Binder.getCallingUid(), userId); - } finally { - Binder.restoreCallingIdentity(identity); - } - - final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED - | PackageManager.FLAG_PERMISSION_POLICY_FIXED - | PackageManager.FLAG_PERMISSION_USER_FIXED; - - if ((flags & fixedFlags) != 0) { - return false; - } - - return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0; - } - - @Override public boolean isProtectedBroadcast(String actionName) { // allow instant applications synchronized (mProtectedBroadcasts) { @@ -7286,7 +7199,8 @@ public class PackageManagerService extends IPackageManager.Stub } else { // Browser/generic handling case. If there's a default browser, go straight // to that (but only if there is no other higher-priority match). - final String defaultBrowserPackageName = getDefaultBrowserPackageName(userId); + final String defaultBrowserPackageName = + mPermissionManager.getDefaultBrowser(userId); int maxMatchPrio = 0; ResolveInfo defaultBrowserMatch = null; final int numCandidates = matchAllList.size(); @@ -10340,7 +10254,7 @@ public class PackageManagerService extends IPackageManager.Stub * <li>{@link #SCAN_AS_OEM}</li> * <li>{@link #SCAN_AS_VENDOR}</li> * <li>{@link #SCAN_AS_PRODUCT}</li> - * <li>{@link #SCAN_AS_PRODUCT_SERVICES}</li> + * <li>{@link #SCAN_AS_SYSTEM_EXT}</li> * <li>{@link #SCAN_AS_INSTANT_APP}</li> * <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li> * <li>{@link #SCAN_AS_ODM}</li> @@ -10377,8 +10291,8 @@ public class PackageManagerService extends IPackageManager.Stub scanFlags |= SCAN_AS_PRODUCT; } if ((systemPkgSetting.pkgPrivateFlags - & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0) { - scanFlags |= SCAN_AS_PRODUCT_SERVICES; + & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0) { + scanFlags |= SCAN_AS_SYSTEM_EXT; } if ((systemPkgSetting.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_ODM) != 0) { @@ -11156,8 +11070,8 @@ public class PackageManagerService extends IPackageManager.Stub pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT; } - if ((scanFlags & SCAN_AS_PRODUCT_SERVICES) != 0) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES; + if ((scanFlags & SCAN_AS_SYSTEM_EXT) != 0) { + pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT; } if ((scanFlags & SCAN_AS_ODM) != 0) { @@ -12121,8 +12035,8 @@ public class PackageManagerService extends IPackageManager.Stub codeRoot = Environment.getOdmDirectory(); } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) { codeRoot = Environment.getProductDirectory(); - } else if (FileUtils.contains(Environment.getProductServicesDirectory(), codePath)) { - codeRoot = Environment.getProductServicesDirectory(); + } else if (FileUtils.contains(Environment.getSystemExtDirectory(), codePath)) { + codeRoot = Environment.getSystemExtDirectory(); } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) { codeRoot = Environment.getOdmDirectory(); } else { @@ -12826,7 +12740,9 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden) { - enforceSystemOrPhoneCaller("setSystemAppHiddenUntilInstalled"); + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils + .enforceSystemOrPhoneCaller("setSystemAppHiddenUntilInstalled", callingUid); synchronized (mPackages) { final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null || !pkgSetting.isSystem()) { @@ -12849,7 +12765,9 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean setSystemAppInstallState(String packageName, boolean installed, int userId) { - enforceSystemOrPhoneCaller("setSystemAppInstallState"); + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils + .enforceSystemOrPhoneCaller("setSystemAppInstallState", callingUid); synchronized (mPackages) { final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); // The target app should always be in system @@ -13421,7 +13339,7 @@ public class PackageManagerService extends IPackageManager.Stub final long callingId = Binder.clearCallingIdentity(); try { final String activeLauncherPackageName = getActiveLauncherPackageName(userId); - final String dialerPackageName = getDefaultDialerPackageName(userId); + final String dialerPackageName = mPermissionManager.getDefaultDialer(userId); for (int i = 0; i < packageNames.length; i++) { canSuspend[i] = false; final String packageName = packageNames[i]; @@ -13503,19 +13421,6 @@ public class PackageManagerService extends IPackageManager.Stub return resolveInfo == null ? null : resolveInfo.activityInfo.packageName; } - @Nullable - private String getDefaultDialerPackageName(@UserIdInt int userId) { - PackageManagerInternal.DefaultDialerProvider provider; - synchronized (mPackages) { - provider = mDefaultDialerProvider; - } - if (provider == null) { - Slog.e(TAG, "mDefaultDialerProvider is null"); - return null; - } - return provider.getDefaultDialer(userId); - } - @Override public void verifyPendingInstall(int id, int verificationCode) throws RemoteException { mContext.enforceCallingOrSelfPermission( @@ -13874,75 +13779,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - @Override - public boolean setDefaultBrowserPackageName(String packageName, int userId) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); - if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); - } - if (userId == UserHandle.USER_ALL) { - return false; - } - PackageManagerInternal.DefaultBrowserProvider provider; - synchronized (mPackages) { - provider = mDefaultBrowserProvider; - } - if (provider == null) { - Slog.e(TAG, "mDefaultBrowserProvider is null"); - return false; - } - boolean successful = provider.setDefaultBrowser(packageName, userId); - if (!successful) { - return false; - } - if (packageName != null) { - synchronized (mPackages) { - mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultBrowser(packageName, - userId); - } - } - return true; - } - - private void setDefaultBrowserAsyncLPw(@Nullable String packageName, @UserIdInt int userId) { - if (userId == UserHandle.USER_ALL) { - return; - } - if (mDefaultBrowserProvider == null) { - Slog.e(TAG, "mDefaultBrowserProvider is null"); - return; - } - mDefaultBrowserProvider.setDefaultBrowserAsync(packageName, userId); - if (packageName != null) { - synchronized (mPackages) { - mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultBrowser(packageName, - userId); - } - } - } - - @Override - public String getDefaultBrowserPackageName(int userId) { - if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); - } - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - return null; - } - PackageManagerInternal.DefaultBrowserProvider provider; - synchronized (mPackages) { - provider = mDefaultBrowserProvider; - } - if (provider == null) { - Slog.e(TAG, "mDefaultBrowserProvider is null"); - return null; - } - return provider.getDefaultBrowser(userId); - } - /** * Get the "allow unknown sources" setting. * @@ -17678,9 +17514,9 @@ public class PackageManagerService extends IPackageManager.Stub return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; } - private static boolean isProductServicesApp(PackageParser.Package pkg) { + private static boolean isSystemExtApp(PackageParser.Package pkg) { return (pkg.applicationInfo.privateFlags - & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0; + & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0; } private static boolean isOdmApp(PackageParser.Package pkg) { @@ -18445,13 +18281,13 @@ public class PackageManagerService extends IPackageManager.Stub final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app"); final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app"); final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app"); - final File privilegedProductServicesAppDir = - new File(Environment.getProductServicesDirectory(), "priv-app"); + final File privilegedSystemExtAppDir = + new File(Environment.getSystemExtDirectory(), "priv-app"); return path.startsWith(privilegedAppDir.getCanonicalPath() + "/") || path.startsWith(privilegedVendorAppDir.getCanonicalPath() + "/") || path.startsWith(privilegedOdmAppDir.getCanonicalPath() + "/") || path.startsWith(privilegedProductAppDir.getCanonicalPath() + "/") - || path.startsWith(privilegedProductServicesAppDir.getCanonicalPath() + "/"); + || path.startsWith(privilegedSystemExtAppDir.getCanonicalPath() + "/"); } catch (IOException e) { Slog.e(TAG, "Unable to access code path " + path); } @@ -18486,10 +18322,10 @@ public class PackageManagerService extends IPackageManager.Stub return false; } - static boolean locationIsProductServices(String path) { + static boolean locationIsSystemExt(String path) { try { return path.startsWith( - Environment.getProductServicesDirectory().getCanonicalPath() + "/"); + Environment.getSystemExtDirectory().getCanonicalPath() + "/"); } catch (IOException e) { Slog.e(TAG, "Unable to access code path " + path); } @@ -18622,8 +18458,8 @@ public class PackageManagerService extends IPackageManager.Stub if (locationIsProduct(codePathString)) { scanFlags |= SCAN_AS_PRODUCT; } - if (locationIsProductServices(codePathString)) { - scanFlags |= SCAN_AS_PRODUCT_SERVICES; + if (locationIsSystemExt(codePathString)) { + scanFlags |= SCAN_AS_SYSTEM_EXT; } if (locationIsOdm(codePathString)) { scanFlags |= SCAN_AS_ODM; @@ -19688,10 +19524,10 @@ public class PackageManagerService extends IPackageManager.Stub } private void clearDefaultBrowserIfNeededForUser(String packageName, int userId) { - final String defaultBrowserPackageName = getDefaultBrowserPackageName(userId); + final String defaultBrowserPackageName = mPermissionManager.getDefaultBrowser(userId); if (!TextUtils.isEmpty(defaultBrowserPackageName)) { if (packageName.equals(defaultBrowserPackageName)) { - setDefaultBrowserPackageName(null, userId); + mPermissionManager.setDefaultBrowser(null, true, true, userId); } } } @@ -19719,7 +19555,7 @@ public class PackageManagerService extends IPackageManager.Stub // significant refactoring to keep all default apps in the package // manager (cleaner but more work) or have the services provide // callbacks to the package manager to request a default app reset. - setDefaultBrowserPackageName(null, userId); + mPermissionManager.setDefaultBrowser(null, true, true, userId); resetNetworkPolicies(userId); synchronized (mPackages) { scheduleWritePackageRestrictionsLocked(userId); @@ -19972,17 +19808,14 @@ public class PackageManagerService extends IPackageManager.Stub parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name()); restoreFromXml(parser, userId, TAG_DEFAULT_APPS, (parser1, userId1) -> { - String defaultBrowser; + final String defaultBrowser; synchronized (mPackages) { mSettings.readDefaultAppsLPw(parser1, userId1); defaultBrowser = mSettings.removeDefaultBrowserPackageNameLPw(userId1); } if (defaultBrowser != null) { - PackageManagerInternal.DefaultBrowserProvider provider; - synchronized (mPackages) { - provider = mDefaultBrowserProvider; - } - provider.setDefaultBrowser(defaultBrowser, userId1); + mPermissionManager + .setDefaultBrowser(defaultBrowser, false, false, userId1); } }); } catch (Exception e) { @@ -20219,15 +20052,7 @@ public class PackageManagerService extends IPackageManager.Stub } allHomeCandidates.addAll(resolveInfos); - PackageManagerInternal.DefaultHomeProvider provider; - synchronized (mPackages) { - provider = mDefaultHomeProvider; - } - if (provider == null) { - Slog.e(TAG, "mDefaultHomeProvider is null"); - return null; - } - String packageName = provider.getDefaultHome(userId); + final String packageName = mPermissionManager.getDefaultHome(userId); if (packageName == null) { return null; } @@ -20280,15 +20105,7 @@ public class PackageManagerService extends IPackageManager.Stub final String packageName = preferredResolveInfo != null && preferredResolveInfo.activityInfo != null ? preferredResolveInfo.activityInfo.packageName : null; - final PackageManagerInternal.DefaultHomeProvider provider; - synchronized (mPackages) { - provider = mDefaultHomeProvider; - } - if (provider == null) { - Slog.e(TAG, "Default home provider has not been set"); - return false; - } - final String currentPackageName = provider.getDefaultHome(userId); + final String currentPackageName = mPermissionManager.getDefaultHome(userId); if (TextUtils.equals(currentPackageName, packageName)) { return false; } @@ -20298,7 +20115,7 @@ public class PackageManagerService extends IPackageManager.Stub // PermissionController manages default home directly. return false; } - provider.setDefaultHomeAsync(packageName, userId, (successful) -> { + mPermissionManager.setDefaultHome(currentPackageName, userId, (successful) -> { if (successful) { postPreferredActivityChangedBroadcast(userId); } @@ -20854,7 +20671,8 @@ public class PackageManagerService extends IPackageManager.Stub // Disable any carrier apps. We do this very early in boot to prevent the apps from being // disabled after already being started. CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this, - mContext.getContentResolver(), UserHandle.USER_SYSTEM); + mPermissionManagerService, mContext.getContentResolver(), + UserHandle.USER_SYSTEM); disableSkuSpecificApps(); @@ -20868,8 +20686,6 @@ public class PackageManagerService extends IPackageManager.Stub Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled); } - int[] grantPermissionsUserIds = EMPTY_INT_ARRAY; - synchronized (mPackages) { // Verify that all of the preferred activity components actually // exist. It is possible for applications to be updated and at @@ -20899,27 +20715,9 @@ public class PackageManagerService extends IPackageManager.Stub mSettings.mPreferredActivities.keyAt(i)); } } - - for (int userId : UserManagerService.getInstance().getUserIds()) { - if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) { - grantPermissionsUserIds = ArrayUtils.appendInt( - grantPermissionsUserIds, userId); - } - } } sUserManager.systemReady(); - // If we upgraded grant all default permissions before kicking off. - for (int userId : grantPermissionsUserIds) { - mDefaultPermissionPolicy.grantDefaultPermissions(userId); - } - - if (grantPermissionsUserIds == EMPTY_INT_ARRAY) { - // If we did not grant default permissions, we preload from this the - // default permission exceptions lazily to ensure we don't hit the - // disk on a new user creation. - mDefaultPermissionPolicy.scheduleReadDefaultPermissionExceptions(); - } // Now that we've scanned all packages, and granted any default // permissions, ensure permissions are updated. Beware of dragons if you @@ -22943,11 +22741,7 @@ public class PackageManagerService extends IPackageManager.Stub } void onNewUserCreated(final int userId) { - mDefaultPermissionPolicy.grantDefaultPermissions(userId); - synchronized(mPackages) { - // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG - mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, true); - } + mPermissionManager.onNewUserCreated(userId); } @Override @@ -22962,44 +22756,6 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public void setPermissionEnforced(String permission, boolean enforced) { - // TODO: Now that we no longer change GID for storage, this should to away. - mContext.enforceCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, - "setPermissionEnforced"); - if (READ_EXTERNAL_STORAGE.equals(permission)) { - synchronized (mPackages) { - if (mSettings.mReadExternalStorageEnforced == null - || mSettings.mReadExternalStorageEnforced != enforced) { - mSettings.mReadExternalStorageEnforced = - enforced ? Boolean.TRUE : Boolean.FALSE; - mSettings.writeLPr(); - } - } - // kill any non-foreground processes so we restart them and - // grant/revoke the GID. - final IActivityManager am = ActivityManager.getService(); - if (am != null) { - final long token = Binder.clearCallingIdentity(); - try { - am.killProcessesBelowForeground("setPermissionEnforcement"); - } catch (RemoteException e) { - } finally { - Binder.restoreCallingIdentity(token); - } - } - } else { - throw new IllegalArgumentException("No selective enforcement for " + permission); - } - } - - @Override - @Deprecated - public boolean isPermissionEnforced(String permission) { - // allow instant applications - return true; - } - - @Override public boolean isStorageLow() { // allow instant applications final long token = Binder.clearCallingIdentity(); @@ -23463,8 +23219,20 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean filterAppAccess(PackageParser.Package pkg, int callingUid, int userId) { synchronized (mPackages) { - return PackageManagerService.this.filterAppAccessLPr( - (PackageSetting) pkg.mExtras, callingUid, userId); + return PackageManagerService.this + .filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid, userId); + } + } + + @Override + public boolean filterAppAccess(String packageName, int callingUid, int userId) { + synchronized (mPackages) { + final PackageParser.Package pkg = mPackages.get(packageName); + if (pkg == null) { + return false; + } + return PackageManagerService.this + .filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid, userId); } } @@ -23531,7 +23299,7 @@ public class PackageManagerService extends IPackageManager.Stub public String getKnownPackageName(int knownPackage, int userId) { switch(knownPackage) { case PackageManagerInternal.PACKAGE_BROWSER: - return getDefaultBrowserPackageName(userId); + return mPermissionManager.getDefaultBrowser(userId); case PackageManagerInternal.PACKAGE_INSTALLER: return mRequiredInstallerPackage; case PackageManagerInternal.PACKAGE_SETUP_WIZARD: @@ -23565,37 +23333,6 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public void setLocationPackagesProvider(PackagesProvider provider) { - mDefaultPermissionPolicy.setLocationPackagesProvider(provider); - } - - @Override - public void setLocationExtraPackagesProvider(PackagesProvider provider) { - mDefaultPermissionPolicy.setLocationExtraPackagesProvider(provider); - } - - @Override - public void setVoiceInteractionPackagesProvider(PackagesProvider provider) { - mDefaultPermissionPolicy.setVoiceInteractionPackagesProvider(provider); - } - - @Override - public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) { - mDefaultPermissionPolicy.setUseOpenWifiAppPackagesProvider(provider); - } - - @Override - public void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider) { - mDefaultPermissionPolicy.setSyncAdapterPackagesProvider(provider); - } - - @Override - public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) { - mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultUseOpenWifiApp( - packageName, userId); - } - - @Override public void setKeepUninstalledPackages(final List<String> packageList) { Preconditions.checkNotNull(packageList); List<String> removedFromList = null; @@ -24108,27 +23845,6 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider) { - synchronized (mPackages) { - mDefaultBrowserProvider = provider; - } - } - - @Override - public void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider) { - synchronized (mPackages) { - mDefaultDialerProvider = provider; - } - } - - @Override - public void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider) { - synchronized (mPackages) { - mDefaultHomeProvider = provider; - } - } - - @Override public boolean isApexPackage(String packageName) { return PackageManagerService.this.mApexManager.isApexPackage(packageName); } @@ -24174,13 +23890,6 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public boolean wereDefaultPermissionsGrantedSinceBoot(int userId) { - synchronized (mPackages) { - return mDefaultPermissionPolicy.wereDefaultPermissionsGrantedSinceBoot(userId); - } - } - - @Override public void setRuntimePermissionsFingerPrint(@NonNull String fingerPrint, @UserIdInt int userId) { synchronized (mPackages) { @@ -24266,6 +23975,25 @@ public class PackageManagerService extends IPackageManager.Stub && UserHandle.isSameApp(installerPackageSetting.appId, callingUid); } } + + @Override + public boolean areDefaultRuntimePermissionsGranted(int userId) { + synchronized (mPackages) { + return mSettings.areDefaultRuntimePermissionsGrantedLPr(userId); + } + } + + @Override + public void setReadExternalStorageEnforced(boolean enforced) { + synchronized (mPackages) { + if (mSettings.mReadExternalStorageEnforced != null + && mSettings.mReadExternalStorageEnforced == enforced) { + return; + } + mSettings.mReadExternalStorageEnforced = enforced ? Boolean.TRUE : Boolean.FALSE; + mSettings.writeLPr(); + } + } } @GuardedBy("mPackages") @@ -24334,83 +24062,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - @Override - public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) { - enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps"); - synchronized (mPackages) { - final long identity = Binder.clearCallingIdentity(); - try { - mDefaultPermissionPolicy.grantDefaultPermissionsToEnabledCarrierApps( - packageNames, userId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - } - - @Override - public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) { - enforceSystemOrPhoneCaller("grantDefaultPermissionsToEnabledImsServices"); - synchronized (mPackages) { - final long identity = Binder.clearCallingIdentity(); - try { - mDefaultPermissionPolicy.grantDefaultPermissionsToEnabledImsServices( - packageNames, userId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - } - - @Override - public void grantDefaultPermissionsToEnabledTelephonyDataServices( - String[] packageNames, int userId) { - enforceSystemOrPhoneCaller("grantDefaultPermissionsToEnabledTelephonyDataServices"); - synchronized (mPackages) { - Binder.withCleanCallingIdentity( () -> mDefaultPermissionPolicy. - grantDefaultPermissionsToEnabledTelephonyDataServices( - packageNames, userId)); - } - } - - @Override - public void revokeDefaultPermissionsFromDisabledTelephonyDataServices( - String[] packageNames, int userId) { - enforceSystemOrPhoneCaller("revokeDefaultPermissionsFromDisabledTelephonyDataServices"); - synchronized (mPackages) { - Binder.withCleanCallingIdentity( () -> mDefaultPermissionPolicy. - revokeDefaultPermissionsFromDisabledTelephonyDataServices( - packageNames, userId)); - } - } - - @Override - public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) { - enforceSystemOrPhoneCaller("grantDefaultPermissionsToActiveLuiApp"); - synchronized (mPackages) { - final long identity = Binder.clearCallingIdentity(); - try { - mDefaultPermissionPolicy.grantDefaultPermissionsToActiveLuiApp( - packageName, userId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - } - - @Override - public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) { - enforceSystemOrPhoneCaller("revokeDefaultPermissionsFromLuiApps"); - synchronized (mPackages) { - final long identity = Binder.clearCallingIdentity(); - try { - mDefaultPermissionPolicy.revokeDefaultPermissionsFromLuiApps(packageNames, userId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - } - void forEachPackage(Consumer<PackageParser.Package> actionLocked) { synchronized (mPackages) { int numPackages = mPackages.size(); @@ -24435,14 +24086,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - private static void enforceSystemOrPhoneCaller(String tag) { - int callingUid = Binder.getCallingUid(); - if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) { - throw new SecurityException( - "Cannot call " + tag + " from UID " + callingUid); - } - } - boolean isHistoricalPackageUsageAvailable() { return mPackageUsage.isHistoricalPackageUsageAvailable(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index f56e1ef0de09..4c7db9afee0a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -390,6 +390,17 @@ public class PackageManagerServiceUtils { } /** + * Enforces that the caller must be either the system process or the phone process. + * If not, throws a {@link SecurityException}. + */ + public static void enforceSystemOrPhoneCaller(String methodName, int callingUid) { + if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) { + throw new SecurityException( + "Cannot call " + methodName + " from UID " + callingUid); + } + } + + /** * Derive the value of the {@code cpuAbiOverride} based on the provided * value and an optional stored value from the package settings. */ diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 53c1c1f91beb..85bc9f3d56d6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -2020,7 +2020,7 @@ class PackageManagerShellCommand extends ShellCommand { getErrPrintWriter().println("Error: no enforcement specified"); return 1; } - mInterface.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw)); + mPermissionManager.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw)); return 0; } @@ -2042,10 +2042,10 @@ class PackageManagerShellCommand extends ShellCommand { } } - private boolean isProductServicesApp(String pkg) { + private boolean isSystemExtApp(String pkg) { try { final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM); - return info != null && info.applicationInfo.isProductServices(); + return info != null && info.applicationInfo.isSystemExt(); } catch (RemoteException e) { return false; } @@ -2063,9 +2063,9 @@ class PackageManagerShellCommand extends ShellCommand { privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg); } else if (isProductApp(pkg)) { privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg); - } else if (isProductServicesApp(pkg)) { + } else if (isSystemExtApp(pkg)) { privAppPermissions = SystemConfig.getInstance() - .getProductServicesPrivAppPermissions(pkg); + .getSystemExtPrivAppPermissions(pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); } @@ -2087,9 +2087,9 @@ class PackageManagerShellCommand extends ShellCommand { privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg); } else if (isProductApp(pkg)) { privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg); - } else if (isProductServicesApp(pkg)) { + } else if (isSystemExtApp(pkg)) { privAppPermissions = SystemConfig.getInstance() - .getProductServicesPrivAppDenyPermissions(pkg); + .getSystemExtPrivAppDenyPermissions(pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); } diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index e85989315417..4ea8a30fa206 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -148,8 +148,8 @@ public final class PackageSetting extends PackageSettingBase { return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; } - public boolean isProductServices() { - return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0; + public boolean isSystemExt() { + return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0; } public boolean isOdm() { diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java index a24818f04f52..ec9746dabceb 100644 --- a/services/core/java/com/android/server/pm/SettingBase.java +++ b/services/core/java/com/android/server/pm/SettingBase.java @@ -63,7 +63,7 @@ abstract class SettingBase { | ApplicationInfo.PRIVATE_FLAG_OEM | ApplicationInfo.PRIVATE_FLAG_VENDOR | ApplicationInfo.PRIVATE_FLAG_PRODUCT - | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES + | ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER | ApplicationInfo.PRIVATE_FLAG_ODM); } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 11a8f4b895f5..3bc2236a8221 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -774,7 +774,7 @@ public final class Settings { | ApplicationInfo.PRIVATE_FLAG_OEM | ApplicationInfo.PRIVATE_FLAG_VENDOR | ApplicationInfo.PRIVATE_FLAG_PRODUCT - | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES + | ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT | ApplicationInfo.PRIVATE_FLAG_ODM); pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM; pkgSetting.pkgPrivateFlags |= @@ -786,7 +786,7 @@ public final class Settings { pkgSetting.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT; pkgSetting.pkgPrivateFlags |= - pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES; + pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT; pkgSetting.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_ODM; pkgSetting.primaryCpuAbiString = primaryCpuAbi; @@ -4413,7 +4413,7 @@ public final class Settings { ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY", ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR", ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT", - ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES, "PRODUCT_SERVICES", + ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT, "SYSTEM_EXT", ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD", ApplicationInfo.PRIVATE_FLAG_ODM, "ODM", }; diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING index e375fa44cb3f..b829f0b53086 100644 --- a/services/core/java/com/android/server/pm/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/TEST_MAPPING @@ -8,7 +8,9 @@ }, { "name": "CtsCompilationTestCases" - }, + } + ], + "postsubmit": [ { "name": "CtsPermissionTestCases", "options": [ diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index db01d7754d06..fe0b3a3966f9 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -34,8 +34,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; -import android.content.pm.PackageManagerInternal.PackagesProvider; -import android.content.pm.PackageManagerInternal.SyncAdapterPackagesProvider; import android.content.pm.PermissionInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; @@ -69,6 +67,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.util.ArrayUtils; import com.android.internal.util.XmlUtils; import com.android.server.LocalServices; +import com.android.server.pm.permission.PermissionManagerServiceInternal.PackagesProvider; +import com.android.server.pm.permission.PermissionManagerServiceInternal.SyncAdapterPackagesProvider; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -1388,8 +1388,7 @@ public final class DefaultPermissionGrantPolicy { if (dir.isDirectory() && dir.canRead()) { Collections.addAll(ret, dir.listFiles()); } - dir = new File(Environment.getProductServicesDirectory(), - "etc/default-permissions"); + dir = new File(Environment.getSystemExtDirectory(), "etc/default-permissions"); if (dir.isDirectory() && dir.canRead()) { Collections.addAll(ret, dir.listFiles()); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 9d0b42716e7a..673ab6c5f095 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -33,6 +33,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTAL import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM; import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE; import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL; +import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED; import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED; @@ -118,6 +119,9 @@ import com.android.server.pm.PackageManagerServiceUtils; import com.android.server.pm.PackageSetting; import com.android.server.pm.SharedUserSetting; import com.android.server.pm.UserManagerService; +import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultBrowserProvider; +import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultDialerProvider; +import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultHomeProvider; import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback; import com.android.server.pm.permission.PermissionsState.PermissionState; import com.android.server.policy.SoftRestrictedPermissionPolicy; @@ -250,6 +254,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { @GuardedBy("mLock") private final OnPermissionChangeListeners mOnPermissionChangeListeners; + @GuardedBy("mLock") + private DefaultBrowserProvider mDefaultBrowserProvider; + + @GuardedBy("mLock") + private DefaultDialerProvider mDefaultDialerProvider; + + @GuardedBy("mLock") + private DefaultHomeProvider mDefaultHomeProvider; + // TODO: Take a look at the methods defined in the callback. // The callback was initially created to support the split between permission // manager and the package manager. However, it's started to be used for other @@ -1609,6 +1622,226 @@ public class PermissionManagerService extends IPermissionManager.Stub { mPackageManagerInt.writePermissionSettings(asyncUpdatedUsers.toArray(), true); } + @Override + public String getDefaultBrowser(int userId) { + final int callingUid = Binder.getCallingUid(); + if (UserHandle.getUserId(callingUid) != userId) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); + } + if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) { + return null; + } + synchronized (mLock) { + return mDefaultBrowserProvider == null + ? null : mDefaultBrowserProvider.getDefaultBrowser(userId); + } + } + + @Override + public boolean setDefaultBrowser(String packageName, int userId) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); + } + return setDefaultBrowserInternal(packageName, false, true, userId); + } + + private boolean setDefaultBrowserInternal(String packageName, boolean async, + boolean doGrant, int userId) { + synchronized (mLock) { + if (userId == UserHandle.USER_ALL) { + return false; + } + if (mDefaultBrowserProvider == null) { + return false; + } + if (async) { + mDefaultBrowserProvider.setDefaultBrowserAsync(packageName, userId); + } else { + if (!mDefaultBrowserProvider.setDefaultBrowser(packageName, userId)) { + return false; + } + } + if (doGrant && packageName != null) { + mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToDefaultBrowser(packageName, userId); + } + } + return true; + } + + @Override + public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils + .enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps", callingUid); + synchronized (mLock) { + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId)); + } + } + + @Override + public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "grantDefaultPermissionsToEnabledImsServices", callingUid); + synchronized (mLock) { + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToEnabledImsServices(packageNames, userId)); + } + } + + @Override + public void grantDefaultPermissionsToEnabledTelephonyDataServices( + String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid); + synchronized (mLock) { + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToEnabledTelephonyDataServices( + packageNames, userId)); + } + } + + @Override + public void revokeDefaultPermissionsFromDisabledTelephonyDataServices( + String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid); + synchronized (mLock) { + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .revokeDefaultPermissionsFromDisabledTelephonyDataServices( + packageNames, userId)); + } + } + + @Override + public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils + .enforceSystemOrPhoneCaller("grantDefaultPermissionsToActiveLuiApp", callingUid); + synchronized (mLock) { + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToActiveLuiApp(packageName, userId)); + } + } + + @Override + public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils + .enforceSystemOrPhoneCaller("revokeDefaultPermissionsFromLuiApps", callingUid); + synchronized (mLock) { + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .revokeDefaultPermissionsFromLuiApps(packageNames, userId)); + } + } + + @Override + public void setPermissionEnforced(String permName, boolean enforced) { + // TODO: Now that we no longer change GID for storage, this should to away. + mContext.enforceCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, + "setPermissionEnforced"); + if (READ_EXTERNAL_STORAGE.equals(permName)) { + mPackageManagerInt.setReadExternalStorageEnforced(enforced); + // kill any non-foreground processes so we restart them and + // grant/revoke the GID. + final IActivityManager am = ActivityManager.getService(); + if (am != null) { + final long token = Binder.clearCallingIdentity(); + try { + am.killProcessesBelowForeground("setPermissionEnforcement"); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(token); + } + } + } else { + throw new IllegalArgumentException("No selective enforcement for " + permName); + } + } + + /** @deprecated */ + @Override + @Deprecated + public boolean isPermissionEnforced(String permName) { + // allow instant applications + return true; + } + + @Override + public boolean shouldShowRequestPermissionRationale(String permName, + String packageName, int userId) { + final int callingUid = Binder.getCallingUid(); + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "canShowRequestPermissionRationale for user " + userId); + } + + final int uid = + mPackageManagerInt.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId); + if (UserHandle.getAppId(callingUid) != UserHandle.getAppId(uid)) { + return false; + } + + if (checkPermission(permName, packageName, userId) + == PackageManager.PERMISSION_GRANTED) { + return false; + } + + final int flags; + + final long identity = Binder.clearCallingIdentity(); + try { + flags = getPermissionFlagsInternal(permName, packageName, callingUid, userId); + } finally { + Binder.restoreCallingIdentity(identity); + } + + final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED + | PackageManager.FLAG_PERMISSION_POLICY_FIXED + | PackageManager.FLAG_PERMISSION_USER_FIXED; + + if ((flags & fixedFlags) != 0) { + return false; + } + + return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0; + } + + @Override + public boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId) { + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "isPermissionRevokedByPolicy for user " + userId); + } + + if (checkPermission(permName, packageName, userId) == PackageManager.PERMISSION_GRANTED) { + return false; + } + + final int callingUid = Binder.getCallingUid(); + if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId)) { + return false; + } + + final long identity = Binder.clearCallingIdentity(); + try { + final int flags = getPermissionFlagsInternal(permName, packageName, callingUid, userId); + return (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + /** * Get the state of the runtime permissions as xml file. * @@ -2746,9 +2979,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { } else if (pkg.isProduct()) { wlPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName); - } else if (pkg.isProductServices()) { + } else if (pkg.isSystemExt()) { wlPermissions = - SystemConfig.getInstance().getProductServicesPrivAppPermissions( + SystemConfig.getInstance().getSystemExtPrivAppPermissions( pkg.packageName); } else { wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName); @@ -2782,9 +3015,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { } else if (pkg.isProduct()) { deniedPermissions = SystemConfig.getInstance() .getProductPrivAppDenyPermissions(pkg.packageName); - } else if (pkg.isProductServices()) { + } else if (pkg.isSystemExt()) { deniedPermissions = SystemConfig.getInstance() - .getProductServicesPrivAppDenyPermissions(pkg.packageName); + .getSystemExtPrivAppDenyPermissions(pkg.packageName); } else { deniedPermissions = SystemConfig.getInstance() .getPrivAppDenyPermissions(pkg.packageName); @@ -2793,13 +3026,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { deniedPermissions == null || !deniedPermissions.contains(perm); if (permissionViolation) { Slog.w(TAG, "Privileged permission " + perm + " for package " - + pkg.packageName + " - not in privapp-permissions whitelist"); + + pkg.packageName + " (" + pkg.codePath + + ") not in privapp-permissions whitelist"); if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { if (mPrivappPermissionsViolations == null) { mPrivappPermissionsViolations = new ArraySet<>(); } - mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm); + mPrivappPermissionsViolations.add( + pkg.packageName + " (" + pkg.codePath + "): " + perm); } } else { return false; @@ -3714,6 +3949,24 @@ public class PermissionManagerService extends IPermissionManager.Stub { } mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class); + + int[] grantPermissionsUserIds = EMPTY_INT_ARRAY; + for (int userId : UserManagerService.getInstance().getUserIds()) { + if (!mPackageManagerInt.areDefaultRuntimePermissionsGranted(userId)) { + grantPermissionsUserIds = ArrayUtils.appendInt( + grantPermissionsUserIds, userId); + } + } + // If we upgraded grant all default permissions before kicking off. + for (int userId : grantPermissionsUserIds) { + mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId); + } + if (grantPermissionsUserIds == EMPTY_INT_ARRAY) { + // If we did not grant default permissions, we preload from this the + // default permission exceptions lazily to ensure we don't hit the + // disk on a new user creation. + mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions(); + } } private static String getVolumeUuidForPackage(PackageParser.Package pkg) { @@ -3847,20 +4100,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { .getAppOpPermissionPackagesInternal(permName, callingUid); } @Override - public int getPermissionFlags(String permName, String packageName, int callingUid, - int userId) { - return PermissionManagerService.this - .getPermissionFlagsInternal(permName, packageName, callingUid, userId); - } - @Override - public void updatePermissionFlags(String permName, String packageName, int flagMask, - int flagValues, int callingUid, int userId, boolean overridePolicy, - PermissionCallback callback) { - PermissionManagerService.this.updatePermissionFlagsInternal( - permName, packageName, flagMask, flagValues, callingUid, userId, - overridePolicy, callback); - } - @Override public void enforceCrossUserPermission(int callingUid, int userId, boolean requireFullPermission, boolean checkShell, String message) { PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId, @@ -3882,10 +4121,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { return mSettings; } @Override - public DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() { - return mDefaultPermissionGrantPolicy; - } - @Override public BasePermission getPermissionTEMP(String permName) { synchronized (PermissionManagerService.this.mLock) { return mSettings.getPermissionLocked(permName); @@ -3956,9 +4191,166 @@ public class PermissionManagerService extends IPermissionManager.Stub { mCheckPermissionDelegate = delegate; } } + @Override - public void notifyPermissionsChangedTEMP(int uid) { - mOnPermissionChangeListeners.onPermissionsChanged(uid); + public void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider) { + synchronized (mLock) { + mDefaultBrowserProvider = provider; + } + } + + @Override + public void setDefaultBrowser(String packageName, boolean async, boolean doGrant, + int userId) { + setDefaultBrowserInternal(packageName, async, doGrant, userId); + } + + @Override + public void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider) { + synchronized (mLock) { + mDefaultDialerProvider = provider; + } + } + + @Override + public void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider) { + synchronized (mLock) { + mDefaultHomeProvider = provider; + } + } + + @Override + public void setDefaultHome(String packageName, int userId, Consumer<Boolean> callback) { + synchronized (mLock) { + if (userId == UserHandle.USER_ALL) { + return; + } + if (mDefaultHomeProvider == null) { + return; + } + mDefaultHomeProvider.setDefaultHomeAsync(packageName, userId, callback); + } + } + + @Override + public void setDialerAppPackagesProvider(PackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setDialerAppPackagesProvider(provider); + } + } + + @Override + public void setLocationExtraPackagesProvider(PackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setLocationExtraPackagesProvider(provider); + } + } + + @Override + public void setLocationPackagesProvider(PackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setLocationPackagesProvider(provider); + } + } + + @Override + public void setSimCallManagerPackagesProvider(PackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setSimCallManagerPackagesProvider(provider); + } + } + + @Override + public void setSmsAppPackagesProvider(PackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setSmsAppPackagesProvider(provider); + } + } + + @Override + public void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setSyncAdapterPackagesProvider(provider); + } + } + + @Override + public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setUseOpenWifiAppPackagesProvider(provider); + } + } + + @Override + public void setVoiceInteractionPackagesProvider(PackagesProvider provider) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.setVoiceInteractionPackagesProvider(provider); + } + } + + @Override + public String getDefaultBrowser(int userId) { + synchronized (mLock) { + return mDefaultBrowserProvider == null + ? null : mDefaultBrowserProvider.getDefaultBrowser(userId); + } + } + + @Override + public String getDefaultDialer(int userId) { + synchronized (mLock) { + return mDefaultDialerProvider == null + ? null : mDefaultDialerProvider.getDefaultDialer(userId); + } + } + + @Override + public String getDefaultHome(int userId) { + synchronized (mLock) { + return mDefaultHomeProvider == null + ? null : mDefaultHomeProvider.getDefaultHome(userId); + } + } + + @Override + public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToDefaultSimCallManager(packageName, userId); + } + } + + @Override + public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToDefaultUseOpenWifiApp(packageName, userId); + } + } + + @Override + public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToDefaultBrowser(packageName, userId); + } + } + + @Override + public boolean wereDefaultPermissionsGrantedSinceBoot(int userId) { + synchronized (mLock) { + return mDefaultPermissionGrantPolicy.wereDefaultPermissionsGrantedSinceBoot(userId); + } + } + + @Override + public void onNewUserCreated(int userId) { + synchronized (mLock) { + mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId); + // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG + PermissionManagerService.this.updateAllPermissions( + StorageManager.UUID_PRIVATE_INTERNAL, true, mDefaultPermissionCallback); + } } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java index 2fdab4d4d125..04ec5ba04bb6 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java @@ -27,6 +27,7 @@ import android.permission.PermissionManagerInternal; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; /** * Internal interfaces services. @@ -35,6 +36,109 @@ import java.util.List; */ public abstract class PermissionManagerServiceInternal extends PermissionManagerInternal { /** + * Provider for package names. + */ + public interface PackagesProvider { + + /** + * Gets the packages for a given user. + * @param userId The user id. + * @return The package names. + */ + String[] getPackages(int userId); + } + + /** + * Provider for package names. + */ + public interface SyncAdapterPackagesProvider { + + /** + * Gets the sync adapter packages for given authority and user. + * @param authority The authority. + * @param userId The user id. + * @return The package names. + */ + String[] getPackages(String authority, int userId); + } + + /** + * Provider for default browser + */ + public interface DefaultBrowserProvider { + + /** + * Get the package name of the default browser. + * + * @param userId the user id + * + * @return the package name of the default browser, or {@code null} if none + */ + @Nullable + String getDefaultBrowser(@UserIdInt int userId); + + /** + * Set the package name of the default browser. + * + * @param packageName package name of the default browser, or {@code null} to remove + * @param userId the user id + * + * @return whether the default browser was successfully set. + */ + boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId); + + /** + * Set the package name of the default browser asynchronously. + * + * @param packageName package name of the default browser, or {@code null} to remove + * @param userId the user id + */ + void setDefaultBrowserAsync(@Nullable String packageName, @UserIdInt int userId); + } + + /** + * Provider for default dialer + */ + public interface DefaultDialerProvider { + + /** + * Get the package name of the default dialer. + * + * @param userId the user id + * + * @return the package name of the default dialer, or {@code null} if none + */ + @Nullable + String getDefaultDialer(@UserIdInt int userId); + } + + /** + * Provider for default home + */ + public interface DefaultHomeProvider { + + /** + * Get the package name of the default home. + * + * @param userId the user id + * + * @return the package name of the default home, or {@code null} if none + */ + @Nullable + String getDefaultHome(@UserIdInt int userId); + + /** + * Set the package name of the default home. + * + * @param packageName package name of the default home, or {@code null} to remove + * @param userId the user id + * @param callback the callback made after the default home as been updated + */ + void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId, + @NonNull Consumer<Boolean> callback); + } + + /** * Callbacks invoked when interesting actions have been taken on a permission. * <p> * NOTE: The current arguments are merely to support the existing use cases. This @@ -159,17 +263,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager public abstract @Nullable String[] getAppOpPermissionPackages( @NonNull String permName, int callingUid); - public abstract int getPermissionFlags(@NonNull String permName, - @NonNull String packageName, int callingUid, int userId); - - /** - * Updates the flags associated with a permission by replacing the flags in - * the specified mask with the provided flag values. - */ - public abstract void updatePermissionFlags(@NonNull String permName, - @NonNull String packageName, int flagMask, int flagValues, int callingUid, int userId, - boolean overridePolicy, @Nullable PermissionCallback callback); - /** * Enforces the request is from the system or an app that has INTERACT_ACROSS_USERS * or INTERACT_ACROSS_USERS_FULL permissions, if the {@code userid} is not for the caller. @@ -189,13 +282,13 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager public abstract void enforceGrantRevokeRuntimePermissionPermissions(@NonNull String message); public abstract @NonNull PermissionSettings getPermissionSettings(); - public abstract @NonNull DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy(); + + /** Grants default browser permissions to the given package */ + public abstract void grantDefaultPermissionsToDefaultBrowser( + @NonNull String packageName, @UserIdInt int userId); /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */ public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName); - /** HACK HACK notify the permission listener; this shouldn't be needed after permissions - * are fully removed from the package manager */ - public abstract void notifyPermissionsChangedTEMP(int uid); /** Get all permission that have a certain protection level */ public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel( @@ -214,4 +307,142 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager * @param delegate A delegate instance or {@code null} to clear. */ public abstract void setCheckPermissionDelegate(@Nullable CheckPermissionDelegate delegate); + + /** + * Sets the dialer application packages provider. + * @param provider The provider. + */ + public abstract void setDialerAppPackagesProvider(PackagesProvider provider); + + /** + * Set the location extra packages provider. + * @param provider The packages provider. + */ + public abstract void setLocationExtraPackagesProvider(PackagesProvider provider); + + /** + * Sets the location provider packages provider. + * @param provider The packages provider. + */ + public abstract void setLocationPackagesProvider(PackagesProvider provider); + + /** + * Sets the SIM call manager packages provider. + * @param provider The provider. + */ + public abstract void setSimCallManagerPackagesProvider(PackagesProvider provider); + + /** + * Sets the SMS application packages provider. + * @param provider The provider. + */ + public abstract void setSmsAppPackagesProvider(PackagesProvider provider); + + /** + * Sets the sync adapter packages provider. + * @param provider The provider. + */ + public abstract void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider); + + /** + * Sets the Use Open Wifi packages provider. + * @param provider The packages provider. + */ + public abstract void setUseOpenWifiAppPackagesProvider(PackagesProvider provider); + + /** + * Sets the voice interaction packages provider. + * @param provider The packages provider. + */ + public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider); + + /** + * Sets the default browser provider. + * + * @param provider the provider + */ + public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider); + + /** + * Sets the package name of the default browser provider for the given user. + * + * @param packageName The package name of the default browser or {@code null} + * to clear the default browser + * @param async If {@code true}, set the default browser asynchronously, + * otherwise set it synchronously + * @param doGrant If {@code true} and if {@code packageName} is not {@code null}, + * perform default permission grants on the browser, otherwise skip the + * default permission grants. + * @param userId The user to set the default browser for. + */ + public abstract void setDefaultBrowser(@Nullable String packageName, boolean async, + boolean doGrant, @UserIdInt int userId); + + /** + * Sets the default dialer provider. + * + * @param provider the provider + */ + public abstract void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider); + + /** + * Sets the default home provider. + * + * @param provider the provider + */ + public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider); + + /** + * Asynchronously sets the package name of the default home provider for the given user. + * + * @param packageName The package name of the default home or {@code null} + * to clear the default browser + * @param userId The user to set the default browser for + * @param callback Invoked after the default home has been set + */ + public abstract void setDefaultHome(@Nullable String packageName, @UserIdInt int userId, + @NonNull Consumer<Boolean> callback); + + /** + * Returns the default browser package name for the given user. + */ + @Nullable + public abstract String getDefaultBrowser(@UserIdInt int userId); + + /** + * Returns the default dialer package name for the given user. + */ + @Nullable + public abstract String getDefaultDialer(@UserIdInt int userId); + + /** + * Returns the default home package name for the given user. + */ + @Nullable + public abstract String getDefaultHome(@UserIdInt int userId); + + /** + * Requests granting of the default permissions to the current default Use Open Wifi app. + * @param packageName The default use open wifi package name. + * @param userId The user for which to grant the permissions. + */ + public abstract void grantDefaultPermissionsToDefaultSimCallManager( + @NonNull String packageName, @UserIdInt int userId); + + /** + * Requests granting of the default permissions to the current default Use Open Wifi app. + * @param packageName The default use open wifi package name. + * @param userId The user for which to grant the permissions. + */ + public abstract void grantDefaultPermissionsToDefaultUseOpenWifiApp( + @NonNull String packageName, @UserIdInt int userId); + + /** + * Returns whether or not default permission grants have been performed for the given + * user since the device booted. + */ + public abstract boolean wereDefaultPermissionsGrantedSinceBoot(@UserIdInt int userId); + + /** Called when a new user has been created. */ + public abstract void onNewUserCreated(@UserIdInt int userId); } diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING index ee7a098b167b..af94e441f3c0 100644 --- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING @@ -14,9 +14,6 @@ }, { "include-filter": "android.permission.cts.SharedUidPermissionsTest" - }, - { - "include-filter": "android.permission.cts.PermissionUpdateListenerTest" } ] }, @@ -56,6 +53,14 @@ "include-filter": "android.appsecurity.cts.AppSecurityTests#testPermissionDiffCert" } ] + }, + { + "name": "CtsPermissionTestCases", + "options": [ + { + "include-filter": "android.permission.cts.PermissionUpdateListenerTest" + } + ] } ] } diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index a569bffef141..8da7f7bb6898 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -260,9 +260,11 @@ public final class PermissionPolicyService extends SystemService { private void grantOrUpgradeDefaultRuntimePermissionsIfNeeded(@UserIdInt int userId) { if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPermsIfNeeded(" + userId + ")"); - final PackageManagerInternal packageManagerInternal = LocalServices.getService( - PackageManagerInternal.class); - if (packageManagerInternal.wereDefaultPermissionsGrantedSinceBoot(userId)) { + final PackageManagerInternal packageManagerInternal = + LocalServices.getService(PackageManagerInternal.class); + final PermissionManagerServiceInternal permissionManagerInternal = + LocalServices.getService(PermissionManagerServiceInternal.class); + if (permissionManagerInternal.wereDefaultPermissionsGrantedSinceBoot(userId)) { if (DEBUG) Slog.i(LOG_TAG, "defaultPermsWereGrantedSinceBoot(" + userId + ")"); // Now call into the permission controller to apply policy around permissions diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java index d53f6854dfdf..c1a6dbd8ae14 100644 --- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java +++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java @@ -28,11 +28,14 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INST import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; +import static java.lang.Integer.min; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.os.Build; import android.os.UserHandle; @@ -73,6 +76,41 @@ public abstract class SoftRestrictedPermissionPolicy { }; /** + * TargetSDK is per package. To make sure two apps int the same shared UID do not fight over + * what to set, always compute the combined targetSDK. + * + * @param context A context + * @param appInfo The app that is changed + * @param user The user the app belongs to + * + * @return The minimum targetSDK of all apps sharing the uid of the app + */ + private static int getMinimumTargetSDK(@NonNull Context context, + @NonNull ApplicationInfo appInfo, @NonNull UserHandle user) { + PackageManager pm = context.getPackageManager(); + + int minimumTargetSDK = appInfo.targetSdkVersion; + + String[] uidPkgs = pm.getPackagesForUid(appInfo.uid); + if (uidPkgs != null) { + for (String uidPkg : uidPkgs) { + if (!uidPkg.equals(appInfo.packageName)) { + ApplicationInfo uidPkgInfo; + try { + uidPkgInfo = pm.getApplicationInfoAsUser(uidPkg, 0, user); + } catch (PackageManager.NameNotFoundException e) { + continue; + } + + minimumTargetSDK = min(minimumTargetSDK, uidPkgInfo.targetSdkVersion); + } + } + } + + return minimumTargetSDK; + } + + /** * Get the policy for a soft restricted permission. * * @param context A context to use @@ -99,12 +137,36 @@ public abstract class SoftRestrictedPermissionPolicy { final int targetSDK; if (appInfo != null) { - flags = context.getPackageManager().getPermissionFlags(permission, - appInfo.packageName, user); + PackageManager pm = context.getPackageManager(); + flags = pm.getPermissionFlags(permission, appInfo.packageName, user); applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0; - hasRequestedLegacyExternalStorage = appInfo.hasRequestedLegacyExternalStorage(); - targetSDK = appInfo.targetSdkVersion; + targetSDK = getMinimumTargetSDK(context, appInfo, user); + + boolean hasAnyRequestedLegacyExternalStorage = + appInfo.hasRequestedLegacyExternalStorage(); + + // hasRequestedLegacyExternalStorage is per package. To make sure two apps in + // the same shared UID do not fight over what to set, always compute the + // combined hasRequestedLegacyExternalStorage + String[] uidPkgs = pm.getPackagesForUid(appInfo.uid); + if (uidPkgs != null) { + for (String uidPkg : uidPkgs) { + if (!uidPkg.equals(appInfo.packageName)) { + ApplicationInfo uidPkgInfo; + try { + uidPkgInfo = pm.getApplicationInfoAsUser(uidPkg, 0, user); + } catch (PackageManager.NameNotFoundException e) { + continue; + } + + hasAnyRequestedLegacyExternalStorage |= + uidPkgInfo.hasRequestedLegacyExternalStorage(); + } + } + } + + hasRequestedLegacyExternalStorage = hasAnyRequestedLegacyExternalStorage; } else { flags = 0; applyRestriction = false; @@ -155,7 +217,7 @@ public abstract class SoftRestrictedPermissionPolicy { final int flags = context.getPackageManager().getPermissionFlags(permission, appInfo.packageName, user); isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0; - targetSDK = appInfo.targetSdkVersion; + targetSDK = getMinimumTargetSDK(context, appInfo, user); } else { isWhiteListed = false; targetSDK = 0; diff --git a/services/core/java/com/android/server/policy/TEST_MAPPING b/services/core/java/com/android/server/policy/TEST_MAPPING index 9f64039e01a1..484017bf4ef4 100644 --- a/services/core/java/com/android/server/policy/TEST_MAPPING +++ b/services/core/java/com/android/server/policy/TEST_MAPPING @@ -33,6 +33,9 @@ "options": [ { "include-filter": "android.permission2.cts.RestrictedPermissionsTest" + }, + { + "include-filter": "android.permission2.cts.RestrictedStoragePermissionSharedUidTest" } ] }, diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index b503ce87bae2..1948b202fd63 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -76,6 +76,7 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.pm.permission.PermissionManagerServiceInternal; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; @@ -166,11 +167,11 @@ public class RoleManagerService extends SystemService implements RoleUserState.C LocalServices.addService(RoleManagerInternal.class, new Internal()); - PackageManagerInternal packageManagerInternal = LocalServices.getService( - PackageManagerInternal.class); - packageManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider()); - packageManagerInternal.setDefaultDialerProvider(new DefaultDialerProvider()); - packageManagerInternal.setDefaultHomeProvider(new DefaultHomeProvider()); + PermissionManagerServiceInternal permissionManagerInternal = + LocalServices.getService(PermissionManagerServiceInternal.class); + permissionManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider()); + permissionManagerInternal.setDefaultDialerProvider(new DefaultDialerProvider()); + permissionManagerInternal.setDefaultHomeProvider(new DefaultHomeProvider()); registerUserRemovedReceiver(); } @@ -755,7 +756,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } - private class DefaultBrowserProvider implements PackageManagerInternal.DefaultBrowserProvider { + private class DefaultBrowserProvider implements + PermissionManagerServiceInternal.DefaultBrowserProvider { @Nullable @Override @@ -809,7 +811,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } - private class DefaultDialerProvider implements PackageManagerInternal.DefaultDialerProvider { + private class DefaultDialerProvider implements + PermissionManagerServiceInternal.DefaultDialerProvider { @Nullable @Override @@ -819,7 +822,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } - private class DefaultHomeProvider implements PackageManagerInternal.DefaultHomeProvider { + private class DefaultHomeProvider implements + PermissionManagerServiceInternal.DefaultHomeProvider { @Nullable @Override diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java index 54369ca5c367..a853529f49e4 100644 --- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java +++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java @@ -39,7 +39,6 @@ import com.android.internal.telephony.SmsApplication; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.UserManagerService; -import com.android.server.pm.permission.DefaultPermissionGrantPolicy; import com.android.server.pm.permission.PermissionManagerServiceInternal; /** @@ -66,9 +65,9 @@ public class TelecomLoaderService extends SystemService { ServiceManager.addService(Context.TELECOM_SERVICE, service); synchronized (mLock) { + final PermissionManagerServiceInternal permissionManager = + LocalServices.getService(PermissionManagerServiceInternal.class); if (mDefaultSimCallManagerRequests != null) { - final DefaultPermissionGrantPolicy permissionPolicy = - getDefaultPermissionGrantPolicy(); if (mDefaultSimCallManagerRequests != null) { TelecomManager telecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); @@ -80,7 +79,7 @@ public class TelecomLoaderService extends SystemService { for (int i = requestCount - 1; i >= 0; i--) { final int userId = mDefaultSimCallManagerRequests.get(i); mDefaultSimCallManagerRequests.remove(i); - permissionPolicy + permissionManager .grantDefaultPermissionsToDefaultSimCallManager( packageName, userId); } @@ -99,11 +98,6 @@ public class TelecomLoaderService extends SystemService { } } - private DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() { - return LocalServices.getService(PermissionManagerServiceInternal.class) - .getDefaultPermissionGrantPolicy(); - } - private static final ComponentName SERVICE_COMPONENT = new ComponentName( "com.android.server.telecom", "com.android.server.telecom.components.TelecomService"); @@ -162,10 +156,11 @@ public class TelecomLoaderService extends SystemService { private void registerDefaultAppProviders() { - final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy(); + final PermissionManagerServiceInternal permissionManager = + LocalServices.getService(PermissionManagerServiceInternal.class); // Set a callback for the permission grant policy to query the default sms app. - permissionPolicy.setSmsAppPackagesProvider(userId -> { + permissionManager.setSmsAppPackagesProvider(userId -> { synchronized (mLock) { if (mServiceConnection == null) { return null; @@ -180,7 +175,7 @@ public class TelecomLoaderService extends SystemService { }); // Set a callback for the permission grant policy to query the default dialer app. - permissionPolicy.setDialerAppPackagesProvider(userId -> { + permissionManager.setDialerAppPackagesProvider(userId -> { synchronized (mLock) { if (mServiceConnection == null) { return null; @@ -194,7 +189,7 @@ public class TelecomLoaderService extends SystemService { }); // Set a callback for the permission grant policy to query the default sim call manager. - permissionPolicy.setSimCallManagerPackagesProvider(userId -> { + permissionManager.setSimCallManagerPackagesProvider(userId -> { synchronized (mLock) { if (mServiceConnection == null) { if (mDefaultSimCallManagerRequests == null) { @@ -215,12 +210,11 @@ public class TelecomLoaderService extends SystemService { } private void registerDefaultAppNotifier() { - final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy(); // Notify the package manager on default app changes final RoleManager roleManager = mContext.getSystemService(RoleManager.class); roleManager.addOnRoleHoldersChangedListenerAsUser(mContext.getMainExecutor(), - (roleName, user) -> updateSimCallManagerPermissions(permissionPolicy, - user.getIdentifier()), UserHandle.ALL); + (roleName, user) -> updateSimCallManagerPermissions(user.getIdentifier()), + UserHandle.ALL); } @@ -230,7 +224,7 @@ public class TelecomLoaderService extends SystemService { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) { for (int userId : UserManagerService.getInstance().getUserIds()) { - updateSimCallManagerPermissions(getDefaultPermissionGrantPolicy(), userId); + updateSimCallManagerPermissions(userId); } } } @@ -240,16 +234,16 @@ public class TelecomLoaderService extends SystemService { new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED), null, null); } - private void updateSimCallManagerPermissions( - DefaultPermissionGrantPolicy permissionGrantPolicy, int userId) { + private void updateSimCallManagerPermissions(int userId) { + final PermissionManagerServiceInternal permissionManager = + LocalServices.getService(PermissionManagerServiceInternal.class); TelecomManager telecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId); if (phoneAccount != null) { Slog.i(TAG, "updating sim call manager permissions for userId:" + userId); String packageName = phoneAccount.getComponentName().getPackageName(); - permissionGrantPolicy.grantDefaultPermissionsToDefaultSimCallManager( - packageName, userId); + permissionManager.grantDefaultPermissionsToDefaultSimCallManager(packageName, userId); } } } diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 55f062bca2d1..b2f115374305 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -949,7 +949,25 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { return false; } - return readMet && writeMet; + // If this provider says that grants are always required, we need to + // consult it directly to determine if the UID has permission + final boolean forceMet; + if (pi.forceUriPermissions) { + final int providerUserId = UserHandle.getUserId(pi.applicationInfo.uid); + final int clientUserId = UserHandle.getUserId(uid); + if (providerUserId == clientUserId) { + forceMet = (mAmInternal.checkContentProviderUriPermission(grantUri.uri, + providerUserId, uid, modeFlags) == PackageManager.PERMISSION_GRANTED); + } else { + // The provider can't track cross-user permissions, so we have + // to assume they're always denied + forceMet = false; + } + } else { + forceMet = true; + } + + return readMet && writeMet && forceMet; } private void removeUriPermissionIfNeeded(UriPermission perm) { diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index bace7e3c6dab..8abfde2c5c36 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.utils.RegionUtils.forEachRect; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -1126,14 +1127,13 @@ final class AccessibilityController { // Iterate until we figure out what is touchable for the entire screen. for (int i = visibleWindowCount - 1; i >= 0; i--) { final WindowState windowState = visibleWindows.valueAt(i); + final Region regionInScreen = new Region(); + computeWindowRegionInScreen(windowState, regionInScreen); - final Rect boundsInScreen = mTempRect; - computeWindowBoundsInScreen(windowState, boundsInScreen); - - if (windowMattersToAccessibility(windowState, boundsInScreen, unaccountedSpace, + if (windowMattersToAccessibility(windowState, regionInScreen, unaccountedSpace, skipRemainingWindowsForTasks)) { - addPopulatedWindowInfo(windowState, boundsInScreen, windows, addedWindows); - updateUnaccountedSpace(windowState, boundsInScreen, unaccountedSpace, + addPopulatedWindowInfo(windowState, regionInScreen, windows, addedWindows); + updateUnaccountedSpace(windowState, regionInScreen, unaccountedSpace, skipRemainingWindowsForTasks); focusedWindowAdded |= windowState.isFocused(); } @@ -1171,8 +1171,9 @@ final class AccessibilityController { clearAndRecycleWindows(windows); } - private boolean windowMattersToAccessibility(WindowState windowState, Rect boundsInScreen, - Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) { + private boolean windowMattersToAccessibility(WindowState windowState, + Region regionInScreen, Region unaccountedSpace, + HashSet<Integer> skipRemainingWindowsForTasks) { if (windowState.isFocused()) { return true; } @@ -1192,7 +1193,7 @@ final class AccessibilityController { } // If the window is completely covered by other windows - ignore. - if (unaccountedSpace.quickReject(boundsInScreen)) { + if (unaccountedSpace.quickReject(regionInScreen)) { return false; } @@ -1204,7 +1205,7 @@ final class AccessibilityController { return false; } - private void updateUnaccountedSpace(WindowState windowState, Rect boundsInScreen, + private void updateUnaccountedSpace(WindowState windowState, Region regionInScreen, Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) { if (windowState.mAttrs.type != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) { @@ -1212,59 +1213,71 @@ final class AccessibilityController { // Account for the space this window takes if the window // is not an accessibility overlay which does not change // the reported windows. - unaccountedSpace.op(boundsInScreen, unaccountedSpace, + unaccountedSpace.op(regionInScreen, unaccountedSpace, Region.Op.REVERSE_DIFFERENCE); // If a window is modal it prevents other windows from being touched if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) { - // Account for all space in the task, whether the windows in it are - // touchable or not. The modal window blocks all touches from the task's - // area. - unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace, - Region.Op.REVERSE_DIFFERENCE); + if (!windowState.hasTapExcludeRegion()) { + // Account for all space in the task, whether the windows in it are + // touchable or not. The modal window blocks all touches from the task's + // area. + unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace, + Region.Op.REVERSE_DIFFERENCE); + } else { + // If a window has tap exclude region, we need to account it. + final Region displayRegion = new Region(windowState.getDisplayFrameLw()); + final Region tapExcludeRegion = new Region(); + windowState.amendTapExcludeRegion(tapExcludeRegion); + displayRegion.op(tapExcludeRegion, displayRegion, + Region.Op.REVERSE_DIFFERENCE); + unaccountedSpace.op(displayRegion, unaccountedSpace, + Region.Op.REVERSE_DIFFERENCE); + } final Task task = windowState.getTask(); if (task != null) { // If the window is associated with a particular task, we can skip the // rest of the windows for that task. skipRemainingWindowsForTasks.add(task.mTaskId); - } else { + } else if (!windowState.hasTapExcludeRegion()) { // If the window is not associated with a particular task, then it is - // globally modal. In this case we can skip all remaining windows. + // globally modal. In this case we can skip all remaining windows when + // it doesn't has tap exclude region. unaccountedSpace.setEmpty(); } } } } - private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) { + private void computeWindowRegionInScreen(WindowState windowState, Region outRegion) { // Get the touchable frame. Region touchableRegion = mTempRegion1; windowState.getTouchableRegion(touchableRegion); - Rect touchableFrame = mTempRect; - touchableRegion.getBounds(touchableFrame); - - // Move to origin as all transforms are captured by the matrix. - RectF windowFrame = mTempRectF; - windowFrame.set(touchableFrame); - windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top); // Map the frame to get what appears on the screen. Matrix matrix = mTempMatrix; populateTransformationMatrixLocked(windowState, matrix); - matrix.mapRect(windowFrame); - // Got the bounds. - outBounds.set((int) windowFrame.left, (int) windowFrame.top, - (int) windowFrame.right, (int) windowFrame.bottom); + forEachRect(touchableRegion, rect -> { + // Move to origin as all transforms are captured by the matrix. + RectF windowFrame = mTempRectF; + windowFrame.set(rect); + windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top); + + matrix.mapRect(windowFrame); + + // Union all rects. + outRegion.union(new Rect((int) windowFrame.left, (int) windowFrame.top, + (int) windowFrame.right, (int) windowFrame.bottom)); + }); } - private static void addPopulatedWindowInfo( - WindowState windowState, Rect boundsInScreen, + private static void addPopulatedWindowInfo(WindowState windowState, Region regionInScreen, List<WindowInfo> out, Set<IBinder> tokenOut) { final WindowInfo window = windowState.getWindowInfo(); - window.boundsInScreen.set(boundsInScreen); + window.regionInScreen.set(regionInScreen); window.layer = tokenOut.size(); out.add(window); tokenOut.add(window.token); @@ -1293,7 +1306,7 @@ final class AccessibilityController { private void populateVisibleWindowsOnScreenLocked(SparseArray<WindowState> outWindows) { final List<WindowState> tempWindowStatesList = new ArrayList<>(); final DisplayContent dc = mService.getDefaultDisplayContentLocked(); - dc.forAllWindows((w) -> { + dc.forAllWindows(w -> { if (w.isVisibleLw()) { tempWindowStatesList.add(w); } @@ -1306,17 +1319,11 @@ final class AccessibilityController { return; } - // TODO: Use Region instead to get rid of this complicated logic. - // Check the tap exclude region of the parent window. If the tap exclude region - // is empty, it means there is another can-receive-pointer-event view on top of - // the region. Hence, we don't count the window as visible. if (w.isVisibleLw() && parentWindow.getDisplayContent().isDefaultDisplay - && parentWindow.hasTapExcludeRegion() && tempWindowStatesList.contains(parentWindow)) { - tempWindowStatesList.add( - tempWindowStatesList.lastIndexOf(parentWindow) + 1, w); + tempWindowStatesList.add(tempWindowStatesList.lastIndexOf(parentWindow), w); } - }, true /* traverseTopToBottom */); + }, false /* traverseTopToBottom */); for (int i = 0; i < tempWindowStatesList.size(); i++) { outWindows.put(i, tempWindowStatesList.get(i)); } diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index fe4811dce274..cd7282464619 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -174,6 +174,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> mDisplayId = display.getDisplayId(); mDisplay = display; mDisplayContent = createDisplayContent(); + mDisplayContent.reconfigureDisplayLocked(); updateBounds(); } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 9c87ce8e1744..99d290340b77 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -916,8 +916,9 @@ final class ActivityRecord extends ConfigurationContainer { return ResolverActivity.class.getName().equals(className); } - boolean isResolverActivity() { - return isResolverActivity(mActivityComponent.getClassName()); + boolean isResolverOrDelegateActivity() { + return isResolverActivity(mActivityComponent.getClassName()) || Objects.equals( + mActivityComponent, mAtmService.mStackSupervisor.getSystemChooserActivity()); } boolean isResolverOrChildActivity() { @@ -1247,7 +1248,8 @@ final class ActivityRecord extends ConfigurationContainer { && intent.getType() == null; } - private boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) { + @VisibleForTesting + boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) { if (uid == Process.myUid() || uid == 0) { // System process can launch home activity. return true; @@ -1257,8 +1259,8 @@ final class ActivityRecord extends ConfigurationContainer { if (recentTasks != null && recentTasks.isCallerRecents(uid)) { return true; } - // Resolver activity can launch home activity. - return sourceRecord != null && sourceRecord.isResolverActivity(); + // Resolver or system chooser activity can launch home activity. + return sourceRecord != null && sourceRecord.isResolverOrDelegateActivity(); } /** @@ -1277,7 +1279,7 @@ final class ActivityRecord extends ConfigurationContainer { ActivityOptions options, ActivityRecord sourceRecord) { int activityType = ACTIVITY_TYPE_UNDEFINED; if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord)) - && isHomeIntent(intent) && !isResolverActivity()) { + && isHomeIntent(intent) && !isResolverOrDelegateActivity()) { // This sure looks like a home activity! activityType = ACTIVITY_TYPE_HOME; @@ -1523,7 +1525,6 @@ final class ActivityRecord extends ConfigurationContainer { stack.moveToFront(reason, task); // Report top activity change to tracking services and WM if (mRootActivityContainer.getTopResumedActivity() == this) { - // TODO(b/111361570): Support multiple focused apps in WM mAtmService.setResumedActivityUncheckLocked(this, reason); } 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 18a57ae17fda..79098f17899e 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -565,7 +565,6 @@ class ActivityStack extends ConfigurationContainer { + reason); setResumedActivity(record, reason + " - onActivityStateChanged"); if (record == mRootActivityContainer.getTopResumedActivity()) { - // TODO(b/111361570): Support multiple focused apps in WM mService.setResumedActivityUncheckLocked(record, reason); } mStackSupervisor.mRecentTasks.add(record.getTaskRecord()); @@ -3711,9 +3710,6 @@ class ActivityStack extends ConfigurationContainer { if (nextFocusableStack != null) { final ActivityRecord top = nextFocusableStack.topRunningActivityLocked(); if (top != null && top == mRootActivityContainer.getTopResumedActivity()) { - // TODO(b/111361570): Remove this and update focused app per-display in - // WindowManager every time an activity becomes resumed in - // ActivityTaskManagerService#setResumedActivityUncheckLocked(). mService.setResumedActivityUncheckLocked(top, reason); } return; @@ -5651,7 +5647,6 @@ class ActivityStack extends ConfigurationContainer { // If the original state is resumed, there is no state change to update focused app. // So here makes sure the activity focus is set if it is the top. if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) { - // TODO(b/111361570): Support multiple focused apps in WM mService.setResumedActivityUncheckLocked(r, reason); } } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index feb4a3653ced..eb170bdeee2d 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -130,6 +130,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.ReferrerIntent; @@ -323,6 +324,12 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { boolean mUserLeaving = false; /** + * The system chooser activity which worked as a delegate of + * {@link com.android.internal.app.ResolverActivity}. + */ + private ComponentName mSystemChooserActivity; + + /** * We don't want to allow the device to go to sleep while in the process * of launching an activity. This is primarily to allow alarm intent * receivers to launch an activity and get that to run before the device @@ -469,6 +476,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return mKeyguardController; } + ComponentName getSystemChooserActivity() { + if (mSystemChooserActivity == null) { + mSystemChooserActivity = ComponentName.unflattenFromString( + mService.mContext.getResources().getString(R.string.config_chooserActivity)); + } + return mSystemChooserActivity; + } + void setRecentTasks(RecentTasks recentTasks) { mRecentTasks = recentTasks; mRecentTasks.registerCallback(this); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 54eb07f56983..6fd2ebcd1d4f 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1980,8 +1980,8 @@ class ActivityStarter { // Also put noDisplay activities in the source task. These by itself can be placed // in any task/stack, however it could launch other activities like ResolverActivity, // and we want those to stay in the original task. - if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null - && mSourceRecord.inFreeformWindowingMode()) { + if ((mStartActivity.isResolverOrDelegateActivity() || mStartActivity.noDisplay) + && mSourceRecord != null && mSourceRecord.inFreeformWindowingMode()) { mAddingToTask = true; } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 971a24d13643..c37ced55c563 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4912,7 +4912,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } void dumpActivityContainersLocked(PrintWriter pw) { - pw.println("ACTIVITY MANAGER STARTER (dumpsys activity containers)"); + pw.println("ACTIVITY MANAGER CONTAINERS (dumpsys activity containers)"); mRootActivityContainer.dumpChildrenNames(pw, " "); pw.println(" "); } @@ -4928,6 +4928,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * - the cmd arg isn't the flattened component name of an existing activity: * dump all activity whose component contains the cmd as a substring * - A hex number of the ActivityRecord object instance. + * <p> + * The caller should not hold lock when calling this method because it will wait for the + * activities to complete the dump. * * @param dumpVisibleStacksOnly dump activity with {@param name} only if in a visible stack * @param dumpFocusedStackOnly dump activity with {@param name} only if in the focused stack @@ -4980,29 +4983,28 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw, final ActivityRecord r, String[] args, boolean dumpAll) { String innerPrefix = prefix + " "; + IApplicationThread appThread = null; synchronized (mGlobalLock) { pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName); pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r))); pw.print(" pid="); - if (r.hasProcess()) pw.println(r.app.getPid()); - else pw.println("(not running)"); + if (r.hasProcess()) { + pw.println(r.app.getPid()); + appThread = r.app.getThread(); + } else { + pw.println("(not running)"); + } if (dumpAll) { r.dump(pw, innerPrefix); } } - if (r.attachedToProcess()) { + if (appThread != null) { // flush anything that is already in the PrintWriter since the thread is going // to write to the file descriptor directly pw.flush(); - try { - TransferPipe tp = new TransferPipe(); - try { - r.app.getThread().dumpActivity(tp.getWriteFd(), - r.appToken, innerPrefix, args); - tp.go(fd); - } finally { - tp.kill(); - } + try (TransferPipe tp = new TransferPipe()) { + appThread.dumpActivity(tp.getWriteFd(), r.appToken, innerPrefix, args); + tp.go(fd); } catch (IOException e) { pw.println(innerPrefix + "Failure while dumping the activity: " + e); } catch (RemoteException e) { @@ -7063,10 +7065,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args, int opti, boolean dumpAll, boolean dumpVisibleStacksOnly, boolean dumpFocusedStackOnly) { - synchronized (mGlobalLock) { - return ActivityTaskManagerService.this.dumpActivity(fd, pw, name, args, opti, - dumpAll, dumpVisibleStacksOnly, dumpFocusedStackOnly); - } + return ActivityTaskManagerService.this.dumpActivity(fd, pw, name, args, opti, dumpAll, + dumpVisibleStacksOnly, dumpFocusedStackOnly); } @Override diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 8007c0f316e0..d15081ca2665 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -260,9 +260,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree ActivityRecord mActivityRecord; /** - * See {@link #canTurnScreenOn()} + * @see #currentLaunchCanTurnScreenOn() */ - private boolean mCanTurnScreenOn = true; + private boolean mCurrentLaunchCanTurnScreenOn = true; /** * If we are running an animation, this determines the transition type. Must be one of @@ -1002,7 +1002,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree + " " + this); mAppStopped = false; // Allow the window to turn the screen on once the app is resumed again. - setCanTurnScreenOn(true); + setCurrentLaunchCanTurnScreenOn(true); if (!wasStopped) { destroySurfaces(true /*cleanupOnResume*/); } @@ -2420,21 +2420,25 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } /** - * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()} + * Sets whether the current launch can turn the screen on. + * @see #currentLaunchCanTurnScreenOn() */ - void setCanTurnScreenOn(boolean canTurnScreenOn) { - mCanTurnScreenOn = canTurnScreenOn; + void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) { + mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn; } /** * Indicates whether the current launch can turn the screen on. This is to prevent multiple * relayouts from turning the screen back on. The screen should only turn on at most * once per activity resume. + * <p> + * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON} + * or {@link ActivityRecord#canTurnScreenOn} is set. * - * @return true if the screen can be turned on. + * @return {@code true} if the activity is ready to turn on the screen. */ - boolean canTurnScreenOn() { - return mCanTurnScreenOn; + boolean currentLaunchCanTurnScreenOn() { + return mCurrentLaunchCanTurnScreenOn; } /** diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index e2d592826a3a..e29fbdfa17e7 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -122,7 +122,6 @@ import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION; import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS; -import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; @@ -1212,27 +1211,45 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } - /** Notify the configuration change of this display. */ - void postNewConfigurationToHandler() { - mWmService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget(); + void reconfigureDisplayLocked() { + if (!isReady()) { + return; + } + configureDisplayPolicy(); + setLayoutNeeded(); + + boolean configChanged = updateOrientationFromAppTokens(); + final Configuration currentDisplayConfig = getConfiguration(); + mTmpConfiguration.setTo(currentDisplayConfig); + computeScreenConfiguration(mTmpConfiguration); + configChanged |= currentDisplayConfig.diff(mTmpConfiguration) != 0; + + if (configChanged) { + mWaitingForConfig = true; + mWmService.startFreezingDisplayLocked(0 /* exitAnim */, 0 /* enterAnim */, this); + sendNewConfiguration(); + } + + mWmService.mWindowPlacerLocked.performSurfacePlacement(); } void sendNewConfiguration() { - synchronized (mWmService.mGlobalLock) { - final boolean configUpdated = mAcitvityDisplay - .updateDisplayOverrideConfigurationLocked(); - if (!configUpdated) { - // Something changed (E.g. device rotation), but no configuration update is needed. - // E.g. changing device rotation by 180 degrees. Go ahead and perform surface - // placement to unfreeze the display since we froze it when the rotation was updated - // in DisplayContent#updateRotationUnchecked. - if (mWaitingForConfig) { - mWaitingForConfig = false; - mWmService.mLastFinishedFreezeSource = "config-unchanged"; - setLayoutNeeded(); - mWmService.mWindowPlacerLocked.performSurfacePlacement(); - } - } + if (!isReady() || mAcitvityDisplay == null) { + return; + } + final boolean configUpdated = mAcitvityDisplay.updateDisplayOverrideConfigurationLocked(); + if (configUpdated) { + return; + } + // Something changed (E.g. device rotation), but no configuration update is needed. + // E.g. changing device rotation by 180 degrees. Go ahead and perform surface placement to + // unfreeze the display since we froze it when the rotation was updated in + // DisplayContent#updateRotationUnchecked. + if (mWaitingForConfig) { + mWaitingForConfig = false; + mWmService.mLastFinishedFreezeSource = "config-unchanged"; + setLayoutNeeded(); + mWmService.mWindowPlacerLocked.performSurfacePlacement(); } } @@ -1351,7 +1368,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo boolean updateRotationAndSendNewConfigIfNeeded() { final boolean changed = updateRotationUnchecked(false /* forceUpdate */); if (changed) { - postNewConfigurationToHandler(); + sendNewConfiguration(); } return changed; } @@ -2292,7 +2309,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mInitialDisplayHeight = newHeight; mInitialDisplayDensity = newDensity; mInitialDisplayCutout = newCutout; - mWmService.reconfigureDisplayLocked(this); + reconfigureDisplayLocked(); } } @@ -2345,7 +2362,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final boolean updateCurrent = userId == UserHandle.USER_CURRENT; if (mWmService.mCurrentUserId == userId || updateCurrent) { mBaseDisplayDensity = density; - mWmService.reconfigureDisplayLocked(this); + reconfigureDisplayLocked(); } if (updateCurrent) { // We are applying existing settings so no need to save it again. @@ -2366,7 +2383,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mDisplayScalingDisabled = (mode != FORCE_SCALING_MODE_AUTO); Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto")); - mWmService.reconfigureDisplayLocked(this); + reconfigureDisplayLocked(); mWmService.mDisplayWindowSettings.setForcedScalingMode(this, mode); } @@ -2385,7 +2402,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo Slog.i(TAG_WM, "Using new display size: " + width + "x" + height); updateBaseDisplayMetrics(width, height, mBaseDisplayDensity); - mWmService.reconfigureDisplayLocked(this); + reconfigureDisplayLocked(); if (clear) { width = height = 0; @@ -3730,7 +3747,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); if (updateOrientationFromAppTokens()) { setLayoutNeeded(); - postNewConfigurationToHandler(); + sendNewConfiguration(); } } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index cf87203893cf..61ba69fdf404 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -284,6 +284,8 @@ public class DisplayPolicy { /** See {@link #getNavigationBarFrameHeight} */ private int[] mNavigationBarFrameHeightForRotationDefault = new int[4]; + private boolean mIsFreeformWindowOverlappingWithNavBar; + /** Cached value of {@link ScreenShapeHelper#getWindowOutsetBottomPx} */ @Px private int mWindowOutsetBottom; @@ -2379,6 +2381,7 @@ public class DisplayPolicy { mAllowLockscreenWhenOn = false; mShowingDream = false; mWindowSleepTokenNeeded = false; + mIsFreeformWindowOverlappingWithNavBar = false; } /** @@ -2478,6 +2481,13 @@ public class DisplayPolicy { } } + // Check if the freeform window overlaps with the navigation bar area. + final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null; + if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode() + && isOverlappingWithNavBar(win, navBarWin)) { + mIsFreeformWindowOverlappingWithNavBar = true; + } + // Also keep track of any windows that are dimming but not necessarily fullscreen in the // docked stack. if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming() @@ -3458,7 +3468,11 @@ public class DisplayPolicy { } } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { - visibility = setNavBarOpaqueFlag(visibility); + if (mIsFreeformWindowOverlappingWithNavBar) { + visibility = setNavBarTranslucentFlag(visibility); + } else { + visibility = setNavBarOpaqueFlag(visibility); + } } else if (fullscreenDrawsBackground) { visibility = setNavBarTransparentFlag(visibility); } @@ -3747,4 +3761,14 @@ public class DisplayPolicy { wm.removeView(mPointerLocationView); mPointerLocationView = null; } + + @VisibleForTesting + static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) { + if (navBarWindow == null || !navBarWindow.isVisibleLw() + || targetWindow.mAppToken == null || !targetWindow.isVisibleLw()) { + return false; + } + + return Rect.intersects(targetWindow.getFrameLw(), navBarWindow.getFrameLw()); + } } diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java index b16d9564ea7a..6830adebad22 100644 --- a/services/core/java/com/android/server/wm/InputManagerCallback.java +++ b/services/core/java/com/android/server/wm/InputManagerCallback.java @@ -133,7 +133,10 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal @Override public void notifyConfigurationChanged() { // TODO(multi-display): Notify proper displays that are associated with this input device. - mService.mRoot.getDisplayContent(DEFAULT_DISPLAY).sendNewConfiguration(); + + synchronized (mService.mGlobalLock) { + mService.getDefaultDisplayContentLocked().sendNewConfiguration(); + } synchronized (mInputDevicesReadyMonitor) { if (!mInputDevicesReady) { diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index ca4749f7b365..422b6e58e0ed 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -43,11 +43,13 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS import android.os.IBinder; import android.os.RemoteException; import android.os.Trace; +import android.util.EventLog; import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import com.android.internal.policy.IKeyguardDismissCallback; +import com.android.server.am.EventLogTags; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.ActivityTaskManagerInternal.SleepToken; @@ -142,6 +144,11 @@ class KeyguardController { if (!keyguardChanged && !aodChanged) { return; } + EventLog.writeEvent(EventLogTags.AM_SET_KEYGUARD_SHOWN, + keyguardShowing ? 1 : 0, + aodShowing ? 1 : 0, + mKeyguardGoingAway ? 1 : 0, + "setKeyguardShown"); mKeyguardShowing = keyguardShowing; mAodShowing = aodShowing; mWindowManager.setAodShowing(aodShowing); @@ -178,6 +185,11 @@ class KeyguardController { mWindowManager.deferSurfaceLayout(); try { setKeyguardGoingAway(true); + EventLog.writeEvent(EventLogTags.AM_SET_KEYGUARD_SHOWN, + 1 /* keyguardShowing */, + mAodShowing ? 1 : 0, + 1 /* keyguardGoingAway */, + "keyguardGoingAway"); mRootActivityContainer.getDefaultDisplay().mDisplayContent .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */, convertTransitFlags(flags), diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 8a5f52f8c453..a00bee0859ad 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -248,8 +248,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> dc.configureDisplayPolicy(); } - mWmService.reconfigureDisplayLocked(dc); - return dc; } @@ -267,7 +265,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } displayContent.initializeDisplayOverrideConfiguration(); - mWmService.reconfigureDisplayLocked(displayContent); + displayContent.reconfigureDisplayLocked(); // We need to update global configuration as well if config of default display has // changed. Do it inline because ATMS#retrieveSettings() will soon update the diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index bd114d958fd0..f9a6fe725fa0 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -310,6 +310,7 @@ class TaskSnapshotController { } final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE; return new TaskSnapshot( + System.currentTimeMillis() /* id */, appWindowToken.mActivityComponent, screenshotBuffer.getGraphicBuffer(), screenshotBuffer.getColorSpace(), appWindowToken.getTask().getConfiguration().orientation, @@ -404,7 +405,9 @@ class TaskSnapshotController { // Note, the app theme snapshot is never translucent because we enforce a non-translucent // color above - return new TaskSnapshot(topChild.mActivityComponent, hwBitmap.createGraphicBufferHandle(), + return new TaskSnapshot( + System.currentTimeMillis() /* id */, + topChild.mActivityComponent, hwBitmap.createGraphicBufferHandle(), hwBitmap.getColorSpace(), topChild.getTask().getConfiguration().orientation, getInsets(mainWindow), ActivityManager.isLowRamDeviceStatic() /* reduced */, mFullSnapshotScale, false /* isRealSnapshot */, task.getWindowingMode(), diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java index fcd97c1bac5d..696e1c3a2602 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java @@ -92,7 +92,7 @@ class TaskSnapshotLoader { // For legacy snapshots, restore the scale based on the reduced resolution state final float legacyScale = reducedResolution ? mPersister.getReducedScale() : 1f; final float scale = Float.compare(proto.scale, 0f) != 0 ? proto.scale : legacyScale; - return new TaskSnapshot(topActivityComponent, buffer, bitmap.getColorSpace(), + return new TaskSnapshot(proto.id, topActivityComponent, buffer, bitmap.getColorSpace(), proto.orientation, new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom), reducedResolution, scale, proto.isRealSnapshot, proto.windowingMode, diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index 72fc18937ece..32a1d9061160 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -343,6 +343,7 @@ class TaskSnapshotPersister { proto.isTranslucent = mSnapshot.isTranslucent(); proto.topActivityComponent = mSnapshot.getTopActivityComponent().flattenToString(); proto.scale = mSnapshot.getScale(); + proto.id = mSnapshot.getId(); final byte[] bytes = TaskSnapshotProto.toByteArray(proto); final File file = getProtoFile(mTaskId, mUserId); final AtomicFile atomicFile = new AtomicFile(file); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f52bde9a035c..dda27b56e5ac 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -79,7 +79,6 @@ import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; @@ -1651,6 +1650,7 @@ public class WindowManagerService extends IWindowManager.Stub if (display != null) { displayContent = mRoot.createDisplayContent(display, null /* activityDisplay */); + displayContent.reconfigureDisplayLocked(); } } @@ -3751,7 +3751,7 @@ public class WindowManagerService extends IWindowManager.Stub layoutNeeded = true; } if (rotationChanged || alwaysSendConfiguration) { - displayContent.postNewConfigurationToHandler(); + displayContent.sendNewConfiguration(); } } @@ -4421,7 +4421,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayReady = true; // Reconfigure all displays to make sure that forced properties and // DisplayWindowSettings are applied. - mRoot.forAllDisplays(this::reconfigureDisplayLocked); + mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked); mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN); } @@ -4500,7 +4500,6 @@ public class WindowManagerService extends IWindowManager.Stub public static final int FORCE_GC = 15; public static final int ENABLE_SCREEN = 16; public static final int APP_FREEZE_TIMEOUT = 17; - public static final int SEND_NEW_CONFIGURATION = 18; public static final int REPORT_WINDOWS_CHANGE = 19; public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; @@ -4712,23 +4711,6 @@ public class WindowManagerService extends IWindowManager.Stub break; } - case SEND_NEW_CONFIGURATION: { - final DisplayContent displayContent = (DisplayContent) msg.obj; - removeMessages(SEND_NEW_CONFIGURATION, displayContent); - if (displayContent.isReady()) { - displayContent.sendNewConfiguration(); - } else { - // Message could come after display has already been removed. - if (DEBUG_CONFIGURATION) { - final String reason = displayContent.getParent() == null - ? "detached" : "unready"; - Slog.w(TAG, "Trying to send configuration to " + reason + " display=" - + displayContent); - } - } - break; - } - case REPORT_WINDOWS_CHANGE: { if (mWindowsChanged) { synchronized (mGlobalLock) { @@ -5183,29 +5165,6 @@ public class WindowManagerService extends IWindowManager.Stub return 0; } - void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) { - if (!displayContent.isReady()) { - return; - } - displayContent.configureDisplayPolicy(); - displayContent.setLayoutNeeded(); - - boolean configChanged = displayContent.updateOrientationFromAppTokens(); - final Configuration currentDisplayConfig = displayContent.getConfiguration(); - mTempConfiguration.setTo(currentDisplayConfig); - displayContent.computeScreenConfiguration(mTempConfiguration); - configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0; - - if (configChanged) { - displayContent.mWaitingForConfig = true; - startFreezingDisplayLocked(0 /* exitAnim */, - 0 /* enterAnim */, displayContent); - displayContent.postNewConfigurationToHandler(); - } - - mWindowPlacerLocked.performSurfacePlacement(); - } - @Override public void setOverscan(int displayId, int left, int top, int right, int bottom) { if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS) @@ -5235,7 +5194,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayWindowSettings.setOverscanLocked(displayInfo, left, top, right, bottom); - reconfigureDisplayLocked(displayContent); + displayContent.reconfigureDisplayLocked(); } @Override @@ -5547,7 +5506,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (configChanged) { - displayContent.postNewConfigurationToHandler(); + displayContent.sendNewConfiguration(); } mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN); } @@ -6863,12 +6822,11 @@ public class WindowManagerService extends IWindowManager.Stub int lastWindowingMode = displayContent.getWindowingMode(); mDisplayWindowSettings.setWindowingModeLocked(displayContent, mode); - reconfigureDisplayLocked(displayContent); + displayContent.reconfigureDisplayLocked(); if (lastWindowingMode != displayContent.getWindowingMode()) { // reconfigure won't detect this change in isolation because the windowing mode is // already set on the display, so fire off a new config now. - mH.removeMessages(H.SEND_NEW_CONFIGURATION); final long origId = Binder.clearCallingIdentity(); try { @@ -6916,7 +6874,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayWindowSettings.setRemoveContentModeLocked(displayContent, mode); - reconfigureDisplayLocked(displayContent); + displayContent.reconfigureDisplayLocked(); } } @@ -6955,7 +6913,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayWindowSettings.setShouldShowWithInsecureKeyguardLocked(displayContent, shouldShow); - reconfigureDisplayLocked(displayContent); + displayContent.reconfigureDisplayLocked(); } } @@ -6999,7 +6957,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayWindowSettings.setShouldShowSystemDecorsLocked(displayContent, shouldShow); - reconfigureDisplayLocked(displayContent); + displayContent.reconfigureDisplayLocked(); } } @@ -7044,7 +7002,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayWindowSettings.setShouldShowImeLocked(displayContent, shouldShow); - reconfigureDisplayLocked(displayContent); + displayContent.reconfigureDisplayLocked(); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 8b1baebbbbc0..95db44865258 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1633,7 +1633,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP || !mRelayoutCalled || (atoken == null && mToken.isHidden()) || (atoken != null && atoken.hiddenRequested) - || isParentWindowHidden() + || isParentWindowGoneForLayout() || (mAnimatingExit && !isAnimatingLw()) || mDestroying; } @@ -2063,7 +2063,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (wasVisible) { final DisplayContent displayContent = getDisplayContent(); if (displayContent.updateOrientationFromAppTokens()) { - displayContent.postNewConfigurationToHandler(); + displayContent.sendNewConfiguration(); } } mWmService.updateFocusedWindowLocked(isFocused() @@ -2393,10 +2393,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void prepareWindowToDisplayDuringRelayout(boolean wasVisible) { // We need to turn on screen regardless of visibility. - boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0; + final boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0 + || (mAppToken != null && mAppToken.mActivityRecord.canTurnScreenOn()); // The screen will turn on if the following conditions are met - // 1. The window has the flag FLAG_TURN_SCREEN_ON + // 1. The window has the flag FLAG_TURN_SCREEN_ON or ActivityRecord#canTurnScreenOn. // 2. The WMS allows theater mode. // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once // per resume to prevent the screen getting getting turned on for each relayout. Set @@ -2410,7 +2411,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP boolean allowTheaterMode = mWmService.mAllowTheaterModeWakeFromLayout || Settings.Global.getInt(mWmService.mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0) == 0; - boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn(); + boolean canTurnScreenOn = mAppToken == null || mAppToken.currentLaunchCanTurnScreenOn(); if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) { if (DEBUG_VISIBILITY || DEBUG_POWER) { @@ -2421,7 +2422,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } if (mAppToken != null) { - mAppToken.setCanTurnScreenOn(false); + mAppToken.setCurrentLaunchCanTurnScreenOn(false); } } @@ -3847,6 +3848,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return parent != null && parent.mHidden; } + private boolean isParentWindowGoneForLayout() { + final WindowState parent = getParentWindow(); + return parent != null && parent.isGoneForLayoutLw(); + } + void setWillReplaceWindow(boolean animate) { for (int i = mChildren.size() - 1; i >= 0; i--) { final WindowState c = mChildren.get(i); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 73344ac1a430..3ba3280be7bb 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1508,6 +1508,12 @@ class WindowStateAnimator { } void detachChildren() { + + // Do not detach children of starting windows, as their lifecycle is well under control and + // it may lead to issues in case we relaunch when we just added the starting window. + if (mWin.mAttrs.type == TYPE_APPLICATION_STARTING) { + return; + } if (mSurfaceController != null) { mSurfaceController.detachChildren(); } diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java index b1b30701df4f..ce7776f270fd 100644 --- a/services/core/java/com/android/server/wm/utils/RegionUtils.java +++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java @@ -50,6 +50,20 @@ public class RegionUtils { /** * Applies actions on each rect contained within a {@code Region}. * + * @param region the given region. + * @param rectConsumer the action holder. + */ + public static void forEachRect(Region region, Consumer<Rect> rectConsumer) { + final RegionIterator it = new RegionIterator(region); + final Rect rect = new Rect(); + while (it.next(rect)) { + rectConsumer.accept(rect); + } + } + + /** + * Applies actions on each rect contained within a {@code Region}. + * * Order is bottom to top, then right to left. * * @param region the given region. diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 1c8c46c74002..466ca9315f6f 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -41,7 +41,6 @@ #include <utils/Looper.h> #include <utils/threads.h> #include <utils/Trace.h> -#include <utils/SortedVector.h> #include <binder/IServiceManager.h> @@ -307,7 +306,7 @@ private: wp<PointerController> pointerController; // Input devices to be disabled - SortedVector<int32_t> disabledInputDevices; + std::set<int32_t> disabledInputDevices; // Associated Pointer controller display. int32_t pointerDisplayId; @@ -898,13 +897,13 @@ void NativeInputManager::setInputDeviceEnabled(uint32_t deviceId, bool enabled) { // acquire lock AutoMutex _l(mLock); - ssize_t index = mLocked.disabledInputDevices.indexOf(deviceId); - bool currentlyEnabled = index < 0; + auto it = mLocked.disabledInputDevices.find(deviceId); + bool currentlyEnabled = it == mLocked.disabledInputDevices.end(); if (!enabled && currentlyEnabled) { - mLocked.disabledInputDevices.add(deviceId); + mLocked.disabledInputDevices.insert(deviceId); } if (enabled && !currentlyEnabled) { - mLocked.disabledInputDevices.remove(deviceId); + mLocked.disabledInputDevices.erase(deviceId); } } // release lock diff --git a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java index 73b3b8b1ce3c..a785300e98a3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java @@ -19,6 +19,7 @@ package com.android.server.display.color; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; +import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE; import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_DISPLAY_COLOR; import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_SATURATION; @@ -28,6 +29,7 @@ import static org.mockito.ArgumentMatchers.any; import android.hardware.display.ColorDisplayManager; import android.os.SystemProperties; +import android.view.Display; import androidx.test.runner.AndroidJUnit4; @@ -79,7 +81,7 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_natural() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, -1); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("0" /* managed */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -88,7 +90,7 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_boosted() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED, mNightDisplayMatrix); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED, mNightDisplayMatrix, -1); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("0" /* managed */); @@ -98,7 +100,7 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_saturated() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED, mNightDisplayMatrix); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED, mNightDisplayMatrix, -1); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("1" /* unmanaged */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -107,7 +109,7 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_automatic() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC, mNightDisplayMatrix); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC, mNightDisplayMatrix, -1); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("2" /* enhanced */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -116,7 +118,7 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_vendor() { - mDtm.setColorMode(0x100, mNightDisplayMatrix); + mDtm.setColorMode(0x100, mNightDisplayMatrix, -1); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo(Integer.toString(0x100) /* pass-through */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -125,10 +127,38 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_outOfBounds() { - mDtm.setColorMode(0x50, mNightDisplayMatrix); + mDtm.setColorMode(0x50, mNightDisplayMatrix, -1); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo(null); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) .isEqualTo(null); } + + @Test + public void setColorMode_withoutColorSpace() { + String magicPropertyValue = "magic"; + + // Start with a known state, which we expect to remain unmodified + SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE, magicPropertyValue); + + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, + Display.COLOR_MODE_INVALID); + assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE)) + .isEqualTo(magicPropertyValue); + } + + @Test + public void setColorMode_withColorSpace() { + String magicPropertyValue = "magic"; + int testPropertyValue = Display.COLOR_MODE_SRGB; + + // Start with a known state, which we expect to get modified + SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE, magicPropertyValue); + + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, + testPropertyValue); + assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE)) + .isEqualTo(Integer.toString(testPropertyValue)); + } + } diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index e9e96c9c7efb..1ad7b6e8d155 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -72,6 +72,7 @@ import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.devicepolicy.MockUtils; +import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.google.android.collect.Lists; @@ -132,9 +133,10 @@ public class NetworkScoreServiceTest { @Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter; @Mock private WifiInfo mWifiInfo; @Mock private NetworkScoreService.ScoringServiceConnection mServiceConnection; - @Mock private PackageManagerInternal mPackageManagerInternal; + @Mock private PermissionManagerServiceInternal mPermissionManagerInternal; @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor; - @Captor private ArgumentCaptor<PackageManagerInternal.PackagesProvider> mPackagesProviderCaptor; + @Captor private + ArgumentCaptor<PermissionManagerServiceInternal.PackagesProvider> mPackagesProviderCaptor; private ContentResolver mContentResolver; private NetworkScoreService mNetworkScoreService; @@ -162,7 +164,8 @@ public class NetworkScoreServiceTest { when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER); mHandlerThread = new HandlerThread("NetworkScoreServiceTest"); mHandlerThread.start(); - LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal); + LocalServices.addService( + PermissionManagerServiceInternal.class, mPermissionManagerInternal); mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager, networkScorerAppData -> mServiceConnection, mHandlerThread.getLooper()); WifiConfiguration configuration = new WifiConfiguration(); @@ -196,7 +199,7 @@ public class NetworkScoreServiceTest { Settings.Global.putString(mContentResolver, Settings.Global.USE_OPEN_WIFI_PACKAGE, "com.some.app"); - verify(mPackageManagerInternal) + verify(mPermissionManagerInternal) .setUseOpenWifiAppPackagesProvider(mPackagesProviderCaptor.capture()); String[] packages = mPackagesProviderCaptor.getValue().getPackages(0); @@ -209,7 +212,7 @@ public class NetworkScoreServiceTest { Settings.Global.putString(mContentResolver, Settings.Global.USE_OPEN_WIFI_PACKAGE, "com.some.other.app"); - verify(mPackageManagerInternal, timeout(500)) + verify(mPermissionManagerInternal, timeout(500)) .grantDefaultPermissionsToDefaultUseOpenWifiApp("com.some.other.app", 0); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java index 22408cc05b93..e12532931e7c 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java @@ -238,7 +238,7 @@ public class AccessibilityWindowManagerTest { windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION; windowInfo.token = token.asBinder(); windowInfo.layer = 0; - windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mWindowInfos.set(0, windowInfo); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); @@ -305,67 +305,73 @@ public class AccessibilityWindowManagerTest { } @Test - public void computePartialInteractiveRegionForWindow_wholeWindowVisible_returnWholeRegion() { + public void computePartialInteractiveRegionForWindow_wholeVisible_returnWholeRegion() { // Updates top 2 z-order WindowInfo are whole visible. WindowInfo windowInfo = mWindowInfos.get(0); - windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2); + windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2); windowInfo = mWindowInfos.get(1); - windowInfo.boundsInScreen.set(0, SCREEN_HEIGHT / 2, - SCREEN_WIDTH, SCREEN_HEIGHT); + windowInfo.regionInScreen.set(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); int windowId = a11yWindows.get(0).getId(); - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( - windowId, outBounds); + mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2)); windowId = a11yWindows.get(1).getId(); - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( - windowId, outBounds); + mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2)); } @Test - public void computePartialInteractiveRegionForWindow_halfWindowVisible_returnHalfRegion() { + public void computePartialInteractiveRegionForWindow_halfVisible_returnHalfRegion() { // Updates z-order #1 WindowInfo is half visible WindowInfo windowInfo = mWindowInfos.get(0); - windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2); - windowInfo = mWindowInfos.get(1); - windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); int windowId = a11yWindows.get(1).getId(); - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( - windowId, outBounds); + mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2)); } @Test - public void computePartialInteractiveRegionForWindow_windowNotVisible_returnEmptyRegion() { - // Updates z-order #1 WindowInfo is not visible + public void computePartialInteractiveRegionForWindow_notVisible_returnEmptyRegion() { + // Since z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible. + final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); + final Region outBounds = new Region(); + int windowId = a11yWindows.get(1).getId(); + + mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); + assertTrue(outBounds.getBounds().isEmpty()); + } + + @Test + public void computePartialInteractiveRegionForWindow_partialVisible_returnVisibleRegion() { + // Updates z-order #0 WindowInfo to have two interact-able areas. + Region region = new Region(0, 0, SCREEN_WIDTH, 200); + region.op(0, SCREEN_HEIGHT - 200, SCREEN_WIDTH, SCREEN_HEIGHT, Region.Op.UNION); WindowInfo windowInfo = mWindowInfos.get(0); - windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - windowInfo = mWindowInfos.get(1); - windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + windowInfo.regionInScreen.set(region); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); int windowId = a11yWindows.get(1).getId(); - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( - windowId, outBounds); - assertTrue(outBounds.getBounds().isEmpty()); + mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); + assertFalse(outBounds.getBounds().isEmpty()); + assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); + assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT - 400)); } @Test @@ -588,7 +594,7 @@ public class AccessibilityWindowManagerTest { windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION; windowInfo.token = windowToken.asBinder(); windowInfo.layer = layer; - windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mWindowInfos.add(windowInfo); } diff --git a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java index fb2913b09ace..a19b3872949e 100644 --- a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java @@ -18,13 +18,19 @@ package com.android.server.display.color; import static com.google.common.truth.Truth.assertWithMessage; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AlarmManager; import android.content.Context; import android.content.ContextWrapper; +import android.content.res.Resources; import android.hardware.display.ColorDisplayManager; import android.hardware.display.Time; import android.os.Handler; @@ -33,6 +39,7 @@ import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.System; import android.test.mock.MockContentResolver; +import android.view.Display; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -73,6 +80,8 @@ public class ColorDisplayServiceTest { private ColorDisplayService mCds; private ColorDisplayService.BinderService mBinderService; + private Resources mResourcesSpy; + @BeforeClass public static void setDtm() { final DisplayTransformManager dtm = Mockito.mock(DisplayTransformManager.class); @@ -84,6 +93,9 @@ public class ColorDisplayServiceTest { mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); doReturn(mContext).when(mContext).getApplicationContext(); + mResourcesSpy = Mockito.spy(mContext.getResources()); + when(mContext.getResources()).thenReturn(mResourcesSpy); + mUserId = ActivityManager.getCurrentUser(); final MockContentResolver cr = new MockContentResolver(mContext); @@ -1050,6 +1062,80 @@ public class ColorDisplayServiceTest { assertDwbActive(true); } + @Test + public void compositionColorSpaces_noResources() { + final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); + reset(dtm); + + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes)) + .thenReturn(new int[] {}); + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces)) + .thenReturn(new int[] {}); + setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL); + startService(); + verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), + eq(Display.COLOR_MODE_INVALID)); + } + + @Test + public void compositionColorSpaces_invalidResources() { + final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); + reset(dtm); + + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes)) + .thenReturn(new int[] { + ColorDisplayManager.COLOR_MODE_NATURAL, + // Missing second color mode + }); + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces)) + .thenReturn(new int[] { + Display.COLOR_MODE_SRGB, + Display.COLOR_MODE_DISPLAY_P3 + }); + setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL); + startService(); + verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), + eq(Display.COLOR_MODE_INVALID)); + } + + @Test + public void compositionColorSpaces_validResources_validColorMode() { + final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); + reset(dtm); + + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes)) + .thenReturn(new int[] { + ColorDisplayManager.COLOR_MODE_NATURAL + }); + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces)) + .thenReturn(new int[] { + Display.COLOR_MODE_SRGB, + }); + setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL); + startService(); + verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), + eq(Display.COLOR_MODE_SRGB)); + } + + @Test + public void compositionColorSpaces_validResources_invalidColorMode() { + final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); + reset(dtm); + + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes)) + .thenReturn(new int[] { + ColorDisplayManager.COLOR_MODE_NATURAL + }); + when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces)) + .thenReturn(new int[] { + Display.COLOR_MODE_SRGB, + }); + setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED); + startService(); + verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_BOOSTED), any(), + eq(Display.COLOR_MODE_INVALID)); + } + /** * Configures Night display to use a custom schedule. * diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index 95ec3d9c0917..fc7cfec9dc87 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -115,7 +115,7 @@ public class PackageManagerServiceTest { @Test public void testPartitions() throws Exception { - String[] partitions = { "system", "vendor", "odm", "oem", "product", "product_services" }; + String[] partitions = { "system", "vendor", "odm", "oem", "product", "system_ext" }; String[] appdir = { "app", "priv-app" }; for (int i = 0; i < partitions.length; i++) { for (int j = 0; j < appdir.length; j++) { @@ -128,7 +128,7 @@ public class PackageManagerServiceTest { Assert.assertEquals(i == 1 || i == 2, PackageManagerService.locationIsVendor(path)); Assert.assertEquals(i == 3, PackageManagerService.locationIsOem(path)); Assert.assertEquals(i == 4, PackageManagerService.locationIsProduct(path)); - Assert.assertEquals(i == 5, PackageManagerService.locationIsProductServices(path)); + Assert.assertEquals(i == 5, PackageManagerService.locationIsSystemExt(path)); } } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java index 6061d51f3d79..8c3373faa0d4 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -156,7 +156,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { mService.setUsageStats(mUsageStats); mService.setAccessibilityManager(accessibilityManager); mService.mScreenOn = false; - mService.mInCall = false; + mService.mInCallStateOffHook = false; mService.mNotificationPulseEnabled = true; } @@ -681,7 +681,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { mService.buzzBeepBlinkLocked(r); Mockito.reset(mRingtonePlayer); - mService.mInCall = true; + mService.mInCallStateOffHook = true; mService.buzzBeepBlinkLocked(r); verify(mService, times(1)).playInCallNotification(); @@ -1137,7 +1137,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { @Test public void testLightsInCall() { - mService.mInCall = true; + mService.mInCallStateOffHook = true; NotificationRecord r = getLightsNotification(); mService.buzzBeepBlinkLocked(r); verifyNeverLights(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index efbae2b566ad..deca57e98f7c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.os.Process.NOBODY_UID; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_90; @@ -40,6 +41,8 @@ import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE; import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE; import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -54,8 +57,10 @@ import android.app.ActivityOptions; import android.app.servertransaction.ActivityConfigurationChangeItem; import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.PauseActivityItem; +import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.util.MergedConfiguration; @@ -67,6 +72,7 @@ import android.view.RemoteAnimationTarget; import androidx.test.filters.MediumTest; +import com.android.internal.R; import com.android.server.wm.utils.WmDisplayCutout; import org.junit.Before; @@ -611,6 +617,15 @@ public class ActivityRecordTests extends ActivityTestsBase { assertNull(mActivity.pendingOptions); } + @Test + public void testCanLaunchHomeActivityFromChooser() { + ComponentName chooserComponent = ComponentName.unflattenFromString( + Resources.getSystem().getString(R.string.config_chooserActivity)); + ActivityRecord chooserActivity = new ActivityBuilder(mService).setComponent( + chooserComponent).build(); + assertThat(mActivity.canLaunchHomeActivity(NOBODY_UID, chooserActivity)).isTrue(); + } + /** Setup {@link #mActivity} as a size-compat-mode-able activity without fixed orientation. */ private void prepareFixedAspectRatioUnresizableActivity() { setupDisplayContentForCompatDisplayInsets(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 1684f97d28e3..6a3c81ab73bc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLES import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; +import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -49,10 +50,12 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.graphics.PixelFormat; +import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.Surface; import android.view.WindowManager; +import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import org.junit.Test; @@ -273,4 +276,37 @@ public class DisplayPolicyTests extends WindowTestsBase { win.mHasSurface = true; return win; } + + @Test + @FlakyTest(bugId = 131005232) + public void testOverlappingWithNavBar() { + final WindowState targetWin = createApplicationWindow(); + final WindowFrames winFrame = targetWin.getWindowFrames(); + winFrame.mFrame.set(new Rect(100, 100, 200, 200)); + + final WindowState navigationBar = createNavigationBarWindow(); + + navigationBar.getFrameLw().set(new Rect(100, 200, 200, 300)); + + assertFalse("Freeform is overlapping with navigation bar", + DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + + winFrame.mFrame.set(new Rect(100, 101, 200, 201)); + assertTrue("Freeform should be overlapping with navigation bar (bottom)", + DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + + winFrame.mFrame.set(new Rect(99, 200, 199, 300)); + assertTrue("Freeform should be overlapping with navigation bar (right)", + DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + + winFrame.mFrame.set(new Rect(199, 200, 299, 300)); + assertTrue("Freeform should be overlapping with navigation bar (left)", + DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + } + + private WindowState createNavigationBarWindow() { + final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar"); + win.mHasSurface = true; + return win; + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index 2bffc167f418..bfede51f5a3c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -23,7 +23,6 @@ import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeastOnce; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; @@ -624,11 +623,8 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { assertFalse(dc.mWaitingForConfig); // Notify WM that the displays are ready and check that they are reconfigured. - spyOn(mWm); mWm.displayReady(); waitUntilHandlersIdle(); - verify(mWm, atLeastOnce()).reconfigureDisplayLocked(eq(mPrimaryDisplay)); - verify(mWm, atLeastOnce()).reconfigureDisplayLocked(eq(dc)); final Configuration config = new Configuration(); mPrimaryDisplay.computeScreenConfiguration(config); diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index d0ee63435280..df7c9a44dd12 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -177,7 +177,9 @@ public class SystemServicesTestRule implements TestRule { final Display display = mWindowManagerService.mDisplayManager.getDisplay(DEFAULT_DISPLAY); // Display creation is driven by the ActivityManagerService via // ActivityStackSupervisor. We emulate those steps here. - mWindowManagerService.mRoot.createDisplayContent(display, mock(ActivityDisplay.class)); + DisplayContent displayContent = mWindowManagerService.mRoot + .createDisplayContent(display, mock(ActivityDisplay.class)); + displayContent.reconfigureDisplayLocked(); mMockTracker.stopTracking(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java index f958867274cd..b29453a4fa94 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java @@ -64,6 +64,7 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa assertTrueForFiles(files, File::exists, " must exist"); final TaskSnapshot snapshot = mLoader.loadTask(1, mTestUserId, false /* reduced */); assertNotNull(snapshot); + assertEquals(MOCK_SNAPSHOT_ID, snapshot.getId()); assertEquals(TEST_INSETS, snapshot.getContentInsets()); assertNotNull(snapshot.getSnapshot()); assertEquals(Configuration.ORIENTATION_PORTRAIT, snapshot.getOrientation()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java index e004cd3fb0c4..f7496229f66b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java @@ -45,6 +45,7 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase { private static final Rect TEST_INSETS = new Rect(10, 20, 30, 40); static final File FILES_DIR = getInstrumentation().getTargetContext().getFilesDir(); + static final long MOCK_SNAPSHOT_ID = 12345678; TaskSnapshotPersister mPersister; TaskSnapshotLoader mLoader; @@ -129,7 +130,7 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase { Canvas c = buffer.lockCanvas(); c.drawColor(Color.RED); buffer.unlockCanvasAndPost(c); - return new TaskSnapshot(new ComponentName("", ""), buffer, + return new TaskSnapshot(MOCK_SNAPSHOT_ID, new ComponentName("", ""), buffer, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, TEST_INSETS, mReducedResolution, mScale, mIsRealSnapshot, mWindowingMode, mSystemUiVisibility, mIsTranslucent); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java index 4ca01eca238b..74db8202614d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java @@ -64,7 +64,9 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase { int windowFlags, Rect taskBounds) { final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888, GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER); - final TaskSnapshot snapshot = new TaskSnapshot(new ComponentName("", ""), buffer, + final TaskSnapshot snapshot = new TaskSnapshot( + System.currentTimeMillis(), + new ComponentName("", ""), buffer, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 1b57c7924ecb..36698eae274c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -302,43 +302,38 @@ public class WindowStateTests extends WindowTestsBase { @Test public void testPrepareWindowToDisplayDuringRelayout() { - testPrepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - testPrepareWindowToDisplayDuringRelayout(true /*wasVisible*/); - - // Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON - // before calling prepareWindowToDisplayDuringRelayout for windows with flag in the same - // appWindowToken. + // Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON before + // calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same appWindowToken. final AppWindowToken appWindowToken = createAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); final WindowState first = createWindow(null, TYPE_APPLICATION, appWindowToken, "first"); final WindowState second = createWindow(null, TYPE_APPLICATION, appWindowToken, "second"); second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; - reset(sPowerManagerWrapper); - first.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString()); - assertTrue(appWindowToken.canTurnScreenOn()); - - reset(sPowerManagerWrapper); - second.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); - assertFalse(appWindowToken.canTurnScreenOn()); + testPrepareWindowToDisplayDuringRelayout(first, false /* expectedWakeupCalled */, + true /* expectedCurrentLaunchCanTurnScreenOn */); + testPrepareWindowToDisplayDuringRelayout(second, true /* expectedWakeupCalled */, + false /* expectedCurrentLaunchCanTurnScreenOn */); // Call prepareWindowToDisplayDuringRelayout for two window that have FLAG_TURN_SCREEN_ON // from the same appWindowToken. Only one should trigger the wakeup. - appWindowToken.setCanTurnScreenOn(true); + appWindowToken.setCurrentLaunchCanTurnScreenOn(true); first.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; - reset(sPowerManagerWrapper); - first.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); - assertFalse(appWindowToken.canTurnScreenOn()); + testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */, + false /* expectedCurrentLaunchCanTurnScreenOn */); + testPrepareWindowToDisplayDuringRelayout(second, false /* expectedWakeupCalled */, + false /* expectedCurrentLaunchCanTurnScreenOn */); - reset(sPowerManagerWrapper); - second.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString()); - assertFalse(appWindowToken.canTurnScreenOn()); + // Without window flags, the state of ActivityRecord.canTurnScreenOn should still be able to + // turn on the screen. + appWindowToken.setCurrentLaunchCanTurnScreenOn(true); + first.mAttrs.flags &= ~WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; + doReturn(true).when(appWindowToken.mActivityRecord).canTurnScreenOn(); + + testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */, + false /* expectedCurrentLaunchCanTurnScreenOn */); // Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an // appWindowToken. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup @@ -360,6 +355,22 @@ public class WindowStateTests extends WindowTestsBase { verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); } + private void testPrepareWindowToDisplayDuringRelayout(WindowState appWindow, + boolean expectedWakeupCalled, boolean expectedCurrentLaunchCanTurnScreenOn) { + reset(sPowerManagerWrapper); + appWindow.prepareWindowToDisplayDuringRelayout(false /* wasVisible */); + + if (expectedWakeupCalled) { + verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); + } else { + verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString()); + } + // If wakeup is expected to be called, the currentLaunchCanTurnScreenOn should be false + // because the state will be consumed. + assertThat(appWindow.mAppToken.currentLaunchCanTurnScreenOn(), + is(expectedCurrentLaunchCanTurnScreenOn)); + } + @Test public void testCanAffectSystemUiFlags() { final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); @@ -487,15 +498,6 @@ public class WindowStateTests extends WindowTestsBase { assertThat(app.getWmDisplayCutout().getDisplayCutout(), is(cutout.inset(7, 10, 5, 20))); } - private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) { - reset(sPowerManagerWrapper); - final WindowState root = createWindow(null, TYPE_APPLICATION, "root"); - root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; - - root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); - } - @Test public void testVisibilityChangeSwitchUser() { final WindowState window = createWindow(null, TYPE_APPLICATION, "app"); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 3a702cb9521c..dc461d149cee 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -435,7 +435,9 @@ class WindowTestsBase { // Display creation is driven by DisplayWindowController via ActivityStackSupervisor. // We skip those steps here. final ActivityDisplay mockAd = mock(ActivityDisplay.class); - return mWm.mRoot.createDisplayContent(display, mockAd); + final DisplayContent displayContent = mWm.mRoot.createDisplayContent(display, mockAd); + displayContent.reconfigureDisplayLocked(); + return displayContent; } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index e1ffb0f179f8..b2fde548e506 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -33,7 +33,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.ShortcutServiceInternal; @@ -79,6 +78,7 @@ import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.UiThread; +import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.soundtrigger.SoundTriggerInternal; import com.android.server.wm.ActivityTaskManagerInternal; @@ -120,10 +120,10 @@ public class VoiceInteractionManagerService extends SystemService { mUserManager = Preconditions.checkNotNull( context.getSystemService(UserManager.class)); - PackageManagerInternal packageManagerInternal = LocalServices.getService( - PackageManagerInternal.class); - packageManagerInternal.setVoiceInteractionPackagesProvider( - new PackageManagerInternal.PackagesProvider() { + PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService( + PermissionManagerServiceInternal.class); + permissionManagerInternal.setVoiceInteractionPackagesProvider( + new PermissionManagerServiceInternal.PackagesProvider() { @Override public String[] getPackages(int userId) { mServiceStub.initForUser(userId); diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java index a1bea4d417f9..6498e498bfbe 100644 --- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java @@ -22,6 +22,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.os.RemoteException; +import android.permission.IPermissionManager; import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.ArrayMap; @@ -71,8 +72,8 @@ public final class CarrierAppUtils { * privileged apps may have changed. */ public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage, - IPackageManager packageManager, TelephonyManager telephonyManager, - ContentResolver contentResolver, int userId) { + IPackageManager packageManager, IPermissionManager permissionManager, + TelephonyManager telephonyManager, ContentResolver contentResolver, int userId) { if (DEBUG) { Slog.d(TAG, "disableCarrierAppsUntilPrivileged"); } @@ -81,8 +82,8 @@ public final class CarrierAppUtils { config.getDisabledUntilUsedPreinstalledCarrierApps(); ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); - disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, - contentResolver, userId, systemCarrierAppsDisabledUntilUsed, + disableCarrierAppsUntilPrivileged(callingPackage, packageManager, permissionManager, + telephonyManager, contentResolver, userId, systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed); } @@ -98,7 +99,8 @@ public final class CarrierAppUtils { * Manager can kill it, and this can lead to crashes as the app is in an unexpected state. */ public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage, - IPackageManager packageManager, ContentResolver contentResolver, int userId) { + IPackageManager packageManager, IPermissionManager permissionManager, + ContentResolver contentResolver, int userId) { if (DEBUG) { Slog.d(TAG, "disableCarrierAppsUntilPrivileged"); } @@ -109,7 +111,7 @@ public final class CarrierAppUtils { ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); - disableCarrierAppsUntilPrivileged(callingPackage, packageManager, + disableCarrierAppsUntilPrivileged(callingPackage, packageManager, permissionManager, null /* telephonyManager */, contentResolver, userId, systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed); } @@ -117,7 +119,8 @@ public final class CarrierAppUtils { // Must be public b/c framework unit tests can't access package-private methods. @VisibleForTesting public static void disableCarrierAppsUntilPrivileged(String callingPackage, - IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, + IPackageManager packageManager, IPermissionManager permissionManager, + @Nullable TelephonyManager telephonyManager, ContentResolver contentResolver, int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed, ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) { @@ -256,7 +259,7 @@ public final class CarrierAppUtils { // apps. String[] packageNames = new String[enabledCarrierPackages.size()]; enabledCarrierPackages.toArray(packageNames); - packageManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId); + permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId); } } catch (RemoteException e) { Slog.w(TAG, "Could not reach PackageManager", e); diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java index e9a5ff70a7cc..4d8c7d930bde 100644 --- a/test-mock/src/android/test/mock/MockContentProvider.java +++ b/test-mock/src/android/test/mock/MockContentProvider.java @@ -16,6 +16,7 @@ package android.test.mock; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentProvider; import android.content.ContentProviderOperation; @@ -23,6 +24,7 @@ import android.content.ContentProviderResult; import android.content.ContentValues; import android.content.Context; import android.content.IContentProvider; +import android.content.Intent; import android.content.OperationApplicationException; import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; @@ -154,6 +156,11 @@ public class MockContentProvider extends ContentProvider { ICancellationSignal cancellationSignal) throws RemoteException { return MockContentProvider.this.refresh(url, args); } + + @Override + public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) { + return MockContentProvider.this.checkUriPermission(uri, uid, modeFlags); + } } private final InversionIContentProvider mIContentProvider = new InversionIContentProvider(); @@ -266,6 +273,12 @@ public class MockContentProvider extends ContentProvider { throw new UnsupportedOperationException("unimplemented mock method call"); } + /** {@hide} */ + @Override + public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) { + throw new UnsupportedOperationException("unimplemented mock method call"); + } + /** * Returns IContentProvider which calls back same methods in this class. * By overriding this class, we avoid the mechanism hidden behind ContentProvider diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java index fc2a4644b994..b072d7440de4 100644 --- a/test-mock/src/android/test/mock/MockIContentProvider.java +++ b/test-mock/src/android/test/mock/MockIContentProvider.java @@ -16,12 +16,14 @@ package android.test.mock; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentValues; import android.content.EntityIterator; import android.content.IContentProvider; +import android.content.Intent; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.net.Uri; @@ -144,4 +146,10 @@ public class MockIContentProvider implements IContentProvider { ICancellationSignal cancellationSignal) throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } + + /** {@hide} */ + @Override + public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) { + throw new UnsupportedOperationException("unimplemented mock method call"); + } } diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rscript index 0a1742ef3867..0a1742ef3867 100644 --- a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs +++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rscript diff --git a/tests/libs-permissions/Android.bp b/tests/libs-permissions/Android.bp index c7c4b10a8405..330bfc9022df 100644 --- a/tests/libs-permissions/Android.bp +++ b/tests/libs-permissions/Android.bp @@ -14,16 +14,16 @@ prebuilt_etc { } java_library { - name: "com.android.test.libs.product_services", + name: "com.android.test.libs.system_ext", installable: true, - product_services_specific: true, - srcs: ["product_services/java/**/*.java"], - required: ["com.android.test.libs.product_services.xml"], + system_ext_specific: true, + srcs: ["system_ext/java/**/*.java"], + required: ["com.android.test.libs.system_ext.xml"], } prebuilt_etc { - name: "com.android.test.libs.product_services.xml", - src: "product_services/com.android.test.libs.product_services.xml", + name: "com.android.test.libs.system_ext.xml", + src: "system_ext/com.android.test.libs.system_ext.xml", sub_dir: "permissions", - product_services_specific: true, + system_ext_specific: true, } diff --git a/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml b/tests/libs-permissions/system_ext/com.android.test.libs.system_ext.xml index 082a9be80779..fa56004415f9 100644 --- a/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml +++ b/tests/libs-permissions/system_ext/com.android.test.libs.system_ext.xml @@ -15,6 +15,6 @@ --> <permissions> - <library name="com.android.test.libs.product_services" - file="/product_services/framework/com.android.test.libs.product_services.jar" /> + <library name="com.android.test.libs.system_ext" + file="/system_ext/framework/com.android.test.libs.system_ext.jar" /> </permissions> diff --git a/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java b/tests/libs-permissions/system_ext/java/com/android/test/libs/system_ext/LibsSystemExtTest.java index dcbdae809889..9999aba37d8d 100644 --- a/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java +++ b/tests/libs-permissions/system_ext/java/com/android/test/libs/system_ext/LibsSystemExtTest.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.android.test.libs.product_services; +package com.android.test.libs.system_ext; /** - * Test class for product_services libs. + * Test class for system_ext libs. */ -public class LibsProductServicesTest { +public class LibsSystemExtTest { /** * Dummy method for testing. diff --git a/tests/privapp-permissions/Android.bp b/tests/privapp-permissions/Android.bp index ca7864f047c7..b6618508d95d 100644 --- a/tests/privapp-permissions/Android.bp +++ b/tests/privapp-permissions/Android.bp @@ -45,17 +45,17 @@ prebuilt_etc { } android_app { - name: "ProductServicesPrivAppPermissionTest", + name: "SystemExtPrivAppPermissionTest", sdk_version: "current", privileged: true, - manifest: "product_services/AndroidManifest.xml", - product_services_specific: true, - required: ["product_servicesprivapp-permissions-test.xml"], + manifest: "system_ext/AndroidManifest.xml", + system_ext_specific: true, + required: ["system_extprivapp-permissions-test.xml"], } prebuilt_etc { - name: "product_servicesprivapp-permissions-test.xml", - src: "product_services/privapp-permissions-test.xml", + name: "system_extprivapp-permissions-test.xml", + src: "system_ext/privapp-permissions-test.xml", sub_dir: "permissions", - product_services_specific: true, + system_ext_specific: true, } diff --git a/tests/privapp-permissions/product_services/AndroidManifest.xml b/tests/privapp-permissions/system_ext/AndroidManifest.xml index 511ddee729ca..4a0e82f1b599 100644 --- a/tests/privapp-permissions/product_services/AndroidManifest.xml +++ b/tests/privapp-permissions/system_ext/AndroidManifest.xml @@ -16,7 +16,7 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.framework.permission.privapp.tests.product_services"> + package="com.android.framework.permission.privapp.tests.system_ext"> <!-- MANAGE_USB is signature|privileged --> <uses-permission android:name="android.permission.MANAGE_USB"/> diff --git a/tests/privapp-permissions/product_services/privapp-permissions-test.xml b/tests/privapp-permissions/system_ext/privapp-permissions-test.xml index 43baebbb0aad..ad63e8643e97 100644 --- a/tests/privapp-permissions/product_services/privapp-permissions-test.xml +++ b/tests/privapp-permissions/system_ext/privapp-permissions-test.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <permissions> - <privapp-permissions package="com.android.framework.permission.privapp.tests.product_services"> + <privapp-permissions package="com.android.framework.permission.privapp.tests.system_ext"> <permission name="android.permission.MANAGE_USB"/> </privapp-permissions> </permissions> diff --git a/tools/lock_agent/Android.bp b/tools/lock_agent/Android.bp index 408946b28836..79dce4a8ce09 100644 --- a/tools/lock_agent/Android.bp +++ b/tools/lock_agent/Android.bp @@ -12,13 +12,9 @@ cc_library { ], sdk_version: "current", stl: "c++_static", - include_dirs: [ - // NDK headers aren't available in platform NDK builds. - "libnativehelper/include_jni", - // Use ScopedUtfChars. - "libnativehelper/header_only_include", - ], header_libs: [ + // Use ScopedUtfChars. + "libnativehelper_header_only", "libopenjdkjvmti_headers", ], compile_multilib: "both", @@ -32,13 +28,9 @@ cc_binary_host { "libz", "slicer", ], - include_dirs: [ - // NDK headers aren't available in platform NDK builds. - "libnativehelper/include_jni", - // Use ScopedUtfChars. - "libnativehelper/header_only_include", - ], header_libs: [ + // Use ScopedUtfChars. + "libnativehelper_header_only", "libopenjdkjvmti_headers", ], } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java index cd659e2a934a..d37c4a2e78db 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java @@ -190,7 +190,7 @@ public class WifiP2pManager { * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides * the network info in the form of a {@link android.net.NetworkInfo}. A third extra provides - * the details of the group. + * the details of the group and may contain a {@code null}. * * All of these permissions are required to receive this broadcast: * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and |