diff options
90 files changed, 2340 insertions, 737 deletions
diff --git a/api/current.txt b/api/current.txt index 39187b806987..c4ec27feb50f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3883,6 +3883,7 @@ package android.app { method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException; method public deprecated java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException; method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException; + method public boolean isBackgroundRestricted(); method public deprecated boolean isInLockTaskMode(); method public boolean isLowRamDevice(); method public static boolean isRunningInTestHarness(); @@ -25211,10 +25212,14 @@ package android.media { method public android.media.AudioAttributes getAudioAttributes(); method public deprecated int getStreamType(); method public java.lang.String getTitle(android.content.Context); + method public float getVolume(); + method public boolean isLooping(); method public boolean isPlaying(); method public void play(); method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException; + method public void setLooping(boolean); method public deprecated void setStreamType(int); + method public void setVolume(float); method public void stop(); } diff --git a/api/test-current.txt b/api/test-current.txt index d5b43115c125..21d12c357164 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -12,6 +12,7 @@ package android.app { public class ActivityManager { method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int); method public int getPackageImportance(java.lang.String); + method public long getTotalRam(); method public int getUidImportance(int); method public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener); method public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException; @@ -351,6 +352,7 @@ package android.hardware.display { public final class DisplayManager { method public java.util.List<android.hardware.display.BrightnessChangeEvent> getBrightnessEvents(); + method public android.graphics.Point getStableDisplaySize(); method public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration); } @@ -446,6 +448,10 @@ package android.net { package android.os { + public static class Build.VERSION { + field public static final int RESOURCES_SDK_INT; + } + public class IncidentManager { method public void reportIncident(android.os.IncidentReportArgs); method public void reportIncident(java.lang.String, byte[]); diff --git a/cmds/incidentd/src/incidentd_util.cpp b/cmds/incidentd/src/incidentd_util.cpp index fc7cec9dbb40..c095f2bcf144 100644 --- a/cmds/incidentd/src/incidentd_util.cpp +++ b/cmds/incidentd/src/incidentd_util.cpp @@ -94,10 +94,10 @@ const char** varargs(const char* first, va_list rest) { // allocate extra 1 for NULL terminator const char** ret = (const char**)malloc(sizeof(const char*) * (numOfArgs + 1)); ret[0] = first; - for (int i = 0; i < numOfArgs; i++) { + for (int i = 1; i < numOfArgs; i++) { const char* arg = va_arg(rest, const char*); - ret[i + 1] = arg; + ret[i] = arg; } - ret[numOfArgs + 1] = NULL; + ret[numOfArgs] = NULL; return ret; } diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index 8d70a553f1b3..cc57f6c1bee5 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -976,8 +976,6 @@ Landroid/media/RemoteDisplay;->notifyDisplayConnected(Landroid/view/Surface;IIII Landroid/media/RemoteDisplay;->notifyDisplayDisconnected()V Landroid/media/RemoteDisplay;->notifyDisplayError(I)V Landroid/media/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone; -Landroid/media/Ringtone;->setLooping(Z)V -Landroid/media/Ringtone;->setVolume(F)V Landroid/media/session/MediaSessionLegacyHelper;->getHelper(Landroid/content/Context;)Landroid/media/session/MediaSessionLegacyHelper; Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler; Landroid/media/ThumbnailUtils;->createImageThumbnail(Ljava/lang/String;I)Landroid/graphics/Bitmap; diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 03faeeeb91a1..de4d1785745d 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -71,6 +71,7 @@ import com.android.internal.app.procstats.ProcessStats; import com.android.internal.os.RoSystemProperties; import com.android.internal.os.TransferPipe; import com.android.internal.util.FastPrintWriter; +import com.android.internal.util.MemInfoReader; import com.android.server.LocalServices; import org.xmlpull.v1.XmlSerializer; @@ -964,6 +965,17 @@ public class ActivityManager { } /** + * Return the total number of bytes of RAM this device has. + * @hide + */ + @TestApi + public long getTotalRam() { + MemInfoReader memreader = new MemInfoReader(); + memreader.readMemInfo(); + return memreader.getTotalSize(); + } + + /** * Return the maximum number of recents entries that we will maintain and show. * @hide */ @@ -3335,6 +3347,28 @@ public class ActivityManager { } /** + * Query whether the user has enabled background restrictions for this app. + * + * <p> The user may chose to do this, if they see that an app is consuming an unreasonable + * amount of battery while in the background. </p> + * + * <p> If true, any work that the app tries to do will be aggressively restricted while it is in + * the background. At a minimum, jobs and alarms will not execute and foreground services + * cannot be started unless an app activity is in the foreground. </p> + * + * <p><b> Note that these restrictions stay in effect even when the device is charging.</b></p> + * + * @return true if user has enforced background restrictions for this app, false otherwise. + */ + public boolean isBackgroundRestricted() { + try { + return getService().isBackgroundRestricted(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Sets the memory trim mode for a process and schedules a memory trim operation. * * <p><b>Note: this method is only intended for testing framework.</b></p> diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 457f945bff80..379944e2e230 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -143,7 +143,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; import com.android.org.conscrypt.OpenSSLSocketImpl; import com.android.org.conscrypt.TrustedCertificateStore; -import com.android.server.am.proto.MemInfoProto; +import com.android.server.am.proto.MemInfoDumpProto; import dalvik.system.BaseDexClassLoader; import dalvik.system.CloseGuard; @@ -1251,55 +1251,62 @@ public final class ActivityThread extends ClientTransactionHandler { long parcelCount = Parcel.getGlobalAllocCount(); SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo(); - final long mToken = proto.start(MemInfoProto.AppData.PROCESS_MEMORY); - proto.write(MemInfoProto.ProcessMemory.PID, Process.myPid()); - proto.write(MemInfoProto.ProcessMemory.PROCESS_NAME, + final long mToken = proto.start(MemInfoDumpProto.AppData.PROCESS_MEMORY); + proto.write(MemInfoDumpProto.ProcessMemory.PID, Process.myPid()); + proto.write(MemInfoDumpProto.ProcessMemory.PROCESS_NAME, (mBoundApplication != null) ? mBoundApplication.processName : "unknown"); dumpMemInfoTable(proto, memInfo, dumpDalvik, dumpSummaryOnly, nativeMax, nativeAllocated, nativeFree, dalvikMax, dalvikAllocated, dalvikFree); proto.end(mToken); - final long oToken = proto.start(MemInfoProto.AppData.OBJECTS); - proto.write(MemInfoProto.AppData.ObjectStats.VIEW_INSTANCE_COUNT, viewInstanceCount); - proto.write(MemInfoProto.AppData.ObjectStats.VIEW_ROOT_INSTANCE_COUNT, + final long oToken = proto.start(MemInfoDumpProto.AppData.OBJECTS); + proto.write(MemInfoDumpProto.AppData.ObjectStats.VIEW_INSTANCE_COUNT, + viewInstanceCount); + proto.write(MemInfoDumpProto.AppData.ObjectStats.VIEW_ROOT_INSTANCE_COUNT, viewRootInstanceCount); - proto.write(MemInfoProto.AppData.ObjectStats.APP_CONTEXT_INSTANCE_COUNT, + proto.write(MemInfoDumpProto.AppData.ObjectStats.APP_CONTEXT_INSTANCE_COUNT, appContextInstanceCount); - proto.write(MemInfoProto.AppData.ObjectStats.ACTIVITY_INSTANCE_COUNT, + proto.write(MemInfoDumpProto.AppData.ObjectStats.ACTIVITY_INSTANCE_COUNT, activityInstanceCount); - proto.write(MemInfoProto.AppData.ObjectStats.GLOBAL_ASSET_COUNT, globalAssetCount); - proto.write(MemInfoProto.AppData.ObjectStats.GLOBAL_ASSET_MANAGER_COUNT, + proto.write(MemInfoDumpProto.AppData.ObjectStats.GLOBAL_ASSET_COUNT, + globalAssetCount); + proto.write(MemInfoDumpProto.AppData.ObjectStats.GLOBAL_ASSET_MANAGER_COUNT, globalAssetManagerCount); - proto.write(MemInfoProto.AppData.ObjectStats.LOCAL_BINDER_OBJECT_COUNT, + proto.write(MemInfoDumpProto.AppData.ObjectStats.LOCAL_BINDER_OBJECT_COUNT, binderLocalObjectCount); - proto.write(MemInfoProto.AppData.ObjectStats.PROXY_BINDER_OBJECT_COUNT, + proto.write(MemInfoDumpProto.AppData.ObjectStats.PROXY_BINDER_OBJECT_COUNT, binderProxyObjectCount); - proto.write(MemInfoProto.AppData.ObjectStats.PARCEL_MEMORY_KB, parcelSize / 1024); - proto.write(MemInfoProto.AppData.ObjectStats.PARCEL_COUNT, parcelCount); - proto.write(MemInfoProto.AppData.ObjectStats.BINDER_OBJECT_DEATH_COUNT, + proto.write(MemInfoDumpProto.AppData.ObjectStats.PARCEL_MEMORY_KB, + parcelSize / 1024); + proto.write(MemInfoDumpProto.AppData.ObjectStats.PARCEL_COUNT, parcelCount); + proto.write(MemInfoDumpProto.AppData.ObjectStats.BINDER_OBJECT_DEATH_COUNT, binderDeathObjectCount); - proto.write(MemInfoProto.AppData.ObjectStats.OPEN_SSL_SOCKET_COUNT, openSslSocketCount); - proto.write(MemInfoProto.AppData.ObjectStats.WEBVIEW_INSTANCE_COUNT, + proto.write(MemInfoDumpProto.AppData.ObjectStats.OPEN_SSL_SOCKET_COUNT, + openSslSocketCount); + proto.write(MemInfoDumpProto.AppData.ObjectStats.WEBVIEW_INSTANCE_COUNT, webviewInstanceCount); proto.end(oToken); // SQLite mem info - final long sToken = proto.start(MemInfoProto.AppData.SQL); - proto.write(MemInfoProto.AppData.SqlStats.MEMORY_USED_KB, stats.memoryUsed / 1024); - proto.write(MemInfoProto.AppData.SqlStats.PAGECACHE_OVERFLOW_KB, + final long sToken = proto.start(MemInfoDumpProto.AppData.SQL); + proto.write(MemInfoDumpProto.AppData.SqlStats.MEMORY_USED_KB, + stats.memoryUsed / 1024); + proto.write(MemInfoDumpProto.AppData.SqlStats.PAGECACHE_OVERFLOW_KB, stats.pageCacheOverflow / 1024); - proto.write(MemInfoProto.AppData.SqlStats.MALLOC_SIZE_KB, stats.largestMemAlloc / 1024); + proto.write(MemInfoDumpProto.AppData.SqlStats.MALLOC_SIZE_KB, + stats.largestMemAlloc / 1024); int n = stats.dbStats.size(); for (int i = 0; i < n; i++) { DbStats dbStats = stats.dbStats.get(i); - final long dToken = proto.start(MemInfoProto.AppData.SqlStats.DATABASES); - proto.write(MemInfoProto.AppData.SqlStats.Database.NAME, dbStats.dbName); - proto.write(MemInfoProto.AppData.SqlStats.Database.PAGE_SIZE, dbStats.pageSize); - proto.write(MemInfoProto.AppData.SqlStats.Database.DB_SIZE, dbStats.dbSize); - proto.write(MemInfoProto.AppData.SqlStats.Database.LOOKASIDE_B, dbStats.lookaside); - proto.write(MemInfoProto.AppData.SqlStats.Database.CACHE, dbStats.cache); + final long dToken = proto.start(MemInfoDumpProto.AppData.SqlStats.DATABASES); + proto.write(MemInfoDumpProto.AppData.SqlStats.Database.NAME, dbStats.dbName); + proto.write(MemInfoDumpProto.AppData.SqlStats.Database.PAGE_SIZE, dbStats.pageSize); + proto.write(MemInfoDumpProto.AppData.SqlStats.Database.DB_SIZE, dbStats.dbSize); + proto.write(MemInfoDumpProto.AppData.SqlStats.Database.LOOKASIDE_B, + dbStats.lookaside); + proto.write(MemInfoDumpProto.AppData.SqlStats.Database.CACHE, dbStats.cache); proto.end(dToken); } proto.end(sToken); @@ -1307,7 +1314,7 @@ public final class ActivityThread extends ClientTransactionHandler { // Asset details. String assetAlloc = AssetManager.getAssetAllocations(); if (assetAlloc != null) { - proto.write(MemInfoProto.AppData.ASSET_ALLOCATIONS, assetAlloc); + proto.write(MemInfoDumpProto.AppData.ASSET_ALLOCATIONS, assetAlloc); } // Unreachable native memory @@ -1315,7 +1322,7 @@ public final class ActivityThread extends ClientTransactionHandler { int flags = mBoundApplication == null ? 0 : mBoundApplication.appInfo.flags; boolean showContents = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 || android.os.Build.IS_DEBUGGABLE; - proto.write(MemInfoProto.AppData.UNREACHABLE_MEMORY, + proto.write(MemInfoDumpProto.AppData.UNREACHABLE_MEMORY, Debug.getUnreachableMemory(100, showContents)); } } @@ -2505,17 +2512,17 @@ public final class ActivityThread extends ClientTransactionHandler { boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss) { final long token = proto.start(fieldId); - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.NAME, name); - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.TOTAL_PSS_KB, pss); - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.CLEAN_PSS_KB, cleanPss); - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.SHARED_DIRTY_KB, sharedDirty); - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.PRIVATE_DIRTY_KB, privateDirty); - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.SHARED_CLEAN_KB, sharedClean); - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.PRIVATE_CLEAN_KB, privateClean); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.NAME, name); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.TOTAL_PSS_KB, pss); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.CLEAN_PSS_KB, cleanPss); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.SHARED_DIRTY_KB, sharedDirty); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.PRIVATE_DIRTY_KB, privateDirty); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.SHARED_CLEAN_KB, sharedClean); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.PRIVATE_CLEAN_KB, privateClean); if (hasSwappedOutPss) { - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_PSS_KB, dirtySwapPss); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_PSS_KB, dirtySwapPss); } else { - proto.write(MemInfoProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_KB, dirtySwap); + proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_KB, dirtySwap); } proto.end(token); @@ -2530,26 +2537,26 @@ public final class ActivityThread extends ClientTransactionHandler { long dalvikMax, long dalvikAllocated, long dalvikFree) { if (!dumpSummaryOnly) { - final long nhToken = proto.start(MemInfoProto.ProcessMemory.NATIVE_HEAP); - dumpMemoryInfo(proto, MemInfoProto.ProcessMemory.HeapInfo.MEM_INFO, "Native Heap", + final long nhToken = proto.start(MemInfoDumpProto.ProcessMemory.NATIVE_HEAP); + dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "Native Heap", memInfo.nativePss, memInfo.nativeSwappablePss, memInfo.nativeSharedDirty, memInfo.nativePrivateDirty, memInfo.nativeSharedClean, memInfo.nativePrivateClean, memInfo.hasSwappedOutPss, memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, nativeMax); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, nativeAllocated); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, nativeFree); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, nativeMax); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, nativeAllocated); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, nativeFree); proto.end(nhToken); - final long dvToken = proto.start(MemInfoProto.ProcessMemory.DALVIK_HEAP); - dumpMemoryInfo(proto, MemInfoProto.ProcessMemory.HeapInfo.MEM_INFO, "Dalvik Heap", + final long dvToken = proto.start(MemInfoDumpProto.ProcessMemory.DALVIK_HEAP); + dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "Dalvik Heap", memInfo.dalvikPss, memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty, memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean, memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss, memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, dalvikMax); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, dalvikAllocated); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, dalvikFree); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, dalvikMax); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, dalvikAllocated); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, dalvikFree); proto.end(dvToken); int otherPss = memInfo.otherPss; @@ -2573,7 +2580,7 @@ public final class ActivityThread extends ClientTransactionHandler { if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0 || mySharedClean != 0 || myPrivateClean != 0 || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) { - dumpMemoryInfo(proto, MemInfoProto.ProcessMemory.OTHER_HEAPS, + dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.OTHER_HEAPS, Debug.MemoryInfo.getOtherLabel(i), myPss, mySwappablePss, mySharedDirty, myPrivateDirty, mySharedClean, myPrivateClean, @@ -2590,21 +2597,23 @@ public final class ActivityThread extends ClientTransactionHandler { } } - dumpMemoryInfo(proto, MemInfoProto.ProcessMemory.UNKNOWN_HEAP, "Unknown", + dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.UNKNOWN_HEAP, "Unknown", otherPss, otherSwappablePss, otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean, memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss); - final long tToken = proto.start(MemInfoProto.ProcessMemory.TOTAL_HEAP); - dumpMemoryInfo(proto, MemInfoProto.ProcessMemory.HeapInfo.MEM_INFO, "TOTAL", + final long tToken = proto.start(MemInfoDumpProto.ProcessMemory.TOTAL_HEAP); + dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "TOTAL", memInfo.getTotalPss(), memInfo.getTotalSwappablePss(), memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(), memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(), memInfo.hasSwappedOutPss, memInfo.getTotalSwappedOut(), memInfo.getTotalSwappedOutPss()); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, nativeMax + dalvikMax); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, + nativeMax + dalvikMax); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, nativeAllocated + dalvikAllocated); - proto.write(MemInfoProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, nativeFree + dalvikFree); + proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, + nativeFree + dalvikFree); proto.end(tToken); if (dumpDalvik) { @@ -2622,7 +2631,7 @@ public final class ActivityThread extends ClientTransactionHandler { if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0 || mySharedClean != 0 || myPrivateClean != 0 || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) { - dumpMemoryInfo(proto, MemInfoProto.ProcessMemory.DALVIK_DETAILS, + dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.DALVIK_DETAILS, Debug.MemoryInfo.getOtherLabel(i), myPss, mySwappablePss, mySharedDirty, myPrivateDirty, mySharedClean, myPrivateClean, @@ -2632,24 +2641,26 @@ public final class ActivityThread extends ClientTransactionHandler { } } - final long asToken = proto.start(MemInfoProto.ProcessMemory.APP_SUMMARY); - proto.write(MemInfoProto.ProcessMemory.AppSummary.JAVA_HEAP_PSS_KB, + final long asToken = proto.start(MemInfoDumpProto.ProcessMemory.APP_SUMMARY); + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.JAVA_HEAP_PSS_KB, memInfo.getSummaryJavaHeap()); - proto.write(MemInfoProto.ProcessMemory.AppSummary.NATIVE_HEAP_PSS_KB, + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.NATIVE_HEAP_PSS_KB, memInfo.getSummaryNativeHeap()); - proto.write(MemInfoProto.ProcessMemory.AppSummary.CODE_PSS_KB, memInfo.getSummaryCode()); - proto.write(MemInfoProto.ProcessMemory.AppSummary.STACK_PSS_KB, memInfo.getSummaryStack()); - proto.write(MemInfoProto.ProcessMemory.AppSummary.GRAPHICS_PSS_KB, + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.CODE_PSS_KB, + memInfo.getSummaryCode()); + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.STACK_PSS_KB, + memInfo.getSummaryStack()); + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.GRAPHICS_PSS_KB, memInfo.getSummaryGraphics()); - proto.write(MemInfoProto.ProcessMemory.AppSummary.PRIVATE_OTHER_PSS_KB, + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.PRIVATE_OTHER_PSS_KB, memInfo.getSummaryPrivateOther()); - proto.write(MemInfoProto.ProcessMemory.AppSummary.SYSTEM_PSS_KB, + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.SYSTEM_PSS_KB, memInfo.getSummarySystem()); if (memInfo.hasSwappedOutPss) { - proto.write(MemInfoProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS, + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS, memInfo.getSummaryTotalSwapPss()); } else { - proto.write(MemInfoProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS, + proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS, memInfo.getSummaryTotalSwap()); } proto.end(asToken); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index ac301b3cc595..eaa23c6a9b61 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -614,7 +614,7 @@ interface IActivityManager { int sendIntentSender(in IIntentSender target, in IBinder whitelistToken, int code, in Intent intent, in String resolvedType, in IIntentReceiver finishedReceiver, in String requiredPermission, in Bundle options); - + boolean isBackgroundRestricted(in String packageName); // Start of N MR1 transactions void setVrThread(int tid); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 233e09d90f9b..13a6be557dae 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -360,6 +360,23 @@ public class Notification implements Parcelable @Deprecated public RemoteViews headsUpContentView; + private boolean mUsesStandardHeader; + + private static final ArraySet<Integer> STANDARD_LAYOUTS = new ArraySet<>(); + static { + STANDARD_LAYOUTS.add(R.layout.notification_template_material_base); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_big_base); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_big_picture); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_big_text); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_inbox); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_messaging); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_media); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_big_media); + STANDARD_LAYOUTS.add(R.layout.notification_template_ambient_header); + STANDARD_LAYOUTS.add(R.layout.notification_template_header); + STANDARD_LAYOUTS.add(R.layout.notification_template_material_ambient); + } + /** * A large bitmap to be shown in the notification content area. * @@ -2534,6 +2551,8 @@ public class Notification implements Parcelable } parcel.writeInt(mGroupAlertBehavior); + + // mUsesStandardHeader is not written because it should be recomputed in listeners } /** @@ -4092,6 +4111,25 @@ public class Notification implements Parcelable } } + /** + * @hide + */ + public boolean usesStandardHeader() { + if (mN.mUsesStandardHeader) { + return true; + } + if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.N) { + if (mN.contentView == null && mN.bigContentView == null) { + return true; + } + } + boolean contentViewUsesHeader = mN.contentView == null + || STANDARD_LAYOUTS.contains(mN.contentView.getLayoutId()); + boolean bigContentViewUsesHeader = mN.bigContentView == null + || STANDARD_LAYOUTS.contains(mN.bigContentView.getLayoutId()); + return contentViewUsesHeader && bigContentViewUsesHeader; + } + private void resetStandardTemplate(RemoteViews contentView) { resetNotificationHeader(contentView); resetContentMargins(contentView); @@ -4123,6 +4161,7 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.time, View.GONE); contentView.setImageViewIcon(R.id.profile_badge, null); contentView.setViewVisibility(R.id.profile_badge, View.GONE); + mN.mUsesStandardHeader = false; } private void resetContentMargins(RemoteViews contentView) { @@ -4444,6 +4483,7 @@ public class Notification implements Parcelable bindProfileBadge(contentView); } bindExpandButton(contentView); + mN.mUsesStandardHeader = true; } private void bindExpandButton(RemoteViews contentView) { diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index a957aed8b806..cec3badd2e6c 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -1872,9 +1872,10 @@ public class IntentFilter implements Parcelable { du.println(sb.toString()); } } - if (mPriority != 0 || mHasPartialTypes) { + if (mPriority != 0 || mOrder != 0 || mHasPartialTypes) { sb.setLength(0); sb.append(prefix); sb.append("mPriority="); sb.append(mPriority); + sb.append(", mOrder="); sb.append(mOrder); sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes); du.println(sb.toString()); } @@ -1951,6 +1952,7 @@ public class IntentFilter implements Parcelable { dest.writeInt(mHasPartialTypes ? 1 : 0); dest.writeInt(getAutoVerify() ? 1 : 0); dest.writeInt(mInstantAppVisibility); + dest.writeInt(mOrder); } /** @@ -2020,6 +2022,7 @@ public class IntentFilter implements Parcelable { mHasPartialTypes = source.readInt() > 0; setAutoVerify(source.readInt() > 0); setVisibilityToInstantApp(source.readInt()); + mOrder = source.readInt(); } private final boolean findMimeType(String type) { diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 2420b639d678..5f10da1faeab 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3190,7 +3190,7 @@ public class PackageParser { && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) != PermissionInfo.PROTECTION_SIGNATURE) { - outError[0] = "<permission> protectionLevel specifies a non-instnat flag but is " + outError[0] = "<permission> protectionLevel specifies a non-instant flag but is " + "not based on signature type"; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; @@ -3641,7 +3641,9 @@ public class PackageParser { // getting added to the wrong package. final CachedComponentArgs cachedArgs = new CachedComponentArgs(); int type; - + boolean hasActivityOrder = false; + boolean hasReceiverOrder = false; + boolean hasServiceOrder = false; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { @@ -3657,6 +3659,7 @@ public class PackageParser { return false; } + hasActivityOrder |= (a.order != 0); owner.activities.add(a); } else if (tagName.equals("receiver")) { @@ -3667,6 +3670,7 @@ public class PackageParser { return false; } + hasReceiverOrder |= (a.order != 0); owner.receivers.add(a); } else if (tagName.equals("service")) { @@ -3676,6 +3680,7 @@ public class PackageParser { return false; } + hasServiceOrder |= (s.order != 0); owner.services.add(s); } else if (tagName.equals("provider")) { @@ -3694,6 +3699,7 @@ public class PackageParser { return false; } + hasActivityOrder |= (a.order != 0); owner.activities.add(a); } else if (parser.getName().equals("meta-data")) { @@ -3827,6 +3833,15 @@ public class PackageParser { } } + if (hasActivityOrder) { + Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order)); + } + if (hasReceiverOrder) { + Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order)); + } + if (hasServiceOrder) { + Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order)); + } // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after // every activity info has had a chance to set it from its attributes. setMaxAspectRatio(owner); @@ -4368,6 +4383,7 @@ public class PackageParser { + mArchiveSourcePath + " " + parser.getPositionDescription()); } else { + a.order = Math.max(intent.getOrder(), a.order); a.intents.add(intent); } // adjust activity flags when we implicitly expose it via a browsable filter @@ -4745,6 +4761,7 @@ public class PackageParser { + mArchiveSourcePath + " " + parser.getPositionDescription()); } else { + a.order = Math.max(intent.getOrder(), a.order); a.intents.add(intent); } // adjust activity flags when we implicitly expose it via a browsable filter @@ -4952,6 +4969,7 @@ public class PackageParser { intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; } + outInfo.order = Math.max(intent.getOrder(), outInfo.order); outInfo.intents.add(intent); } else if (parser.getName().equals("meta-data")) { @@ -5241,6 +5259,7 @@ public class PackageParser { intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; } + s.order = Math.max(intent.getOrder(), s.order); s.intents.add(intent); } else if (parser.getName().equals("meta-data")) { if ((s.metaData=parseMetaData(res, parser, s.metaData, @@ -5466,6 +5485,10 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0); outInfo.setPriority(priority); + int order = sa.getInt( + com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0); + outInfo.setOrder(order); + TypedValue v = sa.peekValue( com.android.internal.R.styleable.AndroidManifestIntentFilter_label); if (v != null && (outInfo.labelRes=v.resourceId) == 0) { @@ -7053,6 +7076,8 @@ public class PackageParser { public Bundle metaData; public Package owner; + /** The order of this component in relation to its peers */ + public int order; ComponentName componentName; String componentShortName; @@ -7571,6 +7596,7 @@ public class PackageParser { for (ActivityIntentInfo aii : intents) { aii.activity = this; + order = Math.max(aii.getOrder(), order); } if (info.permission != null) { @@ -7660,6 +7686,7 @@ public class PackageParser { for (ServiceIntentInfo aii : intents) { aii.service = this; + order = Math.max(aii.getOrder(), order); } if (info.permission != null) { diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 2baf539317e9..19b5c45f3a81 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -16,10 +16,11 @@ package android.content.res; +import static android.content.ConfigurationProto.COLOR_MODE; import static android.content.ConfigurationProto.DENSITY_DPI; import static android.content.ConfigurationProto.FONT_SCALE; import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN; -import static android.content.ConfigurationProto.HDR_COLOR_MODE; +import static android.content.ConfigurationProto.KEYBOARD; import static android.content.ConfigurationProto.KEYBOARD_HIDDEN; import static android.content.ConfigurationProto.LOCALES; import static android.content.ConfigurationProto.MCC; @@ -33,7 +34,6 @@ import static android.content.ConfigurationProto.SCREEN_WIDTH_DP; import static android.content.ConfigurationProto.SMALLEST_SCREEN_WIDTH_DP; import static android.content.ConfigurationProto.TOUCHSCREEN; import static android.content.ConfigurationProto.UI_MODE; -import static android.content.ConfigurationProto.WIDE_COLOR_GAMUT; import static android.content.ConfigurationProto.WINDOW_CONFIGURATION; import static android.content.ResourcesConfigurationProto.CONFIGURATION; import static android.content.ResourcesConfigurationProto.SCREEN_HEIGHT_PX; @@ -1095,11 +1095,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration protoOutputStream.write(MNC, mnc); mLocaleList.writeToProto(protoOutputStream, LOCALES); protoOutputStream.write(SCREEN_LAYOUT, screenLayout); - protoOutputStream.write(HDR_COLOR_MODE, - (colorMode & Configuration.COLOR_MODE_HDR_MASK) >> COLOR_MODE_HDR_SHIFT); - protoOutputStream.write(WIDE_COLOR_GAMUT, - colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK); + protoOutputStream.write(COLOR_MODE, colorMode); protoOutputStream.write(TOUCHSCREEN, touchscreen); + protoOutputStream.write(KEYBOARD, keyboard); protoOutputStream.write(KEYBOARD_HIDDEN, keyboardHidden); protoOutputStream.write(HARD_KEYBOARD_HIDDEN, hardKeyboardHidden); protoOutputStream.write(NAVIGATION, navigation); diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 6b2059e1c84c..36d5615e6ac2 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -615,6 +615,7 @@ public final class DisplayManager { * @hide */ @SystemApi + @TestApi public Point getStableDisplaySize() { return mGlobal.getStableDisplaySize(); } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 48f56847e88d..6d8831bccdba 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -19,6 +19,7 @@ package android.os; import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.Application; import android.content.Context; import android.text.TextUtils; @@ -287,6 +288,7 @@ public class Build { * we are operating under, we bump the assumed resource platform version by 1. * @hide */ + @TestApi public static final int RESOURCES_SDK_INT = SDK_INT + ACTIVE_CODENAMES.length; /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 02994079d6ec..569a0db768aa 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10516,8 +10516,11 @@ public final class Settings { * entity_list_default use ":" as delimiter for values. Ex: * * <pre> - * smart_selection_dark_launch (boolean) - * smart_selection_enabled_for_edit_text (boolean) + * model_dark_launch_enabled (boolean) + * smart_selection_enabled (boolean) + * smart_text_share_enabled (boolean) + * smart_linkify_enabled (boolean) + * smart_select_animation_enabled (boolean) * suggest_selection_max_range_length (int) * classify_text_max_range_length (int) * generate_links_max_text_length (int) @@ -10530,7 +10533,7 @@ public final class Settings { * <p> * Type: string * @hide - * see also android.view.textclassifier.TextClassifierConstants + * see also android.view.textclassifier.TextClassificationConstants */ public static final String TEXT_CLASSIFIER_CONSTANTS = "text_classifier_constants"; diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java index fbba8abff304..137e820805e2 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -17,6 +17,7 @@ package android.view; import android.annotation.Nullable; +import android.app.AppOpsManager; import android.app.Notification; import android.content.Context; import android.content.res.Resources; @@ -25,6 +26,7 @@ import android.graphics.Canvas; import android.graphics.Outline; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.util.ArraySet; import android.util.AttributeSet; import android.widget.ImageView; import android.widget.RemoteViews; @@ -53,6 +55,10 @@ public class NotificationHeaderView extends ViewGroup { private ImageView mExpandButton; private CachingIconView mIcon; private View mProfileBadge; + private View mOverlayIcon; + private View mCameraIcon; + private View mMicIcon; + private View mAppOps; private int mIconColor; private int mOriginalNotificationColor; private boolean mExpanded; @@ -108,6 +114,10 @@ public class NotificationHeaderView extends ViewGroup { mExpandButton = findViewById(com.android.internal.R.id.expand_button); mIcon = findViewById(com.android.internal.R.id.icon); mProfileBadge = findViewById(com.android.internal.R.id.profile_badge); + mCameraIcon = findViewById(com.android.internal.R.id.camera); + mMicIcon = findViewById(com.android.internal.R.id.mic); + mOverlayIcon = findViewById(com.android.internal.R.id.overlay); + mAppOps = findViewById(com.android.internal.R.id.app_ops); } @Override @@ -198,6 +208,11 @@ public class NotificationHeaderView extends ViewGroup { layoutRight = end - paddingEnd; end = layoutLeft = layoutRight - child.getMeasuredWidth(); } + if (child == mAppOps) { + int paddingEnd = mContentEndMargin; + layoutRight = end - paddingEnd; + end = layoutLeft = layoutRight - child.getMeasuredWidth(); + } if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { int ltrLeft = layoutLeft; layoutLeft = getWidth() - layoutRight; @@ -289,6 +304,22 @@ public class NotificationHeaderView extends ViewGroup { updateExpandButton(); } + /** + * Shows or hides 'app op in use' icons based on app usage. + */ + public void showAppOpsIcons(ArraySet<Integer> appOps) { + if (mOverlayIcon == null || mCameraIcon == null || mMicIcon == null) { + return; + } + + mOverlayIcon.setVisibility(appOps.contains(AppOpsManager.OP_SYSTEM_ALERT_WINDOW) + ? View.VISIBLE : View.GONE); + mCameraIcon.setVisibility(appOps.contains(AppOpsManager.OP_CAMERA) + ? View.VISIBLE : View.GONE); + mMicIcon.setVisibility(appOps.contains(AppOpsManager.OP_RECORD_AUDIO) + ? View.VISIBLE : View.GONE); + } + private void updateExpandButton() { int drawableId; int contentDescriptionId; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index f61b6528bd0e..e28522292ac3 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2953,6 +2953,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG3_NO_REVEAL_ON_FOCUS * 1 PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT * 1 PFLAG3_SCREEN_READER_FOCUSABLE + * 1 PFLAG3_AGGREGATED_VISIBLE + * 1 PFLAG3_AUTOFILLID_EXPLICITLY_SET + * 1 available * |-------|-------|-------|-------| */ @@ -3243,6 +3246,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000; + /** + * Used to indicate that {@link #mAutofillId} was explicitly set through + * {@link #setAutofillId(AutofillId)}. + */ + private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000; + /* End of masks for mPrivateFlags3 */ /** @@ -8205,16 +8214,28 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view. */ public void setAutofillId(@Nullable AutofillId id) { + // TODO(b/37566627): add unit / CTS test for all possible combinations below if (android.view.autofill.Helper.sVerbose) { Log.v(VIEW_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id); } if (isAttachedToWindow()) { throw new IllegalStateException("Cannot set autofill id when view is attached"); } - if (id.isVirtual()) { + if (id != null && id.isVirtual()) { throw new IllegalStateException("Cannot set autofill id assigned to virtual views"); } + if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) { + // Ignore reset because it was never explicitly set before. + return; + } mAutofillId = id; + if (id != null) { + mAutofillViewId = id.getViewId(); + mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET; + } else { + mAutofillViewId = NO_ID; + mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET; + } } /** @@ -18524,7 +18545,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // Hence prevent the same autofill view id from being restored multiple times. ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID; - mAutofillViewId = baseState.mAutofillViewId; + if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) { + // Ignore when view already set it through setAutofillId(); + if (android.view.autofill.Helper.sDebug) { + Log.d(VIEW_LOG_TAG, "onRestoreInstanceState(): not setting autofillId to " + + baseState.mAutofillViewId + " because view explicitly set it to " + + mAutofillId); + } + } else { + mAutofillViewId = baseState.mAutofillViewId; + mAutofillId = null; // will be set on demand by getAutofillId() + } } } } diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java index 1789edf1e876..2b335fb09c61 100644 --- a/core/java/android/view/textclassifier/SystemTextClassifier.java +++ b/core/java/android/view/textclassifier/SystemTextClassifier.java @@ -29,6 +29,8 @@ import android.service.textclassifier.ITextClassifierService; import android.service.textclassifier.ITextLinksCallback; import android.service.textclassifier.ITextSelectionCallback; +import com.android.internal.util.Preconditions; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -40,13 +42,16 @@ final class SystemTextClassifier implements TextClassifier { private static final String LOG_TAG = "SystemTextClassifier"; private final ITextClassifierService mManagerService; + private final TextClassificationConstants mSettings; private final TextClassifier mFallback; private final String mPackageName; - SystemTextClassifier(Context context) throws ServiceManager.ServiceNotFoundException { + SystemTextClassifier(Context context, TextClassificationConstants settings) + throws ServiceManager.ServiceNotFoundException { mManagerService = ITextClassifierService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE)); - mFallback = new TextClassifierImpl(context); + mSettings = Preconditions.checkNotNull(settings); + mFallback = new TextClassifierImpl(context, settings); mPackageName = context.getPackageName(); } @@ -108,6 +113,11 @@ final class SystemTextClassifier implements TextClassifier { public TextLinks generateLinks( @NonNull CharSequence text, @Nullable TextLinks.Options options) { Utils.validate(text, false /* allowInMainThread */); + + if (!mSettings.isSmartLinkifyEnabled()) { + return TextClassifier.NO_OP.generateLinks(text, options); + } + try { if (options == null) { options = new TextLinks.Options().setCallingPackageName(mPackageName); diff --git a/core/java/android/view/textclassifier/TextClassifierConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java index 397473be9d4b..32a7f376c4b1 100644 --- a/core/java/android/view/textclassifier/TextClassifierConstants.java +++ b/core/java/android/view/textclassifier/TextClassificationConstants.java @@ -30,11 +30,15 @@ import java.util.StringJoiner; * This is encoded as a key=value list, separated by commas. Ex: * * <pre> - * smart_selection_dark_launch (boolean) - * smart_selection_enabled_for_edit_text (boolean) + * model_dark_launch_enabled (boolean) + * smart_selection_enabled (boolean) + * smart_text_share_enabled (boolean) + * smart_linkify_enabled (boolean) + * smart_select_animation_enabled (boolean) * suggest_selection_max_range_length (int) * classify_text_max_range_length (int) * generate_links_max_text_length (int) + * generate_links_log_sample_rate (int) * entity_list_default (String[]) * entity_list_not_editable (String[]) * entity_list_editable (String[]) @@ -46,20 +50,24 @@ import java.util.StringJoiner; * * Example of setting the values for testing. * adb shell settings put global text_classifier_constants \ - * smart_selection_dark_launch=true,smart_selection_enabled_for_edit_text=true,\ + * model_dark_launch_enabled=true,smart_selection_enabled=true,\ * entity_list_default=phone:address * @hide */ -public final class TextClassifierConstants { +public final class TextClassificationConstants { - private static final String LOG_TAG = "TextClassifierConstants"; + private static final String LOG_TAG = "TextClassificationConstants"; - private static final String SMART_SELECTION_DARK_LAUNCH = - "smart_selection_dark_launch"; - private static final String SMART_SELECTION_ENABLED_FOR_EDIT_TEXT = - "smart_selection_enabled_for_edit_text"; + private static final String MODEL_DARK_LAUNCH_ENABLED = + "model_dark_launch_enabled"; + private static final String SMART_SELECTION_ENABLED = + "smart_selection_enabled"; + private static final String SMART_TEXT_SHARE_ENABLED = + "smart_text_share_enabled"; private static final String SMART_LINKIFY_ENABLED = "smart_linkify_enabled"; + private static final String SMART_SELECT_ANIMATION_ENABLED = + "smart_select_animation_enabled"; private static final String SUGGEST_SELECTION_MAX_RANGE_LENGTH = "suggest_selection_max_range_length"; private static final String CLASSIFY_TEXT_MAX_RANGE_LENGTH = @@ -75,9 +83,11 @@ public final class TextClassifierConstants { private static final String ENTITY_LIST_EDITABLE = "entity_list_editable"; - private static final boolean SMART_SELECTION_DARK_LAUNCH_DEFAULT = false; - private static final boolean SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT = true; + private static final boolean MODEL_DARK_LAUNCH_ENABLED_DEFAULT = false; + private static final boolean SMART_SELECTION_ENABLED_DEFAULT = true; + private static final boolean SMART_TEXT_SHARE_ENABLED_DEFAULT = true; private static final boolean SMART_LINKIFY_ENABLED_DEFAULT = true; + private static final boolean SMART_SELECT_ANIMATION_ENABLED_DEFAULT = true; private static final int SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT = 10 * 1000; private static final int CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT = 10 * 1000; private static final int GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT = 100 * 1000; @@ -92,12 +102,11 @@ public final class TextClassifierConstants { .add(TextClassifier.TYPE_DATE_TIME) .add(TextClassifier.TYPE_FLIGHT_NUMBER).toString(); - /** Default settings. */ - static final TextClassifierConstants DEFAULT = new TextClassifierConstants(); - - private final boolean mDarkLaunch; - private final boolean mSuggestSelectionEnabledForEditableText; + private final boolean mModelDarkLaunchEnabled; + private final boolean mSmartSelectionEnabled; + private final boolean mSmartTextShareEnabled; private final boolean mSmartLinkifyEnabled; + private final boolean mSmartSelectionAnimationEnabled; private final int mSuggestSelectionMaxRangeLength; private final int mClassifyTextMaxRangeLength; private final int mGenerateLinksMaxTextLength; @@ -106,20 +115,7 @@ public final class TextClassifierConstants { private final List<String> mEntityListNotEditable; private final List<String> mEntityListEditable; - private TextClassifierConstants() { - mDarkLaunch = SMART_SELECTION_DARK_LAUNCH_DEFAULT; - mSuggestSelectionEnabledForEditableText = SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT; - mSmartLinkifyEnabled = SMART_LINKIFY_ENABLED_DEFAULT; - mSuggestSelectionMaxRangeLength = SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT; - mClassifyTextMaxRangeLength = CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT; - mGenerateLinksMaxTextLength = GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT; - mGenerateLinksLogSampleRate = GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT; - mEntityListDefault = parseEntityList(ENTITY_LIST_DEFAULT_VALUE); - mEntityListNotEditable = mEntityListDefault; - mEntityListEditable = mEntityListDefault; - } - - private TextClassifierConstants(@Nullable String settings) { + private TextClassificationConstants(@Nullable String settings) { final KeyValueListParser parser = new KeyValueListParser(','); try { parser.setString(settings); @@ -127,15 +123,21 @@ public final class TextClassifierConstants { // Failed to parse the settings string, log this and move on with defaults. Slog.e(LOG_TAG, "Bad TextClassifier settings: " + settings); } - mDarkLaunch = parser.getBoolean( - SMART_SELECTION_DARK_LAUNCH, - SMART_SELECTION_DARK_LAUNCH_DEFAULT); - mSuggestSelectionEnabledForEditableText = parser.getBoolean( - SMART_SELECTION_ENABLED_FOR_EDIT_TEXT, - SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT); + mModelDarkLaunchEnabled = parser.getBoolean( + MODEL_DARK_LAUNCH_ENABLED, + MODEL_DARK_LAUNCH_ENABLED_DEFAULT); + mSmartSelectionEnabled = parser.getBoolean( + SMART_SELECTION_ENABLED, + SMART_SELECTION_ENABLED_DEFAULT); + mSmartTextShareEnabled = parser.getBoolean( + SMART_TEXT_SHARE_ENABLED, + SMART_TEXT_SHARE_ENABLED_DEFAULT); mSmartLinkifyEnabled = parser.getBoolean( SMART_LINKIFY_ENABLED, SMART_LINKIFY_ENABLED_DEFAULT); + mSmartSelectionAnimationEnabled = parser.getBoolean( + SMART_SELECT_ANIMATION_ENABLED, + SMART_SELECT_ANIMATION_ENABLED_DEFAULT); mSuggestSelectionMaxRangeLength = parser.getInt( SUGGEST_SELECTION_MAX_RANGE_LENGTH, SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT); @@ -160,22 +162,30 @@ public final class TextClassifierConstants { } /** Load from a settings string. */ - public static TextClassifierConstants loadFromString(String settings) { - return new TextClassifierConstants(settings); + public static TextClassificationConstants loadFromString(String settings) { + return new TextClassificationConstants(settings); } - public boolean isDarkLaunch() { - return mDarkLaunch; + public boolean isModelDarkLaunchEnabled() { + return mModelDarkLaunchEnabled; } - public boolean isSuggestSelectionEnabledForEditableText() { - return mSuggestSelectionEnabledForEditableText; + public boolean isSmartSelectionEnabled() { + return mSmartSelectionEnabled; + } + + public boolean isSmartTextShareEnabled() { + return mSmartTextShareEnabled; } public boolean isSmartLinkifyEnabled() { return mSmartLinkifyEnabled; } + public boolean isSmartSelectionAnimationEnabled() { + return mSmartSelectionAnimationEnabled; + } + public int getSuggestSelectionMaxRangeLength() { return mSuggestSelectionMaxRangeLength; } diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java index 300aef2d172e..fea932cf2a50 100644 --- a/core/java/android/view/textclassifier/TextClassificationManager.java +++ b/core/java/android/view/textclassifier/TextClassificationManager.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.annotation.SystemService; import android.content.Context; import android.os.ServiceManager; +import android.provider.Settings; import android.service.textclassifier.TextClassifierService; import com.android.internal.util.Preconditions; @@ -38,12 +39,15 @@ public final class TextClassificationManager { private final Object mLock = new Object(); private final Context mContext; + private final TextClassificationConstants mSettings; private TextClassifier mTextClassifier; private TextClassifier mSystemTextClassifier; /** @hide */ public TextClassificationManager(Context context) { mContext = Preconditions.checkNotNull(context); + mSettings = TextClassificationConstants.loadFromString(Settings.Global.getString( + context.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS)); } /** @@ -56,14 +60,14 @@ public final class TextClassificationManager { if (mSystemTextClassifier == null && isSystemTextClassifierEnabled()) { try { Log.d(LOG_TAG, "Initialized SystemTextClassifier"); - mSystemTextClassifier = new SystemTextClassifier(mContext); + mSystemTextClassifier = new SystemTextClassifier(mContext, mSettings); } catch (ServiceManager.ServiceNotFoundException e) { Log.e(LOG_TAG, "Could not initialize SystemTextClassifier", e); } } if (mSystemTextClassifier == null) { Log.d(LOG_TAG, "Using an in-process TextClassifier as the system default"); - mSystemTextClassifier = new TextClassifierImpl(mContext); + mSystemTextClassifier = new TextClassifierImpl(mContext, mSettings); } } return mSystemTextClassifier; @@ -78,7 +82,7 @@ public final class TextClassificationManager { if (isSystemTextClassifierEnabled()) { mTextClassifier = getSystemDefaultTextClassifier(); } else { - mTextClassifier = new TextClassifierImpl(mContext); + mTextClassifier = new TextClassifierImpl(mContext, mSettings); } } return mTextClassifier; @@ -100,4 +104,17 @@ public final class TextClassificationManager { return SYSTEM_TEXT_CLASSIFIER_ENABLED && TextClassifierService.getServiceComponentName(mContext) != null; } + + /** @hide */ + public static TextClassificationConstants getSettings(Context context) { + Preconditions.checkNotNull(context); + final TextClassificationManager tcm = + context.getSystemService(TextClassificationManager.class); + if (tcm != null) { + return tcm.mSettings; + } else { + return TextClassificationConstants.loadFromString(Settings.Global.getString( + context.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS)); + } + } } diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java index d52a30bcc018..0321bb6d62fa 100644 --- a/core/java/android/view/textclassifier/TextClassifier.java +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -329,14 +329,6 @@ public interface TextClassifier { } /** - * Returns this TextClassifier's settings. - * @hide - */ - default TextClassifierConstants getSettings() { - return TextClassifierConstants.DEFAULT; - } - - /** * Configuration object for specifying what entities to identify. * * Configs are initially based on a predefined preset, and can be modified from there. diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index 5b7095b2f44f..41f1c69a47ed 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -34,7 +34,6 @@ import android.os.UserManager; import android.provider.Browser; import android.provider.CalendarContract; import android.provider.ContactsContract; -import android.provider.Settings; import android.view.textclassifier.logging.DefaultLogger; import android.view.textclassifier.logging.GenerateLinksLogger; import android.view.textclassifier.logging.Logger; @@ -99,13 +98,13 @@ public final class TextClassifierImpl implements TextClassifier { @GuardedBy("mLoggerLock") // Do not access outside this lock. private Logger mLogger; // Should never be null if mLoggerConfig.get() is not null. - private TextClassifierConstants mSettings; + private final TextClassificationConstants mSettings; - public TextClassifierImpl(Context context) { + public TextClassifierImpl(Context context, TextClassificationConstants settings) { mContext = Preconditions.checkNotNull(context); mFallback = TextClassifier.NO_OP; - mGenerateLinksLogger = new GenerateLinksLogger( - getSettings().getGenerateLinksLogSampleRate()); + mSettings = Preconditions.checkNotNull(settings); + mGenerateLinksLogger = new GenerateLinksLogger(mSettings.getGenerateLinksLogSampleRate()); } /** @inheritDoc */ @@ -117,7 +116,7 @@ public final class TextClassifierImpl implements TextClassifier { try { final int rangeLength = selectionEndIndex - selectionStartIndex; if (text.length() > 0 - && rangeLength <= getSettings().getSuggestSelectionMaxRangeLength()) { + && rangeLength <= mSettings.getSuggestSelectionMaxRangeLength()) { final LocaleList locales = (options == null) ? null : options.getDefaultLocales(); final String localesString = concatenateLocales(locales); final Calendar refTime = Calendar.getInstance(); @@ -126,7 +125,7 @@ public final class TextClassifierImpl implements TextClassifier { final String string = text.toString(); final int start; final int end; - if (getSettings().isDarkLaunch() && !darkLaunchAllowed) { + if (mSettings.isModelDarkLaunchEnabled() && !darkLaunchAllowed) { start = selectionStartIndex; end = selectionEndIndex; } else { @@ -179,7 +178,7 @@ public final class TextClassifierImpl implements TextClassifier { Utils.validate(text, startIndex, endIndex, false /* allowInMainThread */); try { final int rangeLength = endIndex - startIndex; - if (text.length() > 0 && rangeLength <= getSettings().getClassifyTextMaxRangeLength()) { + if (text.length() > 0 && rangeLength <= mSettings.getClassifyTextMaxRangeLength()) { final String string = text.toString(); final LocaleList locales = (options == null) ? null : options.getDefaultLocales(); final String localesString = concatenateLocales(locales); @@ -214,7 +213,7 @@ public final class TextClassifierImpl implements TextClassifier { final String textString = text.toString(); final TextLinks.Builder builder = new TextLinks.Builder(textString); - if (!getSettings().isSmartLinkifyEnabled()) { + if (!mSettings.isSmartLinkifyEnabled()) { return builder.build(); } @@ -226,7 +225,7 @@ public final class TextClassifierImpl implements TextClassifier { options != null && options.getEntityConfig() != null ? options.getEntityConfig().resolveEntityListModifications( getEntitiesForHints(options.getEntityConfig().getHints())) - : getSettings().getEntityListDefault(); + : mSettings.getEntityListDefault(); final TextClassifierImplNative nativeImpl = getNative(defaultLocales); final TextClassifierImplNative.AnnotatedSpan[] annotations = @@ -268,7 +267,7 @@ public final class TextClassifierImpl implements TextClassifier { /** @inheritDoc */ @Override public int getMaxGenerateLinksTextLength() { - return getSettings().getGenerateLinksMaxTextLength(); + return mSettings.getGenerateLinksMaxTextLength(); } private Collection<String> getEntitiesForHints(Collection<String> hints) { @@ -278,11 +277,11 @@ public final class TextClassifierImpl implements TextClassifier { // Use the default if there is no hint, or conflicting ones. final boolean useDefault = editable == notEditable; if (useDefault) { - return getSettings().getEntityListDefault(); + return mSettings.getEntityListDefault(); } else if (editable) { - return getSettings().getEntityListEditable(); + return mSettings.getEntityListEditable(); } else { // notEditable - return getSettings().getEntityListNotEditable(); + return mSettings.getEntityListNotEditable(); } } @@ -298,16 +297,6 @@ public final class TextClassifierImpl implements TextClassifier { } } - /** @hide */ - @Override - public TextClassifierConstants getSettings() { - if (mSettings == null) { - mSettings = TextClassifierConstants.loadFromString(Settings.Global.getString( - mContext.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS)); - } - return mSettings; - } - private TextClassifierImplNative getNative(LocaleList localeList) throws FileNotFoundException { synchronized (mLock) { diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java index 84c000a379df..ed122a650e66 100644 --- a/core/java/android/webkit/URLUtil.java +++ b/core/java/android/webkit/URLUtil.java @@ -39,7 +39,7 @@ public final class URLUtil { // "file:///android_res/drawable/bar.png". Use "drawable" to refer to // "drawable-hdpi" directory as well. static final String RESOURCE_BASE = "file:///android_res/"; - static final String FILE_BASE = "file://"; + static final String FILE_BASE = "file:"; static final String PROXY_BASE = "file:///cookieless_proxy/"; static final String CONTENT_BASE = "content:"; diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 2e7b2fd65d33..02f35ca0d4d7 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -107,6 +107,7 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.view.textclassifier.TextClassification; +import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextLinks; import android.widget.AdapterView.OnItemClickListener; import android.widget.TextView.Drawables; @@ -4024,7 +4025,7 @@ public class Editor { private void updateAssistMenuItems(Menu menu) { clearAssistMenuItems(menu); - if (!mTextView.isDeviceProvisioned()) { + if (!shouldEnableAssistMenuItems()) { return; } final TextClassification textClassification = @@ -4097,7 +4098,7 @@ public class Editor { final TextClassification textClassification = getSelectionActionModeHelper().getTextClassification(); - if (!mTextView.isDeviceProvisioned() || textClassification == null) { + if (!shouldEnableAssistMenuItems() || textClassification == null) { // No textClassification result to handle the click. Eat the click. return true; } @@ -4118,6 +4119,12 @@ public class Editor { return true; } + private boolean shouldEnableAssistMenuItems() { + return mTextView.isDeviceProvisioned() + && TextClassificationManager.getSettings(mTextView.getContext()) + .isSmartTextShareEnabled(); + } + @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { getSelectionActionModeHelper().onSelectionAction(item.getItemId()); diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 6ab09d6cbe74..12ab0ee7d56a 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -34,6 +34,8 @@ import android.text.TextUtils; import android.util.Log; import android.view.ActionMode; import android.view.textclassifier.TextClassification; +import android.view.textclassifier.TextClassificationConstants; +import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import android.view.textclassifier.TextSelection; @@ -65,12 +67,10 @@ public final class SelectionActionModeHelper { private static final String LOG_TAG = "SelectActionModeHelper"; - // TODO: Make this a configurable flag. - private static final boolean SMART_SELECT_ANIMATION_ENABLED = true; - private final Editor mEditor; private final TextView mTextView; private final TextClassificationHelper mTextClassificationHelper; + private final TextClassificationConstants mTextClassificationSettings; private TextClassification mTextClassification; private AsyncTask mTextClassificationAsyncTask; @@ -84,6 +84,7 @@ public final class SelectionActionModeHelper { SelectionActionModeHelper(@NonNull Editor editor) { mEditor = Preconditions.checkNotNull(editor); mTextView = mEditor.getTextView(); + mTextClassificationSettings = TextClassificationManager.getSettings(mTextView.getContext()); mTextClassificationHelper = new TextClassificationHelper( mTextView.getContext(), mTextView.getTextClassifier(), @@ -91,7 +92,7 @@ public final class SelectionActionModeHelper { 0, 1, mTextView.getTextLocales()); mSelectionTracker = new SelectionTracker(mTextView); - if (SMART_SELECT_ANIMATION_ENABLED) { + if (mTextClassificationSettings.isSmartSelectionAnimationEnabled()) { mSmartSelectSprite = new SmartSelectSprite(mTextView.getContext(), editor.getTextView().mHighlightColor, mTextView::invalidate); } else { @@ -104,9 +105,7 @@ public final class SelectionActionModeHelper { */ public void startSelectionActionModeAsync(boolean adjustSelection) { // Check if the smart selection should run for editable text. - adjustSelection &= !mTextView.isTextEditable() - || mTextView.getTextClassifier().getSettings() - .isSuggestSelectionEnabledForEditableText(); + adjustSelection &= mTextClassificationSettings.isSmartSelectionEnabled(); mSelectionTracker.onOriginalSelection( getText(mTextView), @@ -249,7 +248,7 @@ public final class SelectionActionModeHelper { || mTextView.isTextEditable() || actionMode == Editor.TextActionMode.TEXT_LINK)) { // Do not change the selection if TextClassifier should be dark launched. - if (!mTextView.getTextClassifier().getSettings().isDarkLaunch()) { + if (!mTextClassificationSettings.isModelDarkLaunchEnabled()) { Selection.setSelection((Spannable) text, result.mStart, result.mEnd); mTextView.invalidate(); } @@ -450,7 +449,6 @@ public final class SelectionActionModeHelper { selectionEnd = mTextView.getSelectionEnd(); } mTextClassificationHelper.init( - mTextView.getContext(), mTextView.getTextClassifier(), getText(mTextView), selectionStart, selectionEnd, @@ -882,7 +880,8 @@ public final class SelectionActionModeHelper { private static final int TRIM_DELTA = 120; // characters - private Context mContext; + private final Context mContext; + private final boolean mDarkLaunchEnabled; private TextClassifier mTextClassifier; /** The original TextView text. **/ @@ -917,13 +916,15 @@ public final class SelectionActionModeHelper { TextClassificationHelper(Context context, TextClassifier textClassifier, CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) { - init(context, textClassifier, text, selectionStart, selectionEnd, locales); + init(textClassifier, text, selectionStart, selectionEnd, locales); + mContext = Preconditions.checkNotNull(context); + mDarkLaunchEnabled = TextClassificationManager.getSettings(mContext) + .isModelDarkLaunchEnabled(); } @UiThread - public void init(Context context, TextClassifier textClassifier, - CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) { - mContext = Preconditions.checkNotNull(context); + public void init(TextClassifier textClassifier, CharSequence text, + int selectionStart, int selectionEnd, LocaleList locales) { mTextClassifier = Preconditions.checkNotNull(textClassifier); mText = Preconditions.checkNotNull(text).toString(); mLastClassificationText = null; // invalidate. @@ -956,7 +957,7 @@ public final class SelectionActionModeHelper { mSelectionOptions.getDefaultLocales()); } // Do not classify new selection boundaries if TextClassifier should be dark launched. - if (!mTextClassifier.getSettings().isDarkLaunch()) { + if (!mDarkLaunchEnabled) { mSelectionStart = Math.max(0, selection.getSelectionStartIndex() + mTrimStart); mSelectionEnd = Math.min( mText.length(), selection.getSelectionEndIndex() + mTrimStart); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index fdb97560c848..242f4229f0ae 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -13348,7 +13348,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true; private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true; - private static final boolean DEFAULT_READ_BINARY_CPU_TIME = false; + private static final boolean DEFAULT_READ_BINARY_CPU_TIME = true; private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000; private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000; diff --git a/core/proto/android/content/configuration.proto b/core/proto/android/content/configuration.proto index 834ecdee6a9f..74b47d2424b2 100644 --- a/core/proto/android/content/configuration.proto +++ b/core/proto/android/content/configuration.proto @@ -35,9 +35,9 @@ message ConfigurationProto { optional uint32 mnc = 3; repeated LocaleProto locales = 4; optional uint32 screen_layout = 5; - optional uint32 hdr_color_mode = 6; - optional uint32 wide_color_gamut = 7; - optional uint32 touchscreen = 8; + optional uint32 color_mode = 6; + optional uint32 touchscreen = 7; + optional uint32 keyboard = 8; optional uint32 keyboard_hidden = 9; optional uint32 hard_keyboard_hidden = 10; optional uint32 navigation = 11; diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index be155977a1ea..7326829b584b 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -214,37 +214,37 @@ message IncidentProto { (section).args = "procstats --proto" ]; - optional com.android.server.am.proto.ActivityStackSupervisorProto activities = 3012 [ + optional com.android.server.am.proto.ActivityManagerServiceDumpActivitiesProto activities = 3012 [ (section).type = SECTION_DUMPSYS, (section).args = "activity --proto activities" ]; - optional com.android.server.am.proto.BroadcastProto broadcasts = 3013 [ + optional com.android.server.am.proto.ActivityManagerServiceDumpBroadcastsProto broadcasts = 3013 [ (section).type = SECTION_DUMPSYS, (section).args = "activity --proto broadcasts" ]; - optional com.android.server.am.proto.ActiveServicesProto amservices = 3014 [ + optional com.android.server.am.proto.ActivityManagerServiceDumpServicesProto amservices = 3014 [ (section).type = SECTION_DUMPSYS, (section).args = "activity --proto service" ]; - optional com.android.server.am.proto.ProcessesProto amprocesses = 3015 [ + optional com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto amprocesses = 3015 [ (section).type = SECTION_DUMPSYS, (section).args = "activity --proto processes" ]; - optional com.android.server.AlarmManagerServiceProto alarm = 3016 [ + optional com.android.server.AlarmManagerServiceDumpProto alarm = 3016 [ (section).type = SECTION_DUMPSYS, (section).args = "alarm --proto" ]; - optional com.android.server.wm.proto.WindowManagerServiceProto window = 3017 [ + optional com.android.server.wm.proto.WindowManagerServiceDumpProto window = 3017 [ (section).type = SECTION_DUMPSYS, (section).args = "window --proto" ]; - optional com.android.server.am.proto.MemInfoProto meminfo = 3018 [ + optional com.android.server.am.proto.MemInfoDumpProto meminfo = 3018 [ (section).type = SECTION_DUMPSYS, (section).args = "meminfo -a --proto" ]; diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 5042ede77d2d..3b9150f44abc 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -40,16 +40,22 @@ option java_multiple_files = true; message ActivityManagerServiceProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; - optional ActivityStackSupervisorProto activities = 1; + optional ActivityManagerServiceDumpActivitiesProto activities = 1; - optional BroadcastProto broadcasts = 2; + optional ActivityManagerServiceDumpBroadcastsProto broadcasts = 2; - optional ActiveServicesProto services = 3; + optional ActivityManagerServiceDumpServicesProto services = 3; - optional ProcessesProto processes = 4; + optional ActivityManagerServiceDumpProcessesProto processes = 4; } // "dumpsys activity --proto activities" +message ActivityManagerServiceDumpActivitiesProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + optional ActivityStackSupervisorProto activity_stack_supervisor = 1; +} + message ActivityStackSupervisorProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; @@ -121,7 +127,7 @@ message KeyguardControllerProto { } // "dumpsys activity --proto broadcasts" -message BroadcastProto { +message ActivityManagerServiceDumpBroadcastsProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; repeated ReceiverListProto receiver_list = 1; @@ -202,7 +208,7 @@ message BroadcastQueueProto { repeated BroadcastSummary historical_broadcasts_summary = 6; } -message MemInfoProto { +message MemInfoDumpProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; optional int64 uptime_duration_ms = 1; @@ -406,6 +412,12 @@ message StickyBroadcastProto { } // "dumpsys activity --proto service" +message ActivityManagerServiceDumpServicesProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + optional ActiveServicesProto active_services = 1; +} + message ActiveServicesProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; @@ -585,7 +597,7 @@ message IntentBindRecordProto { } // TODO: "dumpsys activity --proto processes" -message ProcessesProto { +message ActivityManagerServiceDumpProcessesProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; repeated ProcessRecordProto procs = 1; diff --git a/core/proto/android/server/alarmmanagerservice.proto b/core/proto/android/server/alarmmanagerservice.proto index b288c1149731..53e3ba965120 100644 --- a/core/proto/android/server/alarmmanagerservice.proto +++ b/core/proto/android/server/alarmmanagerservice.proto @@ -28,7 +28,7 @@ package com.android.server; option java_multiple_files = true; // next ID: 43 -message AlarmManagerServiceProto { +message AlarmManagerServiceDumpProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; optional int64 current_time = 1; diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index c11058a22107..7745ee45619e 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -32,7 +32,7 @@ package com.android.server.wm.proto; option java_multiple_files = true; -message WindowManagerServiceProto { +message WindowManagerServiceDumpProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; optional WindowManagerPolicyProto policy = 1; diff --git a/core/proto/android/server/windowmanagertrace.proto b/core/proto/android/server/windowmanagertrace.proto index d96953ee9ded..96a90bfe63da 100644 --- a/core/proto/android/server/windowmanagertrace.proto +++ b/core/proto/android/server/windowmanagertrace.proto @@ -48,5 +48,5 @@ message WindowManagerTraceProto { /* where the trace originated */ optional string where = 2; - optional WindowManagerServiceProto window_manager_service = 3; + optional WindowManagerServiceDumpProto window_manager_service = 3; } diff --git a/core/res/res/drawable/ic_alert_window_layer.xml b/core/res/res/drawable/ic_alert_window_layer.xml new file mode 100644 index 000000000000..15931b807918 --- /dev/null +++ b/core/res/res/drawable/ic_alert_window_layer.xml @@ -0,0 +1,24 @@ +<!-- +Copyright (C) 2018 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11.99,18.54l-7.37,-5.73L3,14.07l9,7 9,-7 -1.63,-1.27 -7.38,5.74zM12,16l7.36,-5.73L21,9l-9,-7 -9,7 1.63,1.27L12,16z"/> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_camera.xml b/core/res/res/drawable/ic_camera.xml new file mode 100644 index 000000000000..2921a689ef8a --- /dev/null +++ b/core/res/res/drawable/ic_camera.xml @@ -0,0 +1,27 @@ +<!-- +Copyright (C) 2018 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z" + android:fillColor="#FFFFFF"/> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_mic.xml b/core/res/res/drawable/ic_mic.xml new file mode 100644 index 000000000000..3212330278aa --- /dev/null +++ b/core/res/res/drawable/ic_mic.xml @@ -0,0 +1,24 @@ +<!-- +Copyright (C) 2018 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z" + android:fillColor="#FFFFFF"/> +</vector>
\ No newline at end of file diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml index 20bdf3fe8fa3..c03cf51d6bca 100644 --- a/core/res/res/layout/notification_template_header.xml +++ b/core/res/res/layout/notification_template_header.xml @@ -14,7 +14,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> - +<!-- extends ViewGroup --> <NotificationHeaderView xmlns:android="http://schemas.android.com/apk/res/android" android:theme="@style/Theme.Material.Notification" @@ -126,5 +126,42 @@ android:visibility="gone" android:contentDescription="@string/notification_work_profile_content_description" /> + + <LinearLayout + android:id="@+id/app_ops" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:orientation="horizontal" > + <ImageButton + android:id="@+id/camera" + android:layout_width="?attr/notificationHeaderIconSize" + android:layout_height="?attr/notificationHeaderIconSize" + android:src="@drawable/ic_camera" + android:tint="@color/notification_secondary_text_color_light" + android:background="?android:selectableItemBackgroundBorderless" + android:layout_marginStart="6dp" + android:visibility="gone" + /> + <ImageButton + android:id="@+id/mic" + android:layout_width="?attr/notificationHeaderIconSize" + android:layout_height="?attr/notificationHeaderIconSize" + android:src="@drawable/ic_mic" + android:tint="@color/notification_secondary_text_color_light" + android:background="?android:selectableItemBackgroundBorderless" + android:layout_marginStart="4dp" + android:visibility="gone" + /> + <ImageButton + android:id="@+id/overlay" + android:layout_width="?attr/notificationHeaderIconSize" + android:layout_height="?attr/notificationHeaderIconSize" + android:src="@drawable/ic_alert_window_layer" + android:tint="@color/notification_secondary_text_color_light" + android:background="?android:selectableItemBackgroundBorderless" + android:layout_marginStart="4dp" + android:visibility="gone" + /> + </LinearLayout> </NotificationHeaderView> diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml index 4f0c0fbc4835..265eaaf39713 100644 --- a/core/res/res/values-land/dimens.xml +++ b/core/res/res/values-land/dimens.xml @@ -27,6 +27,9 @@ <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen> <dimen name="preference_widget_width">72dp</dimen> + <!-- Height of the status bar --> + <dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen> + <!-- Default height of an action bar. --> <dimen name="action_bar_default_height">40dip</dimen> <!-- Vertical padding around action bar icons. --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index cfb5784666b9..c4fa190b228d 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -2348,6 +2348,16 @@ <attr name="logo" /> <attr name="priority" /> <attr name="autoVerify" /> + <!-- Within an application, multiple intent filters may match a particular + intent. This allows the app author to specify the order filters should + be considered. We don't want to use priority because that is global + across applications. + <p>Only use if you really need to forcibly set the order in which + filters are evaluated. It is preferred to target an activity with a + directed intent instead. + <p>The value is a single integer, with higher numbers considered to + be better. If not specified, the default order is 0. --> + <attr name="order" /> </declare-styleable> <!-- Attributes that can be supplied in an AndroidManifest.xml diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 291826025cc1..7ff96fa7def2 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -32,7 +32,11 @@ <dimen name="toast_y_offset">24dp</dimen> <!-- Height of the status bar --> - <dimen name="status_bar_height">24dp</dimen> + <dimen name="status_bar_height">@dimen/status_bar_height_portrait</dimen> + <!-- Height of the status bar in portrait --> + <dimen name="status_bar_height_portrait">24dp</dimen> + <!-- Height of the status bar in landscape --> + <dimen name="status_bar_height_landscape">@dimen/status_bar_height_portrait</dimen> <!-- Height of area above QQS where battery/time go --> <dimen name="quick_qs_offset_height">48dp</dimen> <!-- Total height of QQS (quick_qs_offset_height + 128) --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1babd707c781..3b96861e45fc 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -218,6 +218,10 @@ <java-symbol type="id" name="selection_end_handle" /> <java-symbol type="id" name="insertion_handle" /> <java-symbol type="id" name="accessibilityActionClickOnClickableSpan" /> + <java-symbol type="id" name="camera" /> + <java-symbol type="id" name="mic" /> + <java-symbol type="id" name="overlay" /> + <java-symbol type="id" name="app_ops" /> <java-symbol type="attr" name="actionModeShareDrawable" /> <java-symbol type="attr" name="alertDialogCenterButtons" /> @@ -1389,6 +1393,9 @@ <java-symbol type="drawable" name="stat_notify_mmcc_indication_icn" /> <java-symbol type="drawable" name="autofilled_highlight"/> + <java-symbol type="drawable" name="ic_camera" /> + <java-symbol type="drawable" name="ic_mic" /> + <java-symbol type="drawable" name="ic_alert_window_layer" /> <java-symbol type="drawable" name="ic_account_circle" /> <java-symbol type="color" name="user_icon_1" /> @@ -3238,6 +3245,9 @@ <java-symbol type="string" name="keyguard_accessibility_sim_puk_unlock" /> <java-symbol type="string" name="keyguard_accessibility_password_unlock" /> + <java-symbol type="dimen" name="status_bar_height_portrait" /> + <java-symbol type="dimen" name="status_bar_height_landscape" /> + <java-symbol type="string" name="global_action_logout" /> <java-symbol type="string" name="config_mainBuiltInDisplayCutout" /> <java-symbol type="drawable" name="messaging_user" /> diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java new file mode 100644 index 000000000000..7f16359ad269 --- /dev/null +++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017 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.view.textclassifier; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class TextClassificationConstantsTest { + + @Test + public void testLoadFromString() { + final String s = "model_dark_launch_enabled=true," + + "smart_selection_enabled=true," + + "smart_text_share_enabled=true," + + "smart_linkify_enabled=true," + + "smart_select_animation_enabled=true," + + "suggest_selection_max_range_length=10," + + "classify_text_max_range_length=11," + + "generate_links_max_text_length=12," + + "generate_links_log_sample_rate=13"; + final TextClassificationConstants constants = + TextClassificationConstants.loadFromString(s); + assertTrue("model_dark_launch_enabled", constants.isModelDarkLaunchEnabled()); + assertTrue("smart_selection_enabled", constants.isSmartSelectionEnabled()); + assertTrue("smart_text_share_enabled", constants.isSmartTextShareEnabled()); + assertTrue("smart_linkify_enabled", constants.isSmartLinkifyEnabled()); + assertTrue("smart_select_animation_enabled", constants.isSmartSelectionAnimationEnabled()); + assertEquals("suggest_selection_max_range_length", + 10, constants.getSuggestSelectionMaxRangeLength()); + assertEquals("classify_text_max_range_length", + 11, constants.getClassifyTextMaxRangeLength()); + assertEquals("generate_links_max_text_length", + 12, constants.getGenerateLinksMaxTextLength()); + assertEquals("generate_links_log_sample_rate", + 13, constants.getGenerateLinksLogSampleRate()); + } + + @Test + public void testLoadFromString_differentValues() { + final String s = "model_dark_launch_enabled=false," + + "smart_selection_enabled=false," + + "smart_text_share_enabled=false," + + "smart_linkify_enabled=false," + + "smart_select_animation_enabled=false," + + "suggest_selection_max_range_length=8," + + "classify_text_max_range_length=7," + + "generate_links_max_text_length=6," + + "generate_links_log_sample_rate=5"; + final TextClassificationConstants constants = + TextClassificationConstants.loadFromString(s); + assertFalse("model_dark_launch_enabled", constants.isModelDarkLaunchEnabled()); + assertFalse("smart_selection_enabled", constants.isSmartSelectionEnabled()); + assertFalse("smart_text_share_enabled", constants.isSmartTextShareEnabled()); + assertFalse("smart_linkify_enabled", constants.isSmartLinkifyEnabled()); + assertFalse("smart_select_animation_enabled", + constants.isSmartSelectionAnimationEnabled()); + assertEquals("suggest_selection_max_range_length", + 8, constants.getSuggestSelectionMaxRangeLength()); + assertEquals("classify_text_max_range_length", + 7, constants.getClassifyTextMaxRangeLength()); + assertEquals("generate_links_max_text_length", + 6, constants.getGenerateLinksMaxTextLength()); + assertEquals("generate_links_log_sample_rate", + 5, constants.getGenerateLinksLogSampleRate()); + } + + @Test + public void testEntityListParsing() { + final TextClassificationConstants constants = TextClassificationConstants.loadFromString( + "entity_list_default=phone," + + "entity_list_not_editable=address:flight," + + "entity_list_editable=date:datetime"); + assertEquals(1, constants.getEntityListDefault().size()); + assertEquals("phone", constants.getEntityListDefault().get(0)); + assertEquals(2, constants.getEntityListNotEditable().size()); + assertEquals("address", constants.getEntityListNotEditable().get(0)); + assertEquals("flight", constants.getEntityListNotEditable().get(1)); + assertEquals(2, constants.getEntityListEditable().size()); + assertEquals("date", constants.getEntityListEditable().get(0)); + assertEquals("datetime", constants.getEntityListEditable().get(1)); + } +} diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierConstantsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierConstantsTest.java deleted file mode 100644 index 984eede55684..000000000000 --- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierConstantsTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2017 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.view.textclassifier; - -import static org.junit.Assert.assertEquals; - -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class TextClassifierConstantsTest { - - @Test - public void testEntityListParsing() { - final TextClassifierConstants constants = TextClassifierConstants.loadFromString( - "entity_list_default=phone," - + "entity_list_not_editable=address:flight," - + "entity_list_editable=date:datetime"); - assertEquals(1, constants.getEntityListDefault().size()); - assertEquals("phone", constants.getEntityListDefault().get(0)); - assertEquals(2, constants.getEntityListNotEditable().size()); - assertEquals("address", constants.getEntityListNotEditable().get(0)); - assertEquals("flight", constants.getEntityListNotEditable().get(1)); - assertEquals(2, constants.getEntityListEditable().size()); - assertEquals("date", constants.getEntityListEditable().get(0)); - assertEquals("datetime", constants.getEntityListEditable().get(1)); - } -} diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java index 209ec42dfb0b..c0468dc920ec 100644 --- a/media/java/android/media/Ringtone.java +++ b/media/java/android/media/Ringtone.java @@ -40,7 +40,7 @@ import java.util.ArrayList; * <p> * For ways of retrieving {@link Ringtone} objects or to show a ringtone * picker, see {@link RingtoneManager}. - * + * * @see RingtoneManager */ public class Ringtone { @@ -97,7 +97,7 @@ public class Ringtone { /** * Sets the stream type where this ringtone will be played. - * + * * @param streamType The stream, see {@link AudioManager}. * @deprecated use {@link #setAudioAttributes(AudioAttributes)} */ @@ -111,7 +111,7 @@ public class Ringtone { /** * Gets the stream type where this ringtone will be played. - * + * * @return The stream type, see {@link AudioManager}. * @deprecated use of stream types is deprecated, see * {@link #setAudioAttributes(AudioAttributes)} @@ -146,9 +146,8 @@ public class Ringtone { } /** - * @hide * Sets the player to be looping or non-looping. - * @param looping whether to loop or not + * @param looping whether to loop or not. */ public void setLooping(boolean looping) { synchronized (mPlaybackSettingsLock) { @@ -158,7 +157,16 @@ public class Ringtone { } /** - * @hide + * Returns whether the looping mode was enabled on this player. + * @return true if this player loops when playing. + */ + public boolean isLooping() { + synchronized (mPlaybackSettingsLock) { + return mIsLooping; + } + } + + /** * Sets the volume on this player. * @param volume a raw scalar in range 0.0 to 1.0, where 0.0 mutes this player, and 1.0 * corresponds to no attenuation being applied. @@ -173,6 +181,16 @@ public class Ringtone { } /** + * Returns the volume scalar set on this player. + * @return a value between 0.0f and 1.0f. + */ + public float getVolume() { + synchronized (mPlaybackSettingsLock) { + return mVolume; + } + } + + /** * Must be called synchronized on mPlaybackSettingsLock */ private void applyPlaybackProperties_sync() { @@ -194,8 +212,8 @@ public class Ringtone { /** * Returns a human-presentable title for ringtone. Looks in media * content provider. If not in either, uses the filename - * - * @param context A context used for querying. + * + * @param context A context used for querying. */ public String getTitle(Context context) { if (mTitle != null) return mTitle; @@ -265,12 +283,11 @@ public class Ringtone { if (title == null) { title = context.getString(com.android.internal.R.string.ringtone_unknown); - if (title == null) { title = ""; } } - + return title; } @@ -395,7 +412,7 @@ public class Ringtone { /** * Whether this ringtone is currently playing. - * + * * @return True if playing, false otherwise. */ public boolean isPlaying() { diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 58d5db32a7e3..a75b147a4901 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -876,47 +876,53 @@ <!-- Summary shown for color space correction preference when its value is overridden by another preference [CHAR LIMIT=35] --> <string name="daltonizer_type_overridden">Overridden by <xliff:g id="title" example="Simulate color space">%1$s</xliff:g></string> - <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery discharging --> - <string name="power_remaining_duration_only">About <xliff:g id="time">%1$s</xliff:g> left</string> - <!-- [CHAR_LIMIT=60] Label for estimated remaining duration of battery discharging --> - <string name="power_remaining_duration_only_enhanced">About <xliff:g id="time">%1$s</xliff:g> left based on your usage</string> - <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging --> - <string name="power_remaining_charging_duration_only"><xliff:g id="time">%1$s</xliff:g> left until fully charged</string> - - <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging --> - <string name="power_remaining_duration_only_short"><xliff:g id="time">%1$s</xliff:g> left</string> - - <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount --> - <string name="power_remaining_less_than_duration_only">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining</string> - <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount with the percentage --> - <string name="power_remaining_less_than_duration"><xliff:g id="level">%1$s</xliff:g> - Less than <xliff:g id="threshold">%2$s</xliff:g> remaining</string> - - <!-- Used to let users know that they have more than some amount of battery life remaining with percentage. ex: 75% - more than 1 day remaining [CHAR LIMIT = 80] --> - <string name="power_remaining_more_than_subtext"><xliff:g id="level">%1$s</xliff:g>more than <xliff:g id="time_remaining">%2$s</xliff:g> remaining</string> - <!-- Used to let users know that they have more than some amount of battery life remaining. ex: more than 1 day remaining [CHAR LIMIT = 40] --> - <string name="power_remaining_only_more_than_subtext">more than <xliff:g id="time_remaining">%1$s</xliff:g> remaining</string> - - <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device --> - <string name="power_remaining_duration_only_shutdown_imminent" product="default">phone may shutdown soon</string> - <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device --> - <string name="power_remaining_duration_only_shutdown_imminent" product="tablet">tablet may shutdown soon</string> - <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device --> - <string name="power_remaining_duration_only_shutdown_imminent" product="device">device may shutdown soon</string> - - <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration --> - <string name="power_discharging_duration"><xliff:g id="level">%1$s</xliff:g> - about <xliff:g id="time">%2$s</xliff:g> left</string> - <!-- [CHAR_LIMIT=60] Label for battery level chart when discharging with duration and using enhanced estimate --> - <string name="power_discharging_duration_enhanced"><xliff:g id="level">%1$s</xliff:g> - about <xliff:g id="time">%2$s</xliff:g> left based on your usage</string> - - <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent--> - <string name="power_remaining_duration_shutdown_imminent" product="default"><xliff:g id="level">%1$s</xliff:g> - phone may shutdown soon</string> - <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent--> - <string name="power_remaining_duration_shutdown_imminent" product="tablet"><xliff:g id="level">%1$s</xliff:g> - tablet may shutdown soon</string> - <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent--> - <string name="power_remaining_duration_shutdown_imminent" product="device"><xliff:g id="level">%1$s</xliff:g> - device may shutdown soon</string> + <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery discharging --> + <string name="power_remaining_duration_only">About <xliff:g id="time">%1$s</xliff:g> left</string> + <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration --> + <string name="power_discharging_duration">About <xliff:g id="time">%1$s</xliff:g> left (<xliff:g id="level">%2$s</xliff:g>)</string> + <!-- [CHAR_LIMIT=60] Label for estimated remaining duration of battery discharging --> + <string name="power_remaining_duration_only_enhanced">About <xliff:g id="time">%1$s</xliff:g> left based on your usage</string> + <!-- [CHAR_LIMIT=60] Label for battery level chart when discharging with duration and using enhanced estimate --> + <string name="power_discharging_duration_enhanced">About <xliff:g id="time">%1$s</xliff:g> left based on your usage (<xliff:g id="level">%2$s</xliff:g>)</string> + <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging --> + <string name="power_remaining_duration_only_short"><xliff:g id="time">%1$s</xliff:g> left</string> + + <!-- [CHAR_LIMIT=100] Label for enhanced estimated time that phone will run out of battery --> + <string name="power_discharge_by_enhanced">Will last until about about <xliff:g id="time">%1$s</xliff:g> based on your usage (<xliff:g id="level">%2$s</xliff:g>)</string> + <!-- [CHAR_LIMIT=100] Label for enhanced estimated time that phone will run out of battery with no percentage --> + <string name="power_discharge_by_only_enhanced">Will last until about about <xliff:g id="time">%1$s</xliff:g> based on your usage</string> + <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery --> + <string name="power_discharge_by">Will last until about about <xliff:g id="time">%1$s</xliff:g> (<xliff:g id="level">%2$s</xliff:g>)</string> + <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery --> + <string name="power_discharge_by_only">Will last until about about <xliff:g id="time">%1$s</xliff:g></string> + + <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount --> + <string name="power_remaining_less_than_duration_only">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining</string> + <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount with the percentage --> + <string name="power_remaining_less_than_duration">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining (<xliff:g id="level">%2$s</xliff:g>)</string> + + <!-- Used to let users know that they have more than some amount of battery life remaining with percentage. ex: 75% - more than 1 day remaining [CHAR LIMIT = 80] --> + <string name="power_remaining_more_than_subtext">More than <xliff:g id="time_remaining">%1$s</xliff:g> remaining (<xliff:g id="level">%2$s</xliff:g>)</string> + <!-- Used to let users know that they have more than some amount of battery life remaining. ex: more than 1 day remaining [CHAR LIMIT = 40] --> + <string name="power_remaining_only_more_than_subtext">More than <xliff:g id="time_remaining">%1$s</xliff:g> remaining</string> + + <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device --> + <string name="power_remaining_duration_only_shutdown_imminent" product="default">Phone may shutdown soon</string> + <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device --> + <string name="power_remaining_duration_only_shutdown_imminent" product="tablet">Tablet may shutdown soon</string> + <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device --> + <string name="power_remaining_duration_only_shutdown_imminent" product="device">Device may shutdown soon</string> + <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent--> + <string name="power_remaining_duration_shutdown_imminent" product="default">Phone may shutdown soon (<xliff:g id="level">%1$s</xliff:g>)</string> + <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent--> + <string name="power_remaining_duration_shutdown_imminent" product="tablet">Tablet may shutdown soon (<xliff:g id="level">%1$s</xliff:g>)</string> + <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent--> + <string name="power_remaining_duration_shutdown_imminent" product="device">Device may shutdown soon (<xliff:g id="level">%1$s</xliff:g>)</string> <!-- [CHAR_LIMIT=40] Label for battery level chart when charging --> <string name="power_charging"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="state">%2$s</xliff:g></string> + <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging --> + <string name="power_remaining_charging_duration_only"><xliff:g id="time">%1$s</xliff:g> left until fully charged</string> <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration --> <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> until fully charged</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java index 346ca66bcb13..8b3da3944088 100644 --- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java +++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java @@ -17,22 +17,30 @@ package com.android.settingslib.utils; import android.content.Context; +import android.icu.text.DateFormat; import android.icu.text.MeasureFormat; import android.icu.text.MeasureFormat.FormatWidth; import android.icu.util.Measure; import android.icu.util.MeasureUnit; import android.support.annotation.Nullable; import android.text.TextUtils; +import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.R; -import com.android.settingslib.utils.StringUtil; +import java.time.Clock; +import java.time.Instant; +import java.util.Calendar; +import java.util.Date; import java.util.Locale; import java.util.concurrent.TimeUnit; /** Utility class for keeping power related strings consistent**/ public class PowerUtil { + private static final long SEVEN_MINUTES_MILLIS = TimeUnit.MINUTES.toMillis(7); private static final long FIFTEEN_MINUTES_MILLIS = TimeUnit.MINUTES.toMillis(15); private static final long ONE_DAY_MILLIS = TimeUnit.DAYS.toMillis(1); + private static final long TWO_DAYS_MILLIS = TimeUnit.DAYS.toMillis(2); + private static final long ONE_HOUR_MILLIS = TimeUnit.HOURS.toMillis(1); /** * This method produces the text used in various places throughout the system to describe the @@ -57,11 +65,15 @@ public class PowerUtil { FIFTEEN_MINUTES_MILLIS, false /* withSeconds */); return getUnderFifteenString(context, timeString, percentageString); + } else if (drainTimeMs >= TWO_DAYS_MILLIS) { + // just say more than two day if over 48 hours + return getMoreThanTwoDaysString(context, percentageString); } else if (drainTimeMs >= ONE_DAY_MILLIS) { - // just say more than one day if over 24 hours - return getMoreThanOneDayString(context, percentageString); + // show remaining days & hours if more than a day + return getMoreThanOneDayString(context, drainTimeMs, + percentageString, basedOnUsage); } else { - // show a regular time remaining string + // show the time of day we think you'll run out return getRegularTimeRemainingString(context, drainTimeMs, percentageString, basedOnUsage); } @@ -83,44 +95,69 @@ public class PowerUtil { ? context.getString(R.string.power_remaining_less_than_duration_only, timeString) : context.getString( R.string.power_remaining_less_than_duration, - percentageString, - timeString); + timeString, + percentageString); + + } + private static String getMoreThanOneDayString(Context context, long drainTimeMs, + String percentageString, boolean basedOnUsage) { + final long roundedTimeMs = roundToNearestThreshold(drainTimeMs, ONE_HOUR_MILLIS); + CharSequence timeString = StringUtil.formatElapsedTime(context, + roundedTimeMs, + false /* withSeconds */); + + if (TextUtils.isEmpty(percentageString)) { + int id = basedOnUsage + ? R.string.power_remaining_duration_only_enhanced + : R.string.power_remaining_duration_only; + return context.getString(id, timeString); + } else { + int id = basedOnUsage + ? R.string.power_discharging_duration_enhanced + : R.string.power_discharging_duration; + return context.getString(id, timeString, percentageString); + } } - private static String getMoreThanOneDayString(Context context, String percentageString) { + private static String getMoreThanTwoDaysString(Context context, String percentageString) { final Locale currentLocale = context.getResources().getConfiguration().getLocales().get(0); final MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.SHORT); - final Measure daysMeasure = new Measure(1, MeasureUnit.DAY); + final Measure daysMeasure = new Measure(2, MeasureUnit.DAY); return TextUtils.isEmpty(percentageString) ? context.getString(R.string.power_remaining_only_more_than_subtext, frmt.formatMeasures(daysMeasure)) : context.getString( R.string.power_remaining_more_than_subtext, - percentageString, - frmt.formatMeasures(daysMeasure)); + frmt.formatMeasures(daysMeasure), + percentageString); } private static String getRegularTimeRemainingString(Context context, long drainTimeMs, String percentageString, boolean basedOnUsage) { - // round to the nearest 15 min to not appear oversly precise - final long roundedTimeMs = roundToNearestThreshold(drainTimeMs, - FIFTEEN_MINUTES_MILLIS); - CharSequence timeString = StringUtil.formatElapsedTime(context, - roundedTimeMs, - false /* withSeconds */); + // Get the time of day we think device will die rounded to the nearest 15 min. + final long roundedTimeOfDayMs = + roundToNearestThreshold( + System.currentTimeMillis() + drainTimeMs, + FIFTEEN_MINUTES_MILLIS); + + // convert the time to a properly formatted string. + DateFormat fmt = DateFormat.getTimeInstance(DateFormat.SHORT); + Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs)); + CharSequence timeString = fmt.format(date); + if (TextUtils.isEmpty(percentageString)) { int id = basedOnUsage - ? R.string.power_remaining_duration_only_enhanced - : R.string.power_remaining_duration_only; + ? R.string.power_discharge_by_only_enhanced + : R.string.power_discharge_by_only; return context.getString(id, timeString); } else { int id = basedOnUsage - ? R.string.power_discharging_duration_enhanced - : R.string.power_discharging_duration; - return context.getString(id, percentageString, timeString); + ? R.string.power_discharge_by_enhanced + : R.string.power_discharge_by; + return context.getString(id, timeString, percentageString); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java index 45fdd7860836..68be2b4041b1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java +++ b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java @@ -33,74 +33,74 @@ import java.util.Locale; /** Utility class for generally useful string methods **/ public class StringUtil { - public static final int SECONDS_PER_MINUTE = 60; - public static final int SECONDS_PER_HOUR = 60 * 60; - public static final int SECONDS_PER_DAY = 24 * 60 * 60; + public static final int SECONDS_PER_MINUTE = 60; + public static final int SECONDS_PER_HOUR = 60 * 60; + public static final int SECONDS_PER_DAY = 24 * 60 * 60; - /** - * Returns elapsed time for the given millis, in the following format: - * 2d 5h 40m 29s - * @param context the application context - * @param millis the elapsed time in milli seconds - * @param withSeconds include seconds? - * @return the formatted elapsed time - */ - public static CharSequence formatElapsedTime(Context context, double millis, - boolean withSeconds) { - SpannableStringBuilder sb = new SpannableStringBuilder(); - int seconds = (int) Math.floor(millis / 1000); - if (!withSeconds) { - // Round up. - seconds += 30; - } + /** + * Returns elapsed time for the given millis, in the following format: + * 2d 5h 40m 29s + * @param context the application context + * @param millis the elapsed time in milli seconds + * @param withSeconds include seconds? + * @return the formatted elapsed time + */ + public static CharSequence formatElapsedTime(Context context, double millis, + boolean withSeconds) { + SpannableStringBuilder sb = new SpannableStringBuilder(); + int seconds = (int) Math.floor(millis / 1000); + if (!withSeconds) { + // Round up. + seconds += 30; + } - int days = 0, hours = 0, minutes = 0; - if (seconds >= SECONDS_PER_DAY) { - days = seconds / SECONDS_PER_DAY; - seconds -= days * SECONDS_PER_DAY; - } - if (seconds >= SECONDS_PER_HOUR) { - hours = seconds / SECONDS_PER_HOUR; - seconds -= hours * SECONDS_PER_HOUR; - } - if (seconds >= SECONDS_PER_MINUTE) { - minutes = seconds / SECONDS_PER_MINUTE; - seconds -= minutes * SECONDS_PER_MINUTE; - } + int days = 0, hours = 0, minutes = 0; + if (seconds >= SECONDS_PER_DAY) { + days = seconds / SECONDS_PER_DAY; + seconds -= days * SECONDS_PER_DAY; + } + if (seconds >= SECONDS_PER_HOUR) { + hours = seconds / SECONDS_PER_HOUR; + seconds -= hours * SECONDS_PER_HOUR; + } + if (seconds >= SECONDS_PER_MINUTE) { + minutes = seconds / SECONDS_PER_MINUTE; + seconds -= minutes * SECONDS_PER_MINUTE; + } - final ArrayList<Measure> measureList = new ArrayList(4); - if (days > 0) { - measureList.add(new Measure(days, MeasureUnit.DAY)); - } - if (hours > 0) { - measureList.add(new Measure(hours, MeasureUnit.HOUR)); - } - if (minutes > 0) { - measureList.add(new Measure(minutes, MeasureUnit.MINUTE)); - } - if (withSeconds && seconds > 0) { - measureList.add(new Measure(seconds, MeasureUnit.SECOND)); - } - if (measureList.size() == 0) { - // Everything addable was zero, so nothing was added. We add a zero. - measureList.add(new Measure(0, withSeconds ? MeasureUnit.SECOND : MeasureUnit.MINUTE)); - } - final Measure[] measureArray = measureList.toArray(new Measure[measureList.size()]); + final ArrayList<Measure> measureList = new ArrayList(4); + if (days > 0) { + measureList.add(new Measure(days, MeasureUnit.DAY)); + } + if (hours > 0) { + measureList.add(new Measure(hours, MeasureUnit.HOUR)); + } + if (minutes > 0) { + measureList.add(new Measure(minutes, MeasureUnit.MINUTE)); + } + if (withSeconds && seconds > 0) { + measureList.add(new Measure(seconds, MeasureUnit.SECOND)); + } + if (measureList.size() == 0) { + // Everything addable was zero, so nothing was added. We add a zero. + measureList.add(new Measure(0, withSeconds ? MeasureUnit.SECOND : MeasureUnit.MINUTE)); + } + final Measure[] measureArray = measureList.toArray(new Measure[measureList.size()]); - final Locale locale = context.getResources().getConfiguration().locale; - final MeasureFormat measureFormat = MeasureFormat.getInstance( - locale, FormatWidth.NARROW); - sb.append(measureFormat.formatMeasures(measureArray)); + final Locale locale = context.getResources().getConfiguration().locale; + final MeasureFormat measureFormat = MeasureFormat.getInstance( + locale, FormatWidth.NARROW); + sb.append(measureFormat.formatMeasures(measureArray)); - if (measureArray.length == 1 && MeasureUnit.MINUTE.equals(measureArray[0].getUnit())) { - // Add ttsSpan if it only have minute value, because it will be read as "meters" - final TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes) - .setUnit("minute").build(); - sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } + if (measureArray.length == 1 && MeasureUnit.MINUTE.equals(measureArray[0].getUnit())) { + // Add ttsSpan if it only have minute value, because it will be read as "meters" + final TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes) + .setUnit("minute").build(); + sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } - return sb; - } + return sb; + } /** * Returns relative time for the given millis in the past, in a short format such as "2 days diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java index 9285148f7ae2..c42ff083ff11 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java @@ -24,13 +24,18 @@ import android.content.Context; import com.android.settingslib.R; import com.android.settingslib.SettingsLibRobolectricTestRunner; +import java.time.Clock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import java.time.Duration; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowSettings.ShadowSystem; +import org.robolectric.shadows.ShadowSystemClock; @RunWith(SettingsLibRobolectricTestRunner.class) public class PowerUtilTest { @@ -39,8 +44,12 @@ public class PowerUtilTest { public static final long SEVENTEEN_MIN_MILLIS = Duration.ofMinutes(17).toMillis(); public static final long FIVE_MINUTES_MILLIS = Duration.ofMinutes(5).toMillis(); public static final long TEN_MINUTES_MILLIS = Duration.ofMinutes(10).toMillis(); - public static final long TWO_DAYS_MILLIS = Duration.ofDays(2).toMillis(); - public static final String ONE_DAY_FORMATTED = "1 day"; + public static final long THREE_DAYS_MILLIS = Duration.ofDays(3).toMillis(); + public static final long THIRTY_HOURS_MILLIS = Duration.ofHours(30).toMillis(); + public static final String TWO_DAYS_FORMATTED = "2 days"; + public static final String THIRTY_HOURS_FORMATTED = "1d 6h"; + public static final String NORMAL_CASE_EXPECTED_PREFIX = "Will last until about"; + public static final String ENHANCED_SUFFIX = "based on your usage"; private Context mContext; @@ -51,6 +60,7 @@ public class PowerUtilTest { } @Test + @Config(shadows = {ShadowSystemClock.class}) public void testGetBatteryRemainingStringFormatted_moreThanFifteenMinutes_withPercentage() { String info = PowerUtil.getBatteryRemainingStringFormatted(mContext, SEVENTEEN_MIN_MILLIS, @@ -62,15 +72,13 @@ public class PowerUtilTest { false /* basedOnUsage */); // We only add special mention for the long string - assertThat(info).isEqualTo(mContext.getString( - R.string.power_discharging_duration_enhanced, - TEST_BATTERY_LEVEL_10, - FIFTEEN_MIN_FORMATTED)); + assertThat(info).contains(NORMAL_CASE_EXPECTED_PREFIX); + assertThat(info).contains(ENHANCED_SUFFIX); + assertThat(info).contains("%"); // shortened string should not have extra text - assertThat(info2).isEqualTo(mContext.getString( - R.string.power_discharging_duration, - TEST_BATTERY_LEVEL_10, - FIFTEEN_MIN_FORMATTED)); + assertThat(info2).contains(NORMAL_CASE_EXPECTED_PREFIX); + assertThat(info2).doesNotContain(ENHANCED_SUFFIX); + assertThat(info2).contains("%"); } @Test @@ -84,14 +92,14 @@ public class PowerUtilTest { null /* percentageString */, false /* basedOnUsage */); - // We only add special mention for the long string - assertThat(info).isEqualTo(mContext.getString( - R.string.power_remaining_duration_only_enhanced, - FIFTEEN_MIN_FORMATTED)); + // We only have % when it is provided + assertThat(info).contains(NORMAL_CASE_EXPECTED_PREFIX); + assertThat(info).contains(ENHANCED_SUFFIX); + assertThat(info).doesNotContain("%"); // shortened string should not have extra text - assertThat(info2).isEqualTo(mContext.getString( - R.string.power_remaining_duration_only, - FIFTEEN_MIN_FORMATTED)); + assertThat(info2).contains(NORMAL_CASE_EXPECTED_PREFIX); + assertThat(info2).doesNotContain(ENHANCED_SUFFIX); + assertThat(info2).doesNotContain("%"); } @@ -107,12 +115,9 @@ public class PowerUtilTest { true /* basedOnUsage */); // additional battery percentage in this string - assertThat(info).isEqualTo(mContext.getString( - R.string.power_remaining_duration_shutdown_imminent, - TEST_BATTERY_LEVEL_10)); + assertThat(info).isEqualTo("Phone may shutdown soon (10%)"); // shortened string should not have percentage - assertThat(info2).isEqualTo(mContext.getString( - R.string.power_remaining_duration_only_shutdown_imminent)); + assertThat(info2).isEqualTo("Phone may shutdown soon"); } @Test @@ -127,35 +132,42 @@ public class PowerUtilTest { true /* basedOnUsage */); // shortened string should not have percentage - assertThat(info).isEqualTo(mContext.getString( - R.string.power_remaining_less_than_duration_only, - FIFTEEN_MIN_FORMATTED)); + assertThat(info).isEqualTo("Less than 15m remaining"); // Add percentage to string when provided - assertThat(info2).isEqualTo(mContext.getString( - R.string.power_remaining_less_than_duration, - TEST_BATTERY_LEVEL_10, - FIFTEEN_MIN_FORMATTED)); + assertThat(info2).isEqualTo("Less than 15m remaining (10%)"); } @Test - public void testGetBatteryRemainingStringFormatted_moreThanOneDay_usesCorrectString() { + public void testGetBatteryRemainingStringFormatted_betweenOneAndTwoDays_usesCorrectString() { String info = PowerUtil.getBatteryRemainingStringFormatted(mContext, - TWO_DAYS_MILLIS, + THIRTY_HOURS_MILLIS, null /* percentageString */, true /* basedOnUsage */); String info2 = PowerUtil.getBatteryRemainingStringFormatted(mContext, - TWO_DAYS_MILLIS, + THIRTY_HOURS_MILLIS, + TEST_BATTERY_LEVEL_10 /* percentageString */, + false /* basedOnUsage */); + + // We only add special mention for the long string + assertThat(info).isEqualTo("About 1d 6h left based on your usage"); + // shortened string should not have extra text + assertThat(info2).isEqualTo("About 1d 6h left (10%)"); + } + + @Test + public void testGetBatteryRemainingStringFormatted_moreThanTwoDays_usesCorrectString() { + String info = PowerUtil.getBatteryRemainingStringFormatted(mContext, + THREE_DAYS_MILLIS, + null /* percentageString */, + true /* basedOnUsage */); + String info2 = PowerUtil.getBatteryRemainingStringFormatted(mContext, + THREE_DAYS_MILLIS, TEST_BATTERY_LEVEL_10 /* percentageString */, true /* basedOnUsage */); // shortened string should not have percentage - assertThat(info).isEqualTo(mContext.getString( - R.string.power_remaining_only_more_than_subtext, - ONE_DAY_FORMATTED)); + assertThat(info).isEqualTo("More than 2 days remaining"); // Add percentage to string when provided - assertThat(info2).isEqualTo(mContext.getString( - R.string.power_remaining_more_than_subtext, - TEST_BATTERY_LEVEL_10, - ONE_DAY_FORMATTED)); + assertThat(info2).isEqualTo("More than 2 days remaining (10%)"); } } diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index 4614999e3c4f..2e7ab7fe8904 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -15,6 +15,7 @@ limitations under the License. --> +<!-- extends FrameLayout --> <com.android.systemui.statusbar.ExpandableNotificationRow xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" @@ -54,6 +55,7 @@ android:paddingStart="8dp" /> + <!-- TODO: remove --> <ImageButton android:id="@+id/helper" android:layout_width="48dp" @@ -64,7 +66,7 @@ android:tint="#FF0000" android:background="@drawable/ripple_drawable" android:visibility="visible" - /> + /> <ViewStub android:layout="@layout/notification_children_container" diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java index 0103cad4a6c4..2f28c814c76b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java @@ -17,6 +17,7 @@ package com.android.systemui.shared.system; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; +import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; @@ -403,6 +404,25 @@ public class ActivityManagerWrapper { } /** + * @return whether screen pinning is active. + */ + public boolean isScreenPinningActive() { + try { + return ActivityManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED; + } catch (RemoteException e) { + return false; + } + } + + /** + * @return whether screen pinning is enabled. + */ + public boolean isScreenPinningEnabled() { + final ContentResolver cr = AppGlobals.getInitialApplication().getContentResolver(); + return Settings.System.getInt(cr, Settings.System.LOCK_TO_APP_ENABLED, 0) != 0; + } + + /** * @return whether there is currently a locked task (ie. in screen pinning). */ public boolean isLockToAppActive() { @@ -415,9 +435,9 @@ public class ActivityManagerWrapper { /** * @return whether screen pinning is enabled. + * @deprecated See {@link #isScreenPinningEnabled} */ public boolean isLockToAppEnabled() { - final ContentResolver cr = AppGlobals.getInitialApplication().getContentResolver(); - return Settings.System.getInt(cr, Settings.System.LOCK_TO_APP_ENABLED, 0) != 0; + return isScreenPinningEnabled(); } } diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 7403ddc441f6..cad155c43867 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -44,6 +44,7 @@ import com.android.systemui.power.EnhancedEstimates; import com.android.systemui.power.EnhancedEstimatesImpl; import com.android.systemui.power.PowerNotificationWarnings; import com.android.systemui.power.PowerUI; +import com.android.systemui.statusbar.AppOpsListener; import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl; import com.android.systemui.statusbar.phone.LightBarController; @@ -314,6 +315,8 @@ public class Dependency extends SystemUI { mProviders.put(EnhancedEstimates.class, () -> new EnhancedEstimatesImpl()); + mProviders.put(AppOpsListener.class, () -> new AppOpsListener(mContext)); + // Put all dependencies above here so the factory can override them if it wants. SystemUIFactory.getInstance().injectDependencies(mProviders, mContext); } diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java index a2c9ab4871c2..5a2263cf26c7 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java @@ -14,7 +14,9 @@ package com.android.systemui; +import android.annotation.Nullable; import android.service.notification.StatusBarNotification; +import android.util.ArraySet; public interface ForegroundServiceController { /** @@ -46,4 +48,32 @@ public interface ForegroundServiceController { * @return true if sbn is the system-provided "dungeon" (list of running foreground services). */ boolean isDungeonNotification(StatusBarNotification sbn); + + /** + * @return true if sbn is one of the window manager "drawing over other apps" notifications + */ + boolean isSystemAlertNotification(StatusBarNotification sbn); + + /** + * Returns the key of the foreground service from this package using the standard template, + * if one exists. + */ + @Nullable String getStandardLayoutKey(int userId, String pkg); + + /** + * @return true if this user/pkg has a missing or custom layout notification and therefore needs + * a disclosure notification for system alert windows. + */ + boolean isSystemAlertWarningNeeded(int userId, String pkg); + + /** + * Records active app ops. App Ops are stored in FSC in addition to NotificationData in + * case they change before we have a notification to tag. + */ + void onAppOpChanged(int code, int uid, String packageName, boolean active); + + /** + * Gets active app ops for this user and package. + */ + @Nullable ArraySet<Integer> getAppOps(int userId, String packageName); } diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java index 3714c4ea7e2c..fc2b5b490e2c 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java @@ -18,13 +18,13 @@ import android.app.Notification; import android.app.NotificationManager; import android.content.Context; import android.os.Bundle; +import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto; import java.util.Arrays; @@ -34,17 +34,19 @@ import java.util.Arrays; */ public class ForegroundServiceControllerImpl implements ForegroundServiceController { - + // shelf life of foreground services before they go bad public static final long FG_SERVICE_GRACE_MILLIS = 5000; private static final String TAG = "FgServiceController"; private static final boolean DBG = false; + private final Context mContext; private final SparseArray<UserServices> mUserServices = new SparseArray<>(); private final Object mMutex = new Object(); public ForegroundServiceControllerImpl(Context context) { + mContext = context; } @Override @@ -57,6 +59,52 @@ public class ForegroundServiceControllerImpl } @Override + public boolean isSystemAlertWarningNeeded(int userId, String pkg) { + synchronized (mMutex) { + final UserServices services = mUserServices.get(userId); + if (services == null) return false; + return services.getStandardLayoutKey(pkg) == null; + } + } + + @Override + public String getStandardLayoutKey(int userId, String pkg) { + synchronized (mMutex) { + final UserServices services = mUserServices.get(userId); + if (services == null) return null; + return services.getStandardLayoutKey(pkg); + } + } + + @Override + public ArraySet<Integer> getAppOps(int userId, String pkg) { + synchronized (mMutex) { + final UserServices services = mUserServices.get(userId); + if (services == null) { + return null; + } + return services.getFeatures(pkg); + } + } + + @Override + public void onAppOpChanged(int code, int uid, String packageName, boolean active) { + int userId = UserHandle.getUserId(uid); + synchronized (mMutex) { + UserServices userServices = mUserServices.get(userId); + if (userServices == null) { + userServices = new UserServices(); + mUserServices.put(userId, userServices); + } + if (active) { + userServices.addOp(packageName, code); + } else { + userServices.removeOp(packageName, code); + } + } + } + + @Override public void addNotification(StatusBarNotification sbn, int importance) { updateNotification(sbn, importance); } @@ -102,9 +150,16 @@ public class ForegroundServiceControllerImpl } } else { userServices.removeNotification(sbn.getPackageName(), sbn.getKey()); - if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) - && newImportance > NotificationManager.IMPORTANCE_MIN) { - userServices.addNotification(sbn.getPackageName(), sbn.getKey()); + if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)) { + if (newImportance > NotificationManager.IMPORTANCE_MIN) { + userServices.addImportantNotification(sbn.getPackageName(), sbn.getKey()); + } + final Notification.Builder builder = Notification.Builder.recoverBuilder( + mContext, sbn.getNotification()); + if (builder.usesStandardHeader()) { + userServices.addStandardLayoutNotification( + sbn.getPackageName(), sbn.getKey()); + } } } } @@ -117,42 +172,105 @@ public class ForegroundServiceControllerImpl && sbn.getPackageName().equals("android"); } + @Override + public boolean isSystemAlertNotification(StatusBarNotification sbn) { + // TODO: tag system alert notifications so they can be suppressed if app's notification + // is tagged + return false; + } + /** * Struct to track relevant packages and notifications for a userid's foreground services. */ private static class UserServices { private String[] mRunning = null; private long mServiceStartTime = 0; - private ArrayMap<String, ArraySet<String>> mNotifications = new ArrayMap<>(1); + // package -> sufficiently important posted notification keys + private ArrayMap<String, ArraySet<String>> mImportantNotifications = new ArrayMap<>(1); + // package -> standard layout posted notification keys + private ArrayMap<String, ArraySet<String>> mStandardLayoutNotifications = new ArrayMap<>(1); + + // package -> app ops + private ArrayMap<String, ArraySet<Integer>> mAppOps = new ArrayMap<>(1); + public void setRunningServices(String[] pkgs, long serviceStartTime) { mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null; mServiceStartTime = serviceStartTime; } - public void addNotification(String pkg, String key) { - if (mNotifications.get(pkg) == null) { - mNotifications.put(pkg, new ArraySet<String>()); + + public void addOp(String pkg, int op) { + if (mAppOps.get(pkg) == null) { + mAppOps.put(pkg, new ArraySet<>(3)); + } + mAppOps.get(pkg).add(op); + } + + public boolean removeOp(String pkg, int op) { + final boolean found; + final ArraySet<Integer> keys = mAppOps.get(pkg); + if (keys == null) { + found = false; + } else { + found = keys.remove(op); + if (keys.size() == 0) { + mAppOps.remove(pkg); + } } - mNotifications.get(pkg).add(key); + return found; } + + public void addImportantNotification(String pkg, String key) { + addNotification(mImportantNotifications, pkg, key); + } + + public boolean removeImportantNotification(String pkg, String key) { + return removeNotification(mImportantNotifications, pkg, key); + } + + public void addStandardLayoutNotification(String pkg, String key) { + addNotification(mStandardLayoutNotifications, pkg, key); + } + + public boolean removeStandardLayoutNotification(String pkg, String key) { + return removeNotification(mStandardLayoutNotifications, pkg, key); + } + public boolean removeNotification(String pkg, String key) { + boolean removed = false; + removed |= removeImportantNotification(pkg, key); + removed |= removeStandardLayoutNotification(pkg, key); + return removed; + } + + public void addNotification(ArrayMap<String, ArraySet<String>> map, String pkg, + String key) { + if (map.get(pkg) == null) { + map.put(pkg, new ArraySet<>()); + } + map.get(pkg).add(key); + } + + public boolean removeNotification(ArrayMap<String, ArraySet<String>> map, + String pkg, String key) { final boolean found; - final ArraySet<String> keys = mNotifications.get(pkg); + final ArraySet<String> keys = map.get(pkg); if (keys == null) { found = false; } else { found = keys.remove(key); if (keys.size() == 0) { - mNotifications.remove(pkg); + map.remove(pkg); } } return found; } + public boolean isDungeonNeeded() { if (mRunning != null && System.currentTimeMillis() - mServiceStartTime >= FG_SERVICE_GRACE_MILLIS) { for (String pkg : mRunning) { - final ArraySet<String> set = mNotifications.get(pkg); + final ArraySet<String> set = mImportantNotifications.get(pkg); if (set == null || set.size() == 0) { return true; } @@ -160,5 +278,27 @@ public class ForegroundServiceControllerImpl } return false; } + + public ArraySet<Integer> getFeatures(String pkg) { + return mAppOps.get(pkg); + } + + public String getStandardLayoutKey(String pkg) { + final ArraySet<String> set = mStandardLayoutNotifications.get(pkg); + if (set == null || set.size() == 0) { + return null; + } + return set.valueAt(0); + } + + @Override + public String toString() { + return "UserServices{" + + "mRunning=" + Arrays.toString(mRunning) + + ", mServiceStartTime=" + mServiceStartTime + + ", mImportantNotifications=" + mImportantNotifications + + ", mStandardLayoutNotifications=" + mStandardLayoutNotifications + + '}'; + } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index 47b0de94f133..df4a975cb0a8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -449,7 +449,7 @@ public class Recents extends SystemUI final int activityType = runningTask != null ? runningTask.configuration.windowConfiguration.getActivityType() : ACTIVITY_TYPE_UNDEFINED; - boolean screenPinningActive = ActivityManagerWrapper.getInstance().isLockToAppActive(); + boolean screenPinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive(); boolean isRunningTaskInHomeOrRecentsStack = activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS; if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 3f6f30bba8c4..055e72e2f8fb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -24,7 +24,6 @@ import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASO import android.app.ActivityManager; import android.app.ActivityOptions; -import android.app.KeyguardManager; import android.app.trust.TrustManager; import android.content.ActivityNotFoundException; import android.content.Context; @@ -34,7 +33,6 @@ import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; -import android.os.AsyncTask.Status; import android.os.Handler; import android.os.SystemClock; import android.util.ArraySet; @@ -385,8 +383,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void toggleRecents(int growTarget) { - // Skip preloading if the task is locked - if (ActivityManagerWrapper.getInstance().isLockToAppActive()) { + if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) { return; } @@ -464,8 +461,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void preloadRecents() { - // Skip preloading if the task is locked - if (ActivityManagerWrapper.getInstance().isLockToAppActive()) { + if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 3cc3273c0db4..89288d84aceb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -2188,7 +2188,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal private void readSystemFlags() { SystemServicesProxy ssp = Recents.getSystemServices(); mTouchExplorationEnabled = ssp.isTouchExplorationEnabled(); - mScreenPinningEnabled = ActivityManagerWrapper.getInstance().isLockToAppEnabled(); + mScreenPinningEnabled = ActivityManagerWrapper.getInstance().isScreenPinningEnabled() + && !ActivityManagerWrapper.getInstance().isLockToAppActive(); } private void updateStackActionButtonVisibility() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java new file mode 100644 index 000000000000..2ec78cfe9382 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar; + +import android.app.AppOpsManager; +import android.content.Context; + +import com.android.systemui.Dependency; +import com.android.systemui.ForegroundServiceController; + +/** + * This class handles listening to notification updates and passing them along to + * NotificationPresenter to be displayed to the user. + */ +public class AppOpsListener implements AppOpsManager.OnOpActiveChangedListener { + private static final String TAG = "NotificationListener"; + + // Dependencies: + private final ForegroundServiceController mFsc = + Dependency.get(ForegroundServiceController.class); + + private final Context mContext; + protected NotificationPresenter mPresenter; + protected NotificationEntryManager mEntryManager; + protected final AppOpsManager mAppOps; + + protected static final int[] OPS = new int[] {AppOpsManager.OP_CAMERA, + AppOpsManager.OP_SYSTEM_ALERT_WINDOW, + AppOpsManager.OP_RECORD_AUDIO}; + + public AppOpsListener(Context context) { + mContext = context; + mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + } + + public void setUpWithPresenter(NotificationPresenter presenter, + NotificationEntryManager entryManager) { + mPresenter = presenter; + mEntryManager = entryManager; + mAppOps.startWatchingActive(OPS, this); + } + + public void destroy() { + mAppOps.stopWatchingActive(this); + } + + @Override + public void onOpActiveChanged(int code, int uid, String packageName, boolean active) { + mFsc.onAppOpChanged(code, uid, packageName, active); + mPresenter.getHandler().post(() -> { + mEntryManager.updateNotificationsForAppOps(code, uid, packageName, active); + }); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index bc2dff917b9a..785fc1cc5922 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -36,6 +36,7 @@ import android.os.Build; import android.os.Bundle; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; +import android.util.ArraySet; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.MathUtils; @@ -1354,6 +1355,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mHelperButton.setVisibility(show ? View.VISIBLE : View.GONE); } + public void showAppOpsIcons(ArraySet<Integer> activeOps) { + if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() != null) { + mChildrenContainer.getHeaderView().showAppOpsIcons(activeOps); + } + mPrivateLayout.showAppOpsIcons(activeOps); + mPublicLayout.showAppOpsIcons(activeOps); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -2629,6 +2638,16 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mChildrenContainer = childrenContainer; } + @VisibleForTesting + protected void setPrivateLayout(NotificationContentView privateLayout) { + mPrivateLayout = privateLayout; + } + + @VisibleForTesting + protected void setPublicLayout(NotificationContentView publicLayout) { + mPublicLayout = publicLayout; + } + /** * Equivalent to View.OnLongClickListener with coordinates */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 91960df9b01d..73c87953cf45 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -23,6 +23,7 @@ import android.content.Context; import android.graphics.Rect; import android.os.Build; import android.service.notification.StatusBarNotification; +import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; import android.view.NotificationHeaderView; @@ -1423,6 +1424,17 @@ public class NotificationContentView extends FrameLayout { return header; } + public void showAppOpsIcons(ArraySet<Integer> activeOps) { + if (mContractedChild != null && mContractedWrapper.getNotificationHeader() != null) { + mContractedWrapper.getNotificationHeader().showAppOpsIcons(activeOps); + } + if (mExpandedChild != null && mExpandedWrapper.getNotificationHeader() != null) { + mExpandedWrapper.getNotificationHeader().showAppOpsIcons(activeOps); + } + if (mHeadsUpChild != null && mHeadsUpWrapper.getNotificationHeader() != null) { + mHeadsUpWrapper.getNotificationHeader().showAppOpsIcons(activeOps); + } + } public NotificationHeaderView getContractedNotificationHeader() { if (mContractedChild != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 127f3f918fba..d53cb03cfcb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar; import android.app.AppGlobals; +import android.app.AppOpsManager; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -34,6 +35,7 @@ import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; +import android.util.ArraySet; import android.view.View; import android.widget.ImageView; import android.widget.RemoteViews; @@ -65,6 +67,8 @@ public class NotificationData { private final Environment mEnvironment; private HeadsUpManager mHeadsUpManager; + final ForegroundServiceController mFsc = Dependency.get(ForegroundServiceController.class); + public static final class Entry { private static final long LAUNCH_COOLDOWN = 2000; private static final long REMOTE_INPUT_COOLDOWN = 500; @@ -95,6 +99,7 @@ public class NotificationData { private Throwable mDebugThrowable; public CharSequence remoteInputTextWhenReset; public long lastRemoteInputSent = NOT_LAUNCHED_YET; + public ArraySet<Integer> mActiveAppOps = new ArraySet<>(3); public Entry(StatusBarNotification n) { this.key = n.getKey(); @@ -194,7 +199,7 @@ public class NotificationData { /** * Update the notification icons. * @param context the context to create the icons with. - * @param n the notification to read the icon from. + * @param sbn the notification to read the icon from. * @throws InflationException */ public void updateIcons(Context context, StatusBarNotification sbn) @@ -375,6 +380,8 @@ public class NotificationData { } mGroupManager.onEntryAdded(entry); + updateAppOps(entry); + updateRankingAndSort(mRankingMap); } @@ -393,6 +400,35 @@ public class NotificationData { updateRankingAndSort(ranking); } + private void updateAppOps(Entry entry) { + final int uid = entry.notification.getUid(); + final String pkg = entry.notification.getPackageName(); + ArraySet<Integer> activeOps = mFsc.getAppOps(entry.notification.getUserId(), pkg); + if (activeOps != null) { + int N = activeOps.size(); + for (int i = 0; i < N; i++) { + updateAppOp(activeOps.valueAt(i), uid, pkg, true); + } + } + } + + public void updateAppOp(int appOp, int uid, String pkg, boolean showIcon) { + synchronized (mEntries) { + final int N = mEntries.size(); + for (int i = 0; i < N; i++) { + Entry entry = mEntries.valueAt(i); + if (uid == entry.notification.getUid() + && pkg.equals(entry.notification.getPackageName())) { + if (showIcon) { + entry.mActiveAppOps.add(appOp); + } else { + entry.mActiveAppOps.remove(appOp); + } + } + } + } + } + public boolean isAmbient(String key) { if (mRankingMap != null) { getRanking(key, mTmpRanking); @@ -545,11 +581,14 @@ public class NotificationData { return true; } - final ForegroundServiceController fsc = Dependency.get(ForegroundServiceController.class); - if (fsc.isDungeonNotification(sbn) && !fsc.isDungeonNeededForUser(sbn.getUserId())) { + if (mFsc.isDungeonNotification(sbn) && !mFsc.isDungeonNeededForUser(sbn.getUserId())) { // this is a foreground-service disclosure for a user that does not need to show one return true; } + if (mFsc.isSystemAlertNotification(sbn) && !mFsc.isSystemAlertWarningNeeded( + sbn.getUserId(), sbn.getPackageName())) { + return true; + } return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java index 7360486ac7e9..71f7911b41f1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java @@ -31,6 +31,7 @@ import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.UserHandle; import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationStats; @@ -77,7 +78,7 @@ import java.util.List; public class NotificationEntryManager implements Dumpable, NotificationInflater.InflationCallback, ExpandableNotificationRow.ExpansionLogger, NotificationUpdateHandler, VisualStabilityManager.Callback { - private static final String TAG = "NotificationEntryManager"; + private static final String TAG = "NotificationEntryMgr"; protected static final boolean DEBUG = false; protected static final boolean ENABLE_HEADS_UP = true; protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up"; @@ -734,6 +735,14 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. } } + public void updateNotificationsForAppOps(int appOp, int uid, String pkg, boolean showIcon) { + if (mForegroundServiceController.getStandardLayoutKey( + UserHandle.getUserId(uid), pkg) != null) { + mNotificationData.updateAppOp(appOp, uid, pkg, showIcon); + updateNotifications(); + } + } + private boolean alertAgain(NotificationData.Entry oldEntry, Notification newNotification) { return oldEntry == null || !oldEntry.hasInterrupted() || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index cd4c7ae8d57e..75b8b371119e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -342,6 +342,8 @@ public class NotificationViewHierarchyManager { row.showBlockingHelper(entry.userSentiment == NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE); + + row.showAppOpsIcons(entry.mActiveAppOps); } mPresenter.onUpdateRowStates(); 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 aba5cdf0ca2b..d2cdc27d982c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.support.v4.util.ArraySet; import android.util.Log; @@ -32,6 +33,7 @@ import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; @@ -45,12 +47,12 @@ import java.util.Stack; */ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, ViewTreeObserver.OnComputeInternalInsetsListener, VisualStabilityManager.Callback, - OnHeadsUpChangedListener { + OnHeadsUpChangedListener, ConfigurationController.ConfigurationListener { private static final String TAG = "HeadsUpManagerPhone"; private static final boolean DEBUG = false; private final View mStatusBarWindowView; - private final int mStatusBarHeight; + private int mStatusBarHeight; private final NotificationGroupManager mGroupManager; private final StatusBar mBar; private final VisualStabilityManager mVisualStabilityManager; @@ -291,6 +293,13 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, } } + @Override + public void onConfigChanged(Configuration newConfig) { + Resources resources = mContext.getResources(); + mStatusBarHeight = resources.getDimensionPixelSize( + com.android.internal.R.dimen.status_bar_height); + } + /////////////////////////////////////////////////////////////////////////////////////////////// // VisualStabilityManager.Callback overrides: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index 62151cfa258b..0ed69e66b03e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -708,7 +708,8 @@ public class NavigationBarFragment extends Fragment implements Callbacks { @VisibleForTesting boolean onHomeLongClick(View v) { - if (!mNavigationBarView.isRecentsButtonVisible() && mNavigationBarView.inScreenPinning()) { + if (!mNavigationBarView.isRecentsButtonVisible() + && ActivityManagerWrapper.getInstance().isScreenPinningActive()) { return onLongPressBackHome(v); } if (shouldDisableNavbarGestures()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java index 320b56f98c85..a4daed92cabf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java @@ -43,6 +43,7 @@ import com.android.systemui.RecentsComponent; import com.android.systemui.SysUiServiceProvider; import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper; import com.android.systemui.shared.recents.IOverviewProxy; +import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.stackdivider.Divider; import com.android.systemui.tuner.TunerService; @@ -149,7 +150,8 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture } public boolean onInterceptTouchEvent(MotionEvent event) { - if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing()) { + if (ActivityManagerWrapper.getInstance().isScreenPinningActive() + || mStatusBar.isKeyguardShowing()) { return false; } @@ -182,7 +184,8 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture } public boolean onTouchEvent(MotionEvent event) { - if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing()) { + if (ActivityManagerWrapper.getInstance().isScreenPinningActive() + || mStatusBar.isKeyguardShowing()) { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index a5621e5a4010..74fbed1b0da7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -21,8 +21,6 @@ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.animation.LayoutTransition.TransitionListener; import android.animation.ObjectAnimator; @@ -30,7 +28,6 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.DrawableRes; import android.annotation.StyleRes; -import android.app.ActivityManager; import android.app.StatusBarManager; import android.content.Context; import android.content.res.Configuration; @@ -41,7 +38,6 @@ import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; -import android.os.RemoteException; import android.os.SystemProperties; import android.support.annotation.ColorInt; import android.util.AttributeSet; @@ -60,7 +56,6 @@ import android.widget.FrameLayout; import com.android.settingslib.Utils; import com.android.systemui.Dependency; import com.android.systemui.DockedStackExistsListener; -import com.android.systemui.Interpolators; import com.android.systemui.OverviewProxyService; import com.android.systemui.R; import com.android.systemui.RecentsComponent; @@ -379,15 +374,20 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav return getRecentsButton().getVisibility() == View.VISIBLE; } + public boolean isOverviewEnabled() { + return (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) == 0; + } + public boolean isQuickStepSwipeUpEnabled() { return mOverviewProxyService.getProxy() != null + && isOverviewEnabled() && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_SWIPE_UP) == 0); } public boolean isQuickScrubEnabled() { return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true) - && mOverviewProxyService.getProxy() != null && !isRecentsButtonVisible() + && mOverviewProxyService.getProxy() != null && isOverviewEnabled() && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0); } @@ -575,8 +575,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0); // Always disable recents when alternate car mode UI is active. - boolean disableRecent = mUseCarModeUi - || ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0); + boolean disableRecent = mUseCarModeUi || !isOverviewEnabled(); boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0); @@ -584,17 +583,18 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav // When screen pinning, don't hide back and home when connected service or back and // recents buttons when disconnected from launcher service in screen pinning mode, // as they are used for exiting. + final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive(); if (mOverviewProxyService.getProxy() != null) { // Use interaction flags to show/hide navigation buttons but will be shown if required // to exit screen pinning. final int flags = mOverviewProxyService.getInteractionFlags(); disableRecent |= (flags & FLAG_SHOW_OVERVIEW_BUTTON) == 0; - if (inScreenPinning()) { + if (pinningActive) { disableBack = disableHome = false; } else { disableBack |= (flags & FLAG_HIDE_BACK_BUTTON) != 0; } - } else if (inScreenPinning()) { + } else if (pinningActive) { disableBack = disableRecent = false; } @@ -614,7 +614,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } public boolean inScreenPinning() { - return ActivityManagerWrapper.getInstance().isLockToAppActive(); + return ActivityManagerWrapper.getInstance().isScreenPinningActive(); } public void setLayoutTransitionsEnabled(boolean enabled) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index cc5a93ce71b6..900ec0be4b54 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -264,7 +264,7 @@ public class PhoneStatusBarView extends PanelBar { mScrimController.setPanelExpansion(scrimFraction); } - public void onDensityOrFontScaleChanged() { + public void updateResources() { ViewGroup.LayoutParams layoutParams = getLayoutParams(); layoutParams.height = getResources().getDimensionPixelSize( R.dimen.status_bar_height); 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 2afd05f18f7a..86e618e4690c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -180,6 +180,7 @@ import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.stackdivider.Divider; import com.android.systemui.stackdivider.WindowManagerProxy; import com.android.systemui.statusbar.ActivatableNotificationView; +import com.android.systemui.statusbar.AppOpsListener; import com.android.systemui.statusbar.BackDropView; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CrossFadeHelper; @@ -405,6 +406,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected NotificationLogger mNotificationLogger; protected NotificationEntryManager mEntryManager; protected NotificationViewHierarchyManager mViewHierarchyManager; + protected AppOpsListener mAppOpsListener; /** * Helper that is responsible for showing the right toast when a disallowed activity operation @@ -622,6 +624,8 @@ public class StatusBar extends SystemUI implements DemoMode, mMediaManager = Dependency.get(NotificationMediaManager.class); mEntryManager = Dependency.get(NotificationEntryManager.class); mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class); + mAppOpsListener = Dependency.get(AppOpsListener.class); + mAppOpsListener.setUpWithPresenter(this, mEntryManager); mColorExtractor = Dependency.get(SysuiColorExtractor.class); mColorExtractor.addOnColorsChangedListener(this); @@ -813,6 +817,7 @@ public class StatusBar extends SystemUI implements DemoMode, mHeadsUpManager = new HeadsUpManagerPhone(context, mStatusBarWindow, mGroupManager, this, mVisualStabilityManager); + Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager); mHeadsUpManager.addListener(this); mHeadsUpManager.addListener(mNotificationPanel); mHeadsUpManager.addListener(mGroupManager); @@ -1069,7 +1074,6 @@ public class StatusBar extends SystemUI implements DemoMode, // end old BaseStatusBar.onDensityOrFontScaleChanged(). mScrimController.onDensityOrFontScaleChanged(); // TODO: Remove this. - if (mStatusBarView != null) mStatusBarView.onDensityOrFontScaleChanged(); if (mBrightnessMirrorController != null) { mBrightnessMirrorController.onDensityOrFontScaleChanged(); } @@ -3079,6 +3083,9 @@ public class StatusBar extends SystemUI implements DemoMode, loadDimens(); + if (mStatusBarView != null) { + mStatusBarView.updateResources(); + } if (mNotificationPanel != null) { mNotificationPanel.updateResources(); } @@ -3293,6 +3300,7 @@ public class StatusBar extends SystemUI implements DemoMode, Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null); mDeviceProvisionedController.removeCallback(mUserSetupObserver); Dependency.get(ConfigurationController.class).removeCallback(this); + mAppOpsListener.destroy(); } private boolean mDemoModeAllowed; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 1b55a5b0325f..66fde7986b00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -1394,6 +1394,7 @@ public class NotificationStackScrollLayout extends ViewGroup @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); + mStatusBarHeight = getResources().getDimensionPixelOffset(R.dimen.status_bar_height); float densityScale = getResources().getDisplayMetrics().density; mSwipeHelper.setDensityScale(densityScale); float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index 943020c7b28e..18dd3c734660 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -16,6 +16,14 @@ package com.android.systemui; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.annotation.UserIdInt; import android.app.Notification; import android.app.NotificationManager; @@ -24,17 +32,14 @@ import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import android.widget.RemoteViews; + import com.android.internal.messages.nano.SystemMessageProto; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - @SmallTest @RunWith(AndroidJUnit4.class) public class ForegroundServiceControllerTest extends SysuiTestCase { @@ -49,7 +54,7 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { } @Test - public void testNotificationCRUD() { + public void testNotificationCRUD_dungeon() { StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, "com.example.app1"); StatusBarNotification sbn_user2_app2_fg = makeMockFgSBN(USERID_TWO, "com.example.app2"); StatusBarNotification sbn_user1_app3_fg = makeMockFgSBN(USERID_ONE, "com.example.app3"); @@ -98,6 +103,101 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { } @Test + public void testNotificationCRUD_stdLayout() { + StatusBarNotification sbn_user1_app1_fg = + makeMockFgSBN(USERID_ONE, "com.example.app1", 0, true); + StatusBarNotification sbn_user2_app2_fg = + makeMockFgSBN(USERID_TWO, "com.example.app2", 1, true); + StatusBarNotification sbn_user1_app3_fg = + makeMockFgSBN(USERID_ONE, "com.example.app3", 2, true); + StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1", + 5000, "monkeys", Notification.FLAG_AUTO_CANCEL); + StatusBarNotification sbn_user2_app1 = makeMockSBN(USERID_TWO, "com.example.app1", + 5000, "monkeys", Notification.FLAG_AUTO_CANCEL); + + assertFalse(fsc.removeNotification(sbn_user1_app3_fg)); + assertFalse(fsc.removeNotification(sbn_user2_app2_fg)); + assertFalse(fsc.removeNotification(sbn_user1_app1_fg)); + assertFalse(fsc.removeNotification(sbn_user1_app1)); + assertFalse(fsc.removeNotification(sbn_user2_app1)); + + fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN); + fsc.addNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_MIN); + fsc.addNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_MIN); + fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_MIN); + fsc.addNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_MIN); + + // these are never added to the tracker + assertFalse(fsc.removeNotification(sbn_user1_app1)); + assertFalse(fsc.removeNotification(sbn_user2_app1)); + + fsc.updateNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_MIN); + fsc.updateNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_MIN); + // should still not be there + assertFalse(fsc.removeNotification(sbn_user1_app1)); + assertFalse(fsc.removeNotification(sbn_user2_app1)); + + fsc.updateNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_MIN); + fsc.updateNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_MIN); + fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN); + + assertTrue(fsc.removeNotification(sbn_user1_app3_fg)); + assertFalse(fsc.removeNotification(sbn_user1_app3_fg)); + + assertTrue(fsc.removeNotification(sbn_user2_app2_fg)); + assertFalse(fsc.removeNotification(sbn_user2_app2_fg)); + + assertTrue(fsc.removeNotification(sbn_user1_app1_fg)); + assertFalse(fsc.removeNotification(sbn_user1_app1_fg)); + + assertFalse(fsc.removeNotification(sbn_user1_app1)); + assertFalse(fsc.removeNotification(sbn_user2_app1)); + } + + @Test + public void testAppOpsCRUD() { + // no crash on remove that doesn't exist + fsc.onAppOpChanged(9, 1000, "pkg1", false); + assertNull(fsc.getAppOps(0, "pkg1")); + + // multiuser & multipackage + fsc.onAppOpChanged(8, 50, "pkg1", true); + fsc.onAppOpChanged(1, 60, "pkg3", true); + fsc.onAppOpChanged(7, 500000, "pkg2", true); + + assertEquals(1, fsc.getAppOps(0, "pkg1").size()); + assertTrue(fsc.getAppOps(0, "pkg1").contains(8)); + + assertEquals(1, fsc.getAppOps(UserHandle.getUserId(500000), "pkg2").size()); + assertTrue(fsc.getAppOps(UserHandle.getUserId(500000), "pkg2").contains(7)); + + assertEquals(1, fsc.getAppOps(0, "pkg3").size()); + assertTrue(fsc.getAppOps(0, "pkg3").contains(1)); + + // multiple ops for the same package + fsc.onAppOpChanged(9, 50, "pkg1", true); + fsc.onAppOpChanged(5, 50, "pkg1", true); + + assertEquals(3, fsc.getAppOps(0, "pkg1").size()); + assertTrue(fsc.getAppOps(0, "pkg1").contains(8)); + assertTrue(fsc.getAppOps(0, "pkg1").contains(9)); + assertTrue(fsc.getAppOps(0, "pkg1").contains(5)); + + assertEquals(1, fsc.getAppOps(UserHandle.getUserId(500000), "pkg2").size()); + assertTrue(fsc.getAppOps(UserHandle.getUserId(500000), "pkg2").contains(7)); + + // remove one of the multiples + fsc.onAppOpChanged(9, 50, "pkg1", false); + assertEquals(2, fsc.getAppOps(0, "pkg1").size()); + assertTrue(fsc.getAppOps(0, "pkg1").contains(8)); + assertTrue(fsc.getAppOps(0, "pkg1").contains(5)); + + // remove last op + fsc.onAppOpChanged(1, 60, "pkg3", false); + assertNull(fsc.getAppOps(0, "pkg3")); + } + + @Test public void testDungeonPredicate() { StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1", 5000, "monkeys", Notification.FLAG_AUTO_CANCEL); @@ -252,6 +352,14 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { assertFalse(fsc.isDungeonNeededForUser(USERID_TWO)); assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); + // importance upgrade + fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN); + assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); + assertFalse(fsc.isDungeonNeededForUser(USERID_TWO)); + sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + fsc.updateNotification(sbn_user1_app1_fg, + NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification + // finally, let's turn off the service fsc.addNotification(makeMockDungeon(USERID_ONE, null), NotificationManager.IMPORTANCE_DEFAULT); @@ -260,12 +368,71 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { assertFalse(fsc.isDungeonNeededForUser(USERID_TWO)); } + @Test + public void testStdLayoutBasic() { + final String PKG1 = "com.example.app0"; + + StatusBarNotification sbn_user1_app1 = makeMockFgSBN(USERID_ONE, PKG1, 0, true); + sbn_user1_app1.getNotification().flags = 0; + StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1, 1, true); + fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_MIN); // not fg + assertTrue(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required! + fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN); + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // app1 has got it covered + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, "otherpkg")); + // let's take out the non-fg notification and see what happens. + fsc.removeNotification(sbn_user1_app1); + // still covered by sbn_user1_app1_fg + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, "anyPkg")); + + // let's attempt to downgrade the notification from FLAG_FOREGROUND and see what we get + StatusBarNotification sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1, 1, true); + sbn_user1_app1_fg_sneaky.getNotification().flags = 0; + fsc.updateNotification(sbn_user1_app1_fg_sneaky, NotificationManager.IMPORTANCE_MIN); + assertTrue(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required! + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, "anything")); + // ok, ok, we'll put it back + sbn_user1_app1_fg_sneaky.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE; + fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN); + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, "whatever")); + + assertTrue(fsc.removeNotification(sbn_user1_app1_fg_sneaky)); + assertTrue(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required! + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, "a")); + + // let's try a custom layout + sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1, 1, false); + fsc.updateNotification(sbn_user1_app1_fg_sneaky, NotificationManager.IMPORTANCE_MIN); + assertTrue(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required! + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, "anything")); + // now let's test an upgrade (non fg to fg) + fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_MIN); + assertTrue(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, "b")); + sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + fsc.updateNotification(sbn_user1_app1, + NotificationManager.IMPORTANCE_MIN); // this is now a fg notification + + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, PKG1)); + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); + + // remove it, make sure we're out of compliance again + assertTrue(fsc.removeNotification(sbn_user1_app1)); // was fg, should return true + assertFalse(fsc.removeNotification(sbn_user1_app1)); + assertFalse(fsc.isSystemAlertWarningNeeded(USERID_TWO, PKG1)); + assertTrue(fsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); + } + private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag, int flags) { final Notification n = mock(Notification.class); + n.extras = new Bundle(); n.flags = flags; return makeMockSBN(userid, pkg, id, tag, n); } + private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag, Notification n) { final StatusBarNotification sbn = mock(StatusBarNotification.class); @@ -278,9 +445,25 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { when(sbn.getKey()).thenReturn("MOCK:"+userid+"|"+pkg+"|"+id+"|"+tag); return sbn; } + + private StatusBarNotification makeMockFgSBN(int userid, String pkg, int id, + boolean usesStdLayout) { + StatusBarNotification sbn = + makeMockSBN(userid, pkg, id, "foo", Notification.FLAG_FOREGROUND_SERVICE); + if (usesStdLayout) { + sbn.getNotification().contentView = null; + sbn.getNotification().headsUpContentView = null; + sbn.getNotification().bigContentView = null; + } else { + sbn.getNotification().contentView = mock(RemoteViews.class); + } + return sbn; + } + private StatusBarNotification makeMockFgSBN(int userid, String pkg) { return makeMockSBN(userid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE); } + private StatusBarNotification makeMockDungeon(int userid, String[] pkgs) { final Notification n = mock(Notification.class); n.flags = Notification.FLAG_ONGOING_EVENT; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java new file mode 100644 index 000000000000..2a48c4b67e0e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.AppOpsManager; +import android.os.Handler; +import android.os.Looper; +import android.support.test.filters.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import com.android.systemui.ForegroundServiceController; +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class AppOpsListenerTest extends SysuiTestCase { + private static final String TEST_PACKAGE_NAME = "test"; + private static final int TEST_UID = 0; + + @Mock private NotificationPresenter mPresenter; + @Mock private AppOpsManager mAppOpsManager; + + // Dependency mocks: + @Mock private NotificationEntryManager mEntryManager; + @Mock private ForegroundServiceController mFsc; + + private AppOpsListener mListener; + private Handler mHandler; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); + mDependency.injectTestDependency(ForegroundServiceController.class, mFsc); + getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager); + mHandler = new Handler(Looper.getMainLooper()); + when(mPresenter.getHandler()).thenReturn(mHandler); + + mListener = new AppOpsListener(mContext); + } + + @Test + public void testOnlyListenForFewOps() { + mListener.setUpWithPresenter(mPresenter, mEntryManager); + + verify(mAppOpsManager, times(1)).startWatchingActive(AppOpsListener.OPS, mListener); + } + + @Test + public void testStopListening() { + mListener.destroy(); + verify(mAppOpsManager, times(1)).stopWatchingActive(mListener); + } + + @Test + public void testInformEntryMgrOnAppOpsChange() { + mListener.setUpWithPresenter(mPresenter, mEntryManager); + mListener.onOpActiveChanged( + AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true); + waitForIdleSync(mHandler); + verify(mEntryManager, times(1)).updateNotificationsForAppOps( + AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true); + } + + @Test + public void testInformFscOnAppOpsChange() { + mListener.setUpWithPresenter(mPresenter, mEntryManager); + mListener.onOpActiveChanged( + AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true); + waitForIdleSync(mHandler); + verify(mFsc, times(1)).onAppOpChanged( + AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java index 544585a4a917..ce629bb41e7b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java @@ -19,10 +19,15 @@ package com.android.systemui.statusbar; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.app.AppOpsManager; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import android.util.ArraySet; +import android.view.NotificationHeaderView; import android.view.View; import com.android.systemui.SysuiTestCase; @@ -146,4 +151,34 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { Assert.assertTrue("Should always play sounds when not trusted.", mGroup.isSoundEffectsEnabled()); } + + @Test + public void testShowAppOpsIcons_noHeader() { + // public notification is custom layout - no header + mGroup.setSensitive(true, true); + mGroup.showAppOpsIcons(new ArraySet<>()); + } + + @Test + public void testShowAppOpsIcons_header() throws Exception { + NotificationHeaderView mockHeader = mock(NotificationHeaderView.class); + + NotificationContentView publicLayout = mock(NotificationContentView.class); + mGroup.setPublicLayout(publicLayout); + NotificationContentView privateLayout = mock(NotificationContentView.class); + mGroup.setPrivateLayout(privateLayout); + NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class); + when(mockContainer.getNotificationChildCount()).thenReturn(1); + when(mockContainer.getHeaderView()).thenReturn(mockHeader); + mGroup.setChildrenContainer(mockContainer); + + ArraySet<Integer> ops = new ArraySet<>(); + ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS); + mGroup.showAppOpsIcons(ops); + + verify(mockHeader, times(1)).showAppOpsIcons(ops); + verify(privateLayout, times(1)).showAppOpsIcons(ops); + verify(publicLayout, times(1)).showAppOpsIcons(ops); + + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java index 436849c9d700..1fb4c371a408 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java @@ -16,14 +16,23 @@ package com.android.systemui.statusbar; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.app.AppOpsManager; import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import android.util.ArraySet; +import android.view.NotificationHeaderView; import android.view.View; import com.android.systemui.SysuiTestCase; @@ -75,4 +84,35 @@ public class NotificationContentViewTest extends SysuiTestCase { mView.setHeadsUpAnimatingAway(true); Assert.assertFalse(mView.isAnimatingVisibleType()); } + + @Test + @UiThreadTest + public void testShowAppOpsIcons() { + NotificationHeaderView mockContracted = mock(NotificationHeaderView.class); + when(mockContracted.findViewById(com.android.internal.R.id.notification_header)) + .thenReturn(mockContracted); + NotificationHeaderView mockExpanded = mock(NotificationHeaderView.class); + when(mockExpanded.findViewById(com.android.internal.R.id.notification_header)) + .thenReturn(mockExpanded); + NotificationHeaderView mockHeadsUp = mock(NotificationHeaderView.class); + when(mockHeadsUp.findViewById(com.android.internal.R.id.notification_header)) + .thenReturn(mockHeadsUp); + NotificationHeaderView mockAmbient = mock(NotificationHeaderView.class); + when(mockAmbient.findViewById(com.android.internal.R.id.notification_header)) + .thenReturn(mockAmbient); + + mView.setContractedChild(mockContracted); + mView.setExpandedChild(mockExpanded); + mView.setHeadsUpChild(mockHeadsUp); + mView.setAmbientChild(mockAmbient); + + ArraySet<Integer> ops = new ArraySet<>(); + ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS); + mView.showAppOpsIcons(ops); + + verify(mockContracted, times(1)).showAppOpsIcons(ops); + verify(mockExpanded, times(1)).showAppOpsIcons(ops); + verify(mockAmbient, never()).showAppOpsIcons(ops); + verify(mockHeadsUp, times(1)).showAppOpsIcons(any()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java index 972eddb46901..b1e1c02a035f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java @@ -16,8 +16,16 @@ package com.android.systemui.statusbar; +import static android.app.AppOpsManager.OP_ACCEPT_HANDOVER; +import static android.app.AppOpsManager.OP_CAMERA; + +import static junit.framework.Assert.assertEquals; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -33,7 +41,9 @@ import android.service.notification.StatusBarNotification; import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import android.util.ArraySet; +import com.android.systemui.ForegroundServiceController; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.phone.NotificationGroupManager; @@ -41,6 +51,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidJUnit4.class) @@ -51,6 +63,10 @@ public class NotificationDataTest extends SysuiTestCase { private final StatusBarNotification mMockStatusBarNotification = mock(StatusBarNotification.class); + @Mock + ForegroundServiceController mFsc; + @Mock + NotificationData.Environment mEnvironment; private final IPackageManager mMockPackageManager = mock(IPackageManager.class); private NotificationData mNotificationData; @@ -58,6 +74,7 @@ public class NotificationDataTest extends SysuiTestCase { @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL); when(mMockPackageManager.checkUidPermission( @@ -69,9 +86,11 @@ public class NotificationDataTest extends SysuiTestCase { eq(UID_ALLOW_DURING_SETUP))) .thenReturn(PackageManager.PERMISSION_GRANTED); - NotificationData.Environment mock = mock(NotificationData.Environment.class); - when(mock.getGroupManager()).thenReturn(new NotificationGroupManager()); - mNotificationData = new TestableNotificationData(mock); + mDependency.injectTestDependency(ForegroundServiceController.class, mFsc); + when(mEnvironment.getGroupManager()).thenReturn(new NotificationGroupManager()); + when(mEnvironment.isDeviceProvisioned()).thenReturn(true); + when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true); + mNotificationData = new TestableNotificationData(mEnvironment); mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class)); mRow = new NotificationTestHelper(getContext()).createRow(); } @@ -117,6 +136,117 @@ public class NotificationDataTest extends SysuiTestCase { Assert.assertTrue(mRow.getEntry().channel != null); } + @Test + public void testAdd_appOpsAdded() { + ArraySet<Integer> expected = new ArraySet<>(); + expected.add(3); + expected.add(235); + expected.add(1); + when(mFsc.getAppOps(mRow.getEntry().notification.getUserId(), + mRow.getEntry().notification.getPackageName())).thenReturn(expected); + + mNotificationData.add(mRow.getEntry()); + assertEquals(expected.size(), + mNotificationData.get(mRow.getEntry().key).mActiveAppOps.size()); + for (int op : expected) { + assertTrue(" entry missing op " + op, + mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(op)); + } + } + + @Test + public void testAdd_noExistingAppOps() { + when(mFsc.getAppOps(mRow.getEntry().notification.getUserId(), + mRow.getEntry().notification.getPackageName())).thenReturn(null); + + mNotificationData.add(mRow.getEntry()); + assertEquals(0, mNotificationData.get(mRow.getEntry().key).mActiveAppOps.size()); + } + + @Test + public void testAllRelevantNotisTaggedWithAppOps() throws Exception { + mNotificationData.add(mRow.getEntry()); + ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow(); + mNotificationData.add(row2.getEntry()); + ExpandableNotificationRow diffPkg = + new NotificationTestHelper(getContext()).createRow("pkg", 4000); + mNotificationData.add(diffPkg.getEntry()); + + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + expectedOps.add(OP_ACCEPT_HANDOVER); + + for (int op : expectedOps) { + mNotificationData.updateAppOp(op, NotificationTestHelper.UID, + NotificationTestHelper.PKG, true); + } + for (int op : expectedOps) { + assertTrue(mRow.getEntry().key + " doesn't have op " + op, + mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(op)); + assertTrue(row2.getEntry().key + " doesn't have op " + op, + mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(op)); + assertFalse(diffPkg.getEntry().key + " has op " + op, + mNotificationData.get(diffPkg.getEntry().key).mActiveAppOps.contains(op)); + } + } + + @Test + public void testAppOpsRemoval() throws Exception { + mNotificationData.add(mRow.getEntry()); + ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow(); + mNotificationData.add(row2.getEntry()); + + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + expectedOps.add(OP_ACCEPT_HANDOVER); + + for (int op : expectedOps) { + mNotificationData.updateAppOp(op, NotificationTestHelper.UID, + NotificationTestHelper.PKG, true); + } + + expectedOps.remove(OP_ACCEPT_HANDOVER); + mNotificationData.updateAppOp(OP_ACCEPT_HANDOVER, NotificationTestHelper.UID, + NotificationTestHelper.PKG, false); + + assertTrue(mRow.getEntry().key + " doesn't have op " + OP_CAMERA, + mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(OP_CAMERA)); + assertTrue(row2.getEntry().key + " doesn't have op " + OP_CAMERA, + mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(OP_CAMERA)); + assertFalse(mRow.getEntry().key + " has op " + OP_ACCEPT_HANDOVER, + mNotificationData.get(mRow.getEntry().key) + .mActiveAppOps.contains(OP_ACCEPT_HANDOVER)); + assertFalse(row2.getEntry().key + " has op " + OP_ACCEPT_HANDOVER, + mNotificationData.get(row2.getEntry().key) + .mActiveAppOps.contains(OP_ACCEPT_HANDOVER)); + } + + @Test + public void testSuppressSystemAlertNotification() { + when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false); + when(mFsc.isSystemAlertNotification(any())).thenReturn(true); + + assertTrue(mNotificationData.shouldFilterOut(mRow.getEntry().notification)); + } + + @Test + public void testDoNotSuppressSystemAlertNotification() { + when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true); + when(mFsc.isSystemAlertNotification(any())).thenReturn(true); + + assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry().notification)); + + when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true); + when(mFsc.isSystemAlertNotification(any())).thenReturn(false); + + assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry().notification)); + + when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false); + when(mFsc.isSystemAlertNotification(any())).thenReturn(false); + + assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry().notification)); + } + private void initStatusBarNotification(boolean allowDuringSetup) { Bundle bundle = new Bundle(); bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java index f9ec3f92181f..37dd939ea70a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java @@ -23,14 +23,17 @@ import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; +import android.app.AppOpsManager; import android.app.Notification; import android.app.NotificationManager; import android.content.Context; @@ -274,4 +277,40 @@ public class NotificationEntryManagerTest extends SysuiTestCase { assertNull(mEntryManager.getNotificationData().get(mSbn.getKey())); } + + @Test + public void testUpdateAppOps_foregroundNoti() { + com.android.systemui.util.Assert.isNotMainThread(); + + when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString())) + .thenReturn("something"); + mEntry.row = mRow; + mEntryManager.getNotificationData().add(mEntry); + + + mHandler.post(() -> { + mEntryManager.updateNotificationsForAppOps( + AppOpsManager.OP_CAMERA, mEntry.notification.getUid(), + mEntry.notification.getPackageName(), true); + }); + waitForIdleSync(mHandler); + + verify(mPresenter, times(1)).updateNotificationViews(); + assertTrue(mEntryManager.getNotificationData().get(mEntry.key).mActiveAppOps.contains( + AppOpsManager.OP_CAMERA)); + } + + @Test + public void testUpdateAppOps_otherNoti() { + com.android.systemui.util.Assert.isNotMainThread(); + + when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString())) + .thenReturn(null); + mHandler.post(() -> { + mEntryManager.updateNotificationsForAppOps(AppOpsManager.OP_CAMERA, 1000, "pkg", true); + }); + waitForIdleSync(mHandler); + + verify(mPresenter, never()).updateNotificationViews(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index f3c1171f650c..27642544c129 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -48,6 +48,8 @@ public class NotificationTestHelper { private ExpandableNotificationRow mRow; private InflationException mException; private HeadsUpManager mHeadsUpManager; + protected static final String PKG = "com.android.systemui"; + protected static final int UID = 1000; public NotificationTestHelper(Context context) { mContext = context; @@ -55,7 +57,7 @@ public class NotificationTestHelper { mHeadsUpManager = new HeadsUpManagerPhone(mContext, null, mGroupManager, null, null); } - public ExpandableNotificationRow createRow() throws Exception { + public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception { Notification publicVersion = new Notification.Builder(mContext).setSmallIcon( R.drawable.ic_person) .setCustomContentView(new RemoteViews(mContext.getPackageName(), @@ -67,10 +69,19 @@ public class NotificationTestHelper { .setContentText("Text") .setPublicVersion(publicVersion) .build(); - return createRow(notification); + return createRow(notification, pkg, uid); + } + + public ExpandableNotificationRow createRow() throws Exception { + return createRow(PKG, UID); } public ExpandableNotificationRow createRow(Notification notification) throws Exception { + return createRow(notification, PKG, UID); + } + + public ExpandableNotificationRow createRow(Notification notification, String pkg, int uid) + throws Exception { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( mContext.LAYOUT_INFLATER_SERVICE); mInstrumentation.runOnMainSync(() -> { @@ -83,8 +94,7 @@ public class NotificationTestHelper { row.setHeadsUpManager(mHeadsUpManager); row.setAboveShelfChangedListener(aboveShelf -> {}); UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser()); - StatusBarNotification sbn = new StatusBarNotification("com.android.systemui", - "com.android.systemui", mId++, null, 1000, + StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, mId++, null, uid, 2000, notification, mUser, null, System.currentTimeMillis()); NotificationData.Entry entry = new NotificationData.Entry(sbn); entry.row = row; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java index fbe730a64c6f..76ed45206dff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java @@ -19,6 +19,9 @@ package com.android.systemui.statusbar; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -170,6 +173,19 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { assertEquals(View.VISIBLE, entry1.row.getVisibility()); } + @Test + public void testUpdateNotificationViews_appOps() throws Exception { + NotificationData.Entry entry0 = createEntry(); + entry0.row = spy(entry0.row); + when(mNotificationData.getActiveNotifications()).thenReturn( + Lists.newArrayList(entry0)); + mListContainer.addContainerView(entry0.row); + + mViewHierarchyManager.updateNotificationViews(); + + verify(entry0.row, times(1)).showAppOpsIcons(any()); + } + private class FakeListContainer implements NotificationListContainer { final LinearLayout mLayout = new LinearLayout(mContext); final List<View> mRows = Lists.newArrayList(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 31442af5a04c..ff545f0bd653 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -69,6 +69,7 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.statusbar.ActivatableNotificationView; +import com.android.systemui.statusbar.AppOpsListener; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationData; @@ -145,6 +146,7 @@ public class StatusBarTest extends SysuiTestCase { mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager); mDependency.injectTestDependency(NotificationListener.class, mNotificationListener); mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class)); + mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class)); mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class)); mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class)); diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml index a584a7f3fb90..c22b2e778ff1 100644 --- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml @@ -46,7 +46,8 @@ <bool name="config_fillMainBuiltInDisplayCutout">true</bool> <!-- Height of the status bar --> - <dimen name="status_bar_height">48dp</dimen> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) --> <dimen name="quick_qs_offset_height">48dp</dimen> <!-- Total height of QQS (quick_qs_offset_height + 128) --> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml index 915e16412155..401e09211ae7 100644 --- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml @@ -46,7 +46,8 @@ <bool name="config_fillMainBuiltInDisplayCutout">true</bool> <!-- Height of the status bar --> - <dimen name="status_bar_height">48dp</dimen> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) --> <dimen name="quick_qs_offset_height">48dp</dimen> <!-- Total height of QQS (quick_qs_offset_height + 128) --> diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml index b8e29da8c8e7..f328b83c1cbf 100644 --- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml @@ -46,7 +46,8 @@ <bool name="config_fillMainBuiltInDisplayCutout">true</bool> <!-- Height of the status bar --> - <dimen name="status_bar_height">48dp</dimen> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) --> <dimen name="quick_qs_offset_height">48dp</dimen> <!-- Total height of QQS (quick_qs_offset_height + 128) --> diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index b897c7cc8873..6f31b0a22445 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -5343,6 +5343,11 @@ message MetricsEvent { // OS: P ACTION_BATTERY_TIP_SHOWN = 1324; + // OPEN: Settings > Security & Location > Location > See all + // CATEGORY: SETTINGS + // OS: P + RECENT_LOCATION_REQUESTS_ALL = 1325; + // ---- End P Constants, all P constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 62a7b8feb19e..d17ca7f9e77a 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -2191,42 +2191,42 @@ class AlarmManagerService extends SystemService { synchronized (mLock) { final long nowRTC = System.currentTimeMillis(); final long nowElapsed = SystemClock.elapsedRealtime(); - proto.write(AlarmManagerServiceProto.CURRENT_TIME, nowRTC); - proto.write(AlarmManagerServiceProto.ELAPSED_REALTIME, nowElapsed); - proto.write(AlarmManagerServiceProto.LAST_TIME_CHANGE_CLOCK_TIME, + proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC); + proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed); + proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME, mLastTimeChangeClockTime); - proto.write(AlarmManagerServiceProto.LAST_TIME_CHANGE_REALTIME, + proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_REALTIME, mLastTimeChangeRealtime); - mConstants.dumpProto(proto, AlarmManagerServiceProto.SETTINGS); + mConstants.dumpProto(proto, AlarmManagerServiceDumpProto.SETTINGS); if (mAppStateTracker != null) { mAppStateTracker.dumpProto(proto, - AlarmManagerServiceProto.FORCE_APP_STANDBY_TRACKER); + AlarmManagerServiceDumpProto.FORCE_APP_STANDBY_TRACKER); } - proto.write(AlarmManagerServiceProto.IS_INTERACTIVE, mInteractive); + proto.write(AlarmManagerServiceDumpProto.IS_INTERACTIVE, mInteractive); if (!mInteractive) { // Durations - proto.write(AlarmManagerServiceProto.TIME_SINCE_NON_INTERACTIVE_MS, + proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_NON_INTERACTIVE_MS, nowElapsed - mNonInteractiveStartTime); - proto.write(AlarmManagerServiceProto.MAX_WAKEUP_DELAY_MS, + proto.write(AlarmManagerServiceDumpProto.MAX_WAKEUP_DELAY_MS, currentNonWakeupFuzzLocked(nowElapsed)); - proto.write(AlarmManagerServiceProto.TIME_SINCE_LAST_DISPATCH_MS, + proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_DISPATCH_MS, nowElapsed - mLastAlarmDeliveryTime); - proto.write(AlarmManagerServiceProto.TIME_UNTIL_NEXT_NON_WAKEUP_DELIVERY_MS, + proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_DELIVERY_MS, nowElapsed - mNextNonWakeupDeliveryTime); } - proto.write(AlarmManagerServiceProto.TIME_UNTIL_NEXT_NON_WAKEUP_ALARM_MS, + proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_ALARM_MS, mNextNonWakeup - nowElapsed); - proto.write(AlarmManagerServiceProto.TIME_UNTIL_NEXT_WAKEUP_MS, + proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_WAKEUP_MS, mNextWakeup - nowElapsed); - proto.write(AlarmManagerServiceProto.TIME_SINCE_LAST_WAKEUP_MS, + proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_MS, nowElapsed - mLastWakeup); - proto.write(AlarmManagerServiceProto.TIME_SINCE_LAST_WAKEUP_SET_MS, + proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_SET_MS, nowElapsed - mLastWakeupSet); - proto.write(AlarmManagerServiceProto.TIME_CHANGE_EVENT_COUNT, mNumTimeChanged); + proto.write(AlarmManagerServiceDumpProto.TIME_CHANGE_EVENT_COUNT, mNumTimeChanged); final TreeSet<Integer> users = new TreeSet<>(); final int nextAlarmClockForUserSize = mNextAlarmClockForUser.size(); @@ -2242,14 +2242,14 @@ class AlarmManagerService extends SystemService { final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user); final long time = next != null ? next.getTriggerTime() : 0; final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user); - final long aToken = proto.start(AlarmManagerServiceProto.NEXT_ALARM_CLOCK_METADATA); + final long aToken = proto.start(AlarmManagerServiceDumpProto.NEXT_ALARM_CLOCK_METADATA); proto.write(AlarmClockMetadataProto.USER, user); proto.write(AlarmClockMetadataProto.IS_PENDING_SEND, pendingSend); proto.write(AlarmClockMetadataProto.TRIGGER_TIME_MS, time); proto.end(aToken); } for (Batch b : mAlarmBatches) { - b.writeToProto(proto, AlarmManagerServiceProto.PENDING_ALARM_BATCHES, + b.writeToProto(proto, AlarmManagerServiceDumpProto.PENDING_ALARM_BATCHES, nowElapsed, nowRTC); } for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) { @@ -2257,66 +2257,66 @@ class AlarmManagerService extends SystemService { if (blockedAlarms != null) { for (Alarm a : blockedAlarms) { a.writeToProto(proto, - AlarmManagerServiceProto.PENDING_USER_BLOCKED_BACKGROUND_ALARMS, + AlarmManagerServiceDumpProto.PENDING_USER_BLOCKED_BACKGROUND_ALARMS, nowElapsed, nowRTC); } } } if (mPendingIdleUntil != null) { mPendingIdleUntil.writeToProto( - proto, AlarmManagerServiceProto.PENDING_IDLE_UNTIL, nowElapsed, nowRTC); + proto, AlarmManagerServiceDumpProto.PENDING_IDLE_UNTIL, nowElapsed, nowRTC); } for (Alarm a : mPendingWhileIdleAlarms) { - a.writeToProto(proto, AlarmManagerServiceProto.PENDING_WHILE_IDLE_ALARMS, + a.writeToProto(proto, AlarmManagerServiceDumpProto.PENDING_WHILE_IDLE_ALARMS, nowElapsed, nowRTC); } if (mNextWakeFromIdle != null) { - mNextWakeFromIdle.writeToProto(proto, AlarmManagerServiceProto.NEXT_WAKE_FROM_IDLE, + mNextWakeFromIdle.writeToProto(proto, AlarmManagerServiceDumpProto.NEXT_WAKE_FROM_IDLE, nowElapsed, nowRTC); } for (Alarm a : mPendingNonWakeupAlarms) { - a.writeToProto(proto, AlarmManagerServiceProto.PAST_DUE_NON_WAKEUP_ALARMS, + a.writeToProto(proto, AlarmManagerServiceDumpProto.PAST_DUE_NON_WAKEUP_ALARMS, nowElapsed, nowRTC); } - proto.write(AlarmManagerServiceProto.DELAYED_ALARM_COUNT, mNumDelayedAlarms); - proto.write(AlarmManagerServiceProto.TOTAL_DELAY_TIME_MS, mTotalDelayTime); - proto.write(AlarmManagerServiceProto.MAX_DELAY_DURATION_MS, mMaxDelayTime); - proto.write(AlarmManagerServiceProto.MAX_NON_INTERACTIVE_DURATION_MS, + proto.write(AlarmManagerServiceDumpProto.DELAYED_ALARM_COUNT, mNumDelayedAlarms); + proto.write(AlarmManagerServiceDumpProto.TOTAL_DELAY_TIME_MS, mTotalDelayTime); + proto.write(AlarmManagerServiceDumpProto.MAX_DELAY_DURATION_MS, mMaxDelayTime); + proto.write(AlarmManagerServiceDumpProto.MAX_NON_INTERACTIVE_DURATION_MS, mNonInteractiveTime); - proto.write(AlarmManagerServiceProto.BROADCAST_REF_COUNT, mBroadcastRefCount); - proto.write(AlarmManagerServiceProto.PENDING_INTENT_SEND_COUNT, mSendCount); - proto.write(AlarmManagerServiceProto.PENDING_INTENT_FINISH_COUNT, mSendFinishCount); - proto.write(AlarmManagerServiceProto.LISTENER_SEND_COUNT, mListenerCount); - proto.write(AlarmManagerServiceProto.LISTENER_FINISH_COUNT, mListenerFinishCount); + proto.write(AlarmManagerServiceDumpProto.BROADCAST_REF_COUNT, mBroadcastRefCount); + proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_SEND_COUNT, mSendCount); + proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_FINISH_COUNT, mSendFinishCount); + proto.write(AlarmManagerServiceDumpProto.LISTENER_SEND_COUNT, mListenerCount); + proto.write(AlarmManagerServiceDumpProto.LISTENER_FINISH_COUNT, mListenerFinishCount); for (InFlight f : mInFlight) { - f.writeToProto(proto, AlarmManagerServiceProto.OUTSTANDING_DELIVERIES); + f.writeToProto(proto, AlarmManagerServiceDumpProto.OUTSTANDING_DELIVERIES); } for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) { final long token = proto.start( - AlarmManagerServiceProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES); + AlarmManagerServiceDumpProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES); final int uid = mLastAllowWhileIdleDispatch.keyAt(i); final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i); - proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.UID, uid); - proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime); - proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS, + proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.UID, uid); + proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime); + proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS, lastTime + getWhileIdleMinIntervalLocked(uid)); proto.end(token); } for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) { if (mUseAllowWhileIdleShortTime.valueAt(i)) { - proto.write(AlarmManagerServiceProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME, + proto.write(AlarmManagerServiceDumpProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME, mUseAllowWhileIdleShortTime.keyAt(i)); } } - mLog.writeToProto(proto, AlarmManagerServiceProto.RECENT_PROBLEMS); + mLog.writeToProto(proto, AlarmManagerServiceDumpProto.RECENT_PROBLEMS); final FilterStats[] topFilters = new FilterStats[10]; final Comparator<FilterStats> comparator = new Comparator<FilterStats>() { @@ -2357,13 +2357,13 @@ class AlarmManagerService extends SystemService { } } for (int i = 0; i < len; ++i) { - final long token = proto.start(AlarmManagerServiceProto.TOP_ALARMS); + final long token = proto.start(AlarmManagerServiceDumpProto.TOP_ALARMS); FilterStats fs = topFilters[i]; - proto.write(AlarmManagerServiceProto.TopAlarm.UID, fs.mBroadcastStats.mUid); - proto.write(AlarmManagerServiceProto.TopAlarm.PACKAGE_NAME, + proto.write(AlarmManagerServiceDumpProto.TopAlarm.UID, fs.mBroadcastStats.mUid); + proto.write(AlarmManagerServiceDumpProto.TopAlarm.PACKAGE_NAME, fs.mBroadcastStats.mPackageName); - fs.writeToProto(proto, AlarmManagerServiceProto.TopAlarm.FILTER); + fs.writeToProto(proto, AlarmManagerServiceDumpProto.TopAlarm.FILTER); proto.end(token); } @@ -2372,10 +2372,10 @@ class AlarmManagerService extends SystemService { for (int iu = 0; iu < mBroadcastStats.size(); ++iu) { ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu); for (int ip = 0; ip < uidStats.size(); ++ip) { - final long token = proto.start(AlarmManagerServiceProto.ALARM_STATS); + final long token = proto.start(AlarmManagerServiceDumpProto.ALARM_STATS); BroadcastStats bs = uidStats.valueAt(ip); - bs.writeToProto(proto, AlarmManagerServiceProto.AlarmStat.BROADCAST); + bs.writeToProto(proto, AlarmManagerServiceDumpProto.AlarmStat.BROADCAST); // uidStats is an ArrayMap, which we can't sort. tmpFilters.clear(); @@ -2384,7 +2384,7 @@ class AlarmManagerService extends SystemService { } Collections.sort(tmpFilters, comparator); for (FilterStats fs : tmpFilters) { - fs.writeToProto(proto, AlarmManagerServiceProto.AlarmStat.FILTERS); + fs.writeToProto(proto, AlarmManagerServiceDumpProto.AlarmStat.FILTERS); } proto.end(token); @@ -2395,7 +2395,7 @@ class AlarmManagerService extends SystemService { for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) { IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i); final long token = proto.start( - AlarmManagerServiceProto.ALLOW_WHILE_IDLE_DISPATCHES); + AlarmManagerServiceDumpProto.ALLOW_WHILE_IDLE_DISPATCHES); proto.write(IdleDispatchEntryProto.UID, ent.uid); proto.write(IdleDispatchEntryProto.PKG, ent.pkg); @@ -2411,7 +2411,7 @@ class AlarmManagerService extends SystemService { if (WAKEUP_STATS) { for (WakeupEvent event : mRecentWakeups) { - final long token = proto.start(AlarmManagerServiceProto.RECENT_WAKEUP_HISTORY); + final long token = proto.start(AlarmManagerServiceDumpProto.RECENT_WAKEUP_HISTORY); proto.write(WakeupEventProto.UID, event.uid); proto.write(WakeupEventProto.ACTION, event.action); proto.write(WakeupEventProto.WHEN, event.when); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 5fc43732b404..0c6746e15988 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3861,8 +3861,9 @@ public final class ActiveServices { return new ServiceDumper(fd, pw, args, opti, dumpAll, dumpPackage); } - protected void writeToProto(ProtoOutputStream proto) { + protected void writeToProto(ProtoOutputStream proto, long fieldId) { synchronized (mAm) { + final long outterToken = proto.start(fieldId); int[] users = mAm.mUserController.getUsers(); for (int user : users) { ServiceMap smap = mServiceMap.get(user); @@ -3878,6 +3879,7 @@ public final class ActiveServices { } proto.end(token); } + proto.end(outterToken); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f4b0dba9d860..28a79bdb79c8 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -440,15 +440,17 @@ import com.android.server.Watchdog; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.am.MemoryStatUtil.MemoryStat; import com.android.server.am.proto.ActivityManagerServiceProto; -import com.android.server.am.proto.BroadcastProto; +import com.android.server.am.proto.ActivityManagerServiceDumpActivitiesProto; +import com.android.server.am.proto.ActivityManagerServiceDumpBroadcastsProto; +import com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto; +import com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto; +import com.android.server.am.proto.ActivityManagerServiceDumpServicesProto; import com.android.server.am.proto.GrantUriProto; import com.android.server.am.proto.ImportanceTokenProto; -import com.android.server.am.proto.MemInfoProto; +import com.android.server.am.proto.MemInfoDumpProto; import com.android.server.am.proto.NeededUriGrantsProto; import com.android.server.am.proto.ProcessOomProto; import com.android.server.am.proto.ProcessToGcProto; -import com.android.server.am.proto.ProcessesProto; -import com.android.server.am.proto.ProcessesProto.UidObserverRegistrationProto; import com.android.server.am.proto.StickyBroadcastProto; import com.android.server.firewall.IntentFirewall; import com.android.server.job.JobSchedulerInternal; @@ -1376,9 +1378,9 @@ public class ActivityManagerService extends IActivityManager.Stub void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); - proto.write(ProcessesProto.PendingTempWhitelist.TARGET_UID, targetUid); - proto.write(ProcessesProto.PendingTempWhitelist.DURATION_MS, duration); - proto.write(ProcessesProto.PendingTempWhitelist.TAG, tag); + proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TARGET_UID, targetUid); + proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.DURATION_MS, duration); + proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TAG, tag); proto.end(token); } } @@ -12879,6 +12881,25 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public boolean isBackgroundRestricted(String packageName) { + final int callingUid = Binder.getCallingUid(); + final IPackageManager pm = AppGlobals.getPackageManager(); + try { + final int packageUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.getUserId(callingUid)); + if (packageUid != callingUid) { + throw new IllegalArgumentException("Uid " + callingUid + + " cannot query restriction state for package " + packageName); + } + } catch (RemoteException exc) { + // Ignore. + } + final int mode = mAppOpsService.checkOperation(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, + callingUid, packageName); + return (mode != AppOpsManager.MODE_ALLOWED); + } + + @Override public void backgroundWhitelistUid(final int uid) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("Only the OS may call backgroundWhitelistUid()"); @@ -15754,12 +15775,12 @@ public class ActivityManagerService extends IActivityManager.Stub opti++; if ("activities".equals(cmd) || "a".equals(cmd)) { - // output proto is ActivityStackSupervisorProto + // output proto is ActivityManagerServiceDumpActivitiesProto synchronized (this) { writeActivitiesToProtoLocked(proto); } } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) { - // output proto is BroadcastProto + // output proto is ActivityManagerServiceDumpBroadcastsProto synchronized (this) { writeBroadcastsToProtoLocked(proto); } @@ -15781,7 +15802,8 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println("Use -h for help."); } } else if ("service".equals(cmd)) { - mServices.writeToProto(proto); + // output proto is ActivityManagerServiceDumpServicesProto + mServices.writeToProto(proto, ActivityManagerServiceDumpServicesProto.ACTIVE_SERVICES); } else if ("processes".equals(cmd) || "p".equals(cmd)) { if (opti < args.length) { dumpPackage = args[opti]; @@ -15803,7 +15825,7 @@ public class ActivityManagerService extends IActivityManager.Stub proto.end(broadcastToken); long serviceToken = proto.start(ActivityManagerServiceProto.SERVICES); - mServices.writeToProto(proto); + mServices.writeToProto(proto, ActivityManagerServiceDumpServicesProto.ACTIVE_SERVICES); proto.end(serviceToken); long processToken = proto.start(ActivityManagerServiceProto.PROCESSES); @@ -16166,8 +16188,8 @@ public class ActivityManagerService extends IActivityManager.Stub } private void writeActivitiesToProtoLocked(ProtoOutputStream proto) { - // The output proto of "activity --proto activities" is ActivityStackSupervisorProto - mStackSupervisor.writeToProto(proto); + // The output proto of "activity --proto activities" is ActivityManagerServiceDumpActivitiesProto + mStackSupervisor.writeToProto(proto, ActivityManagerServiceDumpActivitiesProto.ACTIVITY_STACK_SUPERVISOR); } private void dumpLastANRLocked(PrintWriter pw) { @@ -16864,7 +16886,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) { continue; } - r.writeToProto(proto, ProcessesProto.PROCS); + r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PROCS); if (r.persistent) { numPers++; } @@ -16876,7 +16898,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) { continue; } - r.writeToProto(proto, ProcessesProto.ISOLATED_PROCS); + r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.ISOLATED_PROCS); } for (int i=0; i<mActiveInstrumentation.size(); i++) { @@ -16885,7 +16907,7 @@ public class ActivityManagerService extends IActivityManager.Stub && !ai.mTargetInfo.packageName.equals(dumpPackage)) { continue; } - ai.writeToProto(proto, ProcessesProto.ACTIVE_INSTRUMENTATIONS); + ai.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.ACTIVE_INSTRUMENTATIONS); } int whichAppId = getAppId(dumpPackage); @@ -16894,7 +16916,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) { continue; } - uidRec.writeToProto(proto, ProcessesProto.ACTIVE_UIDS); + uidRec.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.ACTIVE_UIDS); } for (int i=0; i<mValidateUids.size(); i++) { @@ -16902,16 +16924,16 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) { continue; } - uidRec.writeToProto(proto, ProcessesProto.VALIDATE_UIDS); + uidRec.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.VALIDATE_UIDS); } if (mLruProcesses.size() > 0) { - long lruToken = proto.start(ProcessesProto.LRU_PROCS); + long lruToken = proto.start(ActivityManagerServiceDumpProcessesProto.LRU_PROCS); int total = mLruProcesses.size(); - proto.write(ProcessesProto.LruProcesses.SIZE, total); - proto.write(ProcessesProto.LruProcesses.NON_ACT_AT, total-mLruProcessActivityStart); - proto.write(ProcessesProto.LruProcesses.NON_SVC_AT, total-mLruProcessServiceStart); - writeProcessOomListToProto(proto, ProcessesProto.LruProcesses.LIST, this, + proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.SIZE, total); + proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.NON_ACT_AT, total-mLruProcessActivityStart); + proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.NON_SVC_AT, total-mLruProcessServiceStart); + writeProcessOomListToProto(proto, ActivityManagerServiceDumpProcessesProto.LruProcesses.LIST, this, mLruProcesses,false, dumpPackage); proto.end(lruToken); } @@ -16923,7 +16945,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (!r.pkgList.containsKey(dumpPackage)) { continue; } - r.writeToProto(proto, ProcessesProto.PIDS_SELF_LOCKED); + r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PIDS_SELF_LOCKED); } } } @@ -16937,7 +16959,7 @@ public class ActivityManagerService extends IActivityManager.Stub || !r.pkgList.containsKey(dumpPackage))) { continue; } - it.writeToProto(proto, ProcessesProto.IMPORTANT_PROCS); + it.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.IMPORTANT_PROCS); } } } @@ -16947,7 +16969,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) { continue; } - r.writeToProto(proto, ProcessesProto.PERSISTENT_STARTING_PROCS); + r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PERSISTENT_STARTING_PROCS); } for (int i=0; i<mRemovedProcesses.size(); i++) { @@ -16955,7 +16977,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) { continue; } - r.writeToProto(proto, ProcessesProto.REMOVED_PROCS); + r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.REMOVED_PROCS); } for (int i=0; i<mProcessesOnHold.size(); i++) { @@ -16963,41 +16985,41 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) { continue; } - r.writeToProto(proto, ProcessesProto.ON_HOLD_PROCS); + r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.ON_HOLD_PROCS); } - writeProcessesToGcToProto(proto, ProcessesProto.GC_PROCS, dumpPackage); - mAppErrors.writeToProto(proto, ProcessesProto.APP_ERRORS, dumpPackage); + writeProcessesToGcToProto(proto, ActivityManagerServiceDumpProcessesProto.GC_PROCS, dumpPackage); + mAppErrors.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.APP_ERRORS, dumpPackage); if (dumpPackage == null) { - mUserController.writeToProto(proto, ProcessesProto.USER_CONTROLLER); - getGlobalConfiguration().writeToProto(proto, ProcessesProto.GLOBAL_CONFIGURATION); - proto.write(ProcessesProto.CONFIG_WILL_CHANGE, getFocusedStack().mConfigWillChange); + mUserController.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.USER_CONTROLLER); + getGlobalConfiguration().writeToProto(proto, ActivityManagerServiceDumpProcessesProto.GLOBAL_CONFIGURATION); + proto.write(ActivityManagerServiceDumpProcessesProto.CONFIG_WILL_CHANGE, getFocusedStack().mConfigWillChange); } if (mHomeProcess != null && (dumpPackage == null || mHomeProcess.pkgList.containsKey(dumpPackage))) { - mHomeProcess.writeToProto(proto, ProcessesProto.HOME_PROC); + mHomeProcess.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.HOME_PROC); } if (mPreviousProcess != null && (dumpPackage == null || mPreviousProcess.pkgList.containsKey(dumpPackage))) { - mPreviousProcess.writeToProto(proto, ProcessesProto.PREVIOUS_PROC); - proto.write(ProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS, mPreviousProcessVisibleTime); + mPreviousProcess.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC); + proto.write(ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS, mPreviousProcessVisibleTime); } if (mHeavyWeightProcess != null && (dumpPackage == null || mHeavyWeightProcess.pkgList.containsKey(dumpPackage))) { - mHeavyWeightProcess.writeToProto(proto, ProcessesProto.HEAVY_WEIGHT_PROC); + mHeavyWeightProcess.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.HEAVY_WEIGHT_PROC); } for (Map.Entry<String, Integer> entry : mCompatModePackages.getPackages().entrySet()) { String pkg = entry.getKey(); int mode = entry.getValue(); if (dumpPackage == null || dumpPackage.equals(pkg)) { - long compatToken = proto.start(ProcessesProto.SCREEN_COMPAT_PACKAGES); - proto.write(ProcessesProto.ScreenCompatPackage.PACKAGE, pkg); - proto.write(ProcessesProto.ScreenCompatPackage.MODE, mode); + long compatToken = proto.start(ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES); + proto.write(ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE, pkg); + proto.write(ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE, mode); proto.end(compatToken); } } @@ -17007,89 +17029,89 @@ public class ActivityManagerService extends IActivityManager.Stub final UidObserverRegistration reg = (UidObserverRegistration) mUidObservers.getRegisteredCallbackCookie(i); if (dumpPackage == null || dumpPackage.equals(reg.pkg)) { - reg.writeToProto(proto, ProcessesProto.UID_OBSERVERS); + reg.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.UID_OBSERVERS); } } for (int v : mDeviceIdleWhitelist) { - proto.write(ProcessesProto.DEVICE_IDLE_WHITELIST, v); + proto.write(ActivityManagerServiceDumpProcessesProto.DEVICE_IDLE_WHITELIST, v); } for (int v : mDeviceIdleTempWhitelist) { - proto.write(ProcessesProto.DEVICE_IDLE_TEMP_WHITELIST, v); + proto.write(ActivityManagerServiceDumpProcessesProto.DEVICE_IDLE_TEMP_WHITELIST, v); } if (mPendingTempWhitelist.size() > 0) { for (int i=0; i < mPendingTempWhitelist.size(); i++) { mPendingTempWhitelist.valueAt(i).writeToProto(proto, - ProcessesProto.PENDING_TEMP_WHITELIST); + ActivityManagerServiceDumpProcessesProto.PENDING_TEMP_WHITELIST); } } if (dumpPackage == null) { - final long sleepToken = proto.start(ProcessesProto.SLEEP_STATUS); - proto.write(ProcessesProto.SleepStatus.WAKEFULNESS, + final long sleepToken = proto.start(ActivityManagerServiceDumpProcessesProto.SLEEP_STATUS); + proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.WAKEFULNESS, PowerManagerInternal.wakefulnessToProtoEnum(mWakefulness)); for (SleepToken st : mStackSupervisor.mSleepTokens) { - proto.write(ProcessesProto.SleepStatus.SLEEP_TOKENS, st.toString()); + proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEP_TOKENS, st.toString()); } - proto.write(ProcessesProto.SleepStatus.SLEEPING, mSleeping); - proto.write(ProcessesProto.SleepStatus.SHUTTING_DOWN, mShuttingDown); - proto.write(ProcessesProto.SleepStatus.TEST_PSS_MODE, mTestPssMode); + proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEPING, mSleeping); + proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SHUTTING_DOWN, mShuttingDown); + proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.TEST_PSS_MODE, mTestPssMode); proto.end(sleepToken); if (mRunningVoice != null) { - final long vrToken = proto.start(ProcessesProto.RUNNING_VOICE); - proto.write(ProcessesProto.VoiceProto.SESSION, mRunningVoice.toString()); - mVoiceWakeLock.writeToProto(proto, ProcessesProto.VoiceProto.WAKELOCK); + final long vrToken = proto.start(ActivityManagerServiceDumpProcessesProto.RUNNING_VOICE); + proto.write(ActivityManagerServiceDumpProcessesProto.VoiceProto.SESSION, mRunningVoice.toString()); + mVoiceWakeLock.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.VoiceProto.WAKELOCK); proto.end(vrToken); } - mVrController.writeToProto(proto, ProcessesProto.VR_CONTROLLER); + mVrController.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.VR_CONTROLLER); } if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient || mOrigWaitForDebugger) { if (dumpPackage == null || dumpPackage.equals(mDebugApp) || dumpPackage.equals(mOrigDebugApp)) { - final long debugAppToken = proto.start(ProcessesProto.DEBUG); - proto.write(ProcessesProto.DebugApp.DEBUG_APP, mDebugApp); - proto.write(ProcessesProto.DebugApp.ORIG_DEBUG_APP, mOrigDebugApp); - proto.write(ProcessesProto.DebugApp.DEBUG_TRANSIENT, mDebugTransient); - proto.write(ProcessesProto.DebugApp.ORIG_WAIT_FOR_DEBUGGER, mOrigWaitForDebugger); + final long debugAppToken = proto.start(ActivityManagerServiceDumpProcessesProto.DEBUG); + proto.write(ActivityManagerServiceDumpProcessesProto.DebugApp.DEBUG_APP, mDebugApp); + proto.write(ActivityManagerServiceDumpProcessesProto.DebugApp.ORIG_DEBUG_APP, mOrigDebugApp); + proto.write(ActivityManagerServiceDumpProcessesProto.DebugApp.DEBUG_TRANSIENT, mDebugTransient); + proto.write(ActivityManagerServiceDumpProcessesProto.DebugApp.ORIG_WAIT_FOR_DEBUGGER, mOrigWaitForDebugger); proto.end(debugAppToken); } } if (mCurAppTimeTracker != null) { - mCurAppTimeTracker.writeToProto(proto, ProcessesProto.CURRENT_TRACKER, true); + mCurAppTimeTracker.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.CURRENT_TRACKER, true); } if (mMemWatchProcesses.getMap().size() > 0) { - final long token = proto.start(ProcessesProto.MEM_WATCH_PROCESSES); + final long token = proto.start(ActivityManagerServiceDumpProcessesProto.MEM_WATCH_PROCESSES); ArrayMap<String, SparseArray<Pair<Long, String>>> procs = mMemWatchProcesses.getMap(); for (int i=0; i<procs.size(); i++) { final String proc = procs.keyAt(i); final SparseArray<Pair<Long, String>> uids = procs.valueAt(i); - final long ptoken = proto.start(ProcessesProto.MemWatchProcess.PROCS); - proto.write(ProcessesProto.MemWatchProcess.Process.NAME, proc); + final long ptoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.PROCS); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.NAME, proc); for (int j=0; j<uids.size(); j++) { - final long utoken = proto.start(ProcessesProto.MemWatchProcess.Process.MEM_STATS); + final long utoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MEM_STATS); Pair<Long, String> val = uids.valueAt(j); - proto.write(ProcessesProto.MemWatchProcess.Process.MemStats.UID, uids.keyAt(j)); - proto.write(ProcessesProto.MemWatchProcess.Process.MemStats.SIZE, + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MemStats.UID, uids.keyAt(j)); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MemStats.SIZE, DebugUtils.sizeValueToString(val.first, new StringBuilder())); - proto.write(ProcessesProto.MemWatchProcess.Process.MemStats.REPORT_TO, val.second); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MemStats.REPORT_TO, val.second); proto.end(utoken); } proto.end(ptoken); } - final long dtoken = proto.start(ProcessesProto.MemWatchProcess.DUMP); - proto.write(ProcessesProto.MemWatchProcess.Dump.PROC_NAME, mMemWatchDumpProcName); - proto.write(ProcessesProto.MemWatchProcess.Dump.FILE, mMemWatchDumpFile); - proto.write(ProcessesProto.MemWatchProcess.Dump.PID, mMemWatchDumpPid); - proto.write(ProcessesProto.MemWatchProcess.Dump.UID, mMemWatchDumpUid); + final long dtoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.DUMP); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME, mMemWatchDumpProcName); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.FILE, mMemWatchDumpFile); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID, mMemWatchDumpPid); + proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID, mMemWatchDumpUid); proto.end(dtoken); proto.end(token); @@ -17097,58 +17119,58 @@ public class ActivityManagerService extends IActivityManager.Stub if (mTrackAllocationApp != null) { if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) { - proto.write(ProcessesProto.TRACK_ALLOCATION_APP, mTrackAllocationApp); + proto.write(ActivityManagerServiceDumpProcessesProto.TRACK_ALLOCATION_APP, mTrackAllocationApp); } } if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null && (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) { if (dumpPackage == null || dumpPackage.equals(mProfileApp)) { - final long token = proto.start(ProcessesProto.PROFILE); - proto.write(ProcessesProto.Profile.APP_NAME, mProfileApp); - mProfileProc.writeToProto(proto,ProcessesProto.Profile.PROC); + final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE); + proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME, mProfileApp); + mProfileProc.writeToProto(proto,ActivityManagerServiceDumpProcessesProto.Profile.PROC); if (mProfilerInfo != null) { - mProfilerInfo.writeToProto(proto, ProcessesProto.Profile.INFO); - proto.write(ProcessesProto.Profile.TYPE, mProfileType); + mProfilerInfo.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.Profile.INFO); + proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE, mProfileType); } proto.end(token); } } if (dumpPackage == null || dumpPackage.equals(mNativeDebuggingApp)) { - proto.write(ProcessesProto.NATIVE_DEBUGGING_APP, mNativeDebuggingApp); + proto.write(ActivityManagerServiceDumpProcessesProto.NATIVE_DEBUGGING_APP, mNativeDebuggingApp); } if (dumpPackage == null) { - proto.write(ProcessesProto.ALWAYS_FINISH_ACTIVITIES, mAlwaysFinishActivities); + proto.write(ActivityManagerServiceDumpProcessesProto.ALWAYS_FINISH_ACTIVITIES, mAlwaysFinishActivities); if (mController != null) { - final long token = proto.start(ProcessesProto.CONTROLLER); - proto.write(ProcessesProto.Controller.CONTROLLER, mController.toString()); - proto.write(ProcessesProto.Controller.IS_A_MONKEY, mControllerIsAMonkey); + final long token = proto.start(ActivityManagerServiceDumpProcessesProto.CONTROLLER); + proto.write(ActivityManagerServiceDumpProcessesProto.Controller.CONTROLLER, mController.toString()); + proto.write(ActivityManagerServiceDumpProcessesProto.Controller.IS_A_MONKEY, mControllerIsAMonkey); proto.end(token); } - proto.write(ProcessesProto.TOTAL_PERSISTENT_PROCS, numPers); - proto.write(ProcessesProto.PROCESSES_READY, mProcessesReady); - proto.write(ProcessesProto.SYSTEM_READY, mSystemReady); - proto.write(ProcessesProto.BOOTED, mBooted); - proto.write(ProcessesProto.FACTORY_TEST, mFactoryTest); - proto.write(ProcessesProto.BOOTING, mBooting); - proto.write(ProcessesProto.CALL_FINISH_BOOTING, mCallFinishBooting); - proto.write(ProcessesProto.BOOT_ANIMATION_COMPLETE, mBootAnimationComplete); - proto.write(ProcessesProto.LAST_POWER_CHECK_UPTIME_MS, mLastPowerCheckUptime); - mStackSupervisor.mGoingToSleep.writeToProto(proto, ProcessesProto.GOING_TO_SLEEP); - mStackSupervisor.mLaunchingActivity.writeToProto(proto, ProcessesProto.LAUNCHING_ACTIVITY); - proto.write(ProcessesProto.ADJ_SEQ, mAdjSeq); - proto.write(ProcessesProto.LRU_SEQ, mLruSeq); - proto.write(ProcessesProto.NUM_NON_CACHED_PROCS, mNumNonCachedProcs); - proto.write(ProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs); - proto.write(ProcessesProto.NEW_NUM_SERVICE_PROCS, mNewNumServiceProcs); - proto.write(ProcessesProto.ALLOW_LOWER_MEM_LEVEL, mAllowLowerMemLevel); - proto.write(ProcessesProto.LAST_MEMORY_LEVEL, mLastMemoryLevel); - proto.write(ProcessesProto.LAST_NUM_PROCESSES, mLastNumProcesses); + proto.write(ActivityManagerServiceDumpProcessesProto.TOTAL_PERSISTENT_PROCS, numPers); + proto.write(ActivityManagerServiceDumpProcessesProto.PROCESSES_READY, mProcessesReady); + proto.write(ActivityManagerServiceDumpProcessesProto.SYSTEM_READY, mSystemReady); + proto.write(ActivityManagerServiceDumpProcessesProto.BOOTED, mBooted); + proto.write(ActivityManagerServiceDumpProcessesProto.FACTORY_TEST, mFactoryTest); + proto.write(ActivityManagerServiceDumpProcessesProto.BOOTING, mBooting); + proto.write(ActivityManagerServiceDumpProcessesProto.CALL_FINISH_BOOTING, mCallFinishBooting); + proto.write(ActivityManagerServiceDumpProcessesProto.BOOT_ANIMATION_COMPLETE, mBootAnimationComplete); + proto.write(ActivityManagerServiceDumpProcessesProto.LAST_POWER_CHECK_UPTIME_MS, mLastPowerCheckUptime); + mStackSupervisor.mGoingToSleep.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.GOING_TO_SLEEP); + mStackSupervisor.mLaunchingActivity.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.LAUNCHING_ACTIVITY); + proto.write(ActivityManagerServiceDumpProcessesProto.ADJ_SEQ, mAdjSeq); + proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mLruSeq); + proto.write(ActivityManagerServiceDumpProcessesProto.NUM_NON_CACHED_PROCS, mNumNonCachedProcs); + proto.write(ActivityManagerServiceDumpProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs); + proto.write(ActivityManagerServiceDumpProcessesProto.NEW_NUM_SERVICE_PROCS, mNewNumServiceProcs); + proto.write(ActivityManagerServiceDumpProcessesProto.ALLOW_LOWER_MEM_LEVEL, mAllowLowerMemLevel); + proto.write(ActivityManagerServiceDumpProcessesProto.LAST_MEMORY_LEVEL, mLastMemoryLevel); + proto.write(ActivityManagerServiceDumpProcessesProto.LAST_NUM_PROCESSES, mLastNumProcesses); long now = SystemClock.uptimeMillis(); - ProtoUtils.toDuration(proto, ProcessesProto.LAST_IDLE_TIME, mLastIdleTime, now); - proto.write(ProcessesProto.LOW_RAM_SINCE_LAST_IDLE_MS, getLowRamTimeSinceIdle(now)); + ProtoUtils.toDuration(proto, ActivityManagerServiceDumpProcessesProto.LAST_IDLE_TIME, mLastIdleTime, now); + proto.write(ActivityManagerServiceDumpProcessesProto.LOW_RAM_SINCE_LAST_IDLE_MS, getLowRamTimeSinceIdle(now)); } } @@ -17458,15 +17480,15 @@ public class ActivityManagerService extends IActivityManager.Stub Iterator it = mRegisteredReceivers.values().iterator(); while (it.hasNext()) { ReceiverList r = (ReceiverList)it.next(); - r.writeToProto(proto, BroadcastProto.RECEIVER_LIST); + r.writeToProto(proto, ActivityManagerServiceDumpBroadcastsProto.RECEIVER_LIST); } } - mReceiverResolver.writeToProto(proto, BroadcastProto.RECEIVER_RESOLVER); + mReceiverResolver.writeToProto(proto, ActivityManagerServiceDumpBroadcastsProto.RECEIVER_RESOLVER); for (BroadcastQueue q : mBroadcastQueues) { - q.writeToProto(proto, BroadcastProto.BROADCAST_QUEUE); + q.writeToProto(proto, ActivityManagerServiceDumpBroadcastsProto.BROADCAST_QUEUE); } for (int user=0; user<mStickyBroadcasts.size(); user++) { - long token = proto.start(BroadcastProto.STICKY_BROADCASTS); + long token = proto.start(ActivityManagerServiceDumpBroadcastsProto.STICKY_BROADCASTS); proto.write(StickyBroadcastProto.USER, mStickyBroadcasts.keyAt(user)); for (Map.Entry<String, ArrayList<Intent>> ent : mStickyBroadcasts.valueAt(user).entrySet()) { @@ -17481,9 +17503,10 @@ public class ActivityManagerService extends IActivityManager.Stub proto.end(token); } - long handlerToken = proto.start(BroadcastProto.HANDLER); - proto.write(BroadcastProto.MainHandler.HANDLER, mHandler.toString()); - mHandler.getLooper().writeToProto(proto, BroadcastProto.MainHandler.LOOPER); + long handlerToken = proto.start(ActivityManagerServiceDumpBroadcastsProto.HANDLER); + proto.write(ActivityManagerServiceDumpBroadcastsProto.MainHandler.HANDLER, mHandler.toString()); + mHandler.getLooper().writeToProto(proto, + ActivityManagerServiceDumpBroadcastsProto.MainHandler.LOOPER); proto.end(handlerToken); } @@ -18245,17 +18268,17 @@ public class ActivityManagerService extends IActivityManager.Stub MemItem mi = items.get(i); final long token = proto.start(fieldId); - proto.write(MemInfoProto.MemItem.TAG, tag); - proto.write(MemInfoProto.MemItem.LABEL, mi.shortLabel); - proto.write(MemInfoProto.MemItem.IS_PROC, mi.isProc); - proto.write(MemInfoProto.MemItem.ID, mi.id); - proto.write(MemInfoProto.MemItem.HAS_ACTIVITIES, mi.hasActivities); - proto.write(MemInfoProto.MemItem.PSS_KB, mi.pss); + proto.write(MemInfoDumpProto.MemItem.TAG, tag); + proto.write(MemInfoDumpProto.MemItem.LABEL, mi.shortLabel); + proto.write(MemInfoDumpProto.MemItem.IS_PROC, mi.isProc); + proto.write(MemInfoDumpProto.MemItem.ID, mi.id); + proto.write(MemInfoDumpProto.MemItem.HAS_ACTIVITIES, mi.hasActivities); + proto.write(MemInfoDumpProto.MemItem.PSS_KB, mi.pss); if (dumpSwapPss) { - proto.write(MemInfoProto.MemItem.SWAP_PSS_KB, mi.swapPss); + proto.write(MemInfoDumpProto.MemItem.SWAP_PSS_KB, mi.swapPss); } if (mi.subitems != null) { - dumpMemItems(proto, MemInfoProto.MemItem.SUB_ITEMS, mi.shortLabel, mi.subitems, + dumpMemItems(proto, MemInfoDumpProto.MemItem.SUB_ITEMS, mi.shortLabel, mi.subitems, true, dumpSwapPss); } proto.end(token); @@ -19009,16 +19032,16 @@ public class ActivityManagerService extends IActivityManager.Stub if (nativeProcs.size() > 0) { ProtoOutputStream proto = new ProtoOutputStream(fd); - proto.write(MemInfoProto.UPTIME_DURATION_MS, uptimeMs); - proto.write(MemInfoProto.ELAPSED_REALTIME_MS, realtimeMs); + proto.write(MemInfoDumpProto.UPTIME_DURATION_MS, uptimeMs); + proto.write(MemInfoDumpProto.ELAPSED_REALTIME_MS, realtimeMs); Debug.MemoryInfo mi = null; for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) { final ProcessCpuTracker.Stats r = nativeProcs.get(i); final int pid = r.pid; - final long nToken = proto.start(MemInfoProto.NATIVE_PROCESSES); + final long nToken = proto.start(MemInfoDumpProto.NATIVE_PROCESSES); - proto.write(MemInfoProto.ProcessMemory.PID, pid); - proto.write(MemInfoProto.ProcessMemory.PROCESS_NAME, r.baseName); + proto.write(MemInfoDumpProto.ProcessMemory.PID, pid); + proto.write(MemInfoDumpProto.ProcessMemory.PROCESS_NAME, r.baseName); if (mi == null) { mi = new Debug.MemoryInfo(); @@ -19050,8 +19073,8 @@ public class ActivityManagerService extends IActivityManager.Stub ProtoOutputStream proto = new ProtoOutputStream(fd); - proto.write(MemInfoProto.UPTIME_DURATION_MS, uptimeMs); - proto.write(MemInfoProto.ELAPSED_REALTIME_MS, realtimeMs); + proto.write(MemInfoDumpProto.UPTIME_DURATION_MS, uptimeMs); + proto.write(MemInfoDumpProto.ELAPSED_REALTIME_MS, realtimeMs); ArrayList<MemItem> procMems = new ArrayList<MemItem>(); final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>(); @@ -19116,10 +19139,10 @@ public class ActivityManagerService extends IActivityManager.Stub } if (opts.dumpDetails) { if (opts.localOnly) { - final long aToken = proto.start(MemInfoProto.APP_PROCESSES); - final long mToken = proto.start(MemInfoProto.AppData.PROCESS_MEMORY); - proto.write(MemInfoProto.ProcessMemory.PID, pid); - proto.write(MemInfoProto.ProcessMemory.PROCESS_NAME, r.processName); + final long aToken = proto.start(MemInfoDumpProto.APP_PROCESSES); + final long mToken = proto.start(MemInfoDumpProto.AppData.PROCESS_MEMORY); + proto.write(MemInfoDumpProto.ProcessMemory.PID, pid); + proto.write(MemInfoDumpProto.ProcessMemory.PROCESS_NAME, r.processName); ActivityThread.dumpMemInfoTable(proto, mi, opts.dumpDalvik, opts.dumpSummaryOnly, 0, 0, 0, 0, 0, 0); proto.end(mToken); @@ -19131,7 +19154,7 @@ public class ActivityManagerService extends IActivityManager.Stub thread.dumpMemInfoProto(tp.getWriteFd(), mi, opts.dumpFullDetails, opts.dumpDalvik, opts.dumpSummaryOnly, opts.dumpUnreachable, innerArgs); - proto.write(MemInfoProto.APP_PROCESSES, tp.get()); + proto.write(MemInfoDumpProto.APP_PROCESSES, tp.get()); } finally { tp.kill(); } @@ -19319,13 +19342,13 @@ public class ActivityManagerService extends IActivityManager.Stub opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && totalSwapPss != 0; if (!opts.oomOnly) { - dumpMemItems(proto, MemInfoProto.TOTAL_PSS_BY_PROCESS, "proc", + dumpMemItems(proto, MemInfoDumpProto.TOTAL_PSS_BY_PROCESS, "proc", procMems, true, opts.dumpSwapPss); } - dumpMemItems(proto, MemInfoProto.TOTAL_PSS_BY_OOM_ADJUSTMENT, "oom", + dumpMemItems(proto, MemInfoDumpProto.TOTAL_PSS_BY_OOM_ADJUSTMENT, "oom", oomMems, false, opts.dumpSwapPss); if (!brief && !opts.oomOnly) { - dumpMemItems(proto, MemInfoProto.TOTAL_PSS_BY_CATEGORY, "cat", + dumpMemItems(proto, MemInfoDumpProto.TOTAL_PSS_BY_CATEGORY, "cat", catMems, true, opts.dumpSwapPss); } MemInfoReader memInfo = new MemInfoReader(); @@ -19343,40 +19366,40 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (!brief) { - proto.write(MemInfoProto.TOTAL_RAM_KB, memInfo.getTotalSizeKb()); - proto.write(MemInfoProto.STATUS, mLastMemoryLevel); - proto.write(MemInfoProto.CACHED_PSS_KB, cachedPss); - proto.write(MemInfoProto.CACHED_KERNEL_KB, memInfo.getCachedSizeKb()); - proto.write(MemInfoProto.FREE_KB, memInfo.getFreeSizeKb()); + proto.write(MemInfoDumpProto.TOTAL_RAM_KB, memInfo.getTotalSizeKb()); + proto.write(MemInfoDumpProto.STATUS, mLastMemoryLevel); + proto.write(MemInfoDumpProto.CACHED_PSS_KB, cachedPss); + proto.write(MemInfoDumpProto.CACHED_KERNEL_KB, memInfo.getCachedSizeKb()); + proto.write(MemInfoDumpProto.FREE_KB, memInfo.getFreeSizeKb()); } long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb(); - proto.write(MemInfoProto.USED_PSS_KB, totalPss - cachedPss); - proto.write(MemInfoProto.USED_KERNEL_KB, memInfo.getKernelUsedSizeKb()); - proto.write(MemInfoProto.LOST_RAM_KB, lostRAM); + proto.write(MemInfoDumpProto.USED_PSS_KB, totalPss - cachedPss); + proto.write(MemInfoDumpProto.USED_KERNEL_KB, memInfo.getKernelUsedSizeKb()); + proto.write(MemInfoDumpProto.LOST_RAM_KB, lostRAM); if (!brief) { if (memInfo.getZramTotalSizeKb() != 0) { - proto.write(MemInfoProto.TOTAL_ZRAM_KB, memInfo.getZramTotalSizeKb()); - proto.write(MemInfoProto.ZRAM_PHYSICAL_USED_IN_SWAP_KB, + proto.write(MemInfoDumpProto.TOTAL_ZRAM_KB, memInfo.getZramTotalSizeKb()); + proto.write(MemInfoDumpProto.ZRAM_PHYSICAL_USED_IN_SWAP_KB, memInfo.getSwapTotalSizeKb() - memInfo.getSwapFreeSizeKb()); - proto.write(MemInfoProto.TOTAL_ZRAM_SWAP_KB, memInfo.getSwapTotalSizeKb()); + proto.write(MemInfoDumpProto.TOTAL_ZRAM_SWAP_KB, memInfo.getSwapTotalSizeKb()); } final long[] ksm = getKsmInfo(); - proto.write(MemInfoProto.KSM_SHARING_KB, ksm[KSM_SHARING]); - proto.write(MemInfoProto.KSM_SHARED_KB, ksm[KSM_SHARED]); - proto.write(MemInfoProto.KSM_UNSHARED_KB, ksm[KSM_UNSHARED]); - proto.write(MemInfoProto.KSM_VOLATILE_KB, ksm[KSM_VOLATILE]); - - proto.write(MemInfoProto.TUNING_MB, ActivityManager.staticGetMemoryClass()); - proto.write(MemInfoProto.TUNING_LARGE_MB, ActivityManager.staticGetLargeMemoryClass()); - proto.write(MemInfoProto.OOM_KB, + proto.write(MemInfoDumpProto.KSM_SHARING_KB, ksm[KSM_SHARING]); + proto.write(MemInfoDumpProto.KSM_SHARED_KB, ksm[KSM_SHARED]); + proto.write(MemInfoDumpProto.KSM_UNSHARED_KB, ksm[KSM_UNSHARED]); + proto.write(MemInfoDumpProto.KSM_VOLATILE_KB, ksm[KSM_VOLATILE]); + + proto.write(MemInfoDumpProto.TUNING_MB, ActivityManager.staticGetMemoryClass()); + proto.write(MemInfoDumpProto.TUNING_LARGE_MB, ActivityManager.staticGetLargeMemoryClass()); + proto.write(MemInfoDumpProto.OOM_KB, mProcessList.getMemLevel(ProcessList.CACHED_APP_MAX_ADJ) / 1024); - proto.write(MemInfoProto.RESTORE_LIMIT_KB, + proto.write(MemInfoDumpProto.RESTORE_LIMIT_KB, mProcessList.getCachedRestoreThresholdKb()); - proto.write(MemInfoProto.IS_LOW_RAM_DEVICE, ActivityManager.isLowRamDeviceStatic()); - proto.write(MemInfoProto.IS_HIGH_END_GFX, ActivityManager.isHighEndGfx()); + proto.write(MemInfoDumpProto.IS_LOW_RAM_DEVICE, ActivityManager.isLowRamDeviceStatic()); + proto.write(MemInfoDumpProto.IS_HIGH_END_GFX, ActivityManager.isHighEndGfx()); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 3d7c9d207f38..81dae394c792 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -51,6 +51,7 @@ import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.hardware.display.DisplayManager; +import android.opengl.GLES10; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -82,16 +83,18 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; -import java.util.Map; +import java.util.Set; import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.opengles.GL; -import javax.microedition.khronos.opengles.GL10; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; import static android.app.ActivityManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityManager.RESIZE_MODE_USER; @@ -1858,6 +1861,137 @@ final class ActivityManagerShellCommand extends ShellCommand { } } + /** + * Adds all supported GL extensions for a provided EGLConfig to a set by creating an EGLContext + * and EGLSurface and querying extensions. + * + * @param egl An EGL API object + * @param display An EGLDisplay to create a context and surface with + * @param config The EGLConfig to get the extensions for + * @param surfaceSize eglCreatePbufferSurface generic parameters + * @param contextAttribs eglCreateContext generic parameters + * @param glExtensions A Set<String> to add GL extensions to + */ + private static void addExtensionsForConfig( + EGL10 egl, + EGLDisplay display, + EGLConfig config, + int[] surfaceSize, + int[] contextAttribs, + Set<String> glExtensions) { + // Create a context. + EGLContext context = + egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, contextAttribs); + // No-op if we can't create a context. + if (context == EGL10.EGL_NO_CONTEXT) { + return; + } + + // Create a surface. + EGLSurface surface = egl.eglCreatePbufferSurface(display, config, surfaceSize); + if (surface == EGL10.EGL_NO_SURFACE) { + egl.eglDestroyContext(display, context); + return; + } + + // Update the current surface and context. + egl.eglMakeCurrent(display, surface, surface, context); + + // Get the list of extensions. + String extensionList = GLES10.glGetString(GLES10.GL_EXTENSIONS); + if (!TextUtils.isEmpty(extensionList)) { + // The list of extensions comes from the driver separated by spaces. + // Split them apart and add them into a Set for deduping purposes. + for (String extension : extensionList.split(" ")) { + glExtensions.add(extension); + } + } + + // Tear down the context and surface for this config. + egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + egl.eglDestroySurface(display, surface); + egl.eglDestroyContext(display, context); + } + + + Set<String> getGlExtensionsFromDriver() { + Set<String> glExtensions = new HashSet<>(); + + // Get the EGL implementation. + EGL10 egl = (EGL10) EGLContext.getEGL(); + if (egl == null) { + getErrPrintWriter().println("Warning: couldn't get EGL"); + return glExtensions; + } + + // Get the default display and initialize it. + EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + int[] version = new int[2]; + egl.eglInitialize(display, version); + + // Call getConfigs() in order to find out how many there are. + int[] numConfigs = new int[1]; + if (!egl.eglGetConfigs(display, null, 0, numConfigs)) { + getErrPrintWriter().println("Warning: couldn't get EGL config count"); + return glExtensions; + } + + // Allocate space for all configs and ask again. + EGLConfig[] configs = new EGLConfig[numConfigs[0]]; + if (!egl.eglGetConfigs(display, configs, numConfigs[0], numConfigs)) { + getErrPrintWriter().println("Warning: couldn't get EGL configs"); + return glExtensions; + } + + // Allocate surface size parameters outside of the main loop to cut down + // on GC thrashing. 1x1 is enough since we are only using it to get at + // the list of extensions. + int[] surfaceSize = + new int[] { + EGL10.EGL_WIDTH, 1, + EGL10.EGL_HEIGHT, 1, + EGL10.EGL_NONE + }; + + // For when we need to create a GLES2.0 context. + final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + int[] gles2 = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; + + // For getting return values from eglGetConfigAttrib + int[] attrib = new int[1]; + + for (int i = 0; i < numConfigs[0]; i++) { + // Get caveat for this config in order to skip slow (i.e. software) configs. + egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_CONFIG_CAVEAT, attrib); + if (attrib[0] == EGL10.EGL_SLOW_CONFIG) { + continue; + } + + // If the config does not support pbuffers we cannot do an eglMakeCurrent + // on it in addExtensionsForConfig(), so skip it here. Attempting to make + // it current with a pbuffer will result in an EGL_BAD_MATCH error + egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_SURFACE_TYPE, attrib); + if ((attrib[0] & EGL10.EGL_PBUFFER_BIT) == 0) { + continue; + } + + final int EGL_OPENGL_ES_BIT = 0x0001; + final int EGL_OPENGL_ES2_BIT = 0x0004; + egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_RENDERABLE_TYPE, attrib); + if ((attrib[0] & EGL_OPENGL_ES_BIT) != 0) { + addExtensionsForConfig(egl, display, configs[i], surfaceSize, null, glExtensions); + } + if ((attrib[0] & EGL_OPENGL_ES2_BIT) != 0) { + addExtensionsForConfig(egl, display, configs[i], surfaceSize, gles2, glExtensions); + } + } + + // Release all EGL resources. + egl.eglTerminate(display); + + return glExtensions; + } + private void writeDeviceConfig(ProtoOutputStream protoOutputStream, long fieldId, PrintWriter pw, Configuration config, DisplayManager dm) { Point stableSize = dm.getStableDisplaySize(); @@ -1906,18 +2040,24 @@ final class ActivityManagerShellCommand extends ShellCommand { } } - /* - GL10 gl = ((GL10)((EGL10)EGLContext.getEGL()).eglGetCurrentContext().getGL()); - protoOutputStream.write(DeviceConfigurationProto.OPENGL_VERSION, - gl.glGetString(GL10.GL_VERSION)); - String glExtensions = gl.glGetString(GL10.GL_EXTENSIONS); - for (String ext : glExtensions.split(" ")) { - protoOutputStream.write(DeviceConfigurationProto.OPENGL_EXTENSIONS, ext); + Set<String> glExtensionsSet = getGlExtensionsFromDriver(); + String[] glExtensions = new String[glExtensionsSet.size()]; + glExtensions = glExtensionsSet.toArray(glExtensions); + Arrays.sort(glExtensions); + for (int i = 0; i < glExtensions.length; i++) { + if (protoOutputStream != null) { + protoOutputStream.write(DeviceConfigurationProto.OPENGL_EXTENSIONS, + glExtensions[i]); + } + if (pw != null) { + pw.print("opengl-extensions: "); pw.println(glExtensions[i]); + } + } - */ PackageManager pm = mInternal.mContext.getPackageManager(); List<SharedLibraryInfo> slibs = pm.getSharedLibraries(0); + Collections.sort(slibs, Comparator.comparing(SharedLibraryInfo::getName)); for (int i = 0; i < slibs.size(); i++) { if (protoOutputStream != null) { protoOutputStream.write(DeviceConfigurationProto.SHARED_LIBRARIES, @@ -1929,6 +2069,8 @@ final class ActivityManagerShellCommand extends ShellCommand { } FeatureInfo[] features = pm.getSystemAvailableFeatures(); + Arrays.sort(features, (o1, o2) -> + (o1.name == o2.name ? 0 : (o1.name == null ? -1 : o1.name.compareTo(o2.name)))); for (int i = 0; i < features.length; i++) { if (features[i].name != null) { if (protoOutputStream != null) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 0157c7c3fd9a..26ffe9529982 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -3777,7 +3777,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mService.mLockTaskController.dump(pw, prefix); } - public void writeToProto(ProtoOutputStream proto) { + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx); @@ -3795,6 +3796,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } proto.write(IS_HOME_RECENTS_COMPONENT, mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser)); + proto.end(token); } /** diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java index d32db7ea2ed9..9d34a8020345 100644 --- a/services/core/java/com/android/server/am/VrController.java +++ b/services/core/java/com/android/server/am/VrController.java @@ -24,7 +24,7 @@ import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoUtils; import com.android.server.LocalServices; -import com.android.server.am.proto.ProcessesProto.VrControllerProto; +import com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto.VrControllerProto; import com.android.server.vr.VrManagerInternal; /** diff --git a/services/core/java/com/android/server/media/MediaUpdateService.java b/services/core/java/com/android/server/media/MediaUpdateService.java index 6921ccde250c..f38b35342f3a 100644 --- a/services/core/java/com/android/server/media/MediaUpdateService.java +++ b/services/core/java/com/android/server/media/MediaUpdateService.java @@ -16,27 +16,21 @@ package com.android.server.media; -import android.content.Context; -import android.content.Intent; -import android.media.IMediaResourceMonitor; -import android.os.Binder; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.Log; -import android.util.Slog; -import com.android.server.SystemService; - import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.media.IMediaExtractorUpdateService; import android.os.IBinder; +import android.os.Handler; import android.os.PatternMatcher; import android.os.ServiceManager; -import android.media.IMediaExtractorUpdateService; - -import java.lang.Exception; +import android.os.UserHandle; +import android.util.Log; +import android.util.Slog; +import com.android.server.SystemService; /** This class provides a system service that manages media framework updates. */ public class MediaUpdateService extends SystemService { @@ -46,9 +40,11 @@ public class MediaUpdateService extends SystemService { private static final String EXTRACTOR_UPDATE_SERVICE_NAME = "media.extractor.update"; private IMediaExtractorUpdateService mMediaExtractorUpdateService; + final Handler mHandler; public MediaUpdateService(Context context) { super(context); + mHandler = new Handler(); } @Override @@ -77,7 +73,12 @@ public class MediaUpdateService extends SystemService { } if (binder != null) { mMediaExtractorUpdateService = IMediaExtractorUpdateService.Stub.asInterface(binder); - packageStateChanged(); + mHandler.post(new Runnable() { + @Override + public void run() { + packageStateChanged(); + } + }); } else { Slog.w(TAG, EXTRACTOR_UPDATE_SERVICE_NAME + " not found."); } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 7efc9876993b..2f1fbf9c5fb4 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -485,7 +485,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mSafeMode; private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>(); WindowState mStatusBar = null; - int mStatusBarHeight; + private final int[] mStatusBarHeightForRotation = new int[4]; WindowState mNavigationBar = null; boolean mHasNavigationBar = false; boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side? @@ -2768,8 +2768,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { Context uiContext = getSystemUiContext(); final Resources res = uiContext.getResources(); - mStatusBarHeight = - res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); + mStatusBarHeightForRotation[mPortraitRotation] = + mStatusBarHeightForRotation[mUpsideDownRotation] = res.getDimensionPixelSize( + com.android.internal.R.dimen.status_bar_height_portrait); + mStatusBarHeightForRotation[mLandscapeRotation] = + mStatusBarHeightForRotation[mSeascapeRotation] = res.getDimensionPixelSize( + com.android.internal.R.dimen.status_bar_height_landscape); // Height of the navigation bar when presented horizontally at bottom mNavigationBarHeightForRotationDefault[mPortraitRotation] = @@ -2884,11 +2888,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // of the screen. // TODO(multi-display): Support status bars on secondary displays. if (displayId == DEFAULT_DISPLAY) { - int statusBarHeight = mStatusBarHeight; + int statusBarHeight = mStatusBarHeightForRotation[rotation]; if (displayCutout != null) { // If there is a cutout, it may already have accounted for some part of the status // bar height. - statusBarHeight = Math.max(0, mStatusBarHeight - displayCutout.getSafeInsetTop()); + statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop()); } return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId, displayCutout) - statusBarHeight; @@ -4649,7 +4653,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { displayFrames.mDisplayCutout); // For layout, the status bar is always at the top with our fixed height. - displayFrames.mStable.top = displayFrames.mUnrestricted.top + mStatusBarHeight; + displayFrames.mStable.top = displayFrames.mUnrestricted.top + + mStatusBarHeightForRotation[displayFrames.mRotation]; boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; boolean statusBarTranslucent = (sysui @@ -6938,7 +6943,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Navigation bar and status bar. getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets); - outInsets.top = Math.max(outInsets.top, mStatusBarHeight); + outInsets.top = Math.max(outInsets.top, mStatusBarHeightForRotation[displayRotation]); } @Override diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 1521afc1b059..bab4399d76ad 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -100,15 +100,15 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSA import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON; 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.proto.WindowManagerServiceProto.APP_TRANSITION; -import static com.android.server.wm.proto.WindowManagerServiceProto.DISPLAY_FROZEN; -import static com.android.server.wm.proto.WindowManagerServiceProto.FOCUSED_APP; -import static com.android.server.wm.proto.WindowManagerServiceProto.FOCUSED_WINDOW; -import static com.android.server.wm.proto.WindowManagerServiceProto.INPUT_METHOD_WINDOW; -import static com.android.server.wm.proto.WindowManagerServiceProto.LAST_ORIENTATION; -import static com.android.server.wm.proto.WindowManagerServiceProto.POLICY; -import static com.android.server.wm.proto.WindowManagerServiceProto.ROOT_WINDOW_CONTAINER; -import static com.android.server.wm.proto.WindowManagerServiceProto.ROTATION; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.APP_TRANSITION; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.DISPLAY_FROZEN; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.FOCUSED_APP; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.FOCUSED_WINDOW; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.INPUT_METHOD_WINDOW; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.LAST_ORIENTATION; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.POLICY; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER; +import static com.android.server.wm.proto.WindowManagerServiceDumpProto.ROTATION; import android.Manifest; import android.Manifest.permission; @@ -6195,7 +6195,7 @@ public class WindowManagerService extends IWindowManager.Stub /** * Write to a protocol buffer output stream. Protocol buffer message definition is at - * {@link com.android.server.wm.proto.WindowManagerServiceProto}. + * {@link com.android.server.wm.proto.WindowManagerServiceDumpProto}. * * @param proto Stream to write the WindowContainer object to. * @param trim If true, reduce the amount of data written. diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java index 30ca9caf56de..1d4348c0b6d4 100644 --- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java +++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java @@ -77,7 +77,9 @@ public class PhoneWindowManagerTestBase { public void setUpBase() throws Exception { mContext = new TestContextWrapper(InstrumentationRegistry.getTargetContext()); mContext.getResourceMocker().addOverride( - com.android.internal.R.dimen.status_bar_height, STATUS_BAR_HEIGHT); + com.android.internal.R.dimen.status_bar_height_portrait, STATUS_BAR_HEIGHT); + mContext.getResourceMocker().addOverride( + com.android.internal.R.dimen.status_bar_height_landscape, STATUS_BAR_HEIGHT); mContext.getResourceMocker().addOverride( com.android.internal.R.dimen.navigation_bar_height, NAV_BAR_HEIGHT); mContext.getResourceMocker().addOverride( |