OSDN Git Service

Merge "Prevent multi-threaded access to digest object" into nyc-dev
authorHall Liu <hallliu@google.com>
Thu, 17 Mar 2016 22:24:38 +0000 (22:24 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Thu, 17 Mar 2016 22:24:40 +0000 (22:24 +0000)
233 files changed:
Android.mk
api/current.txt
api/removed.txt
api/system-current.txt
api/system-removed.txt
api/test-current.txt
api/test-removed.txt
cmds/app_process/app_main.cpp
core/java/android/accessibilityservice/AccessibilityServiceInfo.java
core/java/android/app/Activity.java
core/java/android/app/ActivityOptions.java
core/java/android/app/ActivityThread.java
core/java/android/app/ApplicationPackageManager.java
core/java/android/app/ContextImpl.java
core/java/android/app/LoadedApk.java
core/java/android/app/Notification.java
core/java/android/app/admin/DeviceAdminReceiver.java
core/java/android/app/admin/DevicePolicyManager.java
core/java/android/app/admin/IDevicePolicyManager.aidl
core/java/android/app/admin/SecurityLog.java [moved from core/java/android/auditing/SecurityLog.java with 98% similarity]
core/java/android/app/admin/SecurityLogTags.logtags [moved from core/java/android/auditing/SecurityLogTags.logtags with 93% similarity]
core/java/android/app/backup/BackupAgent.java
core/java/android/app/backup/FullBackup.java
core/java/android/app/job/JobInfo.java
core/java/android/content/ClipData.java
core/java/android/content/Context.java
core/java/android/content/ContextWrapper.java
core/java/android/content/Intent.java
core/java/android/content/pm/ApplicationInfo.java
core/java/android/content/pm/ComponentInfo.java
core/java/android/content/pm/IPackageManager.aidl
core/java/android/content/pm/InstrumentationInfo.java
core/java/android/content/pm/PackageInstaller.java
core/java/android/content/pm/PackageManager.java
core/java/android/content/pm/PackageParser.java
core/java/android/content/pm/PackageUserState.java
core/java/android/content/pm/RegisteredServicesCache.java
core/java/android/content/pm/ShortcutInfo.java
core/java/android/hardware/SystemSensorManager.java
core/java/android/hardware/camera2/params/StreamConfigurationMap.java
core/java/android/hardware/location/ContextHubManager.java
core/java/android/hardware/location/ContextHubService.java
core/java/android/net/ScoredNetwork.java
core/java/android/os/BadParcelableException.java
core/java/android/os/BaseBundle.java
core/java/android/os/BatteryStats.java
core/java/android/os/Bundle.java
core/java/android/os/FileUtils.java
core/java/android/os/PersistableBundle.java
core/java/android/os/PowerManager.java
core/java/android/os/UserManager.java
core/java/android/preference/PreferenceManager.java
core/java/android/preference/SeekBarVolumizer.java
core/java/android/provider/Settings.java
core/java/android/speech/tts/AudioPlaybackQueueItem.java
core/java/android/speech/tts/TextToSpeechService.java
core/java/android/text/BoringLayout.java
core/java/android/text/style/TtsSpan.java
core/java/android/view/View.java
core/java/android/view/ViewGroup.java
core/java/android/view/ViewRootImpl.java
core/java/android/view/Window.java
core/java/android/view/WindowManagerGlobal.java
core/java/android/view/textservice/SpellCheckerSubtype.java
core/java/android/webkit/WebView.java
core/java/android/webkit/WebViewFactory.java
core/java/android/webkit/WebViewProvider.java
core/java/android/widget/GridView.java
core/java/android/widget/ImageView.java
core/java/android/widget/ProgressBar.java
core/java/android/widget/TextView.java
core/java/com/android/internal/inputmethod/InputMethodUtils.java
core/java/com/android/internal/os/BatteryStatsImpl.java
core/java/com/android/internal/policy/DecorView.java
core/jni/Android.mk
core/jni/AndroidRuntime.cpp
core/jni/android/graphics/BitmapFactory.cpp
core/jni/android_app_admin_SecurityLog.cpp [new file with mode: 0644]
core/jni/android_graphics_drawable_VectorDrawable.cpp
core/jni/android_media_AudioRecord.cpp
core/jni/android_media_AudioSystem.cpp
core/jni/android_media_AudioTrack.cpp
core/jni/android_view_RenderNode.cpp
core/jni/android_view_Surface.cpp
core/res/AndroidManifest.xml
core/res/res/values/attrs.xml
core/res/res/values/attrs_manifest.xml
core/res/res/values/public.xml
core/res/res/values/styles_material.xml
core/res/res/values/themes_material.xml
core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
data/fonts/Android.mk
docs/html/guide/topics/graphics/hardware-accel.jd
graphics/java/android/graphics/Outline.java
graphics/java/android/graphics/drawable/VectorDrawable.java
libs/hwui/Caches.h
libs/hwui/FrameBuilder.cpp
libs/hwui/Layer.cpp
libs/hwui/VectorDrawable.cpp
libs/hwui/VectorDrawable.h
libs/hwui/renderthread/CanvasContext.cpp
libs/hwui/renderthread/CanvasContext.h
libs/hwui/tests/scripts/prep_volantis.sh
libs/hwui/tests/unit/FrameBuilderTests.cpp
libs/hwui/tests/unit/GlopBuilderTests.cpp
libs/hwui/thread/Barrier.h
location/java/android/location/GnssMeasurement.java
location/java/android/location/GnssNavigationMessage.java
media/java/android/media/AudioManager.java
media/java/android/media/AudioRecord.java
media/java/android/media/AudioTrack.java
media/java/android/media/MediaFormat.java
media/java/android/media/audiopolicy/AudioMix.java
media/java/android/media/audiopolicy/AudioPolicyConfig.java
media/java/android/media/tv/TvInputManager.java
media/jni/android_media_MediaPlayer.cpp
media/jni/audioeffect/android_media_AudioEffect.cpp
media/jni/audioeffect/android_media_Visualizer.cpp
native/android/sensor.cpp
packages/DefaultContainerService/AndroidManifest.xml
packages/DocumentsUI/app-perf-tests/Android.mk [new file with mode: 0644]
packages/DocumentsUI/app-perf-tests/AndroidManifest.xml [new file with mode: 0644]
packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java [new file with mode: 0644]
packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java [new file with mode: 0644]
packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
packages/DocumentsUI/src/com/android/documentsui/Shared.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestModel.java
packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
packages/ExtServices/AndroidManifest.xml
packages/ExtShared/AndroidManifest.xml
packages/FakeOemFeatures/AndroidManifest.xml
packages/FusedLocation/AndroidManifest.xml
packages/InputDevices/AndroidManifest.xml
packages/Keyguard/AndroidManifest.xml
packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java [moved from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java with 83% similarity]
packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java [new file with mode: 0644]
packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
packages/SettingsLib/res/values/strings.xml
packages/SettingsLib/src/com/android/settingslib/Utils.java
packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
packages/SettingsProvider/AndroidManifest.xml
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
packages/Shell/AndroidManifest.xml
packages/SystemUI/AndroidManifest.xml
packages/SystemUI/res/drawable-hdpi/recents_empty.png [deleted file]
packages/SystemUI/res/drawable-mdpi/recents_empty.png [deleted file]
packages/SystemUI/res/drawable-xhdpi/recents_empty.png [deleted file]
packages/SystemUI/res/drawable-xxhdpi/recents_empty.png [deleted file]
packages/SystemUI/res/drawable-xxxhdpi/recents_empty.png [deleted file]
packages/SystemUI/res/drawable/recents_empty.xml [new file with mode: 0644]
packages/SystemUI/res/layout/qs_detail_header.xml
packages/SystemUI/res/layout/recents_on_tv.xml
packages/SystemUI/res/layout/recents_tv_task_card_view.xml
packages/SystemUI/res/layout/remote_input.xml
packages/SystemUI/res/values/colors.xml
packages/SystemUI/res/values/dimens_tv.xml
packages/SystemUI/res/values/strings.xml
packages/SystemUI/res/values/styles.xml
packages/SystemUI/res/values/values_tv.xml
packages/SystemUI/src/com/android/systemui/ExpandHelper.java
packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java [new file with mode: 0644]
packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
packages/services/Proxy/AndroidManifest.xml
services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java
services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
services/core/Android.mk
services/core/java/com/android/server/AppOpsService.java
services/core/java/com/android/server/InputMethodManagerService.java
services/core/java/com/android/server/MountService.java
services/core/java/com/android/server/NetworkManagementService.java
services/core/java/com/android/server/TextServicesManagerService.java
services/core/java/com/android/server/accounts/AccountManagerService.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityStarter.java
services/core/java/com/android/server/am/ProcessStartLogger.java
services/core/java/com/android/server/audio/AudioService.java
services/core/java/com/android/server/input/InputManagerService.java
services/core/java/com/android/server/job/JobSchedulerService.java
services/core/java/com/android/server/net/NetworkPolicyManagerService.java
services/core/java/com/android/server/notification/NotificationManagerService.java
services/core/java/com/android/server/notification/RankingHelper.java
services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
services/core/java/com/android/server/pm/LauncherAppsService.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/pm/PackageManagerShellCommand.java
services/core/java/com/android/server/pm/Settings.java
services/core/java/com/android/server/pm/ShortcutService.java
services/core/java/com/android/server/policy/ShortcutManager.java
services/core/java/com/android/server/wm/WindowState.java
services/core/java/com/android/server/wm/WindowStateAnimator.java
services/core/java/com/android/server/wm/WindowSurfaceController.java
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
services/java/com/android/server/SystemServer.java
services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
telephony/java/android/telephony/CarrierConfigManager.java
test-runner/src/android/test/mock/MockContext.java
test-runner/src/android/test/mock/MockPackageManager.java
tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml [new file with mode: 0644]
tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml [new file with mode: 0644]
tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
tools/fonts/fontchain_lint.py
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java

index 165aed9..cf6d946 100644 (file)
@@ -42,7 +42,7 @@ LOCAL_SRC_FILES := $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS))
 
 # EventLogTags files.
 LOCAL_SRC_FILES += \
-       core/java/android/auditing/SecurityLogTags.logtags \
+       core/java/android/app/admin/SecurityLogTags.logtags \
        core/java/android/content/EventLogTags.logtags \
        core/java/android/speech/tts/EventLogTags.logtags \
        core/java/android/webkit/EventLogTags.logtags \
index 27d53fd..889ed59 100644 (file)
@@ -443,6 +443,7 @@ package android {
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultHeight = 16844021; // 0x10104f5
+    field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int defaultWidth = 16844020; // 0x10104f4
     field public static final int delay = 16843212; // 0x10101cc
@@ -462,6 +463,7 @@ package android {
     field public static final int dialogTheme = 16843528; // 0x1010308
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
+    field public static final int directBootAware = 16844038; // 0x1010506
     field public static final int direction = 16843217; // 0x10101d1
     field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
@@ -510,7 +512,6 @@ package android {
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final int endX = 16844051; // 0x1010513
@@ -559,6 +560,7 @@ package android {
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -574,7 +576,6 @@ package android {
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
-    field public static final int forceDeviceEncrypted = 16844037; // 0x1010505
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -3536,7 +3537,6 @@ package android.app {
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
@@ -4218,7 +4218,6 @@ package android.app {
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5852,7 +5851,6 @@ package android.app.admin {
     method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5901,6 +5899,7 @@ package android.app.admin {
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void reboot(android.content.ComponentName);
@@ -5910,8 +5909,8 @@ package android.app.admin {
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
@@ -5923,7 +5922,6 @@ package android.app.admin {
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -5956,6 +5954,7 @@ package android.app.admin {
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -6041,6 +6040,27 @@ package android.app.admin {
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6245,6 +6265,8 @@ package android.app.job {
     method public long getIntervalMillis();
     method public long getMaxExecutionDelayMillis();
     method public long getMinLatencyMillis();
+    method public static final long getMinimumFlex();
+    method public static final long getMinimumPeriod();
     method public int getNetworkType();
     method public android.content.ComponentName getService();
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
@@ -6258,8 +6280,6 @@ package android.app.job {
     field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
-    field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
-    field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6581,31 +6601,6 @@ package android.appwidget {
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -7979,7 +7974,7 @@ package android.content {
     method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public abstract deprecated void clearWallpaper() throws java.io.IOException;
     method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public abstract android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(android.view.Display);
     method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] databaseList();
@@ -8037,10 +8032,10 @@ package android.content {
     method public abstract deprecated int getWallpaperDesiredMinimumHeight();
     method public abstract deprecated int getWallpaperDesiredMinimumWidth();
     method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public abstract boolean isDeviceEncryptedStorage();
+    method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
-    method public abstract boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public abstract boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
     method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
     method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
@@ -8175,7 +8170,7 @@ package android.content {
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public deprecated void clearWallpaper() throws java.io.IOException;
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -8227,9 +8222,9 @@ package android.content {
     method public deprecated int getWallpaperDesiredMinimumHeight();
     method public deprecated int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9320,10 +9315,9 @@ package android.content.pm {
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
     field public int compatibleWidthLimitDp;
-    field public java.lang.String credentialEncryptedDataDir;
     field public java.lang.String dataDir;
     field public int descriptionRes;
-    field public java.lang.String deviceEncryptedDataDir;
+    field public java.lang.String deviceProtectedDataDir;
     field public boolean enabled;
     field public int flags;
     field public int largestWidthLimitDp;
@@ -9360,8 +9354,8 @@ package android.content.pm {
     method public boolean isEnabled();
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
+    field public boolean directBootAware;
     field public boolean enabled;
-    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9832,11 +9826,10 @@ package android.content.pm {
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
+    field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
-    field public static final int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
     field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -19267,7 +19260,6 @@ package android.location {
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
-    method public boolean isPseudorangeRateCorrected();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
     field public static final int ADR_STATE_RESET = 2; // 0x2
@@ -29376,10 +29368,6 @@ package android.os {
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
     method public boolean isUserUnlocked();
     method public boolean isUserUnlocked(android.os.UserHandle);
@@ -29941,7 +29929,7 @@ package android.preference {
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
     method public void setStorageDefault();
-    method public void setStorageDeviceEncrypted();
+    method public void setStorageDeviceProtected();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -36833,6 +36821,7 @@ package android.telephony {
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -37917,7 +37906,7 @@ package android.test.mock {
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper();
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -37968,9 +37957,9 @@ package android.test.mock {
     method public int getWallpaperDesiredMinimumHeight();
     method public int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -42597,7 +42586,7 @@ package android.view {
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
-    method public void onVisibilityAggregated(android.view.View, int);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -43694,7 +43683,7 @@ package android.view {
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -57460,6 +57449,10 @@ package java.util {
     method public static void parallelSort(T[], int, int);
     method public static void parallelSort(T[], java.util.Comparator<? super T>);
     method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static void setAll(int[], java.util.function.IntUnaryOperator);
+    method public static void setAll(long[], java.util.function.IntToLongFunction);
+    method public static void setAll(double[], java.util.function.IntToDoubleFunction);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
index 8ac2d63..9b5d3ab 100644 (file)
@@ -17,12 +17,40 @@ package android.app.admin {
 
 }
 
+package android.content {
+
+  public abstract class Context {
+    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
+    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
+    method public deprecated boolean isCredentialEncryptedStorage();
+    method public deprecated boolean isDeviceEncryptedStorage();
+    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
+    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+  }
+
+}
+
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String credentialEncryptedDataDir;
+    field public deprecated java.lang.String deviceEncryptedDataDir;
+  }
+
+  public class ComponentInfo extends android.content.pm.PackageItemInfo {
+    field public deprecated boolean encryptionAware;
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public abstract class PackageManager {
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
+    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
+  }
+
 }
 
 package android.database {
@@ -98,6 +126,19 @@ package android.os {
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
+  }
+
+}
+
+package android.preference {
+
+  public class PreferenceManager {
+    method public deprecated void setStorageCredentialEncrypted();
+    method public deprecated void setStorageDeviceEncrypted();
   }
 
 }
index 32fb87f..947aa90 100644 (file)
@@ -538,6 +538,7 @@ package android {
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultHeight = 16844021; // 0x10104f5
+    field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int defaultWidth = 16844020; // 0x10104f4
     field public static final int delay = 16843212; // 0x10101cc
@@ -557,6 +558,7 @@ package android {
     field public static final int dialogTheme = 16843528; // 0x1010308
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
+    field public static final int directBootAware = 16844038; // 0x1010506
     field public static final int direction = 16843217; // 0x10101d1
     field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
@@ -605,7 +607,6 @@ package android {
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final int endX = 16844051; // 0x1010513
@@ -654,6 +655,7 @@ package android {
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -669,7 +671,6 @@ package android {
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
-    field public static final int forceDeviceEncrypted = 16844037; // 0x1010505
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -3653,7 +3654,6 @@ package android.app {
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
@@ -4350,7 +4350,6 @@ package android.app {
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5991,7 +5990,6 @@ package android.app.admin {
     method public int getCurrentFailedPasswordAttempts();
     method public deprecated java.lang.String getDeviceInitializerApp();
     method public deprecated android.content.ComponentName getDeviceInitializerComponent();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwner();
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.lang.String getDeviceOwnerNameOnAnyUser();
@@ -6047,6 +6045,7 @@ package android.app.admin {
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void notifyPendingSystemUpdate(long);
@@ -6057,8 +6056,8 @@ package android.app.admin {
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException;
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
@@ -6071,7 +6070,6 @@ package android.app.admin {
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -6104,6 +6102,7 @@ package android.app.admin {
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -6198,6 +6197,27 @@ package android.app.admin {
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6511,6 +6531,8 @@ package android.app.job {
     method public long getIntervalMillis();
     method public long getMaxExecutionDelayMillis();
     method public long getMinLatencyMillis();
+    method public static final long getMinimumFlex();
+    method public static final long getMinimumPeriod();
     method public int getNetworkType();
     method public android.content.ComponentName getService();
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
@@ -6524,8 +6546,6 @@ package android.app.job {
     field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
-    field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
-    field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6848,31 +6868,6 @@ package android.appwidget {
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -8277,8 +8272,8 @@ package android.content {
     method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public abstract deprecated void clearWallpaper() throws java.io.IOException;
     method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public abstract android.content.Context createCredentialEncryptedStorageContext();
-    method public abstract android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.Context createCredentialProtectedStorageContext();
+    method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(android.view.Display);
     method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] databaseList();
@@ -8336,11 +8331,11 @@ package android.content {
     method public abstract deprecated int getWallpaperDesiredMinimumHeight();
     method public abstract deprecated int getWallpaperDesiredMinimumWidth();
     method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public abstract boolean isCredentialEncryptedStorage();
-    method public abstract boolean isDeviceEncryptedStorage();
+    method public abstract boolean isCredentialProtectedStorage();
+    method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
-    method public abstract boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public abstract boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
     method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
     method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
@@ -8484,8 +8479,8 @@ package android.content {
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public deprecated void clearWallpaper() throws java.io.IOException;
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createCredentialEncryptedStorageContext();
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createCredentialProtectedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -8537,10 +8532,10 @@ package android.content {
     method public deprecated int getWallpaperDesiredMinimumHeight();
     method public deprecated int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isCredentialEncryptedStorage();
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isCredentialProtectedStorage();
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9643,10 +9638,10 @@ package android.content.pm {
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
     field public int compatibleWidthLimitDp;
-    field public java.lang.String credentialEncryptedDataDir;
+    field public java.lang.String credentialProtectedDataDir;
     field public java.lang.String dataDir;
     field public int descriptionRes;
-    field public java.lang.String deviceEncryptedDataDir;
+    field public java.lang.String deviceProtectedDataDir;
     field public boolean enabled;
     field public int flags;
     field public int largestWidthLimitDp;
@@ -9683,8 +9678,8 @@ package android.content.pm {
     method public boolean isEnabled();
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
+    field public boolean directBootAware;
     field public boolean enabled;
-    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9934,6 +9929,7 @@ package android.content.pm {
     method public void setAppIcon(android.graphics.Bitmap);
     method public void setAppLabel(java.lang.CharSequence);
     method public void setAppPackageName(java.lang.String);
+    method public void setDontKillApp(boolean);
     method public void setGrantedRuntimePermissions(java.lang.String[]);
     method public void setInstallLocation(int);
     method public void setOriginatingUid(int);
@@ -10220,11 +10216,10 @@ package android.content.pm {
     field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
+    field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
-    field public static final int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
     field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -15283,7 +15278,7 @@ package android.hardware.location {
   }
 
   public final class ContextHubManager {
-    method public java.lang.Integer[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
+    method public int[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
     method public int[] getContextHubHandles();
     method public android.hardware.location.ContextHubInfo getContextHubInfo(int);
     method public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
@@ -15299,8 +15294,9 @@ package android.hardware.location {
     field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2
   }
 
-  public abstract class ContextHubManager.ContextHubCallback {
-    ctor public ContextHubManager.ContextHubCallback();
+  public static abstract class ContextHubManager.ContextHubCallback {
+    ctor protected ContextHubManager.ContextHubCallback();
+    method public abstract void onMessageReceipt(int, int, android.hardware.location.ContextHubMessage);
   }
 
   public class ContextHubMessage {
@@ -20436,7 +20432,6 @@ package android.location {
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
-    method public boolean isPseudorangeRateCorrected();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
     field public static final int ADR_STATE_RESET = 2; // 0x2
@@ -24712,8 +24707,6 @@ package android.media.tv {
     method public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, android.media.tv.TvInputManager.HardwareCallback, android.media.tv.TvInputInfo);
     method public void addBlockedRating(android.media.tv.TvContentRating);
     method public boolean captureFrame(java.lang.String, android.view.Surface, android.media.tv.TvStreamConfig);
-    method public void createRecordingSession(java.lang.String, android.media.tv.TvInputManager.SessionCallback, android.os.Handler);
-    method public void createSession(java.lang.String, android.media.tv.TvInputManager.SessionCallback, android.os.Handler);
     method public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(java.lang.String);
     method public java.util.List<android.media.tv.TvContentRating> getBlockedRatings();
     method public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
@@ -24765,39 +24758,6 @@ package android.media.tv {
     method public abstract void onStreamConfigChanged(android.media.tv.TvStreamConfig[]);
   }
 
-  public static final class TvInputManager.Session {
-    method public void dispatchSurfaceChanged(int, int, int);
-    method public java.lang.String getSelectedTrack(int);
-    method public java.util.List<android.media.tv.TvTrackInfo> getTracks(int);
-    method public void release();
-    method public void selectTrack(int, java.lang.String);
-    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
-    method public void setCaptionEnabled(boolean);
-    method public void setStreamVolume(float);
-    method public void setSurface(android.view.Surface);
-    method public void tune(android.net.Uri);
-    method public void tune(android.net.Uri, android.os.Bundle);
-  }
-
-  public static abstract class TvInputManager.SessionCallback {
-    ctor public TvInputManager.SessionCallback();
-    method public void onChannelRetuned(android.media.tv.TvInputManager.Session, android.net.Uri);
-    method public void onContentAllowed(android.media.tv.TvInputManager.Session);
-    method public void onContentBlocked(android.media.tv.TvInputManager.Session, android.media.tv.TvContentRating);
-    method public void onLayoutSurface(android.media.tv.TvInputManager.Session, int, int, int, int);
-    method public void onSessionCreated(android.media.tv.TvInputManager.Session);
-    method public void onSessionEvent(android.media.tv.TvInputManager.Session, java.lang.String, android.os.Bundle);
-    method public void onSessionReleased(android.media.tv.TvInputManager.Session);
-    method public void onTimeShiftCurrentPositionChanged(android.media.tv.TvInputManager.Session, long);
-    method public void onTimeShiftStartPositionChanged(android.media.tv.TvInputManager.Session, long);
-    method public void onTimeShiftStatusChanged(android.media.tv.TvInputManager.Session, int);
-    method public void onTrackSelected(android.media.tv.TvInputManager.Session, int, java.lang.String);
-    method public void onTracksChanged(android.media.tv.TvInputManager.Session, java.util.List<android.media.tv.TvTrackInfo>);
-    method public void onVideoAvailable(android.media.tv.TvInputManager.Session);
-    method public void onVideoSizeChanged(android.media.tv.TvInputManager.Session, int, int);
-    method public void onVideoUnavailable(android.media.tv.TvInputManager.Session, int);
-  }
-
   public static abstract class TvInputManager.TvInputCallback {
     ctor public TvInputManager.TvInputCallback();
     method public void onInputAdded(java.lang.String);
@@ -25724,9 +25684,11 @@ package android.net {
 
   public class ScoredNetwork implements android.os.Parcelable {
     ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
+    ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
+    field public final boolean meteredHint;
     field public final android.net.NetworkKey networkKey;
     field public final android.net.RssiCurve rssiCurve;
   }
@@ -31426,6 +31388,7 @@ package android.os {
     field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+    field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
     field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
     field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
     field public static final int USER_ACTIVITY_EVENT_TOUCH = 2; // 0x2
@@ -31718,10 +31681,6 @@ package android.os {
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
     method public boolean isUserUnlocked();
     method public boolean isUserUnlocked(android.os.UserHandle);
@@ -32282,9 +32241,9 @@ package android.preference {
     method public static void setDefaultValues(android.content.Context, java.lang.String, int, int, boolean);
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
-    method public void setStorageCredentialEncrypted();
+    method public void setStorageCredentialProtected();
     method public void setStorageDefault();
-    method public void setStorageDeviceEncrypted();
+    method public void setStorageDeviceProtected();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -39523,6 +39482,7 @@ package android.telephony {
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -40660,8 +40620,8 @@ package android.test.mock {
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper();
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createCredentialEncryptedStorageContext();
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createCredentialProtectedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -40712,10 +40672,10 @@ package android.test.mock {
     method public int getWallpaperDesiredMinimumHeight();
     method public int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isCredentialEncryptedStorage();
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isCredentialProtectedStorage();
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -45351,7 +45311,7 @@ package android.view {
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
-    method public void onVisibilityAggregated(android.view.View, int);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -46449,7 +46409,7 @@ package android.view {
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -48703,12 +48663,13 @@ package android.webkit {
     ctor public WebViewFactory();
     method public static android.content.pm.PackageInfo getLoadedPackageInfo();
     method public static java.lang.String getWebViewPackageName();
-    method public static int loadWebViewNativeLibraryFromPackage(java.lang.String);
+    method public static int loadWebViewNativeLibraryFromPackage(java.lang.String, java.lang.ClassLoader);
     method public static void prepareWebViewInZygote();
     field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize";
     field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2
     field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7
     field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4
+    field public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10; // 0xa
     field public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; // 0x6
     field public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5; // 0x5
     field public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; // 0x3
@@ -48853,7 +48814,9 @@ package android.webkit {
 
   public static abstract interface WebViewProvider.ViewDelegate {
     method public abstract boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public abstract android.view.View findFocus(android.view.View);
     method public abstract android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
+    method public abstract android.os.Handler getHandler(android.os.Handler);
     method public abstract void onActivityResult(int, int, android.content.Intent);
     method public abstract void onAttachedToWindow();
     method public abstract void onConfigurationChanged(android.content.res.Configuration);
@@ -60551,6 +60514,10 @@ package java.util {
     method public static void parallelSort(T[], int, int);
     method public static void parallelSort(T[], java.util.Comparator<? super T>);
     method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static void setAll(int[], java.util.function.IntUnaryOperator);
+    method public static void setAll(long[], java.util.function.IntToLongFunction);
+    method public static void setAll(double[], java.util.function.IntToDoubleFunction);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
index caeecf5..8bf59df 100644 (file)
@@ -15,12 +15,40 @@ package android.app.admin {
 
 }
 
+package android.content {
+
+  public abstract class Context {
+    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
+    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
+    method public deprecated boolean isCredentialEncryptedStorage();
+    method public deprecated boolean isDeviceEncryptedStorage();
+    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
+    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+  }
+
+}
+
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String credentialEncryptedDataDir;
+    field public deprecated java.lang.String deviceEncryptedDataDir;
+  }
+
+  public class ComponentInfo extends android.content.pm.PackageItemInfo {
+    field public deprecated boolean encryptionAware;
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public abstract class PackageManager {
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
+    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
+  }
+
 }
 
 package android.database {
@@ -96,6 +124,19 @@ package android.os {
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
+  }
+
+}
+
+package android.preference {
+
+  public class PreferenceManager {
+    method public deprecated void setStorageCredentialEncrypted();
+    method public deprecated void setStorageDeviceEncrypted();
   }
 
 }
index 45ef839..908a50e 100644 (file)
@@ -443,6 +443,7 @@ package android {
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultHeight = 16844021; // 0x10104f5
+    field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int defaultWidth = 16844020; // 0x10104f4
     field public static final int delay = 16843212; // 0x10101cc
@@ -462,6 +463,7 @@ package android {
     field public static final int dialogTheme = 16843528; // 0x1010308
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
+    field public static final int directBootAware = 16844038; // 0x1010506
     field public static final int direction = 16843217; // 0x10101d1
     field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
@@ -510,7 +512,6 @@ package android {
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final int endX = 16844051; // 0x1010513
@@ -559,6 +560,7 @@ package android {
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -574,7 +576,6 @@ package android {
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
-    field public static final int forceDeviceEncrypted = 16844037; // 0x1010505
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -3536,7 +3537,6 @@ package android.app {
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
@@ -4218,7 +4218,6 @@ package android.app {
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5856,7 +5855,6 @@ package android.app.admin {
     method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5905,6 +5903,7 @@ package android.app.admin {
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void reboot(android.content.ComponentName);
@@ -5914,8 +5913,8 @@ package android.app.admin {
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
@@ -5927,7 +5926,6 @@ package android.app.admin {
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -5960,6 +5958,7 @@ package android.app.admin {
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -6045,6 +6044,27 @@ package android.app.admin {
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6249,6 +6269,8 @@ package android.app.job {
     method public long getIntervalMillis();
     method public long getMaxExecutionDelayMillis();
     method public long getMinLatencyMillis();
+    method public static final long getMinimumFlex();
+    method public static final long getMinimumPeriod();
     method public int getNetworkType();
     method public android.content.ComponentName getService();
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
@@ -6262,8 +6284,6 @@ package android.app.job {
     field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
-    field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
-    field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6585,31 +6605,6 @@ package android.appwidget {
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -7984,7 +7979,7 @@ package android.content {
     method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public abstract deprecated void clearWallpaper() throws java.io.IOException;
     method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public abstract android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(android.view.Display);
     method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] databaseList();
@@ -8043,10 +8038,10 @@ package android.content {
     method public abstract deprecated int getWallpaperDesiredMinimumHeight();
     method public abstract deprecated int getWallpaperDesiredMinimumWidth();
     method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public abstract boolean isDeviceEncryptedStorage();
+    method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
-    method public abstract boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public abstract boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
     method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
     method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
@@ -8181,7 +8176,7 @@ package android.content {
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public deprecated void clearWallpaper() throws java.io.IOException;
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -8234,9 +8229,9 @@ package android.content {
     method public deprecated int getWallpaperDesiredMinimumHeight();
     method public deprecated int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9329,10 +9324,9 @@ package android.content.pm {
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
     field public int compatibleWidthLimitDp;
-    field public java.lang.String credentialEncryptedDataDir;
     field public java.lang.String dataDir;
     field public int descriptionRes;
-    field public java.lang.String deviceEncryptedDataDir;
+    field public java.lang.String deviceProtectedDataDir;
     field public boolean enabled;
     field public int flags;
     field public int largestWidthLimitDp;
@@ -9369,8 +9363,8 @@ package android.content.pm {
     method public boolean isEnabled();
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
+    field public boolean directBootAware;
     field public boolean enabled;
-    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9842,11 +9836,10 @@ package android.content.pm {
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
+    field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
-    field public static final int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
     field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -19297,7 +19290,6 @@ package android.location {
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
-    method public boolean isPseudorangeRateCorrected();
     method public void reset();
     method public void resetCarrierCycles();
     method public void resetCarrierFrequencyHz();
@@ -19315,7 +19307,6 @@ package android.location {
     method public void setCn0DbHz(double);
     method public void setConstellationType(int);
     method public void setMultipathIndicator(int);
-    method public void setPseudorangeRateCorrected(boolean);
     method public void setPseudorangeRateMetersPerSecond(double);
     method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
     method public void setReceivedSvTimeNanos(long);
@@ -29443,10 +29434,6 @@ package android.os {
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
     method public boolean isUserUnlocked();
     method public boolean isUserUnlocked(android.os.UserHandle);
@@ -30008,7 +29995,7 @@ package android.preference {
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
     method public void setStorageDefault();
-    method public void setStorageDeviceEncrypted();
+    method public void setStorageDeviceProtected();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -36905,6 +36892,7 @@ package android.telephony {
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -37989,7 +37977,7 @@ package android.test.mock {
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper();
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -38041,9 +38029,9 @@ package android.test.mock {
     method public int getWallpaperDesiredMinimumHeight();
     method public int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -42671,7 +42659,7 @@ package android.view {
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
-    method public void onVisibilityAggregated(android.view.View, int);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -43768,7 +43756,7 @@ package android.view {
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -57534,6 +57522,10 @@ package java.util {
     method public static void parallelSort(T[], int, int);
     method public static void parallelSort(T[], java.util.Comparator<? super T>);
     method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static void setAll(int[], java.util.function.IntUnaryOperator);
+    method public static void setAll(long[], java.util.function.IntToLongFunction);
+    method public static void setAll(double[], java.util.function.IntToDoubleFunction);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
index 8ac2d63..9b5d3ab 100644 (file)
@@ -17,12 +17,40 @@ package android.app.admin {
 
 }
 
+package android.content {
+
+  public abstract class Context {
+    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
+    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
+    method public deprecated boolean isCredentialEncryptedStorage();
+    method public deprecated boolean isDeviceEncryptedStorage();
+    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
+    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+  }
+
+}
+
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String credentialEncryptedDataDir;
+    field public deprecated java.lang.String deviceEncryptedDataDir;
+  }
+
+  public class ComponentInfo extends android.content.pm.PackageItemInfo {
+    field public deprecated boolean encryptionAware;
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public abstract class PackageManager {
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
+    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
+  }
+
 }
 
 package android.database {
@@ -98,6 +126,19 @@ package android.os {
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
+  }
+
+}
+
+package android.preference {
+
+  public class PreferenceManager {
+    method public deprecated void setStorageCredentialEncrypted();
+    method public deprecated void setStorageDeviceEncrypted();
   }
 
 }
index 8bcbf51..7590325 100644 (file)
@@ -305,7 +305,7 @@ int main(int argc, char* const argv[])
     }
 
     if (zygote) {
-        PreloadPublicNativeLibraries();
+        InitializeNativeLoader();
         runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
     } else if (className) {
         runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
index 75680e6..4019a56 100644 (file)
@@ -688,7 +688,7 @@ public class AccessibilityServiceInfo implements Parcelable {
 
     /** {@hide} */
     public boolean isEncryptionAware() {
-        return mResolveInfo.serviceInfo.encryptionAware;
+        return mResolveInfo.serviceInfo.directBootAware;
     }
 
     /**
index a0a599e..cc1d68e 100644 (file)
@@ -744,7 +744,7 @@ public class Activity extends ContextThemeWrapper
     Activity mParent;
     boolean mCalled;
     /*package*/ boolean mResumed;
-    private boolean mStopped;
+    /*package*/ boolean mStopped;
     boolean mFinished;
     boolean mStartedActivity;
     private boolean mDestroyed;
index f178455..a6e7d67 100644 (file)
@@ -710,6 +710,10 @@ public class ActivityOptions {
 
     /** @hide */
     public ActivityOptions(Bundle opts) {
+        // If the remote side sent us bad parcelables, they won't get the
+        // results they want, which is their loss.
+        opts.setDefusable(true);
+
         mPackageName = opts.getString(KEY_PACKAGE_NAME);
         try {
             mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT);
index 060ac5e..dbc6c84 100644 (file)
@@ -379,6 +379,33 @@ public final class ActivityThread {
                         ? "no component name" : componentName.toShortString())
                 + "}";
         }
+
+        public String getStateString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("ActivityClientRecord{");
+            sb.append("paused=").append(paused);
+            sb.append(", stopped=").append(stopped);
+            sb.append(", hideForNow=").append(hideForNow);
+            sb.append(", startsNotResumed=").append(startsNotResumed);
+            sb.append(", isForward=").append(isForward);
+            sb.append(", pendingConfigChanges=").append(pendingConfigChanges);
+            sb.append(", onlyLocalRequest=").append(onlyLocalRequest);
+            sb.append(", preserveWindow=").append(mPreserveWindow);
+            if (activity != null) {
+                sb.append(", Activity{");
+                sb.append("resumed=").append(activity.mResumed);
+                sb.append(", stopped=").append(activity.mStopped);
+                sb.append(", finished=").append(activity.isFinishing());
+                sb.append(", destroyed=").append(activity.isDestroyed());
+                sb.append(", startedActivity=").append(activity.mStartedActivity);
+                sb.append(", temporaryPause=").append(activity.mTemporaryPause);
+                sb.append(", changingConfigurations=").append(activity.mChangingConfigurations);
+                sb.append(", visibleBehind=").append(activity.mVisibleBehind);
+                sb.append("}");
+            }
+            sb.append("}");
+            return sb.toString();
+        }
     }
 
     final class ProviderClientRecord {
@@ -3752,9 +3779,10 @@ public final class ActivityThread {
                     return;
                 }
                 RuntimeException e = new RuntimeException(
-                        "Performing stop of activity that is not resumed: "
+                        "Performing stop of activity that is already stopped: "
                         + r.intent.getComponent().toShortString());
                 Slog.e(TAG, e.getMessage(), e);
+                Slog.e(TAG, r.getStateString());
             }
 
             if (info != null) {
@@ -5208,9 +5236,9 @@ public final class ActivityThread {
 
             // Setup a location to store generated/compiled graphics code and
             // JIT profiling data. Note that this data is stored in a
-            // device-encrypted storage area, so these caches must never contain
+            // device-protected storage area, so these caches must never contain
             // user sensitive user data.
-            final Context deviceContext = appContext.createDeviceEncryptedStorageContext();
+            final Context deviceContext = appContext.createDeviceProtectedStorageContext();
             final File codeCacheDir = deviceContext.getCodeCacheDir();
             if (codeCacheDir != null) {
                 setupGraphicsSupport(data.info, codeCacheDir);
index cefb22d..5ef03d1 100644 (file)
@@ -2025,6 +2025,15 @@ public class ApplicationPackageManager extends PackageManager {
     }
 
     @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        try {
+            mPM.flushPackageRestrictionsAsUser(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle user) {
         try {
index 32ace14..63a6829 100644 (file)
@@ -400,7 +400,7 @@ class ContextImpl extends Context {
      *
      * @return the number of files moved, or -1 if there was trouble.
      */
-    private static int migrateFiles(File sourceDir, File targetDir, final String prefix) {
+    private static int moveFiles(File sourceDir, File targetDir, final String prefix) {
         final File[] sourceFiles = FileUtils.listFilesOrEmpty(sourceDir, new FilenameFilter() {
             @Override
             public boolean accept(File dir, String name) {
@@ -430,12 +430,12 @@ class ContextImpl extends Context {
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
         synchronized (ContextImpl.class) {
             final File source = sourceContext.getSharedPreferencesPath(name);
             final File target = getSharedPreferencesPath(name);
 
-            final int res = migrateFiles(source.getParentFile(), target.getParentFile(),
+            final int res = moveFiles(source.getParentFile(), target.getParentFile(),
                     source.getName());
             if (res > 0) {
                 // We moved at least one file, so evict any in-memory caches for
@@ -681,11 +681,11 @@ class ContextImpl extends Context {
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
         synchronized (ContextImpl.class) {
             final File source = sourceContext.getDatabasePath(name);
             final File target = getDatabasePath(name);
-            return migrateFiles(source.getParentFile(), target.getParentFile(),
+            return moveFiles(source.getParentFile(), target.getParentFile(),
                     source.getName()) != -1;
         }
     }
@@ -1332,9 +1332,14 @@ class ContextImpl extends Context {
             }
         }
         try {
-            return ActivityManagerNative.getDefault().registerReceiver(
+            final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
                     mMainThread.getApplicationThread(), mBasePackageName,
                     rd, filter, broadcastPermission, userId);
+            if (intent != null) {
+                intent.setExtrasClassLoader(getClassLoader());
+                intent.prepareToEnterProcess();
+            }
+            return intent;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1900,17 +1905,17 @@ class ContextImpl extends Context {
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
-        final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE)
-                | Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE;
+    public Context createDeviceProtectedStorageContext() {
+        final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
+                | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
                 mUser, flags, mDisplay, null, Display.INVALID_DISPLAY);
     }
 
     @Override
-    public Context createCredentialEncryptedStorageContext() {
-        final int flags = (mFlags & ~Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE)
-                | Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE;
+    public Context createCredentialProtectedStorageContext() {
+        final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
+                | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
                 mUser, flags, mDisplay, null, Display.INVALID_DISPLAY);
     }
@@ -1921,13 +1926,13 @@ class ContextImpl extends Context {
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
-        return (mFlags & Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE) != 0;
+    public boolean isDeviceProtectedStorage() {
+        return (mFlags & Context.CONTEXT_DEVICE_PROTECTED_STORAGE) != 0;
     }
 
     @Override
-    public boolean isCredentialEncryptedStorage() {
-        return (mFlags & Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE) != 0;
+    public boolean isCredentialProtectedStorage() {
+        return (mFlags & Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE) != 0;
     }
 
     @Override
@@ -1939,10 +1944,10 @@ class ContextImpl extends Context {
     public File getDataDir() {
         if (mPackageInfo != null) {
             File res = null;
-            if (isCredentialEncryptedStorage()) {
-                res = mPackageInfo.getCredentialEncryptedDataDirFile();
-            } else if (isDeviceEncryptedStorage()) {
-                res = mPackageInfo.getDeviceEncryptedDataDirFile();
+            if (isCredentialProtectedStorage()) {
+                res = mPackageInfo.getCredentialProtectedDataDirFile();
+            } else if (isDeviceProtectedStorage()) {
+                res = mPackageInfo.getDeviceProtectedDataDirFile();
             } else {
                 res = mPackageInfo.getDataDirFile();
             }
@@ -2008,13 +2013,13 @@ class ContextImpl extends Context {
 
         // If creator didn't specify which storage to use, use the default
         // location for application.
-        if ((flags & (Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE
-                | Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE)) == 0) {
+        if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
+                | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
             final File dataDir = packageInfo.getDataDirFile();
-            if (Objects.equals(dataDir, packageInfo.getCredentialEncryptedDataDirFile())) {
-                flags |= Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE;
-            } else if (Objects.equals(dataDir, packageInfo.getDeviceEncryptedDataDirFile())) {
-                flags |= Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE;
+            if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) {
+                flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
+            } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) {
+                flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
             }
         }
 
index a03fd72..e090aa4 100644 (file)
@@ -16,8 +16,6 @@
 
 package android.app;
 
-import android.text.TextUtils;
-import android.util.ArrayMap;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -37,15 +35,17 @@ import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.StrictMode;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.AndroidRuntimeException;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.DisplayAdjustments;
 import android.view.Display;
-import android.os.SystemProperties;
+import android.view.DisplayAdjustments;
 
 import dalvik.system.VMRuntime;
 
@@ -56,11 +56,10 @@ import java.lang.ref.WeakReference;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.URL;
-import java.util.List;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Objects;
 
 final class IntentReceiverLeaked extends AndroidRuntimeException {
@@ -95,8 +94,8 @@ public final class LoadedApk {
     private String mDataDir;
     private String mLibDir;
     private File mDataDirFile;
-    private File mDeviceEncryptedDataDirFile;
-    private File mCredentialEncryptedDataDirFile;
+    private File mDeviceProtectedDataDirFile;
+    private File mCredentialProtectedDataDirFile;
     private final ClassLoader mBaseClassLoader;
     private final boolean mSecurityViolation;
     private final boolean mIncludeCode;
@@ -186,8 +185,8 @@ public final class LoadedApk {
         mSharedLibraries = null;
         mDataDir = null;
         mDataDirFile = null;
-        mDeviceEncryptedDataDirFile = null;
-        mCredentialEncryptedDataDirFile = null;
+        mDeviceProtectedDataDirFile = null;
+        mCredentialProtectedDataDirFile = null;
         mLibDir = null;
         mBaseClassLoader = null;
         mSecurityViolation = false;
@@ -303,8 +302,8 @@ public final class LoadedApk {
         mDataDir = aInfo.dataDir;
         mLibDir = aInfo.nativeLibraryDir;
         mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
-        mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
-        mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
+        mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
+        mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
     }
 
     public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
@@ -651,12 +650,12 @@ public final class LoadedApk {
         return mDataDirFile;
     }
 
-    public File getDeviceEncryptedDataDirFile() {
-        return mDeviceEncryptedDataDirFile;
+    public File getDeviceProtectedDataDirFile() {
+        return mDeviceProtectedDataDirFile;
     }
 
-    public File getCredentialEncryptedDataDirFile() {
-        return mCredentialEncryptedDataDirFile;
+    public File getCredentialProtectedDataDirFile() {
+        return mCredentialProtectedDataDirFile;
     }
 
     public AssetManager getAssets(ActivityThread mainThread) {
@@ -913,6 +912,8 @@ public final class LoadedApk {
                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                 mStrongRef = strong ? rd : null;
             }
+
+            @Override
             public void performReceive(Intent intent, int resultCode, String data,
                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
@@ -996,6 +997,7 @@ public final class LoadedApk {
                 try {
                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
                     intent.setExtrasClassLoader(cl);
+                    intent.prepareToEnterProcess();
                     setExtrasClassLoader(cl);
                     receiver.setPendingResult(this);
                     receiver.onReceive(mContext, intent);
index 132b6dd..e9d0846 100644 (file)
@@ -3197,6 +3197,7 @@ public class Notification implements Parcelable
         }
 
         private void resetStandardTemplateWithActions(RemoteViews big) {
+            big.setViewVisibility(R.id.actions_container, View.GONE);
             big.setViewVisibility(R.id.actions, View.GONE);
             big.removeAllViews(R.id.actions);
 
@@ -3218,6 +3219,7 @@ public class Notification implements Parcelable
 
             int N = mActions.size();
             if (N > 0) {
+                big.setViewVisibility(R.id.actions_container, View.VISIBLE);
                 big.setViewVisibility(R.id.actions, View.VISIBLE);
                 if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
                 for (int i=0; i<N; i++) {
@@ -4580,13 +4582,13 @@ public class Notification implements Parcelable
 
         private void buildIntoRemoteViewContent(RemoteViews remoteViews,
                 RemoteViews customContent) {
-            remoteViews.removeAllViews(R.id.notification_main_column);
-            // Need to clone customContent before adding, because otherwise it can no longer be
-            // parceled independently of remoteViews.
             if (customContent != null) {
+                // Need to clone customContent before adding, because otherwise it can no longer be
+                // parceled independently of remoteViews.
                 customContent = customContent.clone();
+                remoteViews.removeAllViews(R.id.notification_main_column);
+                remoteViews.addView(R.id.notification_main_column, customContent);
             }
-            remoteViews.addView(R.id.notification_main_column, customContent);
             // also update the end margin if there is an image
             int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
                     R.dimen.notification_content_margin_end);
@@ -4689,13 +4691,13 @@ public class Notification implements Parcelable
 
         private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id,
                 RemoteViews customContent) {
-            remoteViews.removeAllViews(id);
-            // Need to clone customContent before adding, because otherwise it can no longer be
-            // parceled independently of remoteViews.
             if (customContent != null) {
+                // Need to clone customContent before adding, because otherwise it can no longer be
+                // parceled independently of remoteViews.
                 customContent = customContent.clone();
+                remoteViews.removeAllViews(id);
+                remoteViews.addView(id, customContent);
             }
-            remoteViews.addView(id, customContent);
             return remoteViews;
         }
     }
index 3be2cdc..dd70b5d 100644 (file)
@@ -268,7 +268,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
             "android.app.action.BUGREPORT_SHARE";
 
     /**
-     * Broadcast action: notify that a new batch of device logs is ready to be collected.
+     * Broadcast action: notify that a new batch of security logs is ready to be collected.
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -623,13 +623,13 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     }
 
     /**
-     * Called when a new batch of device logs can be retrieved.
+     * Called when a new batch of security logs can be retrieved.
      *
      * <p>This callback is only applicable to device owners.
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
-     * @see DevicePolicyManager#retrieveDeviceLogs(ComponentName)
+     * @see DevicePolicyManager#retrieveSecurityLogs(ComponentName)
      */
     public void onSecurityLogsAvailable(Context context, Intent intent) {
     }
index 9094912..b7d9b80 100644 (file)
@@ -25,7 +25,7 @@ import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
 import android.app.Activity;
-import android.auditing.SecurityLog.SecurityEvent;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -5787,63 +5787,80 @@ public class DevicePolicyManager {
     }
 
     /**
-     * Called by device owner to control the device logging feature. Logging can only be enabled on
-     * single user devices where the sole user is managed by the device owner.
-     * <p>
-     * Device logs contain various information intended for security auditing purposes. See
-     * {@link SecurityEvent} for details.
-     * <p>
-     * There must be only one user on the device, managed by the device owner. Otherwise a
-     * {@link SecurityException} will be thrown.
+     * Called by device owner to control the security logging feature. Logging can only be
+     * enabled on single user devices where the sole user is managed by the device owner.
+     *
+     * <p> Security logs contain various information intended for security auditing purposes.
+     * See {@link SecurityEvent} for details.
+     *
+     * <p>There must be only one user on the device, managed by the device owner.
+     * Otherwise a {@link SecurityException} will be thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @param enabled whether device logging should be enabled or not.
+     * @param enabled whether security logging should be enabled or not.
      * @throws SecurityException if {@code admin} is not a device owner.
-     * @see #retrieveDeviceLogs
+     * @see #retrieveSecurityLogs
      */
-    public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+    public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
         try {
-            mService.setDeviceLoggingEnabled(admin, enabled);
+            mService.setSecurityLoggingEnabled(admin, enabled);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Return whether device logging is enabled or not by the device owner.
-     * <p>
-     * Can only be called by the device owner, otherwise a {@link SecurityException} will be thrown.
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+        setSecurityLoggingEnabled(admin, enabled);
+    }
+
+    /**
+     * Return whether security logging is enabled or not by the device owner.
+     *
+     * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
+     * thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise.
+     * @return {@code true} if security logging is enabled by device owner, {@code false} otherwise.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
+    public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) {
         try {
-            return mService.getDeviceLoggingEnabled(admin);
+            return mService.isSecurityLoggingEnabled(admin);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Called by device owner to retrieve all new device logging entries since the last call to this
-     * API after device boots.
-     * <p>
-     * Access to the logs is rate limited and it will only return new logs after the device owner
-     * has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
-     * <p>
-     * There must be only one user on the device, managed by the device owner. Otherwise a
-     * {@link SecurityException} will be thrown.
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
+        return isSecurityLoggingEnabled(admin);
+    }
+
+    /**
+     * Called by device owner to retrieve all new security logging entries since the last call to
+     * this API after device boots.
+     *
+     * <p> Access to the logs is rate limited and it will only return new logs after the device
+     * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
+     *
+     * <p>There must be only one user on the device, managed by the device owner.
+     * Otherwise a {@link SecurityException} will be thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @return the new batch of device logs which is a list of {@link SecurityEvent}, or
-     *         {@code null} if rate limitation is exceeded or if logging is currently disabled.
+     * @return the new batch of security logs which is a list of {@link SecurityEvent},
+     * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
+    public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrieveDeviceLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
             if (list != null) {
                 return list.getList();
             } else {
@@ -5856,6 +5873,14 @@ public class DevicePolicyManager {
     }
 
     /**
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
+        return retrieveSecurityLogs(admin);
+    }
+
+    /**
      * Called by the system to obtain a {@link DevicePolicyManager} whose calls act on the parent
      * profile.
      *
@@ -5886,9 +5911,9 @@ public class DevicePolicyManager {
      * @return Device logs from before the latest reboot of the system.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) {
+    public List<SecurityEvent> retrievePreRebootSecurityLogs(@NonNull ComponentName admin) {
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrievePreviousDeviceLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
             return list.getList();
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
@@ -5896,6 +5921,14 @@ public class DevicePolicyManager {
     }
 
     /**
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) {
+        return retrievePreRebootSecurityLogs(admin);
+    }
+
+    /**
      * Called by a profile owner of a managed profile to set the color used for customization. This
      * color is used as background color of the confirm credentials screen for that user. The
      * default color is {@link android.graphics.Color#GRAY}.
index c38496d..3ba5bd8 100644 (file)
@@ -290,10 +290,10 @@ interface IDevicePolicyManager {
     void setAffiliationIds(in ComponentName admin, in List<String> ids);
     boolean isAffiliatedUser();
 
-    void setDeviceLoggingEnabled(in ComponentName admin, boolean enabled);
-    boolean getDeviceLoggingEnabled(in ComponentName admin);
-    ParceledListSlice retrieveDeviceLogs(in ComponentName admin);
-    ParceledListSlice retrievePreviousDeviceLogs(in ComponentName admin);
+    void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
+    boolean isSecurityLoggingEnabled(in ComponentName admin);
+    ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
+    ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
 
     boolean isUninstallInQueue(String packageName);
     void uninstallPackageWithActiveAdmins(String packageName);
similarity index 98%
rename from core/java/android/auditing/SecurityLog.java
rename to core/java/android/app/admin/SecurityLog.java
index 13823a2..001a81d 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.auditing;
+package android.app.admin;
 
 import android.annotation.IntDef;
 import android.os.Parcel;
@@ -92,7 +92,7 @@ public class SecurityLog {
     public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
 
     /**
-     * Returns if device logging is enabled. Log producers should only write new logs if this is
+     * Returns if security logging is enabled. Log producers should only write new logs if this is
      * true. Under the hood this is the logical AND of whether device owner exists and whether
      * it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}.
      * @hide
@@ -1,6 +1,6 @@
 # See system/core/logcat/event.logtags for a description of the format of this file.
 
-option java_package android.auditing
+option java_package android.app.admin
 
 210001 security_adb_shell_interactive
 210002 security_adb_shell_command               (command|3)
index aeb3156..801c951 100644 (file)
@@ -18,7 +18,6 @@ package android.app.backup;
 
 import android.app.IBackupAgent;
 import android.app.QueuedWork;
-import android.app.backup.IBackupManager;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.ApplicationInfo;
@@ -36,18 +35,17 @@ import android.system.StructStat;
 import android.util.ArraySet;
 import android.util.Log;
 
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 /**
  * Provides the central interface between an
  * application and Android's data backup infrastructure.  An application that wishes
@@ -310,7 +308,7 @@ public abstract class BackupAgent extends ContextWrapper {
 
         // System apps have control over where their default storage context
         // is pointed, so we're always explicit when building paths.
-        final Context ceContext = createCredentialEncryptedStorageContext();
+        final Context ceContext = createCredentialProtectedStorageContext();
         final String rootDir = ceContext.getDataDir().getCanonicalPath();
         final String filesDir = ceContext.getFilesDir().getCanonicalPath();
         final String noBackupDir = ceContext.getNoBackupFilesDir().getCanonicalPath();
@@ -321,7 +319,7 @@ public abstract class BackupAgent extends ContextWrapper {
         final String cacheDir = ceContext.getCacheDir().getCanonicalPath();
         final String codeCacheDir = ceContext.getCodeCacheDir().getCanonicalPath();
 
-        final Context deContext = createDeviceEncryptedStorageContext();
+        final Context deContext = createDeviceProtectedStorageContext();
         final String deviceRootDir = deContext.getDataDir().getCanonicalPath();
         final String deviceFilesDir = deContext.getFilesDir().getCanonicalPath();
         final String deviceNoBackupDir = deContext.getNoBackupFilesDir().getCanonicalPath();
@@ -516,7 +514,7 @@ public abstract class BackupAgent extends ContextWrapper {
         try {
             // System apps have control over where their default storage context
             // is pointed, so we're always explicit when building paths.
-            final Context ceContext = createCredentialEncryptedStorageContext();
+            final Context ceContext = createCredentialProtectedStorageContext();
             rootDir = ceContext.getDataDir().getCanonicalPath();
             filesDir = ceContext.getFilesDir().getCanonicalPath();
             nbFilesDir = ceContext.getNoBackupFilesDir().getCanonicalPath();
@@ -525,7 +523,7 @@ public abstract class BackupAgent extends ContextWrapper {
             cacheDir = ceContext.getCacheDir().getCanonicalPath();
             codeCacheDir = ceContext.getCodeCacheDir().getCanonicalPath();
 
-            final Context deContext = createDeviceEncryptedStorageContext();
+            final Context deContext = createDeviceProtectedStorageContext();
             deviceRootDir = deContext.getDataDir().getCanonicalPath();
             deviceFilesDir = deContext.getFilesDir().getCanonicalPath();
             deviceNbFilesDir = deContext.getNoBackupFilesDir().getCanonicalPath();
index cdc80e3..478024d 100644 (file)
@@ -19,7 +19,7 @@ package android.app.backup;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.XmlResourceParser;
-import android.os.*;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -31,16 +31,15 @@ import android.util.Log;
 import com.android.internal.annotations.VisibleForTesting;
 
 import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.xmlpull.v1.XmlPullParserException;
 /**
  * Global constant definitions et cetera related to the full-backup-to-fd
  * binary format.  Nothing in this namespace is part of any API; it's all
@@ -289,7 +288,7 @@ public class FullBackup {
 
             // System apps have control over where their default storage context
             // is pointed, so we're always explicit when building paths.
-            final Context ceContext = context.createCredentialEncryptedStorageContext();
+            final Context ceContext = context.createCredentialProtectedStorageContext();
             FILES_DIR = ceContext.getFilesDir();
             DATABASE_DIR = ceContext.getDatabasePath("foo").getParentFile();
             ROOT_DIR = ceContext.getDataDir();
@@ -297,7 +296,7 @@ public class FullBackup {
             CACHE_DIR = ceContext.getCacheDir();
             NOBACKUP_DIR = ceContext.getNoBackupFilesDir();
 
-            final Context deContext = context.createDeviceEncryptedStorageContext();
+            final Context deContext = context.createDeviceProtectedStorageContext();
             DEVICE_FILES_DIR = deContext.getFilesDir();
             DEVICE_DATABASE_DIR = deContext.getDatabasePath("foo").getParentFile();
             DEVICE_ROOT_DIR = deContext.getDataDir();
index bbfec41..828ac38 100644 (file)
@@ -73,9 +73,32 @@ public class JobInfo implements Parcelable {
     public static final int BACKOFF_POLICY_EXPONENTIAL = 1;
 
     /* Minimum interval for a periodic job, in milliseconds. */
-    public static final long MIN_PERIOD_MILLIS = 60 * 60 * 1000L;   // 60 minutes
+    private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L;   // 15 minutes
+
     /* Minimum flex for a periodic job, in milliseconds. */
-    public static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes
+    private static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes
+
+    /**
+     * Query the minimum interval allowed for periodic scheduled jobs.  Attempting
+     * to declare a smaller period that this when scheduling a job will result in a
+     * job that is still periodic, but will run with this effective period.
+     *
+     * @return The minimum available interval for scheduling periodic jobs, in milliseconds.
+     */
+    public static final long getMinimumPeriod() {
+        return MIN_PERIOD_MILLIS;
+    }
+
+    /**
+     * Query the minimum flex time allowed for periodic scheduled jobs.  Attempting
+     * to declare a shorter flex time than this when scheduling such a job will
+     * result in this amount as the effective flex time for the job.
+     *
+     * @return The minimum available flex time for scheduling periodic jobs, in milliseconds.
+     */
+    public static final long getMinimumFlex() {
+        return MIN_FLEX_MILLIS;
+    }
 
     /**
      * Default type of backoff.
@@ -227,7 +250,7 @@ public class JobInfo implements Parcelable {
      * job does not recur periodically.
      */
     public long getIntervalMillis() {
-        return intervalMillis >= MIN_PERIOD_MILLIS ? intervalMillis : MIN_PERIOD_MILLIS;
+        return intervalMillis >= getMinimumPeriod() ? intervalMillis : getMinimumPeriod();
     }
 
     /**
@@ -236,7 +259,7 @@ public class JobInfo implements Parcelable {
     public long getFlexMillis() {
         long interval = getIntervalMillis();
         long percentClamp = 5 * interval / 100;
-        long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, MIN_FLEX_MILLIS));
+        long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, getMinimumFlex()));
         return clampedFlex <= interval ? clampedFlex : interval;
     }
 
@@ -565,9 +588,9 @@ public class JobInfo implements Parcelable {
          * Specify that this job should recur with the provided interval and flex. The job can
          * execute at any time in a window of flex length at the end of the period.
          * @param intervalMillis Millisecond interval for which this job will repeat. A minimum
-         *                       value of {@link #MIN_PERIOD_MILLIS} is enforced.
+         *                       value of {@link #getMinimumPeriod()} is enforced.
          * @param flexMillis Millisecond flex for this job. Flex is clamped to be at least
-         *                   {@link #MIN_FLEX_MILLIS} or 5 percent of the period, whichever is
+         *                   {@link #getMinimumFlex()} or 5 percent of the period, whichever is
          *                   higher.
          */
         public Builder setPeriodic(long intervalMillis, long flexMillis) {
index 0ec58ea..58630b0 100644 (file)
@@ -836,6 +836,17 @@ public class ClipData implements Parcelable {
         }
     }
 
+    /** {@hide} */
+    public void prepareToEnterProcess() {
+        final int size = mItems.size();
+        for (int i = 0; i < size; i++) {
+            final Item item = mItems.get(i);
+            if (item.mIntent != null) {
+                item.mIntent.prepareToEnterProcess();
+            }
+        }
+    }
+
     /** @hide */
     public void fixUris(int contentUserHint) {
         final int size = mItems.size();
index c4dfdcf..ca19b9b 100644 (file)
@@ -695,20 +695,26 @@ public abstract class Context {
     public abstract SharedPreferences getSharedPreferences(File file, int mode);
 
     /**
-     * Migrate an existing shared preferences file from the given source storage
+     * Move an existing shared preferences file from the given source storage
      * context to this context. This is typically used to migrate data between
-     * storage locations after an upgrade, such as migrating from credential
-     * encrypted to device encrypted storage.
+     * storage locations after an upgrade, such as moving to device protected
+     * storage.
      *
      * @param sourceContext The source context which contains the existing
-     *            shared preferences to migrate.
+     *            shared preferences to move.
      * @param name The name of the shared preferences file.
-     * @return {@code true} if the migration was successful or if the shared
+     * @return {@code true} if the move was successful or if the shared
      *         preferences didn't exist in the source context, otherwise
      *         {@code false}.
-     * @see #createDeviceEncryptedStorageContext()
+     * @see #createDeviceProtectedStorageContext()
      */
-    public abstract boolean migrateSharedPreferencesFrom(Context sourceContext, String name);
+    public abstract boolean moveSharedPreferencesFrom(Context sourceContext, String name);
+
+    /** @removed */
+    @Deprecated
+    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+        return moveSharedPreferencesFrom(sourceContext, name);
+    }
 
     /**
      * Delete an existing shared preferences file.
@@ -1397,19 +1403,25 @@ public abstract class Context {
             @Nullable DatabaseErrorHandler errorHandler);
 
     /**
-     * Migrate an existing database file from the given source storage context
-     * to this context. This is typically used to migrate data between storage
-     * locations after an upgrade, such as migrating from credential encrypted
-     * to device encrypted storage.
+     * Move an existing database file from the given source storage context to
+     * this context. This is typically used to migrate data between storage
+     * locations after an upgrade, such as migrating to device protected
+     * storage.
      *
      * @param sourceContext The source context which contains the existing
-     *            database to migrate.
+     *            database to move.
      * @param name The name of the database file.
-     * @return {@code true} if the migration was successful or if the database
-     *         didn't exist in the source context, otherwise {@code false}.
-     * @see #createDeviceEncryptedStorageContext()
+     * @return {@code true} if the move was successful or if the database didn't
+     *         exist in the source context, otherwise {@code false}.
+     * @see #createDeviceProtectedStorageContext()
      */
-    public abstract boolean migrateDatabaseFrom(Context sourceContext, String name);
+    public abstract boolean moveDatabaseFrom(Context sourceContext, String name);
+
+    /** @removed */
+    @Deprecated
+    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+        return moveDatabaseFrom(sourceContext, name);
+    }
 
     /**
      * Delete an existing private SQLiteDatabase associated with this Context's
@@ -4038,19 +4050,19 @@ public abstract class Context {
 
     /**
      * Flag for use with {@link #createPackageContext}: point all file APIs at
-     * device-encrypted storage.
+     * device-protected storage.
      *
      * @hide
      */
-    public static final int CONTEXT_DEVICE_ENCRYPTED_STORAGE = 0x00000008;
+    public static final int CONTEXT_DEVICE_PROTECTED_STORAGE = 0x00000008;
 
     /**
      * Flag for use with {@link #createPackageContext}: point all file APIs at
-     * credential-encrypted storage.
+     * credential-protected storage.
      *
      * @hide
      */
-    public static final int CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE = 0x00000010;
+    public static final int CONTEXT_CREDENTIAL_PROTECTED_STORAGE = 0x00000010;
 
     /**
      * @hide Used to indicate we should tell the activity manager about the process
@@ -4154,53 +4166,73 @@ public abstract class Context {
 
     /**
      * Return a new Context object for the current Context but whose storage
-     * APIs are backed by device-encrypted storage.
+     * APIs are backed by device-protected storage.
+     * <p>
+     * When a device is encrypted, data stored in this location is encrypted
+     * with a key tied to the physical device, and it can be accessed
+     * immediately after the device has booted successfully, both
+     * <em>before and after</em> the user has authenticated with their
+     * credentials (such as a lock pattern or PIN).
      * <p>
-     * Data stored in device-encrypted storage is typically encrypted with a key
-     * tied to the physical device, and it can be accessed when the device has
-     * booted successfully, both <em>before and after</em> the user has
-     * authenticated with their credentials (such as a lock pattern or PIN).
-     * Because device-encrypted data is available before user authentication,
-     * you should carefully consider what data you store using this Context.
+     * Because device-protected data is available without user authentication,
+     * you should carefully limit the data you store using this Context. For
+     * example, storing sensitive authentication tokens or passwords in the
+     * device-protected area is strongly discouraged.
      * <p>
      * If the underlying device does not have the ability to store
-     * device-encrypted and credential-encrypted data using different keys, then
-     * both storage areas will become available at the same time. They remain
-     * two distinct storage areas, and only the window of availability changes.
+     * device-protected and credential-protected data using different keys, then
+     * both storage areas will become available at the same time. They remain as
+     * two distinct storage locations on disk, and only the window of
+     * availability changes.
      * <p>
      * Each call to this method returns a new instance of a Context object;
      * Context objects are not shared, however common state (ClassLoader, other
      * Resources for the same configuration) may be so the Context itself can be
      * fairly lightweight.
      *
-     * @see #isDeviceEncryptedStorage()
+     * @see #isDeviceProtectedStorage()
      */
-    public abstract Context createDeviceEncryptedStorageContext();
+    public abstract Context createDeviceProtectedStorageContext();
+
+    /** @removed */
+    @Deprecated
+    public Context createDeviceEncryptedStorageContext() {
+        return createDeviceProtectedStorageContext();
+    }
 
     /**
      * Return a new Context object for the current Context but whose storage
-     * APIs are backed by credential-encrypted storage.
+     * APIs are backed by credential-protected storage. This is the default
+     * storage area for apps unless
+     * {@link android.R.attr#defaultToDeviceProtectedStorage} was requested.
      * <p>
-     * Data stored in credential-encrypted storage is typically encrypted with a
-     * key tied to user credentials, and they can be accessed
+     * When a device is encrypted, data stored in this location is encrypted
+     * with a key tied to user credentials, which can be accessed
      * <em>only after</em> the user has entered their credentials (such as a
      * lock pattern or PIN).
      * <p>
      * If the underlying device does not have the ability to store
-     * device-encrypted and credential-encrypted data using different keys, then
-     * both storage areas will become available at the same time. They remain
-     * two distinct storage areas, and only the window of availability changes.
+     * device-protected and credential-protected data using different keys, then
+     * both storage areas will become available at the same time. They remain as
+     * two distinct storage locations on disk, and only the window of
+     * availability changes.
      * <p>
      * Each call to this method returns a new instance of a Context object;
      * Context objects are not shared, however common state (ClassLoader, other
      * Resources for the same configuration) may be so the Context itself can be
      * fairly lightweight.
      *
-     * @see #isCredentialEncryptedStorage()
+     * @see #isCredentialProtectedStorage()
      * @hide
      */
     @SystemApi
-    public abstract Context createCredentialEncryptedStorageContext();
+    public abstract Context createCredentialProtectedStorageContext();
+
+    /** @removed */
+    @Deprecated
+    public Context createCredentialEncryptedStorageContext() {
+        return createCredentialProtectedStorageContext();
+    }
 
     /**
      * Gets the display adjustments holder for this context.  This information
@@ -4226,19 +4258,31 @@ public abstract class Context {
 
     /**
      * Indicates if the storage APIs of this Context are backed by
-     * device-encrypted storage.
+     * device-protected storage.
      *
-     * @see #createDeviceEncryptedStorageContext()
+     * @see #createDeviceProtectedStorageContext()
      */
-    public abstract boolean isDeviceEncryptedStorage();
+    public abstract boolean isDeviceProtectedStorage();
+
+    /** @removed */
+    @Deprecated
+    public boolean isDeviceEncryptedStorage() {
+        return isDeviceProtectedStorage();
+    }
 
     /**
      * Indicates if the storage APIs of this Context are backed by
-     * credential-encrypted storage.
+     * credential-protected storage.
      *
-     * @see #createCredentialEncryptedStorageContext()
+     * @see #createCredentialProtectedStorageContext()
      * @hide
      */
     @SystemApi
-    public abstract boolean isCredentialEncryptedStorage();
+    public abstract boolean isCredentialProtectedStorage();
+
+    /** @removed */
+    @Deprecated
+    public boolean isCredentialEncryptedStorage() {
+        return isCredentialProtectedStorage();
+    }
 }
index 323c9bf..b2df207 100644 (file)
@@ -33,8 +33,8 @@ import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.UserHandle;
-import android.view.DisplayAdjustments;
 import android.view.Display;
+import android.view.DisplayAdjustments;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -170,8 +170,8 @@ public class ContextWrapper extends Context {
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
-        return mBase.migrateSharedPreferencesFrom(sourceContext, name);
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
+        return mBase.moveSharedPreferencesFrom(sourceContext, name);
     }
 
     @Override
@@ -288,8 +288,8 @@ public class ContextWrapper extends Context {
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
-        return mBase.migrateDatabaseFrom(sourceContext, name);
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
+        return mBase.moveDatabaseFrom(sourceContext, name);
     }
 
     @Override
@@ -818,26 +818,26 @@ public class ContextWrapper extends Context {
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
-        return mBase.createDeviceEncryptedStorageContext();
+    public Context createDeviceProtectedStorageContext() {
+        return mBase.createDeviceProtectedStorageContext();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public Context createCredentialEncryptedStorageContext() {
-        return mBase.createCredentialEncryptedStorageContext();
+    public Context createCredentialProtectedStorageContext() {
+        return mBase.createCredentialProtectedStorageContext();
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
-        return mBase.isDeviceEncryptedStorage();
+    public boolean isDeviceProtectedStorage() {
+        return mBase.isDeviceProtectedStorage();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public boolean isCredentialEncryptedStorage() {
-        return mBase.isCredentialEncryptedStorage();
+    public boolean isCredentialProtectedStorage() {
+        return mBase.isCredentialProtectedStorage();
     }
 }
index 35dbc34..09aad3b 100644 (file)
@@ -6037,13 +6037,20 @@ public class Intent implements Parcelable, Cloneable {
         return mExtras != null && mExtras.hasFileDescriptors();
     }
 
-    /** @hide */
+    /** {@hide} */
     public void setAllowFds(boolean allowFds) {
         if (mExtras != null) {
             mExtras.setAllowFds(allowFds);
         }
     }
 
+    /** {@hide} */
+    public void setDefusable(boolean defusable) {
+        if (mExtras != null) {
+            mExtras.setDefusable(defusable);
+        }
+    }
+
     /**
      * Retrieve extended data from the intent.
      *
@@ -8938,6 +8945,17 @@ public class Intent implements Parcelable, Cloneable {
      * @hide
      */
     public void prepareToEnterProcess() {
+        // We just entered destination process, so we should be able to read all
+        // parcelables inside.
+        setDefusable(true);
+
+        if (mSelector != null) {
+            mSelector.prepareToEnterProcess();
+        }
+        if (mClipData != null) {
+            mClipData.prepareToEnterProcess();
+        }
+
         if (mContentUserHint != UserHandle.USER_CURRENT) {
             if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
                 fixUris(mContentUserHint);
index 58d75f7..104feb5 100644 (file)
@@ -16,7 +16,9 @@
 
 package android.content.pm;
 
+import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
@@ -24,7 +26,6 @@ import android.os.Environment;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
-import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.Printer;
 
@@ -109,8 +110,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
      * include/exclude criteria.
      * <p>If android:allowBackup is set to false, this attribute is ignored.
      *
-     * @see {@link android.content.Context#getNoBackupFilesDir}
-     * @see {@link #FLAG_ALLOW_BACKUP}
+     * @see android.content.Context#getNoBackupFilesDir()
+     * @see #FLAG_ALLOW_BACKUP
      *
      * @hide
      */
@@ -469,20 +470,20 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     public static final int PRIVATE_FLAG_HAS_DOMAIN_URLS = 1<<4;
 
     /**
-     * When set, default data storage directory for given app is pointed at
-     * device-encrypted location.
+     * When set, the default data storage directory for this app is pointed at
+     * the device-protected location.
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED = 1 << 5;
+    public static final int PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = 1 << 5;
 
     /**
-     * When set, assume that all components under the given app are encryption
+     * When set, assume that all components under the given app are direct boot
      * aware, unless otherwise specified.
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_ENCRYPTION_AWARE = 1 << 6;
+    public static final int PRIVATE_FLAG_DIRECT_BOOT_AWARE = 1 << 6;
 
     /**
      * Value for {@link #privateFlags}: set to {@code true} if the application
@@ -493,11 +494,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     public static final int PRIVATE_FLAG_AUTOPLAY = 1 << 7;
 
     /**
-     * When set, at least one component inside this application is encryption aware.
+     * When set, at least one component inside this application is direct boot
+     * aware.
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE = 1 << 8;
+    public static final int PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE = 1 << 8;
 
     /**
      * Value for {@link #flags}: {@code true} if the application is blocked via restrictions
@@ -627,15 +629,28 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     public String dataDir;
 
     /**
-     * Full path to the device-encrypted directory assigned to the package for
+     * Full path to the device-protected directory assigned to the package for
      * its persistent data.
+     *
+     * @see Context#createDeviceProtectedStorageContext()
      */
+    public String deviceProtectedDataDir;
+
+    /** @removed */
+    @Deprecated
     public String deviceEncryptedDataDir;
 
     /**
-     * Full path to the credential-encrypted directory assigned to the package
+     * Full path to the credential-protected directory assigned to the package
      * for its persistent data.
+     *
+     * @hide
      */
+    @SystemApi
+    public String credentialProtectedDataDir;
+
+    /** @removed */
+    @Deprecated
     public String credentialEncryptedDataDir;
 
     /**
@@ -790,8 +805,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
         }
         pw.println(prefix + "dataDir=" + dataDir);
         if ((flags&DUMP_FLAG_DETAILS) != 0) {
-            pw.println(prefix + "deviceEncryptedDataDir=" + deviceEncryptedDataDir);
-            pw.println(prefix + "credentialEncryptedDataDir=" + credentialEncryptedDataDir);
+            pw.println(prefix + "deviceProtectedDataDir=" + deviceProtectedDataDir);
+            pw.println(prefix + "credentialProtectedDataDir=" + credentialProtectedDataDir);
             if (sharedLibraryFiles != null) {
                 pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles));
             }
@@ -889,8 +904,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
         seinfo = orig.seinfo;
         sharedLibraryFiles = orig.sharedLibraryFiles;
         dataDir = orig.dataDir;
-        deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
-        credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
+        deviceEncryptedDataDir = deviceProtectedDataDir = orig.deviceProtectedDataDir;
+        credentialEncryptedDataDir = credentialProtectedDataDir = orig.credentialProtectedDataDir;
         uid = orig.uid;
         minSdkVersion = orig.minSdkVersion;
         targetSdkVersion = orig.targetSdkVersion;
@@ -944,8 +959,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
         dest.writeString(seinfo);
         dest.writeStringArray(sharedLibraryFiles);
         dest.writeString(dataDir);
-        dest.writeString(deviceEncryptedDataDir);
-        dest.writeString(credentialEncryptedDataDir);
+        dest.writeString(deviceProtectedDataDir);
+        dest.writeString(credentialProtectedDataDir);
         dest.writeInt(uid);
         dest.writeString(minSdkVersion);
         dest.writeInt(targetSdkVersion);
@@ -999,8 +1014,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
         seinfo = source.readString();
         sharedLibraryFiles = source.readStringArray();
         dataDir = source.readString();
-        deviceEncryptedDataDir = source.readString();
-        credentialEncryptedDataDir = source.readString();
+        deviceEncryptedDataDir = deviceProtectedDataDir = source.readString();
+        credentialEncryptedDataDir = credentialProtectedDataDir = source.readString();
         uid = source.readInt();
         minSdkVersion = source.readString();
         targetSdkVersion = source.readInt();
@@ -1056,18 +1071,18 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
             return;
         }
 
-        deviceEncryptedDataDir = Environment
+        deviceEncryptedDataDir = deviceProtectedDataDir = Environment
                 .getDataUserDePackageDirectory(volumeUuid, userId, packageName)
                 .getAbsolutePath();
-        credentialEncryptedDataDir = Environment
+        credentialEncryptedDataDir = credentialProtectedDataDir = Environment
                 .getDataUserCePackageDirectory(volumeUuid, userId, packageName)
                 .getAbsolutePath();
 
-        if ((privateFlags & PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED) != 0
-                && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
-            dataDir = deviceEncryptedDataDir;
+        if ((privateFlags & PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0
+                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+            dataDir = deviceProtectedDataDir;
         } else {
-            dataDir = credentialEncryptedDataDir;
+            dataDir = credentialProtectedDataDir;
         }
     }
 
@@ -1134,18 +1149,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     }
 
     /** @hide */
-    public boolean isForceDeviceEncrypted() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED) != 0;
+    public boolean isDefaultToDeviceProtectedStorage() {
+        return (privateFlags
+                & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0;
     }
 
     /** @hide */
-    public boolean isEncryptionAware() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE) != 0;
+    public boolean isDirectBootAware() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE) != 0;
     }
 
     /** @hide */
-    public boolean isPartiallyEncryptionAware() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE) != 0;
+    public boolean isPartiallyDirectBootAware() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0;
     }
 
     /**
index 63a163d..5cd15dd 100644 (file)
@@ -66,10 +66,14 @@ public class ComponentInfo extends PackageItemInfo {
     public boolean exported = false;
 
     /**
-     * Indicate if this component is aware of encryption lifecycle, and can be
+     * Indicates if this component is aware of direct boot lifecycle, and can be
      * safely run before the user has entered their credentials (such as a lock
      * pattern or PIN).
      */
+    public boolean directBootAware = false;
+
+    /** @removed */
+    @Deprecated
     public boolean encryptionAware = false;
 
     public ComponentInfo() {
@@ -82,7 +86,7 @@ public class ComponentInfo extends PackageItemInfo {
         descriptionRes = orig.descriptionRes;
         enabled = orig.enabled;
         exported = orig.exported;
-        encryptionAware = orig.encryptionAware;
+        encryptionAware = directBootAware = orig.directBootAware;
     }
 
     @Override public CharSequence loadLabel(PackageManager pm) {
@@ -160,7 +164,7 @@ public class ComponentInfo extends PackageItemInfo {
             pw.println(prefix + "processName=" + processName);
         }
         pw.println(prefix + "enabled=" + enabled + " exported=" + exported
-                + " encryptionAware=" + encryptionAware);
+                + " directBootAware=" + directBootAware);
         if (descriptionRes != 0) {
             pw.println(prefix + "description=" + descriptionRes);
         }
@@ -194,7 +198,7 @@ public class ComponentInfo extends PackageItemInfo {
         dest.writeInt(descriptionRes);
         dest.writeInt(enabled ? 1 : 0);
         dest.writeInt(exported ? 1 : 0);
-        dest.writeInt(encryptionAware ? 1 : 0);
+        dest.writeInt(directBootAware ? 1 : 0);
     }
     
     protected ComponentInfo(Parcel source) {
@@ -207,9 +211,9 @@ public class ComponentInfo extends PackageItemInfo {
         descriptionRes = source.readInt();
         enabled = (source.readInt() != 0);
         exported = (source.readInt() != 0);
-        encryptionAware = (source.readInt() != 0);
+        encryptionAware = directBootAware = (source.readInt() != 0);
     }
-    
+
     /**
      * @hide
      */
index c684447..dabc652 100644 (file)
@@ -291,6 +291,8 @@ interface IPackageManager {
      */
      ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates);
 
+    void setHomeActivity(in ComponentName className, int userId);
+
     /**
      * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
      */
@@ -314,6 +316,11 @@ interface IPackageManager {
     int getApplicationEnabledSetting(in String packageName, int userId);
 
     /**
+     * As per {@link android.content.pm.PackageManager#flushPackageRestrictionsAsUser}.
+     */
+    void flushPackageRestrictionsAsUser(in int userId);
+
+    /**
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
      */
@@ -535,5 +542,4 @@ interface IPackageManager {
     boolean isPackageDeviceAdminOnAnyUser(String packageName);
 
     List<String> getPreviousCodePaths(in String packageName);
-
 }
index 44bdf4e..cbeed35 100644 (file)
@@ -62,9 +62,9 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
     public String dataDir;
 
     /** {@hide} */
-    public String deviceEncryptedDataDir;
+    public String deviceProtectedDataDir;
     /** {@hide} */
-    public String credentialEncryptedDataDir;
+    public String credentialProtectedDataDir;
 
     /**
      * Full path to the directory where the native JNI libraries are stored.
@@ -92,8 +92,8 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
         splitSourceDirs = orig.splitSourceDirs;
         splitPublicSourceDirs = orig.splitPublicSourceDirs;
         dataDir = orig.dataDir;
-        deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
-        credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
+        deviceProtectedDataDir = orig.deviceProtectedDataDir;
+        credentialProtectedDataDir = orig.credentialProtectedDataDir;
         nativeLibraryDir = orig.nativeLibraryDir;
         handleProfiling = orig.handleProfiling;
         functionalTest = orig.functionalTest;
@@ -117,8 +117,8 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
         dest.writeStringArray(splitSourceDirs);
         dest.writeStringArray(splitPublicSourceDirs);
         dest.writeString(dataDir);
-        dest.writeString(deviceEncryptedDataDir);
-        dest.writeString(credentialEncryptedDataDir);
+        dest.writeString(deviceProtectedDataDir);
+        dest.writeString(credentialProtectedDataDir);
         dest.writeString(nativeLibraryDir);
         dest.writeInt((handleProfiling == false) ? 0 : 1);
         dest.writeInt((functionalTest == false) ? 0 : 1);
@@ -142,8 +142,8 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
         splitSourceDirs = source.readStringArray();
         splitPublicSourceDirs = source.readStringArray();
         dataDir = source.readString();
-        deviceEncryptedDataDir = source.readString();
-        credentialEncryptedDataDir = source.readString();
+        deviceProtectedDataDir = source.readString();
+        credentialProtectedDataDir = source.readString();
         nativeLibraryDir = source.readString();
         handleProfiling = source.readInt() != 0;
         functionalTest = source.readInt() != 0;
@@ -157,8 +157,8 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
         ai.splitSourceDirs = splitSourceDirs;
         ai.splitPublicSourceDirs = splitPublicSourceDirs;
         ai.dataDir = dataDir;
-        ai.deviceEncryptedDataDir = deviceEncryptedDataDir;
-        ai.credentialEncryptedDataDir = credentialEncryptedDataDir;
+        ai.deviceProtectedDataDir = deviceProtectedDataDir;
+        ai.credentialProtectedDataDir = credentialProtectedDataDir;
         ai.nativeLibraryDir = nativeLibraryDir;
     }
 }
index 6f2786a..ed8143e 100644 (file)
@@ -37,7 +37,6 @@ import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.util.ExceptionUtils;
-import android.util.Log;
 
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -47,7 +46,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.MessageDigest;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -393,13 +391,6 @@ public class PackageInstaller {
      * Return list of all known install sessions, regardless of the installer.
      */
     public @NonNull List<SessionInfo> getAllSessions() {
-        final ApplicationInfo info = mContext.getApplicationInfo();
-        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400110) {
-            Log.d(TAG, "Ignoring callback request from old prebuilt");
-            return Collections.EMPTY_LIST;
-        }
-
         try {
             return mInstaller.getAllSessions(mUserId).getList();
         } catch (RemoteException e) {
@@ -597,14 +588,6 @@ public class PackageInstaller {
      *            calling thread.
      */
     public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
-        // TODO: remove this temporary guard once we have new prebuilts
-        final ApplicationInfo info = mContext.getApplicationInfo();
-        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400110) {
-            Log.d(TAG, "Ignoring callback request from old prebuilt");
-            return;
-        }
-
         synchronized (mDelegates) {
             final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
                     handler.getLooper());
@@ -1074,8 +1057,13 @@ public class PackageInstaller {
         }
 
         /** {@hide} */
-        public void setInstallFlagsDontKillApp() {
-            installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+        @SystemApi
+        public void setDontKillApp(boolean dontKillApp) {
+            if (dontKillApp) {
+                installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+            } else {
+                installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
+            }
         }
 
         /** {@hide} */
index c1017fb..1079f97 100644 (file)
@@ -48,6 +48,7 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.storage.VolumeInfo;
 import android.util.AndroidException;
 import android.util.Log;
@@ -69,7 +70,7 @@ public abstract class PackageManager {
     private static final String TAG = "PackageManager";
 
     /** {@hide} */
-    public static final boolean APPLY_FORCE_DEVICE_ENCRYPTED = true;
+    public static final boolean APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = true;
 
     /**
      * This exception is thrown when a given package, application, or component
@@ -154,9 +155,8 @@ public abstract class PackageManager {
             MATCH_DEFAULT_ONLY,
             MATCH_DISABLED_COMPONENTS,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
-            MATCH_ENCRYPTION_AWARE,
-            MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-            MATCH_ENCRYPTION_UNAWARE,
+            MATCH_DIRECT_BOOT_AWARE,
+            MATCH_DIRECT_BOOT_UNAWARE,
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
     })
@@ -173,9 +173,8 @@ public abstract class PackageManager {
             MATCH_DISABLED_COMPONENTS,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
             MATCH_DEFAULT_ONLY,
-            MATCH_ENCRYPTION_AWARE,
-            MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-            MATCH_ENCRYPTION_UNAWARE,
+            MATCH_DIRECT_BOOT_AWARE,
+            MATCH_DIRECT_BOOT_UNAWARE,
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
     })
@@ -365,21 +364,47 @@ public abstract class PackageManager {
     public static final int MATCH_ALL = 0x00020000;
 
     /**
-     * Querying flag: include only components which are encryption unaware in
+     * Querying flag: match components which are direct boot <em>unaware</em> in
      * the returned info, regardless of the current user state.
+     * <p>
+     * When neither {@link #MATCH_DIRECT_BOOT_AWARE} nor
+     * {@link #MATCH_DIRECT_BOOT_UNAWARE} are specified, the default behavior is
+     * to match only runnable components based on the user state. For example,
+     * when a user is started but credentials have not been presented yet, the
+     * user is running "locked" and only {@link #MATCH_DIRECT_BOOT_AWARE}
+     * components are returned. Once the user credentials have been presented,
+     * the user is running "unlocked" and both {@link #MATCH_DIRECT_BOOT_AWARE}
+     * and {@link #MATCH_DIRECT_BOOT_UNAWARE} components are returned.
+     *
+     * @see UserManager#isUserUnlocked()
      */
-    public static final int MATCH_ENCRYPTION_UNAWARE = 0x00040000;
-
-    /**
-     * Querying flag: include only components which are encryption aware in the
-     * returned info, regardless of the current user state.
-     */
-    public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
+    public static final int MATCH_DIRECT_BOOT_UNAWARE = 0x00040000;
 
     /**
-     * Querying flag: include both encryption aware and unaware components in
+     * Querying flag: match components which are direct boot <em>aware</em> in
      * the returned info, regardless of the current user state.
+     * <p>
+     * When neither {@link #MATCH_DIRECT_BOOT_AWARE} nor
+     * {@link #MATCH_DIRECT_BOOT_UNAWARE} are specified, the default behavior is
+     * to match only runnable components based on the user state. For example,
+     * when a user is started but credentials have not been presented yet, the
+     * user is running "locked" and only {@link #MATCH_DIRECT_BOOT_AWARE}
+     * components are returned. Once the user credentials have been presented,
+     * the user is running "unlocked" and both {@link #MATCH_DIRECT_BOOT_AWARE}
+     * and {@link #MATCH_DIRECT_BOOT_UNAWARE} components are returned.
+     *
+     * @see UserManager#isUserUnlocked()
      */
+    public static final int MATCH_DIRECT_BOOT_AWARE = 0x00080000;
+
+    /** @removed */
+    @Deprecated
+    public static final int MATCH_ENCRYPTION_UNAWARE = 0x00040000;
+    /** @removed */
+    @Deprecated
+    public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
+    /** @removed */
+    @Deprecated
     public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = MATCH_ENCRYPTION_AWARE
             | MATCH_ENCRYPTION_UNAWARE;
 
@@ -401,7 +426,8 @@ public abstract class PackageManager {
      * </ul>
      *
      * @see #MATCH_UNINSTALLED_PACKAGES
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @hide
      */
     public static final int MATCH_DEBUG_TRIAGED_MISSING = 0x10000000;
@@ -2742,21 +2768,21 @@ public abstract class PackageManager {
      * class.
      *
      * @param component The full component name (i.e.
-     * com.google.apps.contacts/com.google.apps.contacts.ContactsList) of an Activity
-     * class.
+     *            com.google.apps.contacts/com.google.apps.contacts.
+     *            ContactsList) of an Activity class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return An {@link ActivityInfo} containing information about the activity.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return An {@link ActivityInfo} containing information about the
+     *         activity.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2764,9 +2790,8 @@ public abstract class PackageManager {
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -2778,21 +2803,21 @@ public abstract class PackageManager {
      * class.
      *
      * @param component The full component name (i.e.
-     * com.google.apps.calendar/com.google.apps.calendar.CalendarAlarm) of a Receiver
-     * class.
+     *            com.google.apps.calendar/com.google.apps.calendar.
+     *            CalendarAlarm) of a Receiver class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return An {@link ActivityInfo} containing information about the receiver.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return An {@link ActivityInfo} containing information about the
+     *         receiver.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2800,9 +2825,8 @@ public abstract class PackageManager {
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -2810,25 +2834,24 @@ public abstract class PackageManager {
             @ComponentInfoFlags int flags) throws NameNotFoundException;
 
     /**
-     * Retrieve all of the information we know about a particular service
-     * class.
+     * Retrieve all of the information we know about a particular service class.
      *
      * @param component The full component name (i.e.
-     * com.google.apps.media/com.google.apps.media.BackgroundPlayback) of a Service
-     * class.
+     *            com.google.apps.media/com.google.apps.media.
+     *            BackgroundPlayback) of a Service class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return A {@link ServiceInfo} object containing information about the service.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return A {@link ServiceInfo} object containing information about the
+     *         service.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2836,9 +2859,8 @@ public abstract class PackageManager {
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -2850,21 +2872,21 @@ public abstract class PackageManager {
      * provider class.
      *
      * @param component The full component name (i.e.
-     * com.google.providers.media/com.google.providers.media.MediaProvider) of a
-     * ContentProvider class.
+     *            com.google.providers.media/com.google.providers.media.
+     *            MediaProvider) of a ContentProvider class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return A {@link ProviderInfo} object containing information about the provider.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return A {@link ProviderInfo} object containing information about the
+     *         provider.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2872,9 +2894,8 @@ public abstract class PackageManager {
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3499,36 +3520,37 @@ public abstract class PackageManager {
     public abstract boolean hasSystemFeature(String name, int version);
 
     /**
-     * Determine the best action to perform for a given Intent.  This is how
-     * {@link Intent#resolveActivity} finds an activity if a class has not
-     * been explicitly specified.
-     *
-     * <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
-     * specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
-     * only flag.  You need to do so to resolve the activity in the same way
-     * that {@link android.content.Context#startActivity(Intent)} and
+     * Determine the best action to perform for a given Intent. This is how
+     * {@link Intent#resolveActivity} finds an activity if a class has not been
+     * explicitly specified.
+     * <p>
+     * <em>Note:</em> if using an implicit Intent (without an explicit
+     * ComponentName specified), be sure to consider whether to set the
+     * {@link #MATCH_DEFAULT_ONLY} only flag. You need to do so to resolve the
+     * activity in the same way that
+     * {@link android.content.Context#startActivity(Intent)} and
      * {@link android.content.Intent#resolveActivity(PackageManager)
-     * Intent.resolveActivity(PackageManager)} do.</p>
+     * Intent.resolveActivity(PackageManager)} do.
+     * </p>
      *
      * @param intent An intent containing all of the desired specification
-     *               (action, data, type, category, and/or component).
+     *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}.
      * @return Returns a ResolveInfo object containing the final activity intent
-     *         that was determined to be the best action.  Returns null if no
+     *         that was determined to be the best action. Returns null if no
      *         matching activity was found. If multiple matching activities are
      *         found and there is no default set, returns a ResolveInfo object
      *         containing something else, such as the activity resolver.
-     *
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3536,46 +3558,46 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
     public abstract ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags);
 
     /**
-     * Determine the best action to perform for a given Intent for a given user. This
-     * is how {@link Intent#resolveActivity} finds an activity if a class has not
-     * been explicitly specified.
-     *
-     * <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
-     * specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
-     * only flag.  You need to do so to resolve the activity in the same way
-     * that {@link android.content.Context#startActivity(Intent)} and
+     * Determine the best action to perform for a given Intent for a given user.
+     * This is how {@link Intent#resolveActivity} finds an activity if a class
+     * has not been explicitly specified.
+     * <p>
+     * <em>Note:</em> if using an implicit Intent (without an explicit
+     * ComponentName specified), be sure to consider whether to set the
+     * {@link #MATCH_DEFAULT_ONLY} only flag. You need to do so to resolve the
+     * activity in the same way that
+     * {@link android.content.Context#startActivity(Intent)} and
      * {@link android.content.Intent#resolveActivity(PackageManager)
-     * Intent.resolveActivity(PackageManager)} do.</p>
+     * Intent.resolveActivity(PackageManager)} do.
+     * </p>
      *
      * @param intent An intent containing all of the desired specification
-     *               (action, data, type, category, and/or component).
+     *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}.
      * @param userId The user id.
-     *
      * @return Returns a ResolveInfo object containing the final activity intent
-     *         that was determined to be the best action.  Returns null if no
+     *         that was determined to be the best action. Returns null if no
      *         matching activity was found. If multiple matching activities are
      *         found and there is no default set, returns a ResolveInfo object
      *         containing something else, such as the activity resolver.
-     *
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3583,12 +3605,10 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract ResolveInfo resolveActivityAsUser(Intent intent, @ResolveInfoFlags int flags,
@@ -3599,22 +3619,22 @@ public abstract class PackageManager {
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *         Or, set {@link #MATCH_ALL} to prevent any filtering of the results.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching activity, ordered from best to worst. In other words, the
-     *         first item is what would be returned by {@link #resolveActivity}.
-     *         If there are no matching activities, an empty list is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}. Or, set
+     *            {@link #MATCH_ALL} to prevent any filtering of the results.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching activity, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveActivity}. If there are no matching activities, an
+     *         empty list is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3622,9 +3642,8 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3632,26 +3651,27 @@ public abstract class PackageManager {
             @ResolveInfoFlags int flags);
 
     /**
-     * Retrieve all activities that can be performed for the given intent, for a specific user.
+     * Retrieve all activities that can be performed for the given intent, for a
+     * specific user.
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *         Or, set {@link #MATCH_ALL} to prevent any filtering of the results.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching activity, ordered from best to worst. In other words, the
-     *         first item is what would be returned by {@link #resolveActivity}.
-     *         If there are no matching activities, an empty list is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}. Or, set
+     *            {@link #MATCH_ALL} to prevent any filtering of the results.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching activity, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveActivity}. If there are no matching activities, an
+     *         empty list is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3659,12 +3679,10 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
@@ -3672,36 +3690,35 @@ public abstract class PackageManager {
 
     /**
      * Retrieve a set of activities that should be presented to the user as
-     * similar options.  This is like {@link #queryIntentActivities}, except it
+     * similar options. This is like {@link #queryIntentActivities}, except it
      * also allows you to supply a list of more explicit Intents that you would
      * like to resolve to particular options, and takes care of returning the
      * final ResolveInfo list in a reasonable order, with no duplicates, based
      * on those inputs.
      *
-     * @param caller The class name of the activity that is making the
-     *               request.  This activity will never appear in the output
-     *               list.  Can be null.
-     * @param specifics An array of Intents that should be resolved to the
-     *                  first specific results.  Can be null.
+     * @param caller The class name of the activity that is making the request.
+     *            This activity will never appear in the output list. Can be
+     *            null.
+     * @param specifics An array of Intents that should be resolved to the first
+     *            specific results. Can be null.
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching activity. The list is ordered first by all of the intents resolved
-     *         in <var>specifics</var> and then any additional activities that
-     *         can handle <var>intent</var> but did not get included by one of
-     *         the <var>specifics</var> intents.  If there are no matching
-     *         activities, an empty list is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching activity. The list is ordered first by all of the
+     *         intents resolved in <var>specifics</var> and then any additional
+     *         activities that can handle <var>intent</var> but did not get
+     *         included by one of the <var>specifics</var> intents. If there are
+     *         no matching activities, an empty list is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3709,9 +3726,8 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3723,18 +3739,17 @@ public abstract class PackageManager {
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching receiver, ordered from best to worst. If there are no matching
-     *         receivers, an empty list or null is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching receiver, ordered from best to worst. If there are
+     *         no matching receivers, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3742,9 +3757,8 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3752,24 +3766,23 @@ public abstract class PackageManager {
             @ResolveInfoFlags int flags);
 
     /**
-     * Retrieve all receivers that can handle a broadcast of the given intent, for a specific
-     * user.
+     * Retrieve all receivers that can handle a broadcast of the given intent,
+     * for a specific user.
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userHandle UserHandle of the user being queried.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching receiver, ordered from best to worst. If there are no matching
-     *         receivers, an empty list or null is returned.
-     *
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching receiver, ordered from best to worst. If there are
+     *         no matching receivers, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3777,12 +3790,10 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     @SystemApi
@@ -3810,20 +3821,19 @@ public abstract class PackageManager {
      * Determine the best service to handle for a given Intent.
      *
      * @param intent An intent containing all of the desired specification
-     *               (action, data, type, category, and/or component).
+     *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @return Returns a ResolveInfo object containing the final service intent
-     *         that was determined to be the best action.  Returns null if no
+     *         that was determined to be the best action. Returns null if no
      *         matching service was found.
-     *
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3831,9 +3841,8 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3844,19 +3853,19 @@ public abstract class PackageManager {
      *
      * @param intent The desired intent as per resolveService().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching service, ordered from best to worst. In other words, the first
-     *         item is what would be returned by {@link #resolveService}. If there are
-     *         no matching services, an empty list or null is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching service, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveService}. If there are no matching services, an
+     *         empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3864,9 +3873,8 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3878,20 +3886,20 @@ public abstract class PackageManager {
      *
      * @param intent The desired intent as per resolveService().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userId The user id.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching service, ordered from best to worst. In other words, the first
-     *         item is what would be returned by {@link #resolveService}. If there are
-     *         no matching services, an empty list or null is returned.
-     *
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching service, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveService}. If there are no matching services, an
+     *         empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3899,12 +3907,10 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent,
@@ -3916,19 +3922,18 @@ public abstract class PackageManager {
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userId The user id.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching provider, ordered from best to worst. If there are no
-     *         matching services, an empty list or null is returned.
-     *
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching provider, ordered from best to worst. If there are
+     *         no matching services, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3936,12 +3941,10 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract List<ResolveInfo> queryIntentContentProvidersAsUser(
@@ -3953,18 +3956,17 @@ public abstract class PackageManager {
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching provider, ordered from best to worst. If there are no
-     *         matching services, an empty list or null is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching provider, ordered from best to worst. If there are
+     *         no matching services, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3972,9 +3974,8 @@ public abstract class PackageManager {
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3986,17 +3987,16 @@ public abstract class PackageManager {
      *
      * @param name The name of the provider to find.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return A {@link ProviderInfo} object containing information about the provider.
-     *         If a provider was not found, returns null.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return A {@link ProviderInfo} object containing information about the
+     *         provider. If a provider was not found, returns null.
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -4004,9 +4004,8 @@ public abstract class PackageManager {
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -4018,18 +4017,17 @@ public abstract class PackageManager {
      *
      * @param name The name of the provider to find.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userId The user id.
-     *
-     * @return A {@link ProviderInfo} object containing information about the provider.
-     *         If a provider was not found, returns null.
-     *
+     * @return A {@link ProviderInfo} object containing information about the
+     *         provider. If a provider was not found, returns null.
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -4037,12 +4035,10 @@ public abstract class PackageManager {
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract ProviderInfo resolveContentProviderAsUser(String name,
@@ -4050,29 +4046,28 @@ public abstract class PackageManager {
 
     /**
      * Retrieve content provider information.
-     *
-     * <p><em>Note: unlike most other methods, an empty result set is indicated
+     * <p>
+     * <em>Note: unlike most other methods, an empty result set is indicated
      * by a null return instead of an empty list.</em>
      *
      * @param processName If non-null, limits the returned providers to only
-     *                    those that are hosted by the given process.  If null,
-     *                    all content providers are returned.
+     *            those that are hosted by the given process. If null, all
+     *            content providers are returned.
      * @param uid If <var>processName</var> is non-null, this is the required
-     *        uid owning the requested content providers.
+     *            uid owning the requested content providers.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @return A list of {@link ProviderInfo} objects containing one entry for
      *         each provider either matching <var>processName</var> or, if
      *         <var>processName</var> is null, all known content providers.
      *         <em>If there are no matching providers, null is returned.</em>
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -4080,9 +4075,8 @@ public abstract class PackageManager {
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -4618,13 +4612,13 @@ public abstract class PackageManager {
         final PackageParser parser = new PackageParser();
         final File apkFile = new File(archiveFilePath);
         try {
-            if ((flags & (MATCH_ENCRYPTION_UNAWARE | MATCH_ENCRYPTION_AWARE)) != 0) {
+            if ((flags & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
                 // Caller expressed an explicit opinion about what encryption
                 // aware/unaware components they want to see, so fall through and
                 // give them what they want
             } else {
                 // Caller expressed no opinion, so match everything
-                flags |= MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+                flags |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
             }
 
             PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0);
@@ -5225,7 +5219,6 @@ public abstract class PackageManager {
     public abstract void setComponentEnabledSetting(ComponentName componentName,
             int newState, int flags);
 
-
     /**
      * Return the enabled setting for a package component (activity,
      * receiver, service, provider).  This returns the last value set by
@@ -5283,6 +5276,16 @@ public abstract class PackageManager {
     public abstract int getApplicationEnabledSetting(String packageName);
 
     /**
+     * Flush the package restrictions for a given user to disk. This forces the package restrictions
+     * like component and package enabled settings to be written to disk and avoids the delay that
+     * is otherwise present when changing those settings.
+     *
+     * @param userId Ther userId of the user whose restrictions are to be flushed.
+     * @hide
+     */
+    public abstract void flushPackageRestrictionsAsUser(int userId);
+
+    /**
      * Puts the package in a hidden state, which is almost like an uninstalled state,
      * making the package unavailable, but it doesn't remove the data or the actual
      * package file. Application can be unhidden by either resetting the hidden state
index 7d7be9a..db7ca2a 100644 (file)
@@ -2865,13 +2865,13 @@ public class PackageParser {
             ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
         }
 
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_forceDeviceEncrypted, false)
-                && (flags & PARSE_IS_SYSTEM) != 0) {
-            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED;
+        if (sa.getBoolean(R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
+                false) && (flags & PARSE_IS_SYSTEM) != 0) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
         }
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_encryptionAware, false)
+        if (sa.getBoolean(R.styleable.AndroidManifestApplication_directBootAware, false)
                 && (flags & PARSE_IS_SYSTEM) != 0) {
-            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE;
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
         }
 
         if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
@@ -3493,9 +3493,9 @@ public class PackageParser {
             a.info.lockTaskLaunchMode =
                     sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
 
-            a.info.encryptionAware = sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_encryptionAware,
-                    owner.applicationInfo.isEncryptionAware());
+            a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_directBootAware,
+                    owner.applicationInfo.isDirectBootAware());
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
@@ -3511,14 +3511,14 @@ public class PackageParser {
                 }
             }
 
-            a.info.encryptionAware = sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_encryptionAware,
-                    owner.applicationInfo.isEncryptionAware());
+            a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_directBootAware,
+                    owner.applicationInfo.isDirectBootAware());
         }
 
-        if (a.info.encryptionAware) {
+        if (a.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
-                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE;
+                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
         sa.recycle();
@@ -3732,7 +3732,7 @@ public class PackageParser {
         info.maxRecents = target.info.maxRecents;
         info.layout = target.info.layout;
         info.resizeMode = target.info.resizeMode;
-        info.encryptionAware = target.info.encryptionAware;
+        info.encryptionAware = info.directBootAware = target.info.directBootAware;
 
         Activity a = new Activity(mParseActivityAliasArgs, info);
         if (outError[0] != null) {
@@ -3921,12 +3921,12 @@ public class PackageParser {
             }
         }
 
-        p.info.encryptionAware = sa.getBoolean(
-                R.styleable.AndroidManifestProvider_encryptionAware,
-                owner.applicationInfo.isEncryptionAware());
-        if (p.info.encryptionAware) {
+        p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
+                R.styleable.AndroidManifestProvider_directBootAware,
+                owner.applicationInfo.isDirectBootAware());
+        if (p.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
-                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE;
+                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
         sa.recycle();
@@ -4213,12 +4213,12 @@ public class PackageParser {
             }
         }
 
-        s.info.encryptionAware = sa.getBoolean(
-                R.styleable.AndroidManifestService_encryptionAware,
-                owner.applicationInfo.isEncryptionAware());
-        if (s.info.encryptionAware) {
+        s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
+                R.styleable.AndroidManifestService_directBootAware,
+                owner.applicationInfo.isDirectBootAware());
+        if (s.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
-                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE;
+                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
         sa.recycle();
index 38e0044..e85311d 100644 (file)
@@ -23,8 +23,8 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
 import android.util.ArraySet;
@@ -98,10 +98,10 @@ public class PackageUserState {
             }
         }
 
-        final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
-                && !componentInfo.encryptionAware;
-        final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
-                && componentInfo.encryptionAware;
+        final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
+                && !componentInfo.directBootAware;
+        final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
+                && componentInfo.directBootAware;
         return matchesUnaware || matchesAware;
     }
 
index bb28bde..6162d1a 100644 (file)
@@ -365,7 +365,8 @@ public abstract class RegisteredServicesCache<V> {
     protected List<ResolveInfo> queryIntentServices(int userId) {
         final PackageManager pm = mContext.getPackageManager();
         return pm.queryIntentServicesAsUser(new Intent(mInterfaceName),
-                PackageManager.GET_META_DATA | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                 userId);
     }
 
index e41136c..b5c1f30 100644 (file)
@@ -524,7 +524,7 @@ public class ShortcutInfo implements Parcelable {
     }
 
     /** @hide*/
-    public void setFlags(@ShortcutFlags int flags) {
+    public void replaceFlags(@ShortcutFlags int flags) {
         mFlags = flags;
     }
 
index c4afbfb..b75e653 100644 (file)
@@ -54,10 +54,9 @@ public class SystemSensorManager extends SensorManager {
     private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
 
+    private static final Object sLock = new Object();
     private static boolean sSensorModuleInitialized = false;
-    private static InjectEventQueue mInjectEventQueue = null;
-
-    private final Object mLock = new Object();
+    private static InjectEventQueue sInjectEventQueue = null;
 
     private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
     private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
@@ -84,24 +83,24 @@ public class SystemSensorManager extends SensorManager {
 
     /** {@hide} */
     public SystemSensorManager(Context context, Looper mainLooper) {
-        mMainLooper = mainLooper;
-        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
-        mContext = context;
-        mNativeInstance = nativeCreate(context.getOpPackageName());
-
-        synchronized(mLock) {
+        synchronized(sLock) {
             if (!sSensorModuleInitialized) {
                 sSensorModuleInitialized = true;
                 nativeClassInit();
             }
+        }
 
-            // initialize the sensor list
-            for (int index = 0;;++index) {
-                Sensor sensor = new Sensor();
-                if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
-                mFullSensorsList.add(sensor);
-                mHandleToSensor.put(sensor.getHandle(), sensor);
-            }
+        mMainLooper = mainLooper;
+        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
+        mContext = context;
+        mNativeInstance = nativeCreate(context.getOpPackageName());
+
+        // initialize the sensor list
+        for (int index = 0;;++index) {
+            Sensor sensor = new Sensor();
+            if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
+            mFullSensorsList.add(sensor);
+            mHandleToSensor.put(sensor.getHandle(), sensor);
         }
     }
 
@@ -257,7 +256,7 @@ public class SystemSensorManager extends SensorManager {
     }
 
     protected boolean initDataInjectionImpl(boolean enable) {
-        synchronized (mLock) {
+        synchronized (sLock) {
             if (enable) {
                 boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance);
                 // The HAL does not support injection OR SensorService hasn't been set in DI mode.
@@ -266,15 +265,15 @@ public class SystemSensorManager extends SensorManager {
                     return false;
                 }
                 // Initialize a client for data_injection.
-                if (mInjectEventQueue == null) {
-                    mInjectEventQueue = new InjectEventQueue(mMainLooper, this,
+                if (sInjectEventQueue == null) {
+                    sInjectEventQueue = new InjectEventQueue(mMainLooper, this,
                             mContext.getPackageName());
                 }
             } else {
                 // If data injection is being disabled clean up the native resources.
-                if (mInjectEventQueue != null) {
-                    mInjectEventQueue.dispose();
-                    mInjectEventQueue = null;
+                if (sInjectEventQueue != null) {
+                    sInjectEventQueue.dispose();
+                    sInjectEventQueue = null;
                 }
             }
             return true;
@@ -283,17 +282,17 @@ public class SystemSensorManager extends SensorManager {
 
     protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
             long timestamp) {
-        synchronized (mLock) {
-            if (mInjectEventQueue == null) {
+        synchronized (sLock) {
+            if (sInjectEventQueue == null) {
                 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
                 return false;
             }
-            int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
+            int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
                                                          timestamp);
             // If there are any errors in data injection clean up the native resources.
             if (ret != 0) {
-                mInjectEventQueue.dispose();
-                mInjectEventQueue = null;
+                sInjectEventQueue.dispose();
+                sInjectEventQueue = null;
             }
             return ret == 0;
         }
index 6cc7fec..dfa19b0 100644 (file)
@@ -1196,7 +1196,7 @@ public final class StreamConfigurationMap {
      *
      * <p>In particular these formats are converted:
      * <ul>
-     * <li>ImageFormat.JPEG => HAL_DATASPACE_JFIF
+     * <li>ImageFormat.JPEG => HAL_DATASPACE_V0_JFIF
      * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH
      * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH
      * <li>others => HAL_DATASPACE_UNKNOWN
@@ -1223,7 +1223,7 @@ public final class StreamConfigurationMap {
     static int imageFormatToDataspace(int format) {
         switch (format) {
             case ImageFormat.JPEG:
-                return HAL_DATASPACE_JFIF;
+                return HAL_DATASPACE_V0_JFIF;
             case ImageFormat.DEPTH_POINT_CLOUD:
             case ImageFormat.DEPTH16:
                 return HAL_DATASPACE_DEPTH;
@@ -1633,8 +1633,16 @@ public final class StreamConfigurationMap {
     private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159;
 
 
+    private static final int HAL_DATASPACE_STANDARD_SHIFT = 16;
+    private static final int HAL_DATASPACE_TRANSFER_SHIFT = 22;
+    private static final int HAL_DATASPACE_RANGE_SHIFT = 27;
+
     private static final int HAL_DATASPACE_UNKNOWN = 0x0;
-    private static final int HAL_DATASPACE_JFIF = 0x101;
+    private static final int HAL_DATASPACE_V0_JFIF =
+            (2 << HAL_DATASPACE_STANDARD_SHIFT) |
+            (3 << HAL_DATASPACE_TRANSFER_SHIFT) |
+            (1 << HAL_DATASPACE_RANGE_SHIFT);
+
     private static final int HAL_DATASPACE_DEPTH = 0x1000;
 
     private static final long DURATION_20FPS_NS = 50000000L;
index 38a760a..8deded2 100644 (file)
  */
 package android.hardware.location;
 
-import android.Manifest;
 import android.annotation.SystemApi;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.ServiceConnection;
-import android.hardware.location.ContextHubService;
-import android.hardware.location.NanoAppInstanceInfo;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -29,19 +24,11 @@ import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 /**
- * A class that exposes the Context hubs on a device to
- * applicaions.
+ * A class that exposes the Context hubs on a device to applications.
  *
- * Please not that this class is not expected to be used by
- * unbundled applications. Also, calling applications are
- * expected to have LOCTION_HARDWARE premissions to use this
- * class.
+ * Please note that this class is not expected to be used by unbundled applications. Also, calling
+ * applications are expected to have LOCATION_HARDWARE permissions to use this class.
  *
  * @hide
  */
@@ -49,21 +36,14 @@ import java.util.concurrent.TimeUnit;
 public final class ContextHubManager {
 
     private static final String TAG = "ContextHubManager";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
-    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
-            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
 
-    private final Context mContext;
     private final Looper mMainLooper;
     private IContextHubService mContextHubService;
-    private boolean mContextHubConnected;
     private ContextHubCallback mCallback;
     private Handler mCallbackHandler;
 
     /**
-     * A special context hub identifer meaning any possible hub on
-     * the system.
+     * A special context hub identifier meaning any possible hub on the system.
      */
     public static final int ANY_HUB       = -1;
     /**
@@ -80,19 +60,24 @@ public final class ContextHubManager {
     public static final int MSG_DATA_SEND       = 3;
 
     /**
-     * an interface to receive asynchronous communication from the context hub
+     * An interface to receive asynchronous communication from the context hub.
      */
-    public abstract class ContextHubCallback {
+    public abstract static class ContextHubCallback {
+        protected ContextHubCallback() {}
+
         /**
-         * callback function called on message receipt from context hub
+         * Callback function called on message receipt from context hub.
          *
-         * @param hubId id of the hub of the message
-         * @param nanoAppId identifier for the app that sent the message
-         * @param msg the context hub message
+         * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
+         * @param nanoAppHandle Handle (unique identifier) for the app that sent the message.
+         * @param message The context hub message.
          *
          * @see ContextHubMessage
          */
-        abstract void onMessageReceipt(int hubId, int nanoAppId, ContextHubMessage msg);
+        public abstract void onMessageReceipt(
+                int hubHandle,
+                int nanoAppHandle,
+                ContextHubMessage message);
     }
 
     /**
@@ -104,7 +89,7 @@ public final class ContextHubManager {
         try {
             retVal = getBinder().getContextHubHandles();
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch context hub handles :" + e.toString());
+            Log.e(TAG, "Could not fetch context hub handles : " + e);
         }
         return retVal;
     }
@@ -112,25 +97,24 @@ public final class ContextHubManager {
     /**
      * Get more information about a specific hub.
      *
-     * @param contexthubHandle Handle of context hub
-     *
-     * @return ContextHubInfo  returned information about the hub
+     * @param hubHandle Handle (system-wide unique identifier) of a context hub.
+     * @return ContextHubInfo Information about the requested context hub.
      *
      * @see ContextHubInfo
      */
-    public ContextHubInfo getContextHubInfo(int contexthubHandle) {
+    public ContextHubInfo getContextHubInfo(int hubHandle) {
         ContextHubInfo retVal = null;
         try {
-            retVal = getBinder().getContextHubInfo(contexthubHandle);
+            retVal = getBinder().getContextHubInfo(hubHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch context hub info :" + e.toString());
+            Log.e(TAG, "Could not fetch context hub info :" + e);
         }
 
         return retVal;
     }
 
     /**
-     * Load a nanoapp on a specified context hub
+     * Load a nano app on a specified context hub.
      *
      * @param hubHandle handle of context hub to load the app on.
      * @param app the nanoApp to load on the hub
@@ -149,7 +133,7 @@ public final class ContextHubManager {
         try {
             retVal = getBinder().loadNanoApp(hubHandle, app);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch load nanoApp :" + e.toString());
+            Log.e(TAG, "Could not fetch load nanoApp :" + e);
         }
 
         return retVal;
@@ -158,17 +142,17 @@ public final class ContextHubManager {
     /**
      * Unload a specified nanoApp
      *
-     * @param nanoAppInstanceHandle handle of the nanoApp to load
+     * @param nanoAppHandle handle of the nanoApp to load
      *
-     * @return int  0 on success, -1 otherewise
+     * @return int  0 on success, -1 otherwise
      */
-    public int unloadNanoApp(int nanoAppInstanceHandle) {
+    public int unloadNanoApp(int nanoAppHandle) {
         int retVal = -1;
 
         try {
-            retVal = getBinder().unloadNanoApp(nanoAppInstanceHandle);
+            retVal = getBinder().unloadNanoApp(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch unload nanoApp :" + e.toString());
+            Log.e(TAG, "Could not fetch unload nanoApp :" + e);
         }
 
         return retVal;
@@ -177,20 +161,18 @@ public final class ContextHubManager {
     /**
      * get information about the nano app instance
      *
-     * @param nanoAppInstanceHandle handle of the nanoAppInstance
-     *
-     * @return NanoAppInstanceInfo Inforamtion about the nano app
-     *         instance.
+     * @param nanoAppHandle handle of the nanoAppInstance
+     * @return NanoAppInstanceInfo Information about the nano app instance.
      *
      * @see NanoAppInstanceInfo
      */
-    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) {
+    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
         NanoAppInstanceInfo retVal = null;
 
         try {
-            retVal = getBinder().getNanoAppInstanceInfo(nanoAppInstanceHandle);
+            retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch nanoApp info :" + e.toString());
+            Log.e(TAG, "Could not fetch nanoApp info :" + e);
         }
 
         return retVal;
@@ -204,33 +186,24 @@ public final class ContextHubManager {
      *
      * @see NanoAppFilter
      *
-     * @return Integer[] Array of handles to any found nano apps
+     * @return int[] Array of handles to any found nano apps
      */
-    public Integer[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
-        int[] temp;
-        Integer[] retVal = null;
-
+    public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
+        int[] retVal = null;
         try {
-            temp = getBinder().findNanoAppOnHub(hubHandle, filter);
-            retVal = new Integer[temp.length];
-            for (int i = 0; i < temp.length; i++) {
-                retVal[i] = temp[i];
-            }
+            retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not query nanoApp instance :" + e.toString());
+            Log.e(TAG, "Could not query nanoApp instance :" + e);
         }
-
         return retVal;
     }
 
     /**
-     * Send a message to a spcific nano app instance on a context
-     * hub
-     *
+     * Send a message to a specific nano app instance on a context hub.
      *
      * @param hubHandle handle of the hub to send the message to
      * @param nanoAppHandle  handle of the nano app to send to
-     * @param msg Message to be sent
+     * @param message Message to be sent
      *
      * @see ContextHubMessage
      *
@@ -251,7 +224,6 @@ public final class ContextHubManager {
     /**
      * Set a callback to receive messages from the context hub
      *
-     *
      * @param callback Callback object
      *
      * @see ContextHubCallback
@@ -265,9 +237,8 @@ public final class ContextHubManager {
     /**
      * Set a callback to receive messages from the context hub
      *
-     *
      * @param callback Callback object
-     * @param hander Hander object
+     * @param handler Handler object
      *
      * @see ContextHubCallback
      *
@@ -286,8 +257,7 @@ public final class ContextHubManager {
     }
 
     /**
-     * Unregister a callback for receive messages from the context
-     * hub
+     * Unregister a callback for receive messages from the context hub.
      *
      * @see ContextHubCallback
      *
@@ -308,14 +278,10 @@ public final class ContextHubManager {
       return 0;
     }
 
-    private void checkPermissions() {
-        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
-    }
-
     private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
         @Override
         public void onMessageReceipt(final int hubId, final int nanoAppId,
-                final ContextHubMessage message) throws RemoteException {
+                final ContextHubMessage message) {
             if (mCallback != null) {
                 synchronized(this) {
                     final ContextHubCallback callback = mCallback;
@@ -336,8 +302,6 @@ public final class ContextHubManager {
 
     /** @hide */
     public ContextHubManager(Context context, Looper mainLooper) {
-        checkPermissions();
-        mContext = context;
         mMainLooper = mainLooper;
 
         IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
@@ -347,7 +311,7 @@ public final class ContextHubManager {
             try {
                 getBinder().registerCallback(mClientCallback);
             } catch (RemoteException e) {
-                Log.e(TAG, "Could not register callback:" + e.toString());
+                Log.e(TAG, "Could not register callback:" + e);
             }
 
         } else {
index 658d90b..274babe 100644 (file)
 
 package android.hardware.location;
 
-import android.app.Service;
+import android.Manifest;
 import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -32,6 +30,9 @@ import java.util.HashMap;
 public class ContextHubService extends IContextHubService.Stub {
 
     private static final String TAG = "ContextHubService";
+    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
 
     public static final String CONTEXTHUB_SERVICE = "contexthub_service";
 
@@ -56,6 +57,7 @@ public class ContextHubService extends IContextHubService.Stub {
 
     @Override
     public int registerCallback(IContextHubCallback callback) throws RemoteException{
+        checkPermissions();
         mCallback = callback;
         return 0;
     }
@@ -83,6 +85,7 @@ public class ContextHubService extends IContextHubService.Stub {
 
     @Override
     public int[] getContextHubHandles() throws RemoteException {
+        checkPermissions();
         int [] returnArray = new int[mContextHubInfo.length];
 
         for (int i = 0; i < returnArray.length; ++i) {
@@ -96,6 +99,7 @@ public class ContextHubService extends IContextHubService.Stub {
 
     @Override
     public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
+        checkPermissions();
         contextHubHandle -= 1;
         if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
             return null; // null means fail
@@ -106,6 +110,7 @@ public class ContextHubService extends IContextHubService.Stub {
 
     @Override
     public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
+        checkPermissions();
         contextHubHandle -= 1;
 
         if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
@@ -123,11 +128,12 @@ public class ContextHubService extends IContextHubService.Stub {
         return nativeSendMessage(msgHeader, app.getAppBinary());
     }
 
-      @Override
-      public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+    @Override
+    public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+        checkPermissions();
         NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
         if (info == null) {
-          return -1; //means failed
+            return -1; //means failed
         }
 
         // Call Native interface here
@@ -137,10 +143,12 @@ public class ContextHubService extends IContextHubService.Stub {
         msgHeader[2] = info.getHandle();
 
         return nativeSendMessage(msgHeader, null);
-      }
+    }
 
     @Override
-    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) throws RemoteException {
+    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
+            throws RemoteException {
+        checkPermissions();
         // This assumes that all the nanoAppInfo is current. This is reasonable
         // for the use cases for tightly controlled nanoApps.
         if (mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
@@ -152,6 +160,7 @@ public class ContextHubService extends IContextHubService.Stub {
 
     @Override
     public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
+        checkPermissions();
         ArrayList<Integer> foundInstances = new ArrayList<Integer>();
 
         for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
@@ -171,7 +180,9 @@ public class ContextHubService extends IContextHubService.Stub {
     }
 
     @Override
-    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException {
+    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
+            throws RemoteException {
+        checkPermissions();
         int[] msgHeader = new int[8];
         msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
         msgHeader[1] = hubHandle;
@@ -181,5 +192,9 @@ public class ContextHubService extends IContextHubService.Stub {
 
         return nativeSendMessage(msgHeader, msg.getData());
     }
+
+    private void checkPermissions() {
+        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+    }
 }
 
index 2dfb061..8582150 100644 (file)
@@ -43,6 +43,16 @@ public class ScoredNetwork implements Parcelable {
     public final RssiCurve rssiCurve;
 
     /**
+     * A boolean value that indicates whether or not the network is believed to be metered.
+     *
+     * <p>A network can be classified as metered if the user would be
+     * sensitive to heavy data usage on that connection due to monetary costs,
+     * data limitations or battery/performance issues. A typical example would
+     * be a wifi connection where the user would be charged for usage.
+     */
+    public final boolean meteredHint;
+
+    /**
      * Construct a new {@link ScoredNetwork}.
      *
      * @param networkKey the {@link NetworkKey} uniquely identifying this network.
@@ -54,8 +64,26 @@ public class ScoredNetwork implements Parcelable {
      *     the scorer may choose to issue an out-of-band update at any time.
      */
     public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) {
+        this(networkKey, rssiCurve, false /* meteredHint */);
+    }
+
+    /**
+     * Construct a new {@link ScoredNetwork}.
+     *
+     * @param networkKey the {@link NetworkKey} uniquely identifying this network.
+     * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+     *     RSSI. This field is optional, and may be skipped to represent a network which the scorer
+     *     has opted not to score at this time. Passing a null value here is strongly preferred to
+     *     not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+     *     indicates to the system not to request scores for this network in the future, although
+     *     the scorer may choose to issue an out-of-band update at any time.
+     * @param meteredHint A boolean value indicating whether or not the network is believed to be
+     *     metered.
+     */
+    public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint) {
         this.networkKey = networkKey;
         this.rssiCurve = rssiCurve;
+        this.meteredHint = meteredHint;
     }
 
     private ScoredNetwork(Parcel in) {
@@ -65,6 +93,7 @@ public class ScoredNetwork implements Parcelable {
         } else {
             rssiCurve = null;
         }
+        meteredHint = in.readByte() != 0;
     }
 
     @Override
@@ -81,6 +110,7 @@ public class ScoredNetwork implements Parcelable {
         } else {
             out.writeByte((byte) 0);
         }
+        out.writeByte((byte) (meteredHint ? 1 : 0));
     }
 
     @Override
@@ -90,18 +120,20 @@ public class ScoredNetwork implements Parcelable {
 
         ScoredNetwork that = (ScoredNetwork) o;
 
-        return Objects.equals(networkKey, that.networkKey) &&
-                Objects.equals(rssiCurve, that.rssiCurve);
+        return Objects.equals(networkKey, that.networkKey)
+            && Objects.equals(rssiCurve, that.rssiCurve)
+            && Objects.equals(meteredHint, that.meteredHint);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(networkKey, rssiCurve);
+        return Objects.hash(networkKey, rssiCurve, meteredHint);
     }
 
     @Override
     public String toString() {
-        return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]";
+        return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve
+            + ",meteredHint=" + meteredHint + "]";
     }
 
     public static final Parcelable.Creator<ScoredNetwork> CREATOR =
index a1c5bb2..7e0b1a5 100644 (file)
  */
 
 package android.os;
+
 import android.util.AndroidRuntimeException;
 
 /**
- * The object you are calling has died, because its hosting process
- * no longer exists.
+ * Exception thrown when a {@link Parcelable} is malformed or otherwise invalid.
+ * <p>
+ * This is typically encountered when a custom {@link Parcelable} object is
+ * passed to another process that doesn't have the same {@link Parcelable} class
+ * in its {@link ClassLoader}.
  */
 public class BadParcelableException extends AndroidRuntimeException {
     public BadParcelableException(String msg) {
index 5c71373..6e50155 100644 (file)
@@ -26,7 +26,9 @@ import java.util.ArrayList;
 import java.util.Set;
 
 /**
- * A mapping from String values to various types.
+ * A mapping from String keys to values of various types. In most cases, you
+ * should work directly with either the {@link Bundle} or
+ * {@link PersistableBundle} subclass.
  */
 public class BaseBundle {
     private static final String TAG = "Bundle";
@@ -35,6 +37,32 @@ public class BaseBundle {
     // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
     static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
 
+    /**
+     * Flag indicating that this Bundle is okay to "defuse." That is, it's okay
+     * for system processes to ignore any {@link BadParcelableException}
+     * encountered when unparceling it, leaving an empty bundle in its place.
+     * <p>
+     * This should <em>only</em> be set when the Bundle reaches its final
+     * destination, otherwise a system process may clobber contents that were
+     * destined for an app that could have unparceled them.
+     */
+    static final int FLAG_DEFUSABLE = 1 << 0;
+
+    private static volatile boolean sShouldDefuse = false;
+
+    /**
+     * Set global variable indicating that any Bundles parsed in this process
+     * should be "defused." That is, any {@link BadParcelableException}
+     * encountered will be suppressed and logged, leaving an empty Bundle
+     * instead of crashing.
+     *
+     * @hide
+     */
+    public static void setShouldDefuse(boolean shouldDefuse) {
+        sShouldDefuse = shouldDefuse;
+    }
+
+    /** {@hide} */
     static final Parcel EMPTY_PARCEL;
 
     static {
@@ -58,6 +86,9 @@ public class BaseBundle {
      */
     private ClassLoader mClassLoader;
 
+    /** {@hide} */
+    int mFlags;
+
     /**
      * Constructs a new, empty Bundle that uses a specific ClassLoader for
      * instantiating Parcelable and Serializable objects.
@@ -197,6 +228,11 @@ public class BaseBundle {
             return;
         }
 
+        if (sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {
+            Log.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may "
+                    + "clobber all data inside!", new Throwable());
+        }
+
         if (mParcelledData == EMPTY_PARCEL) {
             if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
                     + ": empty");
@@ -221,9 +257,19 @@ public class BaseBundle {
             mMap.erase();
             mMap.ensureCapacity(N);
         }
-        mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
-        mParcelledData.recycle();
-        mParcelledData = null;
+        try {
+            mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
+        } catch (BadParcelableException e) {
+            if (sShouldDefuse) {
+                Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
+                mMap.erase();
+            } else {
+                throw e;
+            }
+        } finally {
+            mParcelledData.recycle();
+            mParcelledData = null;
+        }
         if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
                 + " final map: " + mMap);
     }
@@ -1371,9 +1417,8 @@ public class BaseBundle {
             return;
         }
 
-        int magic = parcel.readInt();
+        final int magic = parcel.readInt();
         if (magic != BUNDLE_MAGIC) {
-            //noinspection ThrowableInstanceNeverThrown
             throw new IllegalStateException("Bad magic number for Bundle: 0x"
                     + Integer.toHexString(magic));
         }
index e1c7ad7..6df2a9d 100644 (file)
@@ -477,10 +477,10 @@ public abstract class BatteryStats implements Parcelable {
          * also be bumped.
          */
         static final String[] USER_ACTIVITY_TYPES = {
-            "other", "button", "touch"
+            "other", "button", "touch", "accessibility"
         };
         
-        public static final int NUM_USER_ACTIVITY_TYPES = 3;
+        public static final int NUM_USER_ACTIVITY_TYPES = 4;
 
         public abstract void noteUserActivityLocked(int type);
         public abstract boolean hasUserActivity();
index 74699fd..1097cad 100644 (file)
@@ -27,11 +27,17 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * A mapping from String values to various Parcelable types.
+ * A mapping from String keys to various {@link Parcelable} values.
  *
+ * @see PersistableBundle
  */
 public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
+    private static final int FLAG_HAS_FDS = 1 << 8;
+    private static final int FLAG_HAS_FDS_KNOWN = 1 << 9;
+    private static final int FLAG_ALLOW_FDS = 1 << 10;
+
     public static final Bundle EMPTY;
+
     static final Parcel EMPTY_PARCEL;
 
     static {
@@ -40,15 +46,12 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
         EMPTY_PARCEL = BaseBundle.EMPTY_PARCEL;
     }
 
-    private boolean mHasFds = false;
-    private boolean mFdsKnown = true;
-    private boolean mAllowFds = true;
-
     /**
      * Constructs a new, empty Bundle.
      */
     public Bundle() {
         super();
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -59,16 +62,18 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
      */
     Bundle(Parcel parcelledData) {
         super(parcelledData);
-
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     /* package */ Bundle(Parcel parcelledData, int length) {
         super(parcelledData, length);
-
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     /**
@@ -80,6 +85,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
      */
     public Bundle(ClassLoader loader) {
         super(loader);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -90,6 +96,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
      */
     public Bundle(int capacity) {
         super(capacity);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -100,9 +107,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
      */
     public Bundle(Bundle b) {
         super(b);
-
-        mHasFds = b.mHasFds;
-        mFdsKnown = b.mFdsKnown;
+        mFlags = b.mFlags;
     }
 
     /**
@@ -113,6 +118,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
      */
     public Bundle(PersistableBundle b) {
         super(b);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -145,14 +151,37 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
         return super.getClassLoader();
     }
 
-    /** @hide */
+    /** {@hide} */
     public boolean setAllowFds(boolean allowFds) {
-        boolean orig = mAllowFds;
-        mAllowFds = allowFds;
+        final boolean orig = (mFlags & FLAG_ALLOW_FDS) != 0;
+        if (allowFds) {
+            mFlags |= FLAG_ALLOW_FDS;
+        } else {
+            mFlags &= ~FLAG_ALLOW_FDS;
+        }
         return orig;
     }
 
     /**
+     * Mark if this Bundle is okay to "defuse." That is, it's okay for system
+     * processes to ignore any {@link BadParcelableException} encountered when
+     * unparceling it, leaving an empty bundle in its place.
+     * <p>
+     * This should <em>only</em> be set when the Bundle reaches its final
+     * destination, otherwise a system process may clobber contents that were
+     * destined for an app that could have unparceled them.
+     *
+     * @hide
+     */
+    public void setDefusable(boolean defusable) {
+        if (defusable) {
+            mFlags |= FLAG_DEFUSABLE;
+        } else {
+            mFlags &= ~FLAG_DEFUSABLE;
+        }
+    }
+
+    /**
      * Clones the current Bundle. The internal map is cloned, but the keys and
      * values to which it refers are copied by reference.
      */
@@ -167,9 +196,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
     @Override
     public void clear() {
         super.clear();
-
-        mHasFds = false;
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -182,16 +209,20 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
         bundle.unparcel();
         mMap.putAll(bundle.mMap);
 
-        // fd state is now known if and only if both bundles already knew
-        mHasFds |= bundle.mHasFds;
-        mFdsKnown = mFdsKnown && bundle.mFdsKnown;
+        // FD state is now known if and only if both bundles already knew
+        if ((bundle.mFlags & FLAG_HAS_FDS) != 0) {
+            mFlags |= FLAG_HAS_FDS;
+        }
+        if ((bundle.mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
+            mFlags &= ~FLAG_HAS_FDS_KNOWN;
+        }
     }
 
     /**
      * Reports whether the bundle contains any parcelled file descriptors.
      */
     public boolean hasFileDescriptors() {
-        if (!mFdsKnown) {
+        if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
             boolean fdFound = false;    // keep going until we find one or run out of data
 
             if (mParcelledData != null) {
@@ -247,10 +278,12 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
                 }
             }
 
-            mHasFds = fdFound;
-            mFdsKnown = true;
+            if (fdFound) {
+                mFlags |= FLAG_HAS_FDS;
+            }
+            mFlags |= FLAG_HAS_FDS_KNOWN;
         }
-        return mHasFds;
+        return (mFlags & FLAG_HAS_FDS) != 0;
     }
 
     /**
@@ -346,7 +379,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
     public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -384,7 +417,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
     public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -399,14 +432,14 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
             @Nullable ArrayList<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /** {@hide} */
     public void putParcelableList(String key, List<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -421,7 +454,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
             @Nullable SparseArray<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -1074,7 +1107,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
      */
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
+        final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0);
         try {
             super.writeToParcelInner(parcel, flags);
         } finally {
@@ -1089,8 +1122,10 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
      */
     public void readFromParcel(Parcel parcel) {
         super.readFromParcelInner(parcel);
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     @Override
@@ -1105,5 +1140,4 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
         }
         return "Bundle[" + mMap.toString() + "]";
     }
-
 }
index 1b79497..dd73e53 100644 (file)
@@ -605,6 +605,30 @@ public class FileUtils {
      */
     public static File buildUniqueFile(File parent, String mimeType, String displayName)
             throws FileNotFoundException {
+        final String[] parts = splitFileName(mimeType, displayName);
+        final String name = parts[0];
+        final String ext = parts[1];
+        File file = buildFile(parent, name, ext);
+
+        // If conflicting file, try adding counter suffix
+        int n = 0;
+        while (file.exists()) {
+            if (n++ >= 32) {
+                throw new FileNotFoundException("Failed to create unique file");
+            }
+            file = buildFile(parent, name + " (" + n + ")", ext);
+        }
+
+        return file;
+    }
+
+    /**
+     * Splits file name into base name and extension.
+     * If the display name doesn't have an extension that matches the requested MIME type, the
+     * extension is regarded as a part of filename and default extension for that MIME type is
+     * appended.
+     */
+    public static String[] splitFileName(String mimeType, String displayName) {
         String name;
         String ext;
 
@@ -642,18 +666,11 @@ public class FileUtils {
             }
         }
 
-        File file = buildFile(parent, name, ext);
-
-        // If conflicting file, try adding counter suffix
-        int n = 0;
-        while (file.exists()) {
-            if (n++ >= 32) {
-                throw new FileNotFoundException("Failed to create unique file");
-            }
-            file = buildFile(parent, name + " (" + n + ")", ext);
+        if (ext == null) {
+            ext = "";
         }
 
-        return file;
+        return new String[] { name, ext };
     }
 
     private static File buildFile(File parent, String name, String ext) {
index 5872f74..b947c97 100644 (file)
@@ -18,7 +18,9 @@ package android.os;
 
 import android.annotation.Nullable;
 import android.util.ArrayMap;
+
 import com.android.internal.util.XmlUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -26,9 +28,11 @@ import org.xmlpull.v1.XmlSerializer;
 import java.io.IOException;
 
 /**
- * A mapping from String values to various types that can be saved to persistent and later
- * restored.
+ * A mapping from String keys to values of various types. The set of types
+ * supported by this class is purposefully restricted to simple objects that can
+ * safely be persisted to and restored from disk.
  *
+ * @see Bundle
  */
 public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable,
         XmlUtils.WriteMapCallback {
@@ -57,6 +61,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
      */
     public PersistableBundle() {
         super();
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -67,6 +72,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
      */
     public PersistableBundle(int capacity) {
         super(capacity);
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -77,6 +83,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
      */
     public PersistableBundle(PersistableBundle b) {
         super(b);
+        mFlags = b.mFlags;
     }
 
 
@@ -101,6 +108,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
      */
     private PersistableBundle(ArrayMap<String, Object> map) {
         super();
+        mFlags = FLAG_DEFUSABLE;
 
         // First stuff everything in.
         putAll(map);
@@ -123,6 +131,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
 
     /* package */ PersistableBundle(Parcel parcelledData, int length) {
         super(parcelledData, length);
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -278,5 +287,4 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
         }
         return "PersistableBundle[" + mMap.toString() + "]";
     }
-
 }
index 2a4507c..cb4caea 100644 (file)
@@ -318,6 +318,13 @@ public final class PowerManager {
     public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
 
     /**
+     * User activity event type: Accessibility taking action on behalf of user.
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3;
+
+    /**
      * User activity flag: If already dimmed, extend the dim timeout
      * but do not brighten.  This flag is useful for keeping the screen on
      * a little longer without causing a visible change such as when
index e2675b1..92e1862 100644 (file)
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.os;
 
 import android.Manifest;
@@ -882,25 +883,13 @@ public class UserManager {
         }
     }
 
-    /**
-     * Return whether the calling user is running in a "locked" state. A user is
-     * unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndLocked() {
         return isUserRunningAndLocked(Process.myUserHandle());
     }
 
-    /**
-     * Return whether the given user is running in a "locked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     *
-     * @param user to retrieve the unlocked state for.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndLocked(UserHandle user) {
         try {
@@ -911,25 +900,13 @@ public class UserManager {
         }
     }
 
-    /**
-     * Return whether the calling user is running in an "unlocked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndUnlocked() {
         return isUserRunningAndUnlocked(Process.myUserHandle());
     }
 
-    /**
-     * Return whether the given user is running in an "unlocked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     *
-     * @param user to retrieve the unlocked state for.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndUnlocked(UserHandle user) {
         try {
@@ -944,7 +921,11 @@ public class UserManager {
      * Return whether the calling user is running in an "unlocked" state. A user
      * is unlocked only after they've entered their credentials (such as a lock
      * pattern or PIN), and credential-encrypted private app data storage is
+     * available. When a user is locked, only device-protected data storage is
      * available.
+     *
+     * @see Intent#ACTION_USER_UNLOCKED
+     * @see Context#createDeviceProtectedStorageContext()
      */
     public boolean isUserUnlocked() {
         return isUserUnlocked(Process.myUserHandle());
@@ -953,10 +934,13 @@ public class UserManager {
     /**
      * Return whether the given user is running in an "unlocked" state. A user
      * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
+     * pattern or PIN), and credential-protected private app data storage is
+     * available. When a user is locked, only device-protected data storage is
      * available.
      *
      * @param user to retrieve the unlocked state for.
+     * @see Intent#ACTION_USER_UNLOCKED
+     * @see Context#createDeviceProtectedStorageContext()
      */
     public boolean isUserUnlocked(UserHandle user) {
         return isUserUnlocked(user.getIdentifier());
index ebb12fd..c36680c 100644 (file)
@@ -113,8 +113,8 @@ public class PreferenceManager {
     private int mSharedPreferencesMode;
 
     private static final int STORAGE_DEFAULT = 0;
-    private static final int STORAGE_DEVICE_ENCRYPTED = 1;
-    private static final int STORAGE_CREDENTIAL_ENCRYPTED = 2;
+    private static final int STORAGE_DEVICE_PROTECTED = 1;
+    private static final int STORAGE_CREDENTIAL_PROTECTED = 2;
 
     private int mStorage = STORAGE_DEFAULT;
 
@@ -360,35 +360,58 @@ public class PreferenceManager {
 
     /**
      * Explicitly set the storage location used internally by this class to be
-     * device-encrypted storage.
+     * device-protected storage.
      * <p>
-     * Data stored in device-encrypted storage is typically encrypted with a key
-     * tied to the physical device, and it can be accessed when the device has
-     * booted successfully, both <em>before and after</em> the user has
-     * authenticated with their credentials (such as a lock pattern or PIN).
-     * Because device-encrypted data is available before user authentication,
-     * you should carefully consider what data you store using this mode.
+     * <p>
+     * When a device is encrypted, data stored in this location is encrypted
+     * with a key tied to the physical device, and it can be accessed
+     * immediately after the device has booted successfully, both
+     * <em>before and after</em> the user has authenticated with their
+     * credentials (such as a lock pattern or PIN).
+     * <p>
+     * Because device-protected data is available without user authentication,
+     * you should carefully limit the data you store using this Context. For
+     * example, storing sensitive authentication tokens or passwords in the
+     * device-protected area is strongly discouraged.
      *
-     * @see Context#createDeviceEncryptedStorageContext()
+     * @see Context#createDeviceProtectedStorageContext()
      */
-    public void setStorageDeviceEncrypted() {
-        mStorage = STORAGE_DEVICE_ENCRYPTED;
+    public void setStorageDeviceProtected() {
+        mStorage = STORAGE_DEVICE_PROTECTED;
         mSharedPreferences = null;
     }
 
+    /** @removed */
+    @Deprecated
+    public void setStorageDeviceEncrypted() {
+        setStorageDeviceProtected();
+    }
+
     /**
      * Explicitly set the storage location used internally by this class to be
-     * credential-encrypted storage.
+     * credential-protected storage. This is the default storage area for apps
+     * unless {@code forceDeviceProtectedStorage} was requested.
+     * <p>
+     * When a device is encrypted, data stored in this location is encrypted
+     * with a key tied to user credentials, which can be accessed
+     * <em>only after</em> the user has entered their credentials (such as a
+     * lock pattern or PIN).
      *
-     * @see Context#createCredentialEncryptedStorageContext()
+     * @see Context#createCredentialProtectedStorageContext()
      * @hide
      */
     @SystemApi
-    public void setStorageCredentialEncrypted() {
-        mStorage = STORAGE_CREDENTIAL_ENCRYPTED;
+    public void setStorageCredentialProtected() {
+        mStorage = STORAGE_CREDENTIAL_PROTECTED;
         mSharedPreferences = null;
     }
 
+    /** @removed */
+    @Deprecated
+    public void setStorageCredentialEncrypted() {
+        setStorageCredentialProtected();
+    }
+
     /**
      * Gets a SharedPreferences instance that preferences managed by this will
      * use.
@@ -400,11 +423,11 @@ public class PreferenceManager {
         if (mSharedPreferences == null) {
             final Context storageContext;
             switch (mStorage) {
-                case STORAGE_DEVICE_ENCRYPTED:
-                    storageContext = mContext.createDeviceEncryptedStorageContext();
+                case STORAGE_DEVICE_PROTECTED:
+                    storageContext = mContext.createDeviceProtectedStorageContext();
                     break;
-                case STORAGE_CREDENTIAL_ENCRYPTED:
-                    storageContext = mContext.createCredentialEncryptedStorageContext();
+                case STORAGE_CREDENTIAL_PROTECTED:
+                    storageContext = mContext.createCredentialProtectedStorageContext();
                     break;
                 default:
                     storageContext = mContext;
index 2445bc2..1ec00db 100644 (file)
@@ -38,6 +38,8 @@ import android.util.Log;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
+import com.android.internal.annotations.GuardedBy;
+
 /**
  * Turns a {@link SeekBar} into a volume control.
  * @hide
@@ -67,6 +69,10 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
     private Observer mVolumeObserver;
     private int mOriginalStreamVolume;
     private int mLastAudibleStreamVolume;
+    // When the old handler is destroyed and a new one is created, there could be a situation where
+    // this is accessed at the same time in different handlers. So, access to this field needs to be
+    // synchronized.
+    @GuardedBy("this")
     private Ringtone mRingtone;
     private int mLastProgress = -1;
     private boolean mMuted;
@@ -174,9 +180,11 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
     }
 
     private void onInitSample() {
-        mRingtone = RingtoneManager.getRingtone(mContext, mDefaultUri);
-        if (mRingtone != null) {
-            mRingtone.setStreamType(mStreamType);
+        synchronized (this) {
+            mRingtone = RingtoneManager.getRingtone(mContext, mDefaultUri);
+            if (mRingtone != null) {
+                mRingtone.setStreamType(mStreamType);
+            }
         }
     }
 
@@ -192,16 +200,19 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
             if (mCallback != null) {
                 mCallback.onSampleStarting(this);
             }
-            if (mRingtone != null) {
-                try {
-                    mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
-                            .getAudioAttributes())
-                            .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
-                                    AudioAttributes.FLAG_BYPASS_MUTE)
-                            .build());
-                    mRingtone.play();
-                } catch (Throwable e) {
-                    Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e);
+
+            synchronized (this) {
+                if (mRingtone != null) {
+                    try {
+                        mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
+                                .getAudioAttributes())
+                                .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
+                                        AudioAttributes.FLAG_BYPASS_MUTE)
+                                .build());
+                        mRingtone.play();
+                    } catch (Throwable e) {
+                        Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e);
+                    }
                 }
             }
         }
@@ -216,8 +227,10 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
     }
 
     private void onStopSample() {
-        if (mRingtone != null) {
-            mRingtone.stop();
+        synchronized (this) {
+            if (mRingtone != null) {
+                mRingtone.stop();
+            }
         }
     }
 
@@ -274,7 +287,9 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
     }
 
     public boolean isSamplePlaying() {
-        return mRingtone != null && mRingtone.isPlaying();
+        synchronized (this) {
+            return mRingtone != null && mRingtone.isPlaying();
+        }
     }
 
     public void startSample() {
index 136abab..5fc2899 100755 (executable)
@@ -2093,7 +2093,7 @@ public final class Settings {
          */
         public static void clearConfiguration(Configuration inoutConfig) {
             inoutConfig.fontScale = 0;
-            if (!inoutConfig.userSetLocale) {
+            if (!inoutConfig.userSetLocale && !inoutConfig.getLocales().isEmpty()) {
                 inoutConfig.setLocales(LocaleList.getEmptyLocaleList());
             }
         }
@@ -2708,24 +2708,6 @@ public final class Settings {
         public static final String VOLUME_MASTER = "volume_master";
 
         /**
-         * Master volume mute (int 1 = mute, 0 = not muted).
-         *
-         * @hide
-         */
-        public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
-
-        private static final Validator VOLUME_MASTER_MUTE_VALIDATOR = sBooleanValidator;
-
-        /**
-         * Microphone mute (int 1 = mute, 0 = not muted).
-         *
-         * @hide
-         */
-        public static final String MICROPHONE_MUTE = "microphone_mute";
-
-        private static final Validator MICROPHONE_MUTE_VALIDATOR = sBooleanValidator;
-
-        /**
          * Master mono (int 1 = mono, 0 = normal).
          *
          * @hide
@@ -3515,8 +3497,6 @@ public final class Settings {
             PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
             PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
             PRIVATE_SETTINGS.add(VOLUME_MASTER);
-            PRIVATE_SETTINGS.add(VOLUME_MASTER_MUTE);
-            PRIVATE_SETTINGS.add(MICROPHONE_MUTE);
             PRIVATE_SETTINGS.add(MASTER_MONO);
             PRIVATE_SETTINGS.add(NOTIFICATIONS_USE_RING_VOLUME);
             PRIVATE_SETTINGS.add(VIBRATE_IN_SILENT);
@@ -3594,8 +3574,6 @@ public final class Settings {
             VALIDATORS.put(ADVANCED_SETTINGS, ADVANCED_SETTINGS_VALIDATOR);
             VALIDATORS.put(SCREEN_AUTO_BRIGHTNESS_ADJ, SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR);
             VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR);
-            VALIDATORS.put(VOLUME_MASTER_MUTE, VOLUME_MASTER_MUTE_VALIDATOR);
-            VALIDATORS.put(MICROPHONE_MUTE, MICROPHONE_MUTE_VALIDATOR);
             VALIDATORS.put(MASTER_MONO, MASTER_MONO_VALIDATOR);
             VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR);
             VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR);
index d4fea53..ed7534d 100644 (file)
@@ -16,7 +16,7 @@
 package android.speech.tts;
 
 import android.content.Context;
-import android.media.AudioSystem;
+import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.net.Uri;
 import android.os.ConditionVariable;
@@ -57,7 +57,7 @@ class AudioPlaybackQueueItem extends PlaybackQueueItem {
         int sessionId = mAudioParams.mSessionId;
         mPlayer = MediaPlayer.create(
                 mContext, mUri, null, mAudioParams.mAudioAttributes,
-                sessionId > 0 ? sessionId : AudioSystem.AUDIO_SESSION_ALLOCATE);
+                sessionId > 0 ? sessionId : AudioManager.AUDIO_SESSION_ID_GENERATE);
         if (mPlayer == null) {
             dispatcher.dispatchOnError(TextToSpeech.ERROR_OUTPUT);
             return;
index fc075de..1eaa7cf 100644 (file)
@@ -19,7 +19,7 @@ import android.annotation.NonNull;
 import android.app.Service;
 import android.content.Intent;
 import android.media.AudioAttributes;
-import android.media.AudioSystem;
+import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -659,7 +659,7 @@ public abstract class TextToSpeechService extends Service {
         /**
          * Audio session identifier. May be used to associate audio playback with one of the
          * {@link android.media.audiofx.AudioEffect} objects. If not specified by client,
-         * it should be equal to {@link AudioSystem#AUDIO_SESSION_ALLOCATE}.
+         * it should be equal to {@link AudioManager#AUDIO_SESSION_ID_GENERATE}.
          */
         public final int mSessionId;
 
@@ -684,7 +684,7 @@ public abstract class TextToSpeechService extends Service {
 
         /** Create AudioOutputParams with default values */
         AudioOutputParams() {
-            mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+            mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
             mVolume = Engine.DEFAULT_VOLUME;
             mPan = Engine.DEFAULT_PAN;
             mAudioAttributes = null;
@@ -722,7 +722,7 @@ public abstract class TextToSpeechService extends Service {
             return new AudioOutputParams(
                     paramsBundle.getInt(
                             Engine.KEY_PARAM_SESSION_ID,
-                            AudioSystem.AUDIO_SESSION_ALLOCATE),
+                            AudioManager.AUDIO_SESSION_ID_GENERATE),
                     paramsBundle.getFloat(
                             Engine.KEY_PARAM_VOLUME,
                             Engine.DEFAULT_VOLUME),
index bfe5c3f..a1bc2d1 100644 (file)
@@ -247,23 +247,22 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
      */
     public static Metrics isBoring(CharSequence text, TextPaint paint,
             TextDirectionHeuristic textDir, Metrics metrics) {
-        char[] temp = TextUtils.obtain(500);
-        int length = text.length();
+        final int MAX_BUF_LEN = 500;
+        final char[] buffer = TextUtils.obtain(MAX_BUF_LEN);
+        final int textLength = text.length();
         boolean boring = true;
 
         outer:
-        for (int i = 0; i < length; i += 500) {
-            int j = i + 500;
+        for (int start = 0; start < textLength; start += MAX_BUF_LEN) {
+            final int end = Math.min(start + MAX_BUF_LEN, textLength);
 
-            if (j > length)
-                j = length;
+            // No need to worry about getting half codepoints, since we reject surrogate code units
+            // as non-boring as soon we see one.
+            TextUtils.getChars(text, start, end, buffer, 0);
 
-            TextUtils.getChars(text, i, j, temp, 0);
-
-            int n = j - i;
-
-            for (int a = 0; a < n; a++) {
-                char c = temp[a];
+            final int len = end - start;
+            for (int i = 0; i < len; i++) {
+                final char c = buffer[i];
 
                 if (c == '\n' || c == '\t' ||
                         (c >= 0x0590 && c <= 0x08FF) ||  // RTL scripts
@@ -279,17 +278,19 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
                 }
             }
 
-            if (textDir != null && textDir.isRtl(temp, 0, n)) {
+            // TODO: This looks a little suspicious, and in some cases can result in O(n^2)
+            // run time. Consider moving outside the loop.
+            if (textDir != null && textDir.isRtl(buffer, 0, len)) {
                boring = false;
                break outer;
             }
         }
 
-        TextUtils.recycle(temp);
+        TextUtils.recycle(buffer);
 
         if (boring && text instanceof Spanned) {
             Spanned sp = (Spanned) text;
-            Object[] styles = sp.getSpans(0, length, ParagraphStyle.class);
+            Object[] styles = sp.getSpans(0, textLength, ParagraphStyle.class);
             if (styles.length > 0) {
                 boring = false;
             }
@@ -302,7 +303,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
             }
 
             TextLine line = TextLine.obtain();
-            line.set(paint, text, 0, length, Layout.DIR_LEFT_TO_RIGHT,
+            line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
                     Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null);
             fm.width = (int) Math.ceil(line.metrics(fm));
             TextLine.recycle(line);
index 93a156b..e9153dd 100644 (file)
@@ -1013,7 +1013,7 @@ public class TtsSpan implements ParcelableSpan {
          * @return This instance.
          */
         public MeasureBuilder setIntegerPart(long integerPart) {
-            return setNumber(String.valueOf(integerPart));
+            return setIntegerPart(String.valueOf(integerPart));
         }
 
         /**
index 55393b1..a7bf73a 100644 (file)
@@ -10210,44 +10210,38 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
      *
-     * @param changedView the view that changed, either <code>this</code> or an ancestor
-     * @param visibility aggregated visibility of this view's parent or changedView, whichever
-     *                   is closer
-     * @return the aggregated visibility for this view
+     * @param isVisible true if this view's visibility to the user is uninterrupted by its
+     *                  ancestors or by window visibility
+     * @return true if this view is visible to the user, not counting clipping or overlapping
      */
-    int dispatchVisibilityAggregated(View changedView, @Visibility int visibility) {
-        visibility = Math.max(visibility, getVisibility());
-        onVisibilityAggregated(changedView, visibility);
-        return visibility;
+    @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
+        final boolean thisVisible = getVisibility() == VISIBLE;
+        if (thisVisible) {
+            onVisibilityAggregated(isVisible);
+        }
+        return thisVisible && isVisible;
     }
 
     /**
      * Called when the user-visibility of this View is potentially affected by a change
      * to this view itself, an ancestor view or the window this view is attached to.
      *
-     * <p>The visibility value reported will be one of {@link #VISIBLE}, {@link #INVISIBLE}
-     * or {@link #GONE}, reflecting this view's aggregated visibility within its window.
-     * The visibility parameter takes this view's own visibility into account.
-     * Calls to this method may be repeated with the same visibility values; implementations
-     * should ensure that work done is not duplicated unnecessarily.</p>
-     *
-     * @param changedView the view that changed; may be <code>this</code> or an ancestor
-     * @param visibility the visibility of this view in the context of the full window
+     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
+     *                  and this view's window is also visible
      */
     @CallSuper
-    public void onVisibilityAggregated(View changedView, @Visibility int visibility) {
-        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
-        if (visible && mAttachInfo != null) {
+    public void onVisibilityAggregated(boolean isVisible) {
+        if (isVisible && mAttachInfo != null) {
             initialAwakenScrollBars();
         }
 
         final Drawable dr = mBackground;
-        if (dr != null && visible != dr.isVisible()) {
-            dr.setVisible(visible, false);
+        if (dr != null && isVisible != dr.isVisible()) {
+            dr.setVisible(isVisible, false);
         }
         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
-        if (fg != null && visible != fg.isVisible()) {
-            fg.setVisible(visible, false);
+        if (fg != null && isVisible != fg.isVisible()) {
+            fg.setVisible(isVisible, false);
         }
     }
 
@@ -11376,7 +11370,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                 // to change animation states.
                 if (mParent != null && getWindowVisibility() == VISIBLE &&
                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
-                    dispatchVisibilityAggregated(this, newVisibility);
+                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
                 }
                 notifySubtreeAccessibilityStateChangedIfNeeded();
             }
@@ -15289,7 +15283,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         if (vis != GONE) {
             onWindowVisibilityChanged(vis);
             if (isShown()) {
-                onVisibilityAggregated(this, vis);
+                // Calling onVisibilityChanged directly here since the subtree will also
+                // receive dispatchAttachedToWindow and this same call
+                onVisibilityAggregated(vis == VISIBLE);
             }
         }
 
@@ -15312,7 +15308,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
             if (vis != GONE) {
                 onWindowVisibilityChanged(GONE);
                 if (isShown()) {
-                    onVisibilityAggregated(this, GONE);
+                    // Invoking onVisibilityAggregated directly here since the subtree
+                    // will also receive detached from window
+                    onVisibilityAggregated(false);
                 }
             }
         }
@@ -18001,12 +17999,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
 
         /*
          * Regardless of whether we're setting a new background or not, we want
-         * to clear the previous drawable.
+         * to clear the previous drawable. setVisible first while we still have the callback set.
          */
         if (mBackground != null) {
+            if (isAttachedToWindow()) {
+                mBackground.setVisible(false, false);
+            }
             mBackground.setCallback(null);
             unscheduleDrawable(mBackground);
-            mBackground.setVisible(false, false);
         }
 
         if (background != null) {
@@ -18043,12 +18043,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                 requestLayout = true;
             }
 
+            // Set mBackground before we set this as the callback and start making other
+            // background drawable state change calls. In particular, the setVisible call below
+            // can result in drawables attempting to start animations or otherwise invalidate,
+            // which requires the view set as the callback (us) to recognize the drawable as
+            // belonging to it as per verifyDrawable.
+            mBackground = background;
             background.setCallback(this);
             if (background.isStateful()) {
                 background.setState(getDrawableState());
             }
-            background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
-            mBackground = background;
+            if (isAttachedToWindow()) {
+                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            }
 
             applyBackgroundTint();
 
@@ -18227,9 +18234,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         }
 
         if (mForegroundInfo.mDrawable != null) {
+            if (isAttachedToWindow()) {
+                mForegroundInfo.mDrawable.setVisible(false, false);
+            }
             mForegroundInfo.mDrawable.setCallback(null);
             unscheduleDrawable(mForegroundInfo.mDrawable);
-            mForegroundInfo.mDrawable.setVisible(false, false);
         }
 
         mForegroundInfo.mDrawable = foreground;
@@ -18244,7 +18253,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                 foreground.setState(getDrawableState());
             }
             applyForegroundTint();
-            foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            if (isAttachedToWindow()) {
+                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            }
         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
             mPrivateFlags |= PFLAG_SKIP_DRAW;
         }
index 36a5db1..aa11e3f 100644 (file)
@@ -1291,20 +1291,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
     }
 
     @Override
-    int dispatchVisibilityAggregated(View changedView, @Visibility int visibility) {
-        visibility = super.dispatchVisibilityAggregated(changedView, visibility);
+    boolean dispatchVisibilityAggregated(boolean isVisible) {
+        isVisible = super.dispatchVisibilityAggregated(isVisible);
         final int count = mChildrenCount;
         final View[] children = mChildren;
         for (int i = 0; i < count; i++) {
-            // Only dispatch to children with at least the same level of visibility
-            // that we're reporting, otherwise it won't affect that child/subtree at all
-            // so it's not worth telling them about it. Note that we use <= here
-            // because VISIBLE < INVISIBLE < GONE as constant values.
-            if (children[i].getVisibility() <= visibility) {
-                children[i].dispatchVisibilityAggregated(changedView, visibility);
+            // Only dispatch to visible children. Not visible children and their subtrees already
+            // know that they aren't visible and that's not going to change as a result of
+            // whatever triggered this dispatch.
+            if (children[i].getVisibility() == VISIBLE) {
+                children[i].dispatchVisibilityAggregated(isVisible);
             }
         }
-        return visibility;
+        return isVisible;
     }
 
     @Override
index fecf892..a2295ce 100644 (file)
@@ -1472,7 +1472,7 @@ public final class ViewRootImpl implements ViewParent,
         if (viewVisibilityChanged) {
             mAttachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
-            host.dispatchVisibilityAggregated(host, viewVisibility);
+            host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
                 endDragResizing();
                 destroyHardwareResources();
index 9f05990..63f3744 100644 (file)
@@ -566,8 +566,8 @@ public abstract class Window {
          * @param data The data list to populate with shortcuts.
          * @param menu The current menu, which may be null.
          */
-        public void onProvideKeyboardShortcuts(
-                List<KeyboardShortcutGroup> data, @Nullable Menu menu);
+        default public void onProvideKeyboardShortcuts(
+                List<KeyboardShortcutGroup> data, @Nullable Menu menu) { };
     }
 
     /** @hide */
index a1cbc1d..887cc3a 100644 (file)
@@ -170,7 +170,7 @@ public final class WindowManagerGlobal {
                     sWindowManagerService = getWindowManagerService();
                     ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return sWindowManagerService;
@@ -192,7 +192,7 @@ public final class WindowManagerGlobal {
                             },
                             imm.getClient(), imm.getInputContext());
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to open window session", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return sWindowSession;
index df33698..35d3bf9 100644 (file)
@@ -50,7 +50,10 @@ public final class SpellCheckerSubtype implements Parcelable {
     private static final String TAG = SpellCheckerSubtype.class.getSimpleName();
     private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
     private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
-    private static final int SUBTYPE_ID_NONE = 0;
+    /**
+     * @hide
+     */
+    public static final int SUBTYPE_ID_NONE = 0;
     private static final String SUBTYPE_LANGUAGE_TAG_NONE = "";
 
     private final int mSubtypeId;
index 2eb258f..b16508e 100644 (file)
@@ -32,6 +32,7 @@ import android.net.http.SslCertificate;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.StrictMode;
@@ -2622,6 +2623,16 @@ public class WebView extends AbsoluteLayout
         mProvider.getViewDelegate().onFinishTemporaryDetach();
     }
 
+    @Override
+    public Handler getHandler() {
+        return mProvider.getViewDelegate().getHandler(super.getHandler());
+    }
+
+    @Override
+    public View findFocus() {
+        return mProvider.getViewDelegate().findFocus(super.findFocus());
+    }
+
     /**
      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
      *
index 3d72260..0751ab0 100644 (file)
@@ -106,6 +106,9 @@ public final class WebViewFactory {
     public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8;
     public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9;
 
+    // error for namespace lookup
+    public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10;
+
     private static String getWebViewPreparationErrorReason(int error) {
         switch (error) {
             case LIBLOAD_FAILED_WAITING_FOR_RELRO:
@@ -239,7 +242,8 @@ public final class WebViewFactory {
      * Load the native library for the given package name iff that package
      * name is the same as the one providing the webview.
      */
-    public static int loadWebViewNativeLibraryFromPackage(String packageName) {
+    public static int loadWebViewNativeLibraryFromPackage(String packageName,
+                                                          ClassLoader clazzLoader) {
         int ret = waitForProviderAndSetPackageInfo();
         if (ret != LIBLOAD_SUCCESS) {
             return ret;
@@ -247,7 +251,7 @@ public final class WebViewFactory {
         if (!sPackageInfo.packageName.equals(packageName))
             return LIBLOAD_WRONG_PACKAGE_NAME;
 
-        return loadNativeLibrary();
+        return loadNativeLibrary(clazzLoader);
     }
 
     static WebViewFactoryProvider getProvider() {
@@ -333,15 +337,16 @@ public final class WebViewFactory {
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
             }
 
-            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
-            loadNativeLibrary();
-            Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
-
             Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
             try {
                 initialApplication.getAssets().addAssetPathAsSharedLibrary(
                         webViewContext.getApplicationInfo().sourceDir);
                 ClassLoader clazzLoader = webViewContext.getClassLoader();
+
+                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
+                loadNativeLibrary(clazzLoader);
+                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
                 try {
                     return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
@@ -633,7 +638,7 @@ public final class WebViewFactory {
     }
 
     // Assumes that we have waited for relro creation and set sPackageInfo
-    private static int loadNativeLibrary() {
+    private static int loadNativeLibrary(ClassLoader clazzLoader) {
         if (!sAddressSpaceReserved) {
             Log.e(LOGTAG, "can't load with relro file; address space not reserved");
             return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
@@ -641,9 +646,10 @@ public final class WebViewFactory {
 
         String[] args = getWebViewNativeLibraryPaths(sPackageInfo);
         int result = nativeLoadWithRelroFile(args[0] /* path32 */,
-                                                 args[1] /* path64 */,
-                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
-                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
+                                             args[1] /* path64 */,
+                                             CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
+                                             CHROMIUM_WEBVIEW_NATIVE_RELRO_64,
+                                             clazzLoader);
         if (result != LIBLOAD_SUCCESS) {
             Log.w(LOGTAG, "failed to load with relro file, proceeding without");
         } else if (DEBUG) {
@@ -672,5 +678,6 @@ public final class WebViewFactory {
     private static native boolean nativeCreateRelroFile(String lib32, String lib64,
                                                         String relro32, String relro64);
     private static native int nativeLoadWithRelroFile(String lib32, String lib64,
-                                                          String relro32, String relro64);
+                                                      String relro32, String relro64,
+                                                      ClassLoader clazzLoader);
 }
index 94d231c..e5b65e7 100644 (file)
@@ -28,6 +28,7 @@ import android.graphics.drawable.Drawable;
 import android.net.http.SslCertificate;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.Message;
 import android.print.PrintDocumentAdapter;
 import android.view.DragEvent;
@@ -386,6 +387,10 @@ public interface WebViewProvider {
         public void onFinishTemporaryDetach();
 
         public void onActivityResult(int requestCode, int resultCode, Intent data);
+
+        public Handler getHandler(Handler originalHandler);
+
+        public View findFocus(View originalFocusedView);
     }
 
     interface ScrollDelegate {
index 1321221..6d7313d 100644 (file)
@@ -1644,7 +1644,7 @@ public class GridView extends AbsListView {
         boolean handled = false;
         int action = event.getAction();
         if (KeyEvent.isConfirmKey(keyCode)
-                && event.hasNoModifiers() && action == KeyEvent.ACTION_UP) {
+                && event.hasNoModifiers() && action != KeyEvent.ACTION_UP) {
             handled = resurrectSelectionIfNeeded();
             if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) {
                 keyPressed();
index 71b5ce9..04d344f 100644 (file)
@@ -1501,10 +1501,10 @@ public class ImageView extends View {
     }
 
     @Override
-    public void onVisibilityAggregated(View changedView, @Visibility int visibility) {
-        super.onVisibilityAggregated(changedView, visibility);
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
         if (mDrawable != null) {
-            mDrawable.setVisible(visibility == VISIBLE, false);
+            mDrawable.setVisible(isVisible, false);
         }
     }
 
index dd0f91e..e9fa26c 100644 (file)
@@ -617,6 +617,7 @@ public class ProgressBar extends View {
     private void swapCurrentDrawable(Drawable newDrawable) {
         final Drawable oldDrawable = mCurrentDrawable;
         mCurrentDrawable = newDrawable;
+
         if (oldDrawable != mCurrentDrawable) {
             if (oldDrawable != null) {
                 oldDrawable.setVisible(false, false);
@@ -1645,10 +1646,9 @@ public class ProgressBar extends View {
     }
 
     @Override
-    public void onVisibilityAggregated(View changedView, @Visibility int visibility) {
-        super.onVisibilityAggregated(changedView, visibility);
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
 
-        final boolean isVisible = visibility == VISIBLE;
         if (isVisible != mAggregatedIsVisible) {
             mAggregatedIsVisible = isVisible;
 
index fbedbda..5060350 100644 (file)
@@ -6552,7 +6552,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                 if (TextUtils.equals(content.subSequence(start, end), text.text)) {
                     if (text.text instanceof Spanned) {
                         // OK to copy spans only.
-                        TextUtils.copySpansFrom((Spanned) text.text, start, end,
+                        TextUtils.copySpansFrom((Spanned) text.text, 0, end - start,
                                 Object.class, content, start);
                     }
                 } else {
@@ -9646,7 +9646,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     boolean canShare() {
-        return canCopy() && isDeviceProvisioned();
+        if (!getContext().canStartActivityForResult() || !isDeviceProvisioned()) {
+            return false;
+        }
+        return canCopy();
     }
 
     boolean isDeviceProvisioned() {
@@ -9669,16 +9672,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     boolean canProcessText() {
-        if (!getContext().canStartActivityForResult() || getId() == View.NO_ID
-                || hasPasswordTransformationMethod()) {
+        if (getId() == View.NO_ID) {
             return false;
         }
-
-        if (mText.length() > 0 && hasSelection() && mEditor != null) {
-            return true;
-        }
-
-        return false;
+        return canShare();
     }
 
     boolean canSelectAllText() {
index 90ee05e..f3ae688 100644 (file)
@@ -854,7 +854,8 @@ public class InputMethodUtils {
         private final HashMap<String, String> mCopyOnWriteDataStore = new HashMap<>();
 
         private boolean mCopyOnWrite = false;
-        private String mEnabledInputMethodsStrCache;
+        @NonNull
+        private String mEnabledInputMethodsStrCache = "";
         @UserIdInt
         private int mCurrentUserId;
         private int[] mCurrentProfileIds = new int[0];
@@ -908,14 +909,6 @@ public class InputMethodUtils {
             return imsList;
         }
 
-        @Deprecated
-        public InputMethodSettings(
-                Resources res, ContentResolver resolver,
-                HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
-                @UserIdInt int userId) {
-            this(res, resolver, methodMap, methodList, userId, false /* copyOnWrite */);
-        }
-
         public InputMethodSettings(
                 Resources res, ContentResolver resolver,
                 HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
@@ -949,7 +942,7 @@ public class InputMethodUtils {
             // TODO: mCurrentProfileIds should be updated here.
         }
 
-        private void putString(final String key, final String str) {
+        private void putString(@NonNull final String key, @Nullable final String str) {
             if (mCopyOnWrite) {
                 mCopyOnWriteDataStore.put(key, str);
             } else {
@@ -957,12 +950,15 @@ public class InputMethodUtils {
             }
         }
 
-        private String getString(final String key) {
+        @Nullable
+        private String getString(@NonNull final String key, @Nullable final String defaultValue) {
+            final String result;
             if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
-                final String result = mCopyOnWriteDataStore.get(key);
-                return result != null ? result : "";
+                result = mCopyOnWriteDataStore.get(key);
+            } else {
+                result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
             }
-            return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+            return result != null ? result : defaultValue;
         }
 
         private void putInt(final String key, final int value) {
@@ -1124,16 +1120,24 @@ public class InputMethodUtils {
             return res;
         }
 
-        private void putEnabledInputMethodsStr(String str) {
+        private void putEnabledInputMethodsStr(@Nullable String str) {
             if (DEBUG) {
                 Slog.d(TAG, "putEnabledInputMethodStr: " + str);
             }
-            putString(Settings.Secure.ENABLED_INPUT_METHODS, str);
-            mEnabledInputMethodsStrCache = str;
+            if (TextUtils.isEmpty(str)) {
+                // OK to coalesce to null, since getEnabledInputMethodsStr() can take care of the
+                // empty data scenario.
+                putString(Settings.Secure.ENABLED_INPUT_METHODS, null);
+            } else {
+                putString(Settings.Secure.ENABLED_INPUT_METHODS, str);
+            }
+            // TODO: Update callers of putEnabledInputMethodsStr to make str @NonNull.
+            mEnabledInputMethodsStrCache = (str != null ? str : "");
         }
 
+        @NonNull
         public String getEnabledInputMethodsStr() {
-            mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS);
+            mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS, "");
             if (DEBUG) {
                 Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache
                         + ", " + mCurrentUserId);
@@ -1187,11 +1191,17 @@ public class InputMethodUtils {
             saveSubtypeHistory(subtypeHistory, imeId, subtypeId);
         }
 
-        private void putSubtypeHistoryStr(String str) {
+        private void putSubtypeHistoryStr(@NonNull String str) {
             if (DEBUG) {
                 Slog.d(TAG, "putSubtypeHistoryStr: " + str);
             }
-            putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+            if (TextUtils.isEmpty(str)) {
+                // OK to coalesce to null, since getSubtypeHistoryStr() can take care of the empty
+                // data scenario.
+                putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, null);
+            } else {
+                putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+            }
         }
 
         public Pair<String, String> getLastInputMethodAndSubtypeLocked() {
@@ -1308,8 +1318,9 @@ public class InputMethodUtils {
             return imsList;
         }
 
+        @NonNull
         private String getSubtypeHistoryStr() {
-            final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY);
+            final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, "");
             if (DEBUG) {
                 Slog.d(TAG, "getSubtypeHistoryStr: " + history);
             }
@@ -1332,8 +1343,9 @@ public class InputMethodUtils {
             putInt(Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId);
         }
 
+        @Nullable
         public String getSelectedInputMethod() {
-            final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD);
+            final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD, null);
             if (DEBUG) {
                 Slog.d(TAG, "getSelectedInputMethodStr: " + imi);
             }
index 8de9c09..d11787d 100644 (file)
@@ -107,7 +107,7 @@ public class BatteryStatsImpl extends BatteryStats {
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 141 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 142 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
index df48d6d..fbd8fb5 100644 (file)
@@ -2073,11 +2073,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> list) {
         final PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
         if (!mWindow.isDestroyed() && st != null && mWindow.getCallback() != null) {
-            try {
-                mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
-            } catch (AbstractMethodError e) {
-                // We run into this if the app is using supportlib.
-            }
+            mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
         }
     }
 
index 8ef1a22..c6db0ed 100644 (file)
@@ -36,7 +36,7 @@ LOCAL_SRC_FILES:= \
     android_app_Activity.cpp \
     android_app_ApplicationLoaders.cpp \
     android_app_NativeActivity.cpp \
-    android_auditing_SecurityLog.cpp \
+    android_app_admin_SecurityLog.cpp \
     android_opengl_EGL14.cpp \
     android_opengl_EGLExt.cpp \
     android_opengl_GLES10.cpp \
index 95323f7..7ff38fd 100644 (file)
@@ -109,7 +109,7 @@ namespace android {
  * JNI-based registration functions.  Note these are properly contained in
  * namespace android.
  */
-extern int register_android_auditing_SecurityLog(JNIEnv* env);
+extern int register_android_app_admin_SecurityLog(JNIEnv* env);
 extern int register_android_content_AssetManager(JNIEnv* env);
 extern int register_android_util_EventLog(JNIEnv* env);
 extern int register_android_util_Log(JNIEnv* env);
@@ -1253,7 +1253,7 @@ static const RegJNIRec gRegJNI[] = {
     REG_JNI(register_android_util_EventLog),
     REG_JNI(register_android_util_Log),
     REG_JNI(register_android_util_PathParser),
-    REG_JNI(register_android_auditing_SecurityLog),
+    REG_JNI(register_android_app_admin_SecurityLog),
     REG_JNI(register_android_content_AssetManager),
     REG_JNI(register_android_content_StringBlock),
     REG_JNI(register_android_content_XmlBlock),
index fb9b1e5..4001283 100644 (file)
@@ -73,6 +73,9 @@ jstring encodedFormatToString(JNIEnv* env, SkEncodedFormat format) {
         case SkEncodedFormat::kWBMP_SkEncodedFormat:
             mimeType = "image/vnd.wap.wbmp";
             break;
+        case SkEncodedFormat::kRAW_SkEncodedFormat:
+            mimeType = "image/x-adobe-dng";
+            break;
         default:
             mimeType = nullptr;
             break;
diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp
new file mode 100644 (file)
index 0000000..da47c4c
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <fcntl.h>
+
+#include "JNIHelp.h"
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include "log/logger.h"
+
+// The size of the tag number comes out of the payload size.
+#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
+
+namespace android {
+
+static jclass gCollectionClass;
+static jmethodID gCollectionAddID;
+
+static jclass gEventClass;
+static jmethodID gEventInitID;
+
+static jclass gIntegerClass;
+static jfieldID gIntegerValueID;
+
+static jclass gLongClass;
+static jfieldID gLongValueID;
+
+static jclass gFloatClass;
+static jfieldID gFloatValueID;
+
+static jclass gStringClass;
+
+
+static jboolean android_app_admin_SecurityLog_isLoggingEnabled(JNIEnv* env,
+                                                    jobject /* clazz */) {
+    return (bool)__android_log_security();
+}
+
+static jint android_app_admin_SecurityLog_writeEvent_String(JNIEnv* env,
+                                                    jobject /* clazz */,
+                                                    jint tag, jstring value) {
+    uint8_t buf[MAX_EVENT_PAYLOAD];
+
+    // Don't throw NPE -- I feel like it's sort of mean for a logging function
+    // to be all crashy if you pass in NULL -- but make the NULL value explicit.
+    const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL";
+    uint32_t len = strlen(str);
+    size_t max = sizeof(buf) - sizeof(len) - 2;  // Type byte, final newline
+    if (len > max) len = max;
+
+    buf[0] = EVENT_TYPE_STRING;
+    memcpy(&buf[1], &len, sizeof(len));
+    memcpy(&buf[1 + sizeof(len)], str, len);
+    buf[1 + sizeof(len) + len] = '\n';
+
+    if (value != NULL) env->ReleaseStringUTFChars(value, str);
+    return __android_log_security_bwrite(tag, buf, 2 + sizeof(len) + len);
+}
+
+static jint android_app_admin_SecurityLog_writeEvent_Array(JNIEnv* env, jobject clazz,
+                                                   jint tag, jobjectArray value) {
+    if (value == NULL) {
+        return android_app_admin_SecurityLog_writeEvent_String(env, clazz, tag, NULL);
+    }
+
+    uint8_t buf[MAX_EVENT_PAYLOAD];
+    const size_t max = sizeof(buf) - 1;  // leave room for final newline
+    size_t pos = 2;  // Save room for type tag & array count
+
+    jsize copied = 0, num = env->GetArrayLength(value);
+    for (; copied < num && copied < 255; ++copied) {
+        jobject item = env->GetObjectArrayElement(value, copied);
+        if (item == NULL || env->IsInstanceOf(item, gStringClass)) {
+            if (pos + 1 + sizeof(jint) > max) break;
+            const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL";
+            jint len = strlen(str);
+            if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len);
+            buf[pos++] = EVENT_TYPE_STRING;
+            memcpy(&buf[pos], &len, sizeof(len));
+            memcpy(&buf[pos + sizeof(len)], str, len);
+            pos += sizeof(len) + len;
+            if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str);
+        } else if (env->IsInstanceOf(item, gIntegerClass)) {
+            jint intVal = env->GetIntField(item, gIntegerValueID);
+            if (pos + 1 + sizeof(intVal) > max) break;
+            buf[pos++] = EVENT_TYPE_INT;
+            memcpy(&buf[pos], &intVal, sizeof(intVal));
+            pos += sizeof(intVal);
+        } else if (env->IsInstanceOf(item, gLongClass)) {
+            jlong longVal = env->GetLongField(item, gLongValueID);
+            if (pos + 1 + sizeof(longVal) > max) break;
+            buf[pos++] = EVENT_TYPE_LONG;
+            memcpy(&buf[pos], &longVal, sizeof(longVal));
+            pos += sizeof(longVal);
+        } else if (env->IsInstanceOf(item, gFloatClass)) {
+            jfloat floatVal = env->GetFloatField(item, gFloatValueID);
+            if (pos + 1 + sizeof(floatVal) > max) break;
+            buf[pos++] = EVENT_TYPE_FLOAT;
+            memcpy(&buf[pos], &floatVal, sizeof(floatVal));
+            pos += sizeof(floatVal);
+        } else {
+            jniThrowException(env,
+                    "java/lang/IllegalArgumentException",
+                    "Invalid payload item type");
+            return -1;
+        }
+        env->DeleteLocalRef(item);
+    }
+
+    buf[0] = EVENT_TYPE_LIST;
+    buf[1] = copied;
+    buf[pos++] = '\n';
+    return __android_log_security_bwrite(tag, buf, pos);
+}
+
+static void readEvents(JNIEnv* env, int loggerMode, jlong startTime, jobject out) {
+    struct logger_list *logger_list;
+    if (startTime) {
+        logger_list = android_logger_list_alloc_time(loggerMode,
+                log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0);
+    } else {
+        logger_list = android_logger_list_alloc(loggerMode, 0, 0);
+    }
+    if (!logger_list) {
+        jniThrowIOException(env, errno);
+        return;
+    }
+
+    if (!android_logger_open(logger_list, LOG_ID_SECURITY)) {
+        jniThrowIOException(env, errno);
+        android_logger_list_free(logger_list);
+        return;
+    }
+
+    while (1) {
+        log_msg log_msg;
+        int ret = android_logger_list_read(logger_list, &log_msg);
+
+        if (ret == 0) {
+            break;
+        }
+        if (ret < 0) {
+            if (ret == -EINTR) {
+                continue;
+            }
+            if (ret == -EINVAL) {
+                jniThrowException(env, "java/io/IOException", "Event too short");
+            } else if (ret != -EAGAIN) {
+                jniThrowIOException(env, -ret);  // Will throw on return
+            }
+            break;
+        }
+
+        if (log_msg.id() != LOG_ID_SECURITY) {
+            continue;
+        }
+
+        jsize len = ret;
+        jbyteArray array = env->NewByteArray(len);
+        if (array == NULL) {
+            break;
+        }
+
+        jbyte *bytes = env->GetByteArrayElements(array, NULL);
+        memcpy(bytes, log_msg.buf, len);
+        env->ReleaseByteArrayElements(array, bytes, 0);
+
+        jobject event = env->NewObject(gEventClass, gEventInitID, array);
+        if (event == NULL) {
+            break;
+        }
+
+        env->CallBooleanMethod(out, gCollectionAddID, event);
+        env->DeleteLocalRef(event);
+        env->DeleteLocalRef(array);
+    }
+
+    android_logger_list_close(logger_list);
+}
+
+static void android_app_admin_SecurityLog_readEvents(JNIEnv* env, jobject /* clazz */,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out);
+}
+
+static void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject /* clazz */,
+                                             jlong timestamp,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out);
+}
+
+static void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobject /* clazz */,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out);
+}
+
+static void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobject /* clazz */,
+                                             jlong timestamp,
+                                             jobject out) {
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, out);
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gRegisterMethods[] = {
+    /* name, signature, funcPtr */
+    { "isLoggingEnabled",
+      "()Z",
+      (void*) android_app_admin_SecurityLog_isLoggingEnabled
+    },
+    { "writeEvent",
+      "(ILjava/lang/String;)I",
+      (void*) android_app_admin_SecurityLog_writeEvent_String
+    },
+    { "writeEvent",
+      "(I[Ljava/lang/Object;)I",
+      (void*) android_app_admin_SecurityLog_writeEvent_Array
+    },
+    { "readEvents",
+      "(Ljava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEvents
+    },
+    { "readEventsSince",
+      "(JLjava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEventsSince
+    },
+    { "readPreviousEvents",
+      "(Ljava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readPreviousEvents
+    },
+    { "readEventsOnWrapping",
+      "(JLjava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEventsOnWrapping
+    },
+};
+
+static struct { const char *name; jclass *clazz; } gClasses[] = {
+    { "android/app/admin/SecurityLog$SecurityEvent", &gEventClass },
+    { "java/lang/Integer", &gIntegerClass },
+    { "java/lang/Long", &gLongClass },
+    { "java/lang/Float", &gFloatClass },
+    { "java/lang/String", &gStringClass },
+    { "java/util/Collection", &gCollectionClass },
+};
+
+static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
+    { &gIntegerClass, "value", "I", &gIntegerValueID },
+    { &gLongClass, "value", "J", &gLongValueID },
+    { &gFloatClass, "value", "F", &gFloatValueID },
+};
+
+static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
+    { &gEventClass, "<init>", "([B)V", &gEventInitID },
+    { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
+};
+
+int register_android_app_admin_SecurityLog(JNIEnv* env) {
+    for (int i = 0; i < NELEM(gClasses); ++i) {
+        jclass clazz = FindClassOrDie(env, gClasses[i].name);
+        *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz);
+    }
+
+    for (int i = 0; i < NELEM(gFields); ++i) {
+        *gFields[i].id = GetFieldIDOrDie(env,
+                *gFields[i].c, gFields[i].name, gFields[i].ft);
+    }
+
+    for (int i = 0; i < NELEM(gMethods); ++i) {
+        *gMethods[i].id = GetMethodIDOrDie(env,
+                *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
+    }
+
+    return RegisterMethodsOrDie(
+            env,
+            "android/app/admin/SecurityLog",
+            gRegisterMethods, NELEM(gRegisterMethods));
+}
+
+}; // namespace android
index 7314fbc..e17de17 100644 (file)
@@ -78,11 +78,11 @@ static jlong createFullPath(JNIEnv*, jobject, jlong srcFullPathPtr) {
 static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
         jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha,
         jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit,
-        jint strokeLineCap, jint strokeLineJoin) {
+        jint strokeLineCap, jint strokeLineJoin, jint fillType) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
     fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha,
             trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap,
-            strokeLineJoin);
+            strokeLineJoin, fillType);
 }
 
 static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
@@ -331,7 +331,7 @@ static const JNINativeMethod gMethods[] = {
         {"nDraw", "(JJJLandroid/graphics/Rect;ZZ)V", (void*)draw},
         {"nCreateFullPath", "!()J", (void*)createEmptyFullPath},
         {"nCreateFullPath", "!(J)J", (void*)createFullPath},
-        {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
+        {"nUpdateFullPathProperties", "!(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
         {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient},
         {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient},
         {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties},
index 3e4e352..1bc4285 100644 (file)
@@ -200,7 +200,7 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
         ALOGE("Error creating AudioRecord: Error retrieving session id pointer");
         return (jint) AUDIO_JAVA_ERROR;
     }
-    int sessionId = nSession[0];
+    audio_session_t sessionId = (audio_session_t) nSession[0];
     env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
     nSession = NULL;
 
@@ -385,7 +385,7 @@ android_media_AudioRecord_start(JNIEnv *env, jobject thiz, jint event, jint trig
     }
 
     return nativeToJavaStatus(
-            lpRecorder->start((AudioSystem::sync_event_t)event, triggerSession));
+            lpRecorder->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
 }
 
 
index 1eb0111..7496124 100644 (file)
@@ -109,7 +109,8 @@ static struct {
     jfieldID    mRule;
     jfieldID    mFormat;
     jfieldID    mRouteFlags;
-    jfieldID    mRegistrationId;
+    jfieldID    mDeviceType;
+    jfieldID    mDeviceAddress;
     jfieldID    mMixType;
     jfieldID    mCallbackFlags;
 } gAudioMixFields;
@@ -388,7 +389,7 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
 }
 
 static void
-android_media_AudioSystem_recording_callback(int event, int session, int source,
+android_media_AudioSystem_recording_callback(int event, audio_session_t session, int source,
         const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
         audio_patch_handle_t patchHandle)
 {
@@ -1539,7 +1540,7 @@ android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
 static jint
 android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
 {
-    return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
+    return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
 }
 
 static void
@@ -1561,13 +1562,15 @@ static jint convertAudioMixToNative(JNIEnv *env,
 {
     nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
     nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
+    nAudioMix->mDeviceType = (audio_devices_t)
+            env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
 
-    jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
-                                                           gAudioMixFields.mRegistrationId);
-    const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
-    nAudioMix->mRegistrationId = String8(nRegistrationId);
-    env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
-    env->DeleteLocalRef(jRegistrationId);
+    jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
+                                                           gAudioMixFields.mDeviceAddress);
+    const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
+    nAudioMix->mDeviceAddress = String8(nDeviceAddress);
+    env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
+    env->DeleteLocalRef(jDeviceAddress);
 
     nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
 
@@ -1857,7 +1860,8 @@ int register_android_media_AudioSystem(JNIEnv *env)
     gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
                                                 "Landroid/media/AudioFormat;");
     gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
-    gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId",
+    gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
+    gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
                                                       "Ljava/lang/String;");
     gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
     gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
index 302cf63..024c21d 100644 (file)
@@ -235,7 +235,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
         ALOGE("Error creating AudioTrack: Error retrieving session id pointer");
         return (jint) AUDIO_JAVA_ERROR;
     }
-    int sessionId = nSession[0];
+    audio_session_t sessionId = (audio_session_t) nSession[0];
     env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
     nSession = NULL;
 
index a9003c1..a7ac5b8 100644 (file)
@@ -28,6 +28,7 @@
 #include <DamageAccumulator.h>
 #include <Matrix.h>
 #include <RenderNode.h>
+#include <renderthread/CanvasContext.h>
 #include <TreeInfo.h>
 #include <Paint.h>
 
@@ -487,15 +488,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
 
         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
             if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
-            ATRACE_NAME("Update SurfaceView position");
 
-            JNIEnv* env = jnienv();
-            jobject localref = env->NewLocalRef(mWeakRef);
-            if (CC_UNLIKELY(!localref)) {
-                jnienv()->DeleteWeakGlobalRef(mWeakRef);
-                mWeakRef = nullptr;
-                return;
-            }
             Matrix4 transform;
             info.damageAccumulator->computeCurrentTransform(&transform);
             const RenderProperties& props = node.properties();
@@ -505,10 +498,13 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
             bounds.right -= info.windowInsetLeft;
             bounds.top -= info.windowInsetTop;
             bounds.bottom -= info.windowInsetTop;
-            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
-                    (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
-                    (jint) bounds.right, (jint) bounds.bottom);
-            env->DeleteLocalRef(localref);
+
+            auto functor = std::bind(
+                std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this,
+                (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
+                (jint) bounds.right, (jint) bounds.bottom);
+
+            info.canvasContext.enqueueFrameWork(std::move(functor));
         }
 
     private:
@@ -520,6 +516,23 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
             return env;
         }
 
+        void doUpdatePosition(jlong frameNumber, jint left, jint top,
+                jint right, jint bottom) {
+            ATRACE_NAME("Update SurfaceView position");
+
+            JNIEnv* env = jnienv();
+            jobject localref = env->NewLocalRef(mWeakRef);
+            if (CC_UNLIKELY(!localref)) {
+                jnienv()->DeleteWeakGlobalRef(mWeakRef);
+                mWeakRef = nullptr;
+                return;
+            }
+
+            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
+                    frameNumber, left, top, right, bottom);
+            env->DeleteLocalRef(localref);
+        }
+
         JavaVM* mVm;
         jobject mWeakRef;
     };
index b7701d6..14252dc 100644 (file)
@@ -144,7 +144,7 @@ android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
         PublicFormat f) {
     switch(f) {
         case PublicFormat::JPEG:
-            return HAL_DATASPACE_JFIF;
+            return HAL_DATASPACE_V0_JFIF;
         case PublicFormat::DEPTH_POINT_CLOUD:
         case PublicFormat::DEPTH16:
             return HAL_DATASPACE_DEPTH;
@@ -156,7 +156,7 @@ android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
         case PublicFormat::YUV_420_888:
         case PublicFormat::NV21:
         case PublicFormat::YV12:
-            return HAL_DATASPACE_JFIF;
+            return HAL_DATASPACE_V0_JFIF;
         default:
             // Most formats map to UNKNOWN
             return HAL_DATASPACE_UNKNOWN;
@@ -210,7 +210,7 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
             switch (dataSpace) {
                 case HAL_DATASPACE_DEPTH:
                     return PublicFormat::DEPTH_POINT_CLOUD;
-                case HAL_DATASPACE_JFIF:
+                case HAL_DATASPACE_V0_JFIF:
                     return PublicFormat::JPEG;
                 default:
                     // Assume otherwise-marked blobs are also JPEG
index 6444c6c..97a51d5 100644 (file)
                  android:icon="@drawable/ic_launcher_android"
                  android:supportsRtl="true"
                  android:theme="@style/Theme.Material.DayNight.DarkActionBar"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
                 android:theme="@style/Theme.DeviceDefault.Resolver"
                 android:finishOnCloseSystemDialogs="true"
index 50c7bfb..a52c4e5 100644 (file)
@@ -5876,6 +5876,12 @@ i
         </attr>
         <!-- sets the Miter limit for a stroked path -->
         <attr name="strokeMiterLimit" format="float"/>
+        <!-- sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
+             For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty -->
+        <attr name="fillType" format="enum">
+            <enum name="nonZero" value="0"/>
+            <enum name="evenOdd" value="1"/>
+        </attr>
     </declare-styleable>
 
     <!-- Defines the clip path used in VectorDrawables. -->
index d0d1d5a..5716823 100644 (file)
          included in the system image. Third-party apps cannot use it.</em> -->
     <attr name="allowClearUserData" format="boolean" />
 
-    <!-- Option to let applications specify that user data should
-         never be encrypted if an Encrypted File System solution
-         is enabled. Specifically, this is an "opt-out" feature, meaning
-         that, by default, user data will be encrypted if the EFS feature
-         is enabled. -->
-    <attr name="neverEncrypt" format="boolean" />
-
     <!-- Option to indicate this application is only for testing purposes.
          For example, it may expose functionality or data outside of itself
          that would cause a security hole, but is useful for testing.  This
          single integer, with higher numbers considered to be better. -->
     <attr name="priority" format="integer" />
 
-    <!-- Indicate if this component is aware of encryption lifecycle, and can be
+    <!-- Indicate if this component is aware of direct boot lifecycle, and can be
          safely run before the user has entered their credentials (such as a lock
          pattern or PIN). -->
-    <attr name="encryptionAware" format="boolean" />
+    <attr name="directBootAware" format="boolean" />
 
     <!-- Specify how an activity should be launched.  See the
          <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
         <attr name="restoreNeedsApplication" />
         <attr name="restoreAnyVersion" />
         <attr name="backupInForeground" />
-        <attr name="neverEncrypt" />
         <!-- Request that your application's processes be created with
              a large Dalvik heap.  This applies to <em>all</em> processes
              created for the application.  It only applies to the first
         <attr name="usesCleartextTraffic" />
         <attr name="multiArch" />
         <attr name="extractNativeLibs" />
-        <attr name="forceDeviceEncrypted" format="boolean" />
-        <attr name="encryptionAware" />
+        <attr name="defaultToDeviceProtectedStorage" format="boolean" />
+        <attr name="directBootAware" />
         <attr name="resizeableActivity" />
     </declare-styleable>
     <!-- The <code>permission</code> tag declares a security permission that can be
         <attr name="enabled" />
         <attr name="exported" />
         <attr name="singleUser" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
     </declare-styleable>
 
     <!-- Attributes that can be supplied in an AndroidManifest.xml
              with it is through the Service API (binding and starting). -->
         <attr name="isolatedProcess" format="boolean" />
         <attr name="singleUser" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
         <!-- If the service is an {@link android.R.attr#isolatedProcess} service, this permits a
              client to bind to the service as if it were running it its own package.  The service
              must also be {@link android.R.attr#exported} if this flag is set. -->
         <attr name="enabled" />
         <attr name="exported" />
         <attr name="singleUser" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
     </declare-styleable>
 
     <!-- The <code>activity</code> tag declares an
         <attr name="supportsPictureInPicture" />
         <attr name="lockTaskMode" />
         <attr name="showForAllUsers" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
         <!-- @hide This activity is always focusable regardless of if it is in a task/stack whose
              activities are normally not focusable.
              For example, {@link android.R.attr#supportsPictureInPicture} activities are placed
index 2b0ef42..3c5b4c0 100644 (file)
     <public type="attr" name="contextPopupMenuStyle" />
     <public type="attr" name="textAppearancePopupMenuHeader" />
     <public type="attr" name="windowBackgroundFallback" />
-    <public type="attr" name="forceDeviceEncrypted" />
-    <public type="attr" name="encryptionAware" />
+    <public type="attr" name="defaultToDeviceProtectedStorage" />
+    <public type="attr" name="directBootAware" />
     <public type="attr" name="preferenceFragmentStyle" />
     <public type="attr" name="canControlMagnification" />
     <public type="attr" name="languageTag" />
     <public type="attr" name="canRecord" />
     <public type="attr" name="tunerCount" />
     <public type="attr" name="nfcAntennaPositionDrawable" />
+    <public type="attr" name="fillType" />
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
index a65a813..e636bc0 100644 (file)
@@ -993,7 +993,7 @@ please see styles_device_defaults.xml.
     </style>
 
     <style name="Widget.Material.SuggestionItem" parent="@android:style/TextAppearance.Material.Body1">
-        <item name="textColor">#8a000000</item>  <!-- alpha=.54, textColor=@color/black -->
+        <item name="textColor">?attr/textColorSecondary</item>
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
         <item name="layout_gravity">start|center_vertical</item>
@@ -1008,11 +1008,11 @@ please see styles_device_defaults.xml.
     </style>
 
     <style name="TextAppearance.Material.TextSuggestionHighlight" parent="Widget.Material.SuggestionItem">
-        <item name="textColor">#de000000</item>  <!-- alpha=.87, textColor=@color/black -->
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
     <style name="Widget.Material.SuggestionButton" parent="@android:style/TextAppearance.Material.Button">
-        <item name="textColor">#de009688</item>  <!-- alpha=.87, textColor=#009688 -->
+        <item name="textColor">?attr/colorAccent</item>
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
         <item name="layout_gravity">start|center_vertical</item>
index 5970a22..a361eda 100644 (file)
@@ -223,6 +223,7 @@ please see themes_device_defaults.xml.
         <item name="textSelectHandleWindowStyle">@style/Widget.Material.TextSelectHandle</item>
         <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item_material</item>
         <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container_material</item>
+        <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Material.TextSuggestionHighlight</item>
         <item name="textCursorDrawable">@drawable/text_cursor_material</item>
 
         <!-- Widget styles -->
index cbf17a4..ec8cd71 100644 (file)
@@ -37,6 +37,8 @@ import android.print.mockservice.PrintServiceCallbacks;
 import android.print.mockservice.PrinterDiscoverySessionCallbacks;
 import android.print.mockservice.StubbablePrinterDiscoverySession;
 
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
@@ -253,6 +255,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.getPrintJobInfo
      */
+    @LargeTest
     public void testGetPrintJobInfo() throws Exception {
         startPrinting();
 
@@ -274,6 +277,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.getPrintJobInfos
      */
+    @LargeTest
     public void testGetPrintJobInfos() throws Exception {
         startPrinting();
 
@@ -301,6 +305,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.print
      */
+    @LargeTest
     public void testPrint() throws Exception {
         final String name = "dummy print job";
 
@@ -354,6 +359,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.cancelPrintJob
      */
+    @LargeTest
     public void testCancelPrintJob() throws Exception {
         startPrinting();
 
@@ -377,6 +383,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.restartPrintJob
      */
+    @LargeTest
     public void testRestartPrintJob() throws Exception {
         startPrinting();
 
@@ -399,6 +406,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.addPrintJobStateChangeListener
      */
+    @MediumTest
     public void testAddPrintJobStateChangeListener() throws Exception {
         final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
 
@@ -424,6 +432,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.removePrintJobStateChangeListener
      */
+    @MediumTest
     public void testRemovePrintJobStateChangeListener() throws Exception {
         final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
 
@@ -447,6 +456,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.addPrintServicesChangeListener
      */
+    @MediumTest
     public void testAddPrintServicesChangeListener() throws Exception {
         final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
 
@@ -465,6 +475,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.removePrintServicesChangeListener
      */
+    @MediumTest
     public void testRemovePrintServicesChangeListener() throws Exception {
         final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
 
@@ -488,6 +499,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.getPrintServices
      */
+    @MediumTest
     public void testGetPrintServices() throws Exception {
         List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
                 PrintManager.ALL_SERVICES, mUserId);
@@ -509,6 +521,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.setPrintServiceEnabled
      */
+    @MediumTest
     public void testSetPrintServiceEnabled() throws Exception {
         final ComponentName printService = mIPrintManager.getPrintServices(
                 PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
@@ -548,6 +561,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.createPrinterDiscoverySession
      */
+    @MediumTest
     public void testCreatePrinterDiscoverySession() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
@@ -573,6 +587,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.startPrinterDiscovery
      */
+    @LargeTest
     public void testStartPrinterDiscovery() throws Exception {
         startPrinting();
 
@@ -615,6 +630,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.stopPrinterDiscovery
      */
+    @MediumTest
     public void testStopPrinterDiscovery() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
@@ -638,6 +654,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.validatePrinters
      */
+    @LargeTest
     public void testValidatePrinters() throws Exception {
         startPrinting();
 
@@ -678,6 +695,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.startPrinterStateTracking
      */
+    @LargeTest
     public void testStartPrinterStateTracking() throws Exception {
         startPrinting();
 
@@ -699,6 +717,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.getCustomPrinterIcon
      */
+    @LargeTest
     public void testGetCustomPrinterIcon() throws Exception {
         startPrinting();
 
@@ -720,6 +739,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.stopPrinterStateTracking
      */
+    @LargeTest
     public void testStopPrinterStateTracking() throws Exception {
         startPrinting();
 
@@ -746,6 +766,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
     /**
      * test IPrintManager.destroyPrinterDiscoverySession
      */
+    @MediumTest
     public void testDestroyPrinterDiscoverySession() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
index dc85046..fd28f64 100644 (file)
@@ -105,4 +105,4 @@ FONTCHAIN_LINTER := frameworks/base/tools/fonts/fontchain_lint.py
 .PHONY: fontchain_lint
 fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml
        PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \
-       python $(FONTCHAIN_LINTER) $(TARGET_OUT)
\ No newline at end of file
+       python $(FONTCHAIN_LINTER) $(TARGET_OUT) external/unicode
index e3f1d9e..ca7255b 100644 (file)
@@ -284,7 +284,7 @@ changed.</li>
     </tr>
     <tr>
         <td class="label_neg">drawPicture()</td>
-        <td class="value_neg">23</td>
+        <td class="value_pos">23</td>
     </tr>
     <tr>
         <td class="label_pos">drawPosText()</td>
@@ -421,14 +421,6 @@ changed.</li>
         <td colspan="5" class="s5">Xfermode</td>
     </tr>
     <tr>
-        <td class="label_neg">AvoidXfermode</td>
-        <td class="value_neg">&#10007;</td>
-    </tr>
-    <tr>
-        <td class="label_neg">PixelXorXfermode</td>
-        <td class="value_neg">&#10007;</td>
-    </tr>
-    <tr>
         <td class="label_neg">PorterDuff.Mode.DARKEN (framebuffer)</td>
         <td class="value_neg">&#10007;</td>
     </tr>
index 3e86e6f..3973f2f 100644 (file)
 package android.graphics;
 
 import android.annotation.FloatRange;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Defines a simple shape, used for bounding graphical regions.
  * <p>
@@ -34,11 +37,28 @@ import android.graphics.drawable.Drawable;
 public final class Outline {
     private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
 
+    private static final int MODE_EMPTY = 0;
+    private static final int MODE_RECT = 1;
+    private static final int MODE_CONVEX_PATH = 2;
+
     /** @hide */
-    public Path mPath;
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = false,
+            value = {
+                    MODE_EMPTY,
+                    MODE_RECT,
+                    MODE_CONVEX_PATH,
+            })
+    public @interface Mode {}
+
+    @Mode
+    private int mMode = MODE_EMPTY;
 
     /** @hide */
-    public Rect mRect;
+    public final Path mPath = new Path();
+
+    /** @hide */
+    public final Rect mRect = new Rect();
     /** @hide */
     public float mRadius = RADIUS_UNDEFINED;
     /** @hide */
@@ -63,8 +83,9 @@ public final class Outline {
      * @see #isEmpty()
      */
     public void setEmpty() {
-        mPath = null;
-        mRect = null;
+        mMode = MODE_EMPTY;
+        mPath.rewind();
+        mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
     }
 
@@ -77,7 +98,7 @@ public final class Outline {
      * @see #setEmpty()
      */
     public boolean isEmpty() {
-        return mRect == null && mPath == null;
+        return mMode == MODE_EMPTY;
     }
 
 
@@ -90,7 +111,7 @@ public final class Outline {
      * @see {@link android.view.View#setClipToOutline(boolean)}
      */
     public boolean canClip() {
-        return !isEmpty() && mRect != null;
+        return mMode != MODE_CONVEX_PATH;
     }
 
     /**
@@ -122,19 +143,9 @@ public final class Outline {
      * @param src Source outline to copy from.
      */
     public void set(@NonNull Outline src) {
-        if (src.mPath != null) {
-            if (mPath == null) {
-                mPath = new Path();
-            }
-            mPath.set(src.mPath);
-            mRect = null;
-        }
-        if (src.mRect != null) {
-            if (mRect == null) {
-                mRect = new Rect();
-            }
-            mRect.set(src.mRect);
-        }
+        mMode = src.mMode;
+        mPath.set(src.mPath);
+        mRect.set(src.mRect);
         mRadius = src.mRadius;
         mAlpha = src.mAlpha;
     }
@@ -165,10 +176,10 @@ public final class Outline {
             return;
         }
 
-        if (mRect == null) mRect = new Rect();
+        mMode = MODE_RECT;
         mRect.set(left, top, right, bottom);
         mRadius = radius;
-        mPath = null;
+        mPath.rewind();
     }
 
     /**
@@ -188,7 +199,7 @@ public final class Outline {
      *         bounds, or {@code false} if no outline bounds are set
      */
     public boolean getRect(@NonNull Rect outRect) {
-        if (mRect == null) {
+        if (mMode != MODE_RECT) {
             return false;
         }
         outRect.set(mRect);
@@ -221,10 +232,10 @@ public final class Outline {
             return;
         }
 
-        if (mPath == null) mPath = new Path();
-        mPath.reset();
+        mMode = MODE_CONVEX_PATH;
+        mPath.rewind();
         mPath.addOval(left, top, right, bottom, Path.Direction.CW);
-        mRect = null;
+        mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
     }
 
@@ -248,10 +259,10 @@ public final class Outline {
         if (!convexPath.isConvex()) {
             throw new IllegalArgumentException("path must be convex");
         }
-        if (mPath == null) mPath = new Path();
 
+        mMode = MODE_CONVEX_PATH;
         mPath.set(convexPath);
-        mRect = null;
+        mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
     }
 
@@ -259,9 +270,9 @@ public final class Outline {
      * Offsets the Outline by (dx,dy)
      */
     public void offset(int dx, int dy) {
-        if (mRect != null) {
+        if (mMode == MODE_RECT) {
             mRect.offset(dx, dy);
-        } else if (mPath != null) {
+        } else if (mMode == MODE_CONVEX_PATH) {
             mPath.offset(dx, dy);
         }
     }
index ae98c22..bd069ff 100644 (file)
@@ -1281,8 +1281,10 @@ public class VectorDrawable extends Drawable {
         private static final int STROKE_LINE_CAP_INDEX = 8;
         private static final int STROKE_LINE_JOIN_INDEX = 9;
         private static final int STROKE_MITER_LIMIT_INDEX = 10;
-        private static final int TOTAL_PROPERTY_COUNT = 11;
+        private static final int FILL_TYPE_INDEX = 11;
+        private static final int TOTAL_PROPERTY_COUNT = 12;
 
+        // Property map for animatable attributes.
         private final static HashMap<String, Integer> sPropertyMap
                 = new HashMap<String, Integer> () {
             {
@@ -1399,6 +1401,7 @@ public class VectorDrawable extends Drawable {
             int strokeLineCap =  properties.getInt(STROKE_LINE_CAP_INDEX * 4);
             int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4);
             float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4);
+            int fillType = properties.getInt(FILL_TYPE_INDEX * 4);
             Shader fillGradient = null;
             Shader strokeGradient = null;
             // Account for any configuration changes.
@@ -1474,10 +1477,11 @@ public class VectorDrawable extends Drawable {
                     R.styleable.VectorDrawablePath_trimPathOffset, trimPathOffset);
             trimPathStart = a.getFloat(
                     R.styleable.VectorDrawablePath_trimPathStart, trimPathStart);
+            fillType = a.getInt(R.styleable.VectorDrawablePath_fillType, fillType);
 
             nUpdateFullPathProperties(mNativePtr, strokeWidth, strokeColor, strokeAlpha,
                     fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset,
-                    strokeMiterLimit, strokeLineCap, strokeLineJoin);
+                    strokeMiterLimit, strokeLineCap, strokeLineJoin, fillType);
         }
 
         @Override
@@ -1645,7 +1649,7 @@ public class VectorDrawable extends Drawable {
     private static native void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
             int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
             float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
-            int strokeLineJoin);
+            int strokeLineJoin, int fillType);
     private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr);
     private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr);
 
index 330dc29..eac9359 100644 (file)
@@ -92,6 +92,8 @@ public:
      */
     bool init();
 
+    bool isInitialized() { return mInitialized; }
+
     /**
      * Flush the cache.
      *
index fd5856a..50b21a4 100644 (file)
@@ -646,7 +646,9 @@ static batchid_t textBatchId(const SkPaint& paint) {
 }
 
 void FrameBuilder::deferTextOp(const TextOp& op) {
-    BakedOpState* bakedState = tryBakeOpState(op);
+    BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
+            mAllocator, *mCanvasState.writableSnapshot(), op,
+            BakedOpState::StrokeBehavior::StyleDefined);
     if (!bakedState) return; // quick rejected
 
     batchid_t batchId = textBatchId(*(op.paint));
index 114347d..cdbbbab 100644 (file)
@@ -197,7 +197,12 @@ void Layer::generateTexture() {
 }
 
 void Layer::clearTexture() {
-    caches.textureState().unbindTexture(texture.mId);
+    // There's a rare possibility that Caches could have been destroyed already
+    // since this method is queued up as a task.
+    // Since this is a reset method, treat this as non-fatal.
+    if (caches.isInitialized()) {
+        caches.textureState().unbindTexture(texture.mId);
+    }
     texture.mId = 0;
 }
 
index f7b38e3..d35f764 100644 (file)
@@ -158,7 +158,8 @@ const SkPath& FullPath::getUpdatedPath() {
 
 void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
         SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
-        float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) {
+        float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
+        int fillType) {
     mProperties.strokeWidth = strokeWidth;
     mProperties.strokeColor = strokeColor;
     mProperties.strokeAlpha = strokeAlpha;
@@ -167,6 +168,7 @@ void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float st
     mProperties.strokeMiterLimit = strokeMiterLimit;
     mProperties.strokeLineCap = strokeLineCap;
     mProperties.strokeLineJoin = strokeLineJoin;
+    mProperties.fillType = fillType;
 
     // If any trim property changes, mark trim dirty and update the trim path
     setTrimPathStart(trimPathStart);
@@ -179,7 +181,7 @@ inline SkColor applyAlpha(SkColor color, float alpha) {
     return SkColorSetA(color, alphaBytes * alpha);
 }
 
-void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale,
+void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale,
                         const SkMatrix& matrix){
     // Draw path's fill, if fill color or gradient is valid
     bool needsFill = false;
@@ -196,6 +198,8 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str
     if (needsFill) {
         mPaint.setStyle(SkPaint::Style::kFill_Style);
         mPaint.setAntiAlias(true);
+        SkPath::FillType ft = static_cast<SkPath::FillType>(mProperties.fillType);
+        renderPath.setFillType(ft);
         outCanvas->drawPath(renderPath, mPaint);
     }
 
@@ -306,7 +310,7 @@ void FullPath::setPropertyValue(int propertyId, float value) {
     }
 }
 
-void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
         float strokeScale, const SkMatrix& matrix){
     outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
 }
index 36a8aeb..4d2fed0 100644 (file)
@@ -96,7 +96,7 @@ public:
 
 protected:
     virtual const SkPath& getUpdatedPath();
-    virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
+    virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) = 0;
     Data mData;
     SkPath mSkPath;
@@ -118,6 +118,7 @@ struct Properties {
     int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
     int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
     float strokeMiterLimit = 4;
+    int fillType = 0; /* non-zero or kWinding_FillType in Skia */
 };
 
     FullPath(const FullPath& path); // for cloning
@@ -133,7 +134,7 @@ struct Properties {
     void updateProperties(float strokeWidth, SkColor strokeColor,
             float strokeAlpha, SkColor fillColor, float fillAlpha,
             float trimPathStart, float trimPathEnd, float trimPathOffset,
-            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
+            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType);
     // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
     float getStrokeWidth() {
         return mProperties.strokeWidth;
@@ -197,7 +198,7 @@ struct Properties {
 
 protected:
     const SkPath& getUpdatedPath() override;
-    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) override;
 
 private:
@@ -213,6 +214,7 @@ private:
         StrokeLineCap,
         StrokeLineJoin,
         StrokeMiterLimit,
+        FillType,
         Count,
     };
     // Applies trimming to the specified path.
@@ -233,7 +235,7 @@ public:
     ClipPath(const Data& nodes) : Path(nodes) {}
 
 protected:
-    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) override;
 };
 
index a496b49..c539d63 100644 (file)
@@ -484,6 +484,8 @@ void CanvasContext::draw() {
     bool drew = mCanvas->finish();
 #endif
 
+    waitOnFences();
+
     GL_CHECKPOINT(LOW);
 
     // Even if we decided to cancel the frame, from the perspective of jank
@@ -726,6 +728,37 @@ void CanvasContext::serializeDisplayListTree() {
 #endif
 }
 
+void CanvasContext::waitOnFences() {
+    if (mFrameFences.size()) {
+        ATRACE_CALL();
+        for (auto& fence : mFrameFences) {
+            fence->getResult();
+        }
+        mFrameFences.clear();
+    }
+}
+
+class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> {
+public:
+    FuncTaskProcessor(Caches& caches)
+            : TaskProcessor<bool>(&caches.tasks) {}
+
+    virtual void onProcess(const sp<Task<bool> >& task) override {
+        FuncTask* t = static_cast<FuncTask*>(task.get());
+        t->func();
+        task->setResult(true);
+    }
+};
+
+void CanvasContext::enqueueFrameWork(std::function<void()>&& func) {
+    if (!mFrameWorkProcessor.get()) {
+        mFrameWorkProcessor = new FuncTaskProcessor(Caches::getInstance());
+    }
+    sp<FuncTask> task(new FuncTask());
+    task->func = func;
+    mFrameWorkProcessor->add(task);
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
index cb61e51..6706c30 100644 (file)
@@ -24,6 +24,8 @@
 #include "IContextFactory.h"
 #include "LayerUpdateQueue.h"
 #include "RenderNode.h"
+#include "thread/Task.h"
+#include "thread/TaskProcessor.h"
 #include "utils/RingBuffer.h"
 #include "renderthread/RenderTask.h"
 #include "renderthread/RenderThread.h"
@@ -41,6 +43,7 @@
 #include <utils/Functor.h>
 #include <gui/Surface.h>
 
+#include <functional>
 #include <set>
 #include <string>
 #include <vector>
@@ -159,6 +162,9 @@ public:
         }
     }
 
+    // Used to queue up work that needs to be completed before this frame completes
+    ANDROID_API void enqueueFrameWork(std::function<void()>&& func);
+
 private:
     friend class RegisterFrameCallbackTask;
     // TODO: Replace with something better for layer & other GL object
@@ -170,6 +176,8 @@ private:
 
     void freePrefetechedLayers();
 
+    void waitOnFences();
+
     EGLint mLastFrameWidth = 0;
     EGLint mLastFrameHeight = 0;
 
@@ -213,6 +221,16 @@ private:
 
     // Stores the bounds of the main content.
     Rect mContentDrawBounds;
+
+    // TODO: This is really a Task<void> but that doesn't really work
+    // when Future<> expects to be able to get/set a value
+    struct FuncTask : public Task<bool> {
+        std::function<void()> func;
+    };
+    class FuncTaskProcessor;
+
+    std::vector< sp<FuncTask> > mFrameFences;
+    sp<TaskProcessor<bool> > mFrameWorkProcessor;
 };
 
 } /* namespace renderthread */
index 09d4869..0572ee5 100755 (executable)
@@ -49,6 +49,6 @@ adb shell "echo 0 > /sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/enable"
 # 684000 708000 756000 804000 852000 (kHz)
 
 S=324000000
-echo "set gpu to $s hz"
+echo "set gpu to $S hz"
 adb shell "echo 1 > /d/clock/override.gbus/state"
 adb shell "echo $S > /d/clock/override.gbus/rate"
index f147fd4..31555f2 100644 (file)
@@ -316,6 +316,61 @@ TEST(FrameBuilder, textStrikethrough) {
             << "Expect number of ops = 2 * loop count";
 }
 
+static auto styles = {
+        SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style };
+
+TEST(FrameBuilder, textStyle) {
+    class TextStyleTestRenderer : public TestRendererBase {
+    public:
+        void onMergedTextOps(const MergedBakedOpList& opList) override {
+            ASSERT_EQ(0, mIndex);
+            ASSERT_EQ(3u, opList.count);
+            mIndex += opList.count;
+
+            int index = 0;
+            for (auto style : styles) {
+                auto state = opList.states[index++];
+                ASSERT_EQ(style, state->op->paint->getStyle())
+                        << "Remainder of validation relies upon stable merged order";
+                ASSERT_EQ(0, state->computedState.clipSideFlags)
+                        << "Clipped bounds validation requires unclipped ops";
+            }
+
+            Rect fill = opList.states[0]->computedState.clippedBounds;
+            Rect stroke = opList.states[1]->computedState.clippedBounds;
+            EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds)
+                    << "Stroke+Fill should be same as stroke";
+
+            EXPECT_TRUE(stroke.contains(fill));
+            EXPECT_FALSE(fill.contains(stroke));
+
+            Rect outsetFill(fill);
+            outsetFill.outset(10);
+            EXPECT_EQ(stroke, outsetFill);
+        }
+    };
+    auto node = TestUtils::createNode(0, 0, 400, 400,
+            [](RenderProperties& props, TestCanvas& canvas) {
+        SkPaint paint;
+        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        paint.setAntiAlias(true);
+        paint.setTextSize(50);
+        paint.setStrokeWidth(10);
+
+        // draw 3 copies of the same text overlapping, each with a different style.
+        // They'll get merged, but with
+        for (auto style : styles) {
+            paint.setStyle(style);
+            TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100);
+        }
+    });
+    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+    TextStyleTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops";
+}
+
 RENDERTHREAD_TEST(FrameBuilder, textureLayer) {
     class TextureLayerTestRenderer : public TestRendererBase {
     public:
index 949c541..454011f 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <gtest/gtest.h>
 
-#include "BakedOpRenderer.h"
 #include "Glop.h"
 #include "GlopBuilder.h"
 #include "Rect.h"
index 6cb23e5..0a7acb0 100644 (file)
@@ -33,11 +33,6 @@ public:
         mCondition.signal(mType);
     }
 
-    void close() {
-        Mutex::Autolock l(mLock);
-        mOpened = false;
-    }
-
     void wait() const {
         Mutex::Autolock l(mLock);
         while (!mOpened) {
index 11fecfb..a7eb73f 100644 (file)
@@ -47,7 +47,6 @@ public final class GnssMeasurement implements Parcelable {
     private double mCarrierPhaseUncertainty;
     private int mMultipathIndicator;
     private double mSnrInDb;
-    private boolean mPseudorangeRateCorrected;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
@@ -440,25 +439,6 @@ public final class GnssMeasurement implements Parcelable {
     }
 
     /**
-     * See {@link #getPseudorangeRateMetersPerSecond()} for more details.
-     *
-     * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected
-     *         value, {@code false} if it contains an uncorrected value.
-     */
-    public boolean isPseudorangeRateCorrected() {
-        return mPseudorangeRateCorrected;
-    }
-
-    /**
-     * Sets whether the pseudorange corrected.
-     * @hide
-     */
-    @TestApi
-    public void setPseudorangeRateCorrected(boolean value) {
-        mPseudorangeRateCorrected = value;
-    }
-
-    /**
      * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
      * The uncertainty is represented as an absolute (single sided) value.
      */
@@ -813,7 +793,6 @@ public final class GnssMeasurement implements Parcelable {
             gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
             gnssMeasurement.mMultipathIndicator = parcel.readInt();
             gnssMeasurement.mSnrInDb = parcel.readDouble();
-            gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0);
 
             return gnssMeasurement;
         }
@@ -845,7 +824,6 @@ public final class GnssMeasurement implements Parcelable {
         parcel.writeDouble(mCarrierPhaseUncertainty);
         parcel.writeInt(mMultipathIndicator);
         parcel.writeDouble(mSnrInDb);
-        parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0));
     }
 
     @Override
@@ -880,10 +858,6 @@ public final class GnssMeasurement implements Parcelable {
                 mPseudorangeRateMetersPerSecond,
                 "PseudorangeRateUncertaintyMetersPerSecond",
                 mPseudorangeRateUncertaintyMetersPerSecond));
-        builder.append(String.format(
-                format,
-                "PseudorangeRateIsCorrected",
-                isPseudorangeRateCorrected()));
 
         builder.append(String.format(
                 format,
@@ -943,7 +917,6 @@ public final class GnssMeasurement implements Parcelable {
         resetCarrierPhaseUncertainty();
         setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
         resetSnrInDb();
-        setPseudorangeRateCorrected(false);
     }
 
     private void setFlag(int flag) {
index ac255c8..e5c0f27 100644 (file)
@@ -286,18 +286,11 @@ public final class GnssNavigationMessage implements Parcelable {
             navigationMessage.setSvid(parcel.readInt());
             navigationMessage.setMessageId(parcel.readInt());
             navigationMessage.setSubmessageId(parcel.readInt());
-
             int dataLength = parcel.readInt();
             byte[] data = new byte[dataLength];
             parcel.readByteArray(data);
             navigationMessage.setData(data);
-
-            if (parcel.dataAvail() >= Integer.SIZE) {
-                int status = parcel.readInt();
-                navigationMessage.setStatus(status);
-            } else {
-                navigationMessage.setStatus(STATUS_UNKNOWN);
-            }
+            navigationMessage.setStatus(parcel.readInt());
 
             return navigationMessage;
         }
index d179171..3c42161 100644 (file)
@@ -1076,9 +1076,6 @@ public class AudioManager {
      * <p>
      * This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
-     * <p>From N onward, stream mute changes that would toggle Do Not Disturb are not allowed unless
-     * the app has been granted Do Not Disturb Access.
-     * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * <p>
      * This method was deprecated in API level 22. Prior to API level 22 this
      * method had significantly different behavior and should be used carefully.
index 0f82cfc..ca306cc 100644 (file)
@@ -228,7 +228,7 @@ public class AudioRecord implements AudioRouting
     /**
      * Audio session ID
      */
-    private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+    private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
     /**
      * AudioAttributes
      */
index c5d1120..e1dab09 100644 (file)
@@ -295,7 +295,7 @@ public class AudioTrack implements AudioRouting
     /**
      * Audio session ID
      */
-    private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+    private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
     /**
      * Reference to the app-ops service.
      */
@@ -368,7 +368,7 @@ public class AudioTrack implements AudioRouting
             int bufferSizeInBytes, int mode)
     throws IllegalArgumentException {
         this(streamType, sampleRateInHz, channelConfig, audioFormat,
-                bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE);
+                bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);
     }
 
     /**
index 26061e4..346f083 100644 (file)
@@ -508,7 +508,8 @@ public final class MediaFormat {
      * The associated value is an integer.
      * Constants are declared in {@link MediaCodecInfo.CodecProfileLevel}.
      * This key is used as a hint, and is only supported for codecs
-     * that specify a profile.
+     * that specify a profile. Note: Codecs are free to use all the available
+     * coding tools at the specified profile.
      *
      * @see MediaCodecInfo.CodecCapabilities#profileLevels
      */
index 56d3c99..adeb834 100644 (file)
@@ -36,30 +36,28 @@ public class AudioMix {
     private AudioMixingRule mRule;
     private AudioFormat mFormat;
     private int mRouteFlags;
-    private String mRegistrationId;
     private int mMixType = MIX_TYPE_INVALID;
 
     // written by AudioPolicy
     int mMixState = MIX_STATE_DISABLED;
     int mCallbackFlags;
+    String mDeviceAddress;
 
     // initialized in constructor, read by AudioPolicyConfig
-    final int mDeviceId;
-    final String mDeviceAddress;
+    final int mDeviceSystemType; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
 
     /**
      * All parameters are guaranteed valid through the Builder.
      */
     private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags,
-            int deviceId, String deviceAddress) {
+            int deviceType, String deviceAddress) {
         mRule = rule;
         mFormat = format;
         mRouteFlags = routeFlags;
-        mRegistrationId = null;
         mMixType = rule.getTargetMixType();
         mCallbackFlags = callbackFlags;
-        mDeviceId = deviceId;
-        mDeviceAddress = deviceAddress;
+        mDeviceSystemType = deviceType;
+        mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress;
     }
 
     // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined
@@ -155,12 +153,12 @@ public class AudioMix {
     }
 
     void setRegistration(String regId) {
-        mRegistrationId = regId;
+        mDeviceAddress = regId;
     }
 
     /** @hide */
     public String getRegistration() {
-        return mRegistrationId;
+        return mDeviceAddress;
     }
 
     /** @hide */
@@ -185,7 +183,8 @@ public class AudioMix {
         private AudioFormat mFormat = null;
         private int mRouteFlags = 0;
         private int mCallbackFlags = 0;
-        private int mDeviceId = -1;
+        // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
+        private int mDeviceSystemType = AudioSystem.DEVICE_NONE;
         private String mDeviceAddress = null;
 
         /**
@@ -243,12 +242,12 @@ public class AudioMix {
         /**
          * @hide
          * Only used by AudioPolicyConfig, not a public API.
-         * @param deviceId
+         * @param deviceType an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
          * @param address
          * @return the same Builder instance.
          */
-        Builder setDevice(int deviceId, String address) {
-            mDeviceId = deviceId;
+        Builder setDevice(int deviceType, String address) {
+            mDeviceSystemType = deviceType;
             mDeviceAddress = address;
             return this;
         }
@@ -312,7 +311,7 @@ public class AudioMix {
             if (!device.isSink()) {
                 throw new IllegalArgumentException("Unsupported device type on mix, not a sink");
             }
-            mDeviceId = device.getId();
+            mDeviceSystemType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
             mDeviceAddress = device.getAddress();
             return this;
         }
@@ -344,7 +343,9 @@ public class AudioMix {
                 }
                 mFormat = new AudioFormat.Builder().setSampleRate(rate).build();
             }
-            if (mDeviceId != -1) {
+            if ((mDeviceSystemType != AudioSystem.DEVICE_NONE)
+                    && (mDeviceSystemType != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)
+                    && (mDeviceSystemType != AudioSystem.DEVICE_IN_REMOTE_SUBMIX)) {
                 if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) {
                     throw new IllegalArgumentException(
                             "Can't have audio device without flag ROUTE_FLAG_RENDER");
@@ -357,8 +358,17 @@ public class AudioMix {
                     throw new IllegalArgumentException(
                             "Can't have flag ROUTE_FLAG_RENDER without an audio device");
                 }
+                if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_LOOP_BACK) {
+                    if (mRule.getTargetMixType() == MIX_TYPE_PLAYERS) {
+                        mDeviceSystemType = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+                    } else if (mRule.getTargetMixType() == MIX_TYPE_RECORDERS) {
+                        mDeviceSystemType = AudioSystem.DEVICE_IN_REMOTE_SUBMIX;
+                    } else {
+                        throw new IllegalArgumentException("Unknown mixing rule type");
+                    }
+                }
             }
-            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceId,
+            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType,
                     mDeviceAddress);
         }
     }
index 3af3ae7..cafa5a8 100644 (file)
@@ -84,7 +84,7 @@ public class AudioPolicyConfig implements Parcelable {
             // write callback flags
             dest.writeInt(mix.mCallbackFlags);
             // write device information
-            dest.writeInt(mix.mDeviceId);
+            dest.writeInt(mix.mDeviceSystemType);
             dest.writeString(mix.mDeviceAddress);
             // write mix format
             dest.writeInt(mix.getFormat().getSampleRate());
index 89e4577..3eb3359 100644 (file)
@@ -302,7 +302,6 @@ public final class TvInputManager {
      * Interface used to receive the created session.
      * @hide
      */
-    @SystemApi
     public abstract static class SessionCallback {
         /**
          * This is called after {@link TvInputManager#createSession} has been processed.
@@ -418,9 +417,7 @@ public final class TvInputManager {
          * @param top Top position.
          * @param right Right position.
          * @param bottom Bottom position.
-         * @hide
          */
-        @SystemApi
         public void onLayoutSurface(Session session, int left, int top, int right, int bottom) {
         }
 
@@ -430,9 +427,7 @@ public final class TvInputManager {
          * @param session A {@link TvInputManager.Session} associated with this callback
          * @param eventType The type of the event.
          * @param eventArgs Optional arguments of the event.
-         * @hide
          */
-        @SystemApi
         public void onSessionEvent(Session session, String eventType, Bundle eventArgs) {
         }
 
@@ -1347,7 +1342,6 @@ public final class TvInputManager {
      * @param handler A {@link Handler} that the session creation will be delivered to.
      * @hide
      */
-    @SystemApi
     public void createSession(@NonNull String inputId, @NonNull final SessionCallback callback,
             @NonNull Handler handler) {
         createSessionInternal(inputId, false, callback, handler);
@@ -1364,7 +1358,6 @@ public final class TvInputManager {
      * @param handler A {@link Handler} that the session creation will be delivered to.
      * @hide
      */
-    @SystemApi
     public void createRecordingSession(@NonNull String inputId,
             @NonNull final SessionCallback callback, @NonNull Handler handler) {
         createSessionInternal(inputId, true, callback, handler);
@@ -1544,7 +1537,6 @@ public final class TvInputManager {
      * The Session provides the per-session functionality of TV inputs.
      * @hide
      */
-    @SystemApi
     public static final class Session {
         static final int DISPATCH_IN_PROGRESS = -1;
         static final int DISPATCH_NOT_HANDLED = 0;
@@ -1656,9 +1648,7 @@ public final class TvInputManager {
          * @param format The new PixelFormat of the surface.
          * @param width The new width of the surface.
          * @param height The new height of the surface.
-         * @hide
          */
-        @SystemApi
         public void dispatchSurfaceChanged(int format, int width, int height) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
@@ -1706,9 +1696,7 @@ public final class TvInputManager {
          *
          * @param channelUri The URI of a channel.
          * @param params A set of extra parameters which might be handled with this tune event.
-         * @hide
          */
-        @SystemApi
         public void tune(@NonNull Uri channelUri, Bundle params) {
             Preconditions.checkNotNull(channelUri);
             if (mToken == null) {
@@ -2065,9 +2053,7 @@ public final class TvInputManager {
          *            i.e. prefixed with a package name you own, so that different developers will
          *            not create conflicting commands.
          * @param data Any data to include with the command.
-         * @hide
          */
-        @SystemApi
         public void sendAppPrivateCommand(String action, Bundle data) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
index e9d62de..2fb1a3b 100644 (file)
@@ -906,14 +906,16 @@ android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz)
     android_media_MediaPlayer_release(env, thiz);
 }
 
-static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env,  jobject thiz, jint sessionId) {
+static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env,  jobject thiz,
+        jint sessionId) {
     ALOGV("set_session_id(): %d", sessionId);
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return;
     }
-    process_media_player_call( env, thiz, mp->setAudioSessionId(sessionId), NULL, NULL );
+    process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL,
+            NULL);
 }
 
 static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env,  jobject thiz) {
index fa69135..10efe18 100644 (file)
@@ -351,7 +351,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
                                     priority,
                                     effectCallback,
                                     &lpJniStorage->mCallbackData,
-                                    sessionId,
+                                    (audio_session_t) sessionId,
                                     0);
     if (lpAudioEffect == 0) {
         ALOGE("Error creating AudioEffect");
@@ -819,7 +819,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _
     effect_descriptor_t *descriptors = new effect_descriptor_t[AudioEffect::kMaxPreProcessing];
     uint32_t numEffects = AudioEffect::kMaxPreProcessing;
 
-    status_t status = AudioEffect::queryDefaultPreProcessing(audioSession,
+    status_t status = AudioEffect::queryDefaultPreProcessing((audio_session_t) audioSession,
                                            descriptors,
                                            &numEffects);
     if (status != NO_ERROR || numEffects == 0) {
index 3d3adba..f1a8c6f 100644 (file)
@@ -388,7 +388,7 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
                                   0,
                                   android_media_visualizer_effect_callback,
                                   lpJniStorage,
-                                  sessionId);
+                                  (audio_session_t) sessionId);
     if (lpVisualizer == 0) {
         ALOGE("Error creating Visualizer");
         goto setup_failure;
index 76c701a..5cfe300 100644 (file)
@@ -105,6 +105,14 @@ int ASensorManager_destroyEventQueue(ASensorManager* manager,
 
 /*****************************************************************************/
 
+int ASensorEventQueue_registerSensor(ASensorEventQueue* queue, ASensor const* sensor,
+        int32_t samplingPeriodUs, int maxBatchReportLatencyUs)
+{
+    return static_cast<SensorEventQueue*>(queue)->enableSensor(
+            static_cast<Sensor const*>(sensor)->getHandle(), samplingPeriodUs,
+                    maxBatchReportLatencyUs, 0);
+}
+
 int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor)
 {
     return static_cast<SensorEventQueue*>(queue)->enableSensor(
index ccf1501..55d000c 100644 (file)
@@ -13,8 +13,8 @@
 
     <application android:label="@string/service_name"
                  android:allowBackup="false"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
 
         <service android:name=".DefaultContainerService"
                  android:enabled="true"
diff --git a/packages/DocumentsUI/app-perf-tests/Android.mk b/packages/DocumentsUI/app-perf-tests/Android.mk
new file mode 100644 (file)
index 0000000..3f12906
--- /dev/null
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
+
+LOCAL_PACKAGE_NAME := DocumentsUIAppPerfTests
+LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..1c3ed80
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.documentsui.appperftests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name="com.android.documentsui.LauncherActivity" />
+    </application>
+
+    <!-- This package instrumentates itself, so the DocumentsUI process can be killed without
+         killing the testing package. -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.documentsui.appperftests"
+        android:label="App performance tests for DocumentsUI" />
+
+</manifest>
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
new file mode 100644 (file)
index 0000000..d6e8a96
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 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.documentsui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.support.test.uiautomator.UiDevice;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+@LargeTest
+public class FilesAppPerfTest extends InstrumentationTestCase {
+
+    // Keys used to report metrics to APCT.
+    private static final String KEY_FILES_COLD_START_PERFORMANCE_MEDIAN =
+            "files-cold-start-performance-median";
+    private static final String KEY_FILES_WARM_START_PERFORMANCE_MEDIAN =
+            "files-warm-start-performance-median";
+
+    private static final String TARGET_PACKAGE = "com.android.documentsui";
+
+    private static final int NUM_MEASUREMENTS = 10;
+
+    private LauncherActivity mActivity;
+    private UiDevice mDevice;
+
+    @Override
+    public void setUp() {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+    }
+
+    public void testFilesColdStartPerformance() throws Exception {
+        runFilesStartPerformanceTest(true);
+    }
+
+    public void testFilesWarmStartPerformance() throws Exception {
+        runFilesStartPerformanceTest(false);
+    }
+
+    public void runFilesStartPerformanceTest(boolean cold) throws Exception {
+        long[] measurements = new long[NUM_MEASUREMENTS];
+        for (int i = 0; i < NUM_MEASUREMENTS; i++) {
+            if (cold) {
+                // Kill all providers, as well as DocumentsUI to measure a cold start.
+                killProviders();
+                mDevice.executeShellCommand("am force-stop " + TARGET_PACKAGE);
+            }
+            mDevice.waitForIdle();
+
+            LauncherActivity.testCaseLatch = new CountDownLatch(1);
+            mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
+                    LauncherActivity.class, null);
+            LauncherActivity.testCaseLatch.await();
+            measurements[i] = LauncherActivity.measurement;
+        }
+
+        reportMetrics(cold ? KEY_FILES_COLD_START_PERFORMANCE_MEDIAN
+                : KEY_FILES_WARM_START_PERFORMANCE_MEDIAN, measurements);
+    }
+
+    private void reportMetrics(String key, long[] measurements) {
+        final Bundle status = new Bundle();
+        Arrays.sort(measurements);
+        final long median = measurements[NUM_MEASUREMENTS / 2 - 1];
+        status.putDouble(key, median);
+
+        getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+    }
+
+    private void killProviders() throws Exception {
+        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+        final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0);
+        for (ResolveInfo info : providers) {
+            final String packageName = info.providerInfo.packageName;
+            mDevice.executeShellCommand("am force-stop " + packageName);
+        }
+    }
+}
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
new file mode 100644 (file)
index 0000000..21fc52e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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.documentsui;
+
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+
+public class LauncherActivity extends Activity {
+    private static final String TARGET_PACKAGE = "com.android.documentsui";
+    private static final int BENCHMARK_REQUEST_CODE = 1986;
+
+    public static CountDownLatch testCaseLatch = null;
+    public static long measurement = -1;
+
+    private long mStartTime = -1;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        new Handler().post(new Runnable() {
+            @Override public void run() {
+                final Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT");
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
+                intent.putExtra(EXTRA_BENCHMARK, true);
+                intent.setType("*/*");
+
+                mStartTime = System.currentTimeMillis();
+                startActivityForResult(intent, BENCHMARK_REQUEST_CODE);
+            }
+        });
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == BENCHMARK_REQUEST_CODE) {
+            measurement = System.currentTimeMillis() - mStartTime;
+            testCaseLatch.countDown();
+            finish();
+        }
+    }
+}
index c51cbb3..fe61094 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
 import static com.android.documentsui.State.MODE_GRID;
 
 import android.app.Activity;
@@ -30,6 +31,9 @@ import android.content.pm.ProviderInfo;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.MessageQueue;
+import android.os.MessageQueue.IdleHandler;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.support.annotation.CallSuper;
@@ -60,6 +64,8 @@ import java.util.concurrent.Executor;
 public abstract class BaseActivity extends Activity
         implements SearchManagerListener, NavigationView.Environment {
 
+    private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests";
+
     State mState;
     RootsCache mRoots;
     SearchViewManager mSearchManager;
@@ -92,11 +98,20 @@ public abstract class BaseActivity extends Activity
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        final Intent intent = getIntent();
+
+        // If startup benchmark is requested by a whitelisted testing package, then close the
+        // activity once idle, and notify the testing activity.
+        if (intent.getBooleanExtra(EXTRA_BENCHMARK, false) &&
+                BENCHMARK_TESTING_PACKAGE.equals(getCallingPackage())) {
+            closeOnIdleForTesting();
+        }
+
         setContentView(mLayoutId);
 
         mDrawer = DrawerController.create(this);
         mState = getState(icicle);
-        Metrics.logActivityLaunch(this, mState, getIntent());
+        Metrics.logActivityLaunch(this, mState, intent);
 
         mRoots = DocumentsApplication.getRootsCache(this);
 
@@ -668,6 +683,33 @@ public abstract class BaseActivity extends Activity
         }
     }
 
+    /**
+     * Closes the activity when it's idle. Used only for tests.
+     */
+    private void closeOnIdleForTesting() {
+        addEventListener(new EventListener() {
+            @Override
+            public void onDirectoryNavigated(Uri uri) {
+            }
+
+            @Override
+            public void onDirectoryLoaded(Uri uri) {
+                getMainLooper().getQueue().addIdleHandler(new IdleHandler() {
+                    @Override
+                    public boolean queueIdle() {
+                        setResult(RESULT_OK);
+                        finish();
+                        return false;
+                    }
+                });
+                new Handler().post(new Runnable() {
+                    @Override public void run() {
+                    }
+                });
+            }
+        });
+    }
+
     private static final class HandleRootsChangedTask
             extends PairedTask<BaseActivity, RootInfo, RootInfo> {
         DocumentInfo mDownloadsDocument;
index b539421..c32bbff 100644 (file)
@@ -86,6 +86,11 @@ public final class Shared {
      */
     public static final String EXTRA_IGNORE_STATE = "ignoreState";
 
+    /**
+     * Extra for an Intent for enabling performance benchmark. Used only by tests.
+     */
+    public static final String EXTRA_BENCHMARK = "com.android.documentsui.benchmark";
+
     private static final Collator sCollator;
 
     static {
@@ -133,8 +138,7 @@ public final class Shared {
 
     /**
      * Compare two strings against each other using system default collator in a
-     * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX}
-     * before other items.
+     * case-insensitive mode.
      */
     public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
         final boolean leftEmpty = TextUtils.isEmpty(lhs);
index be70417..63a834f 100644 (file)
@@ -98,7 +98,6 @@ import com.android.documentsui.model.RootInfo;
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperationService.OpType;
 import com.android.documentsui.services.FileOperations;
-
 import com.google.common.collect.Lists;
 
 import java.lang.annotation.Retention;
@@ -165,6 +164,7 @@ public class DirectoryFragment extends Fragment
     private String mQuery = null;
     private Selection mSelection = null;
     private boolean mSearchMode = false;
+    private @Nullable ActionMode mActionMode;
 
     @Override
     public View onCreateView(
@@ -406,9 +406,9 @@ public class DirectoryFragment extends Fragment
         int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
         int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
 
-        assert(mRecView.getWidth() > 0);
-
-        int columnCount = Math.max(1,
+        // RecyclerView sometimes gets a width of 0 (see b/27150284).  Clamp so that we always lay
+        // out the grid with at least 2 columns.
+        int columnCount = Math.max(2,
                 (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
 
         return columnCount;
@@ -439,7 +439,6 @@ public class DirectoryFragment extends Fragment
             implements MultiSelectManager.Callback, ActionMode.Callback {
 
         private Selection mSelected = new Selection();
-        private ActionMode mActionMode;
         private int mNoCopyCount = 0;
         private int mNoDeleteCount = 0;
         private int mNoRenameCount = -1;
@@ -578,10 +577,9 @@ public class DirectoryFragment extends Fragment
                     return true;
 
                 case R.id.menu_delete:
-                    // Pass mode along to the delete function so it can
-                    // end action mode when documents are deleted.
+                    // deleteDocuments will end action mode if the documents are deleted.
                     // It won't end action mode if user cancels the delete.
-                    deleteDocuments(selection, mode);
+                    deleteDocuments(selection);
                     return true;
 
                 case R.id.menu_copy_to:
@@ -690,7 +688,7 @@ public class DirectoryFragment extends Fragment
         }.execute(selected);
     }
 
-    private void deleteDocuments(final Selection selected, final ActionMode mode) {
+    private void deleteDocuments(final Selection selected) {
         assert(!selected.isEmpty());
 
         final DocumentInfo srcParent = getDisplayState().stack.peek();
@@ -727,7 +725,9 @@ public class DirectoryFragment extends Fragment
                                 // This is done here, rather in the onActionItemClicked
                                 // so we can avoid de-selecting items in the case where
                                 // the user cancels the delete.
-                                mode.finish();
+                                if (mActionMode != null) {
+                                    mActionMode.finish();
+                                }
                                 // Hide the files in the UI...since the operation
                                 // might be queued up on FileOperationService.
                                 // We're walking a line here.
@@ -1263,12 +1263,25 @@ public class DirectoryFragment extends Fragment
             }
 
             // Handle enter key events
-            if (keyCode == KeyEvent.KEYCODE_ENTER) {
-                if (event.isShiftPressed()) {
-                    return onSelect(doc);
-                } else {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_ENTER:
+                    if (event.isShiftPressed()) {
+                        return onSelect(doc);
+                    }
+                    // For non-shifted enter keypresses, fall through.
+                case KeyEvent.KEYCODE_DPAD_CENTER:
+                case KeyEvent.KEYCODE_BUTTON_A:
                     return onActivate(doc);
-                }
+                case KeyEvent.KEYCODE_FORWARD_DEL:
+                    // This has to be handled here instead of in a keyboard shortcut, because
+                    // keyboard shortcuts all have to be modified with the 'Ctrl' key.
+                    if (mSelectionManager.hasSelection()) {
+                        deleteDocuments(mSelectionManager.getSelection());
+                    }
+                    // Always handle the key, even if there was nothing to delete. This is a
+                    // precaution to prevent other handlers from potentially picking up the event
+                    // and triggering extra behaviours.
+                    return true;
             }
 
             return false;
index 5edda38..450341f 100644 (file)
@@ -77,10 +77,18 @@ public abstract class DocumentHolder
     /**
      * Makes the associated item view appear selected. Note that this merely affects the appearance
      * of the view, it doesn't actually select the item.
+     * TODO: Use the DirectoryItemAnimator instead of manually controlling animation using a boolean
+     * flag.
      *
      * @param selected
+     * @param animate Whether or not to animate the change. Only selection changes initiated by the
+     *            selection manager should be animated. See
+     *            {@link ModelBackedDocumentsAdapter#onBindViewHolder(DocumentHolder, int, java.util.List)}
      */
-    public void setSelected(boolean selected) {
+    public void setSelected(boolean selected, boolean animate) {
+        // Note: the animate param doesn't apply for this base implementation, because the
+        // DirectoryItemAnimator takes care of it. It's required by subclasses, which perform their
+        // own animation.
         itemView.setActivated(selected);
         itemView.setBackgroundColor(selected ? mSelectedBgColor : mDefaultBgColor);
     }
index 39fdf8e..ea1deb4 100644 (file)
@@ -104,7 +104,8 @@ public abstract class FragmentTuner {
                 return false;
             }
 
-            if (mState.action == ACTION_OPEN_TREE) {
+            if (mState.action == ACTION_OPEN_TREE
+                    || mState.action == ACTION_PICK_COPY_DESTINATION) {
                 // In this case nothing *ever* is selectable...the expected user behavior is
                 // they navigate *into* a folder, then click a confirmation button indicating
                 // that the current directory is the directory they are picking.
index 90b2341..ce5bcb1 100644 (file)
@@ -42,12 +42,17 @@ final class GridDirectoryHolder extends DocumentHolder {
     }
 
     @Override
-    public void setSelected(boolean selected) {
-        super.setSelected(selected);
+    public void setSelected(boolean selected, boolean animate) {
+        super.setSelected(selected, animate);
         float checkAlpha = selected ? 1f : 0f;
 
-        mIconCheck.animate().alpha(checkAlpha).start();
-        mIconMime.animate().alpha(1f - checkAlpha).start();
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+            mIconMime.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+            mIconMime.setAlpha(1f - checkAlpha);
+        }
     }
 
     /**
index c8641a8..c4f6f11 100644 (file)
@@ -69,12 +69,16 @@ final class GridDocumentHolder extends DocumentHolder {
     }
 
     @Override
-    public void setSelected(boolean selected) {
+    public void setSelected(boolean selected, boolean animate) {
         // We always want to make sure our check box disappears if we're not selected,
         // even if the item is disabled. This is because this object can be reused
         // and this method will be called to setup initial state.
         float checkAlpha = selected ? 1f : 0f;
-        mIconCheck.animate().alpha(checkAlpha).start();
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+        }
 
         // But it should be an error to be set to selected && be disabled.
         if (!itemView.isEnabled()) {
@@ -82,9 +86,13 @@ final class GridDocumentHolder extends DocumentHolder {
             return;
         }
 
-        super.setSelected(selected);
+        super.setSelected(selected, animate);
 
-        mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+        if (animate) {
+            mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconMimeSm.setAlpha(1f - checkAlpha);
+        }
     }
 
     public void setEnabled(boolean enabled) {
index 3a1be11..ace53e0 100644 (file)
@@ -65,22 +65,31 @@ final class ListDocumentHolder extends DocumentHolder {
     }
 
     @Override
-    public void setSelected(boolean selected) {
+    public void setSelected(boolean selected, boolean animate) {
         // We always want to make sure our check box disappears if we're not selected,
         // even if the item is disabled. But it should be an error (see assert below)
         // to be set to selected && be disabled.
         float checkAlpha = selected ? 1f : 0f;
-        mIconCheck.animate().alpha(checkAlpha).start();
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+        }
 
         if (!itemView.isEnabled()) {
             assert(!selected);
             return;
         }
 
-        super.setSelected(selected);
+        super.setSelected(selected, animate);
 
-        mIconMime.animate().alpha(1f - checkAlpha).start();
-        mIconThumb.animate().alpha(1f - checkAlpha).start();
+        if (animate) {
+            mIconMime.animate().alpha(1f - checkAlpha).start();
+            mIconThumb.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconMime.setAlpha(1f - checkAlpha);
+            mIconThumb.setAlpha(1f - checkAlpha);
+        }
     }
 
     @Override
index 68b1bcc..c5ee592 100644 (file)
@@ -20,9 +20,10 @@ import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME;
 import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
 import static com.android.documentsui.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.model.DocumentInfo.getCursorLong;
+import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
 import android.database.Cursor;
-import android.database.MergeCursor;
 import android.os.Bundle;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
@@ -61,17 +62,34 @@ public class Model {
     private String mIds[] = new String[0];
     private int mSortOrder = SORT_ORDER_DISPLAY_NAME;
 
-    private int mAuthorityIndex = -1;
-    private int mDocIdIndex = -1;
-    private int mMimeTypeIndex = -1;
-    private int mDisplayNameIndex = -1;
-    private int mColumnSizeIndex = -1;
-    private int mLastModifiedIndex = -1;
-
     @Nullable String info;
     @Nullable String error;
     @Nullable DocumentInfo doc;
 
+    /**
+     * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
+     * string that can be used to identify the document referred to by the cursor.
+     *
+     * @param c A cursor that refers to a document.
+     */
+    private static String createModelId(Cursor c) {
+        // TODO: Maybe more efficient to use just the document ID, in cases where there is only one
+        // authority (which should be the majority of cases).
+        return createModelId(
+                getCursorString(c, RootCursorWrapper.COLUMN_AUTHORITY),
+                getCursorString(c, Document.COLUMN_DOCUMENT_ID));
+    }
+
+    /**
+     * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
+     * string that can be used to identify the document referred to by the cursor.
+     *
+     * @param c A cursor that refers to a document.
+     */
+    static String createModelId(String authority, String docId) {
+        return authority + "|" + docId;
+    }
+
     private void notifyUpdateListeners() {
         for (UpdateListener listener: mUpdateListeners) {
             listener.onModelUpdate(this);
@@ -109,13 +127,6 @@ public class Model {
         mCursor = result.cursor;
         mCursorCount = mCursor.getCount();
         mSortOrder = result.sortOrder;
-        mAuthorityIndex = mCursor.getColumnIndex(RootCursorWrapper.COLUMN_AUTHORITY);
-        assert(mAuthorityIndex != -1);
-        mDocIdIndex = mCursor.getColumnIndex(Document.COLUMN_DOCUMENT_ID);
-        mMimeTypeIndex = mCursor.getColumnIndex(Document.COLUMN_MIME_TYPE);
-        mDisplayNameIndex = mCursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME);
-        mColumnSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE);
-
         doc = result.doc;
 
         updateModelData();
@@ -162,30 +173,22 @@ public class Model {
         for (int pos = 0; pos < mCursorCount; ++pos) {
             mCursor.moveToNext();
             positions[pos] = pos;
+            mIds[pos] = createModelId(mCursor);
 
-            // Generates a Model ID for a cursor entry that refers to a document. The Model ID is a
-            // unique string that can be used to identify the document referred to by the cursor.
-            // If the cursor is a merged cursor over multiple authorities, then prefix the ids
-            // with the authority to avoid collisions.
-            if (mCursor instanceof MergeCursor) {
-                mIds[pos] = getString(mAuthorityIndex) + "|" + mCursor.getString(mDocIdIndex);
-            } else {
-                mIds[pos] = mCursor.getString(mDocIdIndex);
-            }
-
-            mimeType = getString(mMimeTypeIndex);
+            mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
             isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
 
-            switch (mSortOrder) {
+            switch(mSortOrder) {
                 case SORT_ORDER_DISPLAY_NAME:
-                    displayNames[pos] = getString(mDisplayNameIndex);
+                    final String displayName = getCursorString(
+                            mCursor, Document.COLUMN_DISPLAY_NAME);
+                    displayNames[pos] = displayName;
                     break;
                 case SORT_ORDER_LAST_MODIFIED:
-                    longValues[pos] = getLastModified();
+                    longValues[pos] = getLastModified(mCursor);
                     break;
                 case SORT_ORDER_SIZE:
-                    longValues[pos] = mColumnSizeIndex != -1
-                            ? mCursor.getLong(mColumnSizeIndex) : 0;
+                    longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE);
                     break;
             }
         }
@@ -361,17 +364,13 @@ public class Model {
         }
     }
 
-    private String getString(int columnIndex) {
-        return columnIndex != -1 ? mCursor.getString(columnIndex) : null;
-    }
-
     /**
      * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
      * timestamp - these will be replaced with MAX_LONG so that such files get sorted to the top
      * when sorting by date.
      */
-    private long getLastModified() {
-        long l = mCursor.getLong(mLastModifiedIndex);
+    long getLastModified(Cursor cursor) {
+        long l = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED);
         return (l == -1) ? Long.MAX_VALUE : l;
     }
 
index 149ecdd..ca3b2e2 100644 (file)
@@ -29,7 +29,6 @@ import android.util.SparseArray;
 import android.view.ViewGroup;
 
 import com.android.documentsui.State;
-
 import com.google.common.collect.Sets;
 
 import java.util.ArrayList;
@@ -103,7 +102,7 @@ final class ModelBackedDocumentsAdapter extends DocumentsAdapter {
     public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
         if (payload.contains(SELECTION_CHANGED_MARKER)) {
             final boolean selected = mEnv.isSelected(mModelIds.get(position));
-            holder.setSelected(selected);
+            holder.setSelected(selected, true);
         } else {
             onBindViewHolder(holder, position);
         }
@@ -124,7 +123,7 @@ final class ModelBackedDocumentsAdapter extends DocumentsAdapter {
             assert(!selected);
         }
         holder.setEnabled(enabled);
-        holder.setSelected(mEnv.isSelected(modelId));
+        holder.setSelected(mEnv.isSelected(modelId), false);
 
         mEnv.onBindDocumentHolder(holder, cursor);
     }
index b0cc09a..b80486d 100644 (file)
@@ -903,7 +903,7 @@ public final class MultiSelectManager {
             public Selection createFromParcel(Parcel in, ClassLoader loader) {
                 return new Selection(
                         in.readString(),
-                        (ArrayList<String>) in.readArrayList(loader));
+                        in.readArrayList(loader));
             }
 
             @Override
@@ -931,7 +931,6 @@ public final class MultiSelectManager {
         Rect getAbsoluteRectForChildViewAt(int index);
         int getAdapterPositionAt(int index);
         int getColumnCount();
-        int getRowCount();
         int getChildCount();
         int getVisibleChildCount();
         /**
@@ -1008,13 +1007,6 @@ public final class MultiSelectManager {
         }
 
         @Override
-        public int getRowCount() {
-            int numFullColumns = getChildCount() / getColumnCount();
-            boolean hasPartiallyFullColumn = getChildCount() % getColumnCount() != 0;
-            return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
-        }
-
-        @Override
         public int getHeight() {
             return mView.getHeight();
         }
@@ -1202,6 +1194,7 @@ public final class MultiSelectManager {
             }
 
             mCurrentPosition = input.getOrigin();
+            mModel.resizeSelection(input.getOrigin());
             scrollViewIfNecessary();
             resizeBandSelectRectangle();
         }
@@ -1549,11 +1542,7 @@ public final class MultiSelectManager {
                         mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right));
             }
 
-            if (mRowBounds.size() != mHelper.getRowCount()) {
-                // If not all y-limits have been recorded, record this one.
-                recordLimits(
-                        mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
-            }
+            recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
 
             SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
             if (columnList == null) {
@@ -1747,6 +1736,11 @@ public final class MultiSelectManager {
                 return ((Limits) other).lowerLimit == lowerLimit &&
                         ((Limits) other).upperLimit == upperLimit;
             }
+
+            @Override
+            public String toString() {
+                return "(" + lowerLimit + ", " + upperLimit + ")";
+            }
         }
 
         /**
index 3536593..c6ad511 100644 (file)
@@ -284,7 +284,7 @@ public class ModelTest extends AndroidTestCase {
             String id = Integer.toString(i);
             row.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY);
             row.add(Document.COLUMN_DOCUMENT_ID, id);
-            currentDownloads.add(id);
+            currentDownloads.add(Model.createModelId(AUTHORITY, id));
         }
 
         DirectoryResult r = new DirectoryResult();
index 353d4bd..0c0e0b7 100644 (file)
@@ -27,6 +27,7 @@ import android.test.suitebuilder.annotation.SmallTest;
 import com.android.documentsui.dirlist.MultiSelectManager.GridModel;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 
 @SmallTest
@@ -42,6 +43,17 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase {
     private Set<String> lastSelection;
     private int viewWidth;
 
+    // TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and
+    // #resizeSelection methods instead.
+    //
+    // The reason for this is that selection is stateful and involves operations that take the
+    // current UI state (e.g scrolling) into account. This test maintains its own copy of the
+    // selection bounds as control data for verifying selections. Keep this data in sync by calling
+    // #startSelection and
+    // #resizeSelection.
+    private Point mSelectionOrigin;
+    private Point mSelectionPoint;
+
     private void initData(final int numChildren, int numColumns) {
         env = new TestEnvironment(numChildren, numColumns);
         adapter = new TestDocumentsAdapter(new ArrayList<String>()) {
@@ -76,139 +88,241 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase {
 
     public void testSelectionLeftOfItems() {
         initData(20, 5);
-        model.startSelection(new Point(0, 10));
-        model.resizeSelection(new Point(1, 11));
-        assertSelected();
+        startSelection(new Point(0, 10));
+        resizeSelection(new Point(1, 11));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionRightOfItems() {
         initData(20, 4);
-        model.startSelection(new Point(viewWidth - 1, 10));
-        model.resizeSelection(new Point(viewWidth - 2, 11));
-        assertSelected();
+        startSelection(new Point(viewWidth - 1, 10));
+        resizeSelection(new Point(viewWidth - 2, 11));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionAboveItems() {
         initData(20, 4);
-        model.startSelection(new Point(10, 0));
-        model.resizeSelection(new Point(11, 1));
-        assertSelected();
+        startSelection(new Point(10, 0));
+        resizeSelection(new Point(11, 1));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionBelowItems() {
         initData(5, 4);
-        model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
-        model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
-        assertSelected();
+        startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
+        resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testVerticalSelectionBetweenItems() {
         initData(20, 4);
-        model.startSelection(new Point(106, 0));
-        model.resizeSelection(new Point(107, 200));
-        assertSelected();
+        startSelection(new Point(106, 0));
+        resizeSelection(new Point(107, 200));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testHorizontalSelectionBetweenItems() {
         initData(20, 4);
-        model.startSelection(new Point(0, 105));
-        model.resizeSelection(new Point(200, 106));
-        assertSelected();
+        startSelection(new Point(0, 105));
+        resizeSelection(new Point(200, 106));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testGrowingAndShrinkingSelection() {
         initData(20, 4);
-        model.startSelection(new Point(0, 0));
-        model.resizeSelection(new Point(5, 5));
-        assertSelected(0);
-        model.resizeSelection(new Point(109, 109));
-        assertSelected(0);
-        model.resizeSelection(new Point(110, 109));
-        assertSelected(0, 1);
-        model.resizeSelection(new Point(110, 110));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(214, 214));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(215, 214));
-        assertSelected(0, 1, 2, 4, 5, 6);
-        model.resizeSelection(new Point(214, 214));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(110, 110));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(110, 109));
-        assertSelected(0, 1);
-        model.resizeSelection(new Point(109, 109));
-        assertSelected(0);
-        model.resizeSelection(new Point(5, 5));
-        assertSelected(0);
-        model.resizeSelection(new Point(0, 0));
-        assertSelected();
+        startSelection(new Point(0, 0));
+
+        resizeSelection(new Point(5, 5));
+        verifySelection();
+
+        resizeSelection(new Point(109, 109));
+        verifySelection();
+
+        resizeSelection(new Point(110, 109));
+        verifySelection();
+
+        resizeSelection(new Point(110, 110));
+        verifySelection();
+
+        resizeSelection(new Point(214, 214));
+        verifySelection();
+
+        resizeSelection(new Point(215, 214));
+        verifySelection();
+
+        resizeSelection(new Point(214, 214));
+        verifySelection();
+
+        resizeSelection(new Point(110, 110));
+        verifySelection();
+
+        resizeSelection(new Point(110, 109));
+        verifySelection();
+
+        resizeSelection(new Point(109, 109));
+        verifySelection();
+
+        resizeSelection(new Point(5, 5));
+        verifySelection();
+
+        resizeSelection(new Point(0, 0));
+        verifySelection();
+
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionMovingAroundOrigin() {
         initData(16, 4);
-        model.startSelection(new Point(210, 210));
-        model.resizeSelection(new Point(viewWidth - 1, 0));
-        assertSelected(2, 3, 6, 7);
-        model.resizeSelection(new Point(0, 0));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(0, 420));
-        assertSelected(8, 9, 12, 13);
-        model.resizeSelection(new Point(viewWidth - 1, 420));
-        assertSelected(10, 11, 14, 15);
-        assertEquals(10, model.getPositionNearestOrigin());
+
+        startSelection(new Point(210, 210));
+        resizeSelection(new Point(viewWidth - 1, 0));
+        verifySelection();
+
+        resizeSelection(new Point(0, 0));
+        verifySelection();
+
+        resizeSelection(new Point(0, 420));
+        verifySelection();
+
+        resizeSelection(new Point(viewWidth - 1, 420));
+        verifySelection();
+
+        // This is manually figured and will need to be adjusted if the separator position is
+        // changed.
+        assertEquals(7, model.getPositionNearestOrigin());
     }
 
     public void testScrollingBandSelect() {
         initData(40, 4);
-        model.startSelection(new Point(0, 0));
-        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 4, 8, 12, 16);
+
+        startSelection(new Point(0, 0));
+        resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         scroll(CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 4, 8, 12, 16, 20);
-        model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21);
+        verifySelection();
+
+        resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         scroll(CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25);
+        verifySelection();
+
         scroll(-2 * CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17);
-        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 4, 8, 12, 16);
+        verifySelection();
+
+        resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         assertEquals(0, model.getPositionNearestOrigin());
     }
 
-    private void assertSelected(int... selectedPositions) {
-        assertEquals(selectedPositions.length, lastSelection.size());
-        for (int position : selectedPositions) {
-            assertTrue(lastSelection.contains(Integer.toString(position)));
+    /** Returns the current selection area as a Rect. */
+    private Rect getSelectionArea() {
+        // Construct a rect from the two selection points.
+        Rect selectionArea = new Rect(
+                mSelectionOrigin.x, mSelectionOrigin.y, mSelectionOrigin.x, mSelectionOrigin.y);
+        selectionArea.union(mSelectionPoint.x, mSelectionPoint.y);
+        // Rect intersection tests are exclusive of bounds, while the MSM's selection code is
+        // inclusive. Expand the rect by 1 pixel in all directions to account for this.
+        selectionArea.inset(-1, -1);
+
+        return selectionArea;
+    }
+
+    /** Asserts that the selection is currently empty. */
+    private void assertNoSelection() {
+        assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(),
+                0, lastSelection.size());
+    }
+
+    /** Verifies the selection using actual bbox checks. */
+    private void verifySelection() {
+        Rect selectionArea = getSelectionArea();
+        for (TestEnvironment.Item item: env.items) {
+            if (Rect.intersects(selectionArea, item.rect)) {
+                assertTrue("Expected item " + item + " was not in selection " + selectionArea,
+                        lastSelection.contains(item.name));
+            } else {
+                assertFalse("Unexpected item " + item + " in selection" + selectionArea,
+                        lastSelection.contains(item.name));
+            }
         }
     }
 
+    private void startSelection(Point p) {
+        model.startSelection(p);
+        mSelectionOrigin = env.createAbsolutePoint(p);
+    }
+
+    private void resizeSelection(Point p) {
+        model.resizeSelection(p);
+        mSelectionPoint = env.createAbsolutePoint(p);
+    }
+
     private void scroll(int dy) {
         assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight());
         env.verticalOffset += dy;
+        // Correct the cached selection point as well.
+        mSelectionPoint.y += dy;
         model.onScrolled(null, 0, dy);
     }
 
     private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment {
 
-        public int horizontalOffset = 0;
-        public int verticalOffset = 0;
         private final int mNumColumns;
         private final int mNumRows;
         private final int mNumChildren;
+        private final int mSeparatorPosition;
+
+        public int horizontalOffset = 0;
+        public int verticalOffset = 0;
+        private List<Item> items = new ArrayList<>();
 
         public TestEnvironment(int numChildren, int numColumns) {
             mNumChildren = numChildren;
             mNumColumns = numColumns;
-            mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
+            mSeparatorPosition = mNumColumns + 1;
+            mNumRows = setupGrid();
+        }
+
+        private int setupGrid() {
+            // Split the input set into folders and documents. Do this such that there is a
+            // partially-populated row in the middle of the grid, to test corner cases in layout
+            // code.
+            int y = VIEW_PADDING_PX;
+            int i = 0;
+            int numRows = 0;
+            while (i < mNumChildren) {
+                int top = y;
+                int height = CHILD_VIEW_EDGE_PX;
+                int width = CHILD_VIEW_EDGE_PX;
+                for (int j = 0; j < mNumColumns && i < mNumChildren; j++) {
+                    int left = VIEW_PADDING_PX + (j * (width + VIEW_PADDING_PX));
+                    items.add(new Item(
+                            Integer.toString(i),
+                            new Rect(
+                                    left,
+                                    top,
+                                    left + width - 1,
+                                    top + height - 1)));
+
+                    // Create a partially populated row at the separator position.
+                    if (++i == mSeparatorPosition) {
+                        break;
+                    }
+                }
+                y += height + VIEW_PADDING_PX;
+                numRows++;
+            }
+
+            return numRows;
         }
 
         private int getTotalHeight() {
@@ -227,8 +341,16 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase {
 
         private int getNumItemsInRow(int index) {
             assertTrue(index >= 0 && index < mNumRows);
-            if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) {
-                return mNumChildren % mNumColumns;
+            int mod = mSeparatorPosition % mNumColumns;
+            if (index == (mSeparatorPosition / mNumColumns)) {
+                // The row containing the separator may be incomplete
+                return mod > 0 ? mod : mNumColumns;
+            }
+            // Account for the partial separator row in the final row tally.
+            if (index == mNumRows - 1) {
+                // The last row may be incomplete
+                int finalRowCount = (mNumChildren - mod) % mNumColumns;
+                return finalRowCount > 0 ? finalRowCount : mNumColumns;
             }
 
             return mNumColumns;
@@ -257,21 +379,18 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase {
 
         @Override
         public int getAdapterPositionAt(int index) {
-            return index + mNumColumns * (getFirstVisibleRowIndex());
+            // Account for partial rows by actually tallying up the items in hidden rows.
+            int hiddenCount = 0;
+            for (int i = 0; i < getFirstVisibleRowIndex(); i++) {
+                hiddenCount += getNumItemsInRow(i);
+            }
+            return index + hiddenCount;
         }
 
         @Override
         public Rect getAbsoluteRectForChildViewAt(int index) {
-            int adapterPosition = (getFirstVisibleRowIndex() * mNumColumns) + index;
-            int rowIndex = adapterPosition / mNumColumns;
-            int columnIndex = adapterPosition % mNumColumns;
-
-            Rect rect = new Rect();
-            rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
-            rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1;
-            rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
-            rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1;
-            return rect;
+            int adapterPosition = getAdapterPositionAt(index);
+            return items.get(adapterPosition).rect;
         }
 
         @Override
@@ -285,11 +404,6 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase {
         }
 
         @Override
-        public int getRowCount() {
-            return mNumRows;
-        }
-
-        @Override
         public void showBand(Rect rect) {
             throw new UnsupportedOperationException();
         }
@@ -328,5 +442,19 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase {
         public boolean isLayoutItem(int adapterPosition) {
             return false;
         }
+
+        public static final class Item {
+            public String name;
+            public Rect rect;
+
+            public Item(String n, Rect r) {
+                name = n;
+                rect = r;
+            }
+
+            public String toString() {
+                return name + ": " + rect;
+            }
+        }
     }
 }
index 2d819ff..d8c29db 100644 (file)
@@ -62,7 +62,9 @@ public class TestModel extends Model {
         update(r);
     }
 
+    // Note that model id includes authority qualifier and is distinct
+    // WRT documentId because of this.
     String idForPosition(int p) {
-        return Integer.toString(p);
+        return createModelId(mAuthority, Integer.toString(p));
     }
 }
index 8e624a0..56e54a6 100644 (file)
@@ -87,11 +87,6 @@ public class TestSelectionEnvironment implements SelectionEnvironment {
     }
 
     @Override
-    public int getRowCount() {
-        return 0;
-    }
-
-    @Override
     public int getChildCount() {
         return 0;
     }
index 519db66..c2ca998 100644 (file)
@@ -22,8 +22,8 @@
     coreApp="true">
 
     <application android:label="@string/app_name"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <library android:name="android.ext.services"/>
 
index e2e81d0..04d865e 100644 (file)
@@ -22,8 +22,8 @@
 
     <application android:label="@string/app_name"
         android:allowBackup="false"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <library android:name="android.ext.shared"/>
 
index fe74ad8..a66521d 100644 (file)
@@ -12,8 +12,8 @@
         android:allowBackup="false"
         android:hardwareAccelerated="true"
         android:label="Fake OEM Features"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <service android:name=".FakeCoreService" android:process=":core"
                 android:label="Fake OEM Core Service" />
index ed84c0d..a8319ab 100644 (file)
@@ -29,8 +29,8 @@
     <application
             android:label="@string/app_label"
             android:process="system"
-            android:forceDeviceEncrypted="true"
-            android:encryptionAware="true">
+            android:defaultToDeviceProtectedStorage="true"
+            android:directBootAware="true">
 
         <uses-library android:name="com.android.location.provider" />
 
index 07885ea..9507c9f 100644 (file)
@@ -7,8 +7,8 @@
             android:allowClearUserData="false"
             android:label="@string/app_label"
             android:process="system"
-            android:forceDeviceEncrypted="true"
-            android:encryptionAware="true">
+            android:defaultToDeviceProtectedStorage="true"
+            android:directBootAware="true">
 
         <receiver android:name=".InputDeviceReceiver"
                 android:label="@string/keyboard_layouts_label">
index 54972b4..165fe05 100644 (file)
@@ -46,8 +46,8 @@
         android:process="com.android.systemui"
         android:persistent="true"
         android:supportsRtl="true"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
     </application>
 </manifest>
  * limitations under the License.
  */
 
-package com.android.mtp.exceptions;
+package com.android.mtp;
 
 import java.io.IOException;
 
 /**
  * Exception thrown when the device is busy and the requested operation cannon be completed.
  */
-public class BusyDeviceException extends IOException {
+class BusyDeviceException extends IOException {
+    BusyDeviceException() {
+        super("The MTP device is busy.");
+    }
 }
index 4582226..68c1992 100644 (file)
@@ -30,6 +30,8 @@ import android.mtp.MtpObjectInfo;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.FileUriExposedException;
+import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
 import android.provider.DocumentsContract.Document;
@@ -41,7 +43,6 @@ import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.mtp.exceptions.BusyDeviceException;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -324,25 +325,61 @@ public class MtpDocumentsProvider extends DocumentsProvider {
         if (DEBUG) {
             Log.d(TAG, "createDocument: " + displayName);
         }
+        final Identifier parentId;
+        final MtpDeviceRecord record;
+        final ParcelFileDescriptor[] pipe;
         try {
-            final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
+            parentId = mDatabase.createIdentifier(parentDocumentId);
             openDevice(parentId.mDeviceId);
-            final MtpDeviceRecord record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
+            record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
             if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
-                throw new UnsupportedOperationException();
+                throw new UnsupportedOperationException(
+                        "Writing operation is not supported by the device.");
+            }
+            pipe = ParcelFileDescriptor.createReliablePipe();
+            int objectHandle = -1;
+            MtpObjectInfo info = null;
+            try {
+                pipe[0].close();  // 0 bytes for a new document.
+
+                final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
+                        MtpConstants.FORMAT_ASSOCIATION :
+                        MediaFile.getFormatCode(displayName, mimeType);
+                info = new MtpObjectInfo.Builder()
+                        .setStorageId(parentId.mStorageId)
+                        .setParent(parentId.mObjectHandle)
+                        .setFormat(formatCode)
+                        .setName(displayName)
+                        .build();
+
+                final String[] parts = FileUtils.splitFileName(mimeType, displayName);
+                final String baseName = parts[0];
+                final String extension = parts[1];
+                for (int i = 0; i <= 32; i++) {
+                    final MtpObjectInfo infoUniqueName;
+                    if (i == 0) {
+                        infoUniqueName = info;
+                    } else {
+                        infoUniqueName = new MtpObjectInfo.Builder(info).setName(
+                                baseName + " (" + i + ")." + extension).build();
+                    }
+                    try {
+                        objectHandle = mMtpManager.createDocument(
+                                parentId.mDeviceId, infoUniqueName, pipe[1]);
+                        break;
+                    } catch (SendObjectInfoFailure exp) {
+                        // This can be caused when we have an existing file with the same name.
+                        continue;
+                    }
+                }
+            } finally {
+                pipe[1].close();
+            }
+            if (objectHandle == -1) {
+                throw new IllegalArgumentException(
+                        "The file name \"" + displayName + "\" is conflicted with existing files " +
+                        "and the provider failed to find unique name.");
             }
-            final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
-            pipe[0].close();  // 0 bytes for a new document.
-            final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
-                    MtpConstants.FORMAT_ASSOCIATION :
-                    MediaFile.getFormatCode(displayName, mimeType);
-            final MtpObjectInfo info = new MtpObjectInfo.Builder()
-                    .setStorageId(parentId.mStorageId)
-                    .setParent(parentId.mObjectHandle)
-                    .setFormat(formatCode)
-                    .setName(displayName)
-                    .build();
-            final int objectHandle = mMtpManager.createDocument(parentId.mDeviceId, info, pipe[1]);
             final MtpObjectInfo infoWithHandle =
                     new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
             final String documentId = mDatabase.putNewDocument(
@@ -351,9 +388,12 @@ public class MtpDocumentsProvider extends DocumentsProvider {
             getDocumentLoader(parentId).clearTask(parentId);
             notifyChildDocumentsChange(parentDocumentId);
             return documentId;
+        } catch (FileNotFoundException | RuntimeException error) {
+            Log.e(TAG, "createDocument", error);
+            throw error;
         } catch (IOException error) {
             Log.e(TAG, "createDocument", error);
-            throw new FileNotFoundException(error.getMessage());
+            throw new IllegalStateException(error);
         }
     }
 
index 0202343..6fb2a78 100644 (file)
@@ -33,7 +33,6 @@ import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.mtp.exceptions.BusyDeviceException;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -190,7 +189,7 @@ class MtpManager {
         synchronized (device) {
             final MtpObjectInfo sendObjectInfoResult = device.sendObjectInfo(objectInfo);
             if (sendObjectInfoResult == null) {
-                throw new IOException("Failed to create a document");
+                throw new SendObjectInfoFailure();
             }
             if (objectInfo.getFormat() != MtpConstants.FORMAT_ASSOCIATION) {
                 if (!device.sendObject(sendObjectInfoResult.getObjectHandle(),
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
new file mode 100644 (file)
index 0000000..db7d777
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.mtp;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when sendObjectInfo failed.
+ */
+class SendObjectInfoFailure extends IOException {
+    SendObjectInfoFailure() {
+        super("Failed to MtpDevice#sendObjectInfo.");
+    }
+}
index afcb457..9c1880a 100644 (file)
@@ -30,8 +30,6 @@ import android.provider.DocumentsContract;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.android.mtp.exceptions.BusyDeviceException;
-
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.Arrays;
index 606f4eb..645e182 100644 (file)
@@ -20,6 +20,8 @@ import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.print.PageRange;
 import android.print.PrintAttributes.MediaSize;
@@ -570,7 +572,14 @@ public final class PageAdapter extends Adapter<ViewHolder> {
             if (DEBUG) {
                 Log.i(LOG_TAG, "Requesting pages: " + Arrays.toString(mRequestedPages));
             }
-            mCallbacks.onRequestContentUpdate();
+
+            // This call might come from a recylerview that is currently updating. Hence delay to
+            // after the update
+            (new Handler(Looper.getMainLooper())).post(new Runnable() {
+                @Override public void run() {
+                    mCallbacks.onRequestContentUpdate();
+                }
+            });
         }
     }
 
index e4c2cbc..1aee490 100644 (file)
     <!-- Developer settings: select WebView provider dialog title [CHAR LIMIT=30] -->
     <string name="select_webview_provider_dialog_title">Set WebView implementation</string>
     <!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] -->
-    <string name="select_webview_provider_toast_text">The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated.</string>
+    <string name="select_webview_provider_toast_text">This choice is no longer valid. Try again.</string>
 
     <!-- Developer settings screen, convert userdata to file encryption option name -->
     <string name="convert_to_file_encryption">Convert to file encryption</string>
index fa2226d..74c1ebd 100644 (file)
@@ -151,10 +151,17 @@ public class Utils {
         if (sSystemSignature == null) {
             sSystemSignature = new Signature[]{ getSystemSignature(pm) };
         }
-        return sSystemSignature[0] != null && sSystemSignature[0].equals(getFirstSignature(pkg));
+        if (sPermissionControllerPackageName == null) {
+            sPermissionControllerPackageName = pm.getPermissionControllerPackageName();
+        }
+        return (sSystemSignature[0] != null
+                        && sSystemSignature[0].equals(getFirstSignature(pkg)))
+                || (sPermissionControllerPackageName != null
+                        && sPermissionControllerPackageName.equals(pkg.packageName));
     }
 
     private static Signature[] sSystemSignature;
+    private static String sPermissionControllerPackageName;
 
     private static Signature getFirstSignature(PackageInfo pkg) {
         if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
index 7a1c741..ce69c5a 100644 (file)
@@ -103,16 +103,6 @@ public class SettingsDrawerActivity extends Activity {
     }
 
     @Override
-    public void onBackPressed() {
-        if (mShowingMenu) {
-            // If we are showing the menu, then we are a top level activity and the back should
-            // kick back to settings home.
-            openTile(null);
-        }
-        super.onBackPressed();
-    }
-
-    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
                 && mDrawerAdapter.getCount() != 0) {
index ba991fb..6c06d05 100644 (file)
@@ -9,8 +9,8 @@
                  android:backupAgent="SettingsBackupAgent"
                  android:killAfterRestore="false"
                  android:icon="@mipmap/ic_launcher_settings"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
 
         <provider android:name="SettingsProvider"
                   android:authorities="settings"
index 987b5ea..743912a 100644 (file)
@@ -207,6 +207,10 @@ public class SettingsProvider extends ContentProvider {
 
     @Override
     public Bundle call(String method, String name, Bundle args) {
+        // If the remote side sent us bad parcelables, they won't get the
+        // results they want, which is their loss.
+        if (args != null) args.setDefusable(true);
+
         final int requestingUserId = getRequestingUserId(args);
         switch (method) {
             case Settings.CALL_METHOD_GET_GLOBAL: {
index 5b865f9..0c35573 100644 (file)
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
 
     <application android:label="@string/app_label"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
         <provider
             android:name="android.support.v4.content.FileProvider"
             android:authorities="com.android.shell"
index 334035c..073cf14 100644 (file)
         android:process="com.android.systemui"
         android:supportsRtl="true"
         android:theme="@style/systemui_theme"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
         <!-- Keep theme in sync with SystemUIApplication.onCreate().
              Setting the theme on the application does not affect views inflated by services.
              The application theme is set again from onCreate to take effect for those views. -->
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_empty.png b/packages/SystemUI/res/drawable-hdpi/recents_empty.png
deleted file mode 100755 (executable)
index dec97b6..0000000
Binary files a/packages/SystemUI/res/drawable-hdpi/recents_empty.png and /dev/null differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_empty.png b/packages/SystemUI/res/drawable-mdpi/recents_empty.png
deleted file mode 100755 (executable)
index d16763a..0000000
Binary files a/packages/SystemUI/res/drawable-mdpi/recents_empty.png and /dev/null differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_empty.png b/packages/SystemUI/res/drawable-xhdpi/recents_empty.png
deleted file mode 100755 (executable)
index 1e02844..0000000
Binary files a/packages/SystemUI/res/drawable-xhdpi/recents_empty.png and /dev/null differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_empty.png b/packages/SystemUI/res/drawable-xxhdpi/recents_empty.png
deleted file mode 100755 (executable)
index 9d94be7..0000000
Binary files a/packages/SystemUI/res/drawable-xxhdpi/recents_empty.png and /dev/null differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/recents_empty.png b/packages/SystemUI/res/drawable-xxxhdpi/recents_empty.png
deleted file mode 100755 (executable)
index 24599c3..0000000
Binary files a/packages/SystemUI/res/drawable-xxxhdpi/recents_empty.png and /dev/null differ
diff --git a/packages/SystemUI/res/drawable/recents_empty.xml b/packages/SystemUI/res/drawable/recents_empty.xml
new file mode 100644 (file)
index 0000000..5506de1
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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="100dp"
+    android:height="132dp"
+    android:viewportWidth="100"
+    android:viewportHeight="132">
+
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,68.67H13.09c-4.96,0-9,4.04-9,9V119c0,4.96,4.04,9,9,9h73.82c4.96,0,9-4.04,9-9V77.67
+C95.91,72.7,91.87,68.67,86.91,68.67z M27.59,77.27h26.72v3.94H27.59V77.27z
+M18.73,74.74c2.49,0,4.5,2.01,4.5,4.5
+c0,2.49-2.01,4.5-4.5,4.5s-4.5-2.01-4.5-4.5C14.23,76.75,16.24,74.74,18.73,74.74z
+M89.91,119c0,1.65-1.35,3-3,3H13.09 c-1.65,0-3-1.35-3-3V88.67h79.82V119z" />
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,36.3H13.09c-4.96,0-9,4.04-9,9v23c1.65-1.58,3.71-2.73,6-3.28v-9.08h79.82v9.08
+c2.29,0.55,4.35,1.69,6,3.28v-23C95.91,40.34,91.87,36.3,86.91,36.3z
+M18.73,51.38c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,51.38,18.73,51.38z M54.31,48.84H27.59v-3.94h26.72V48.84z" />
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,4H13.09c-4.96,0-9,4.04-9,9v22.94c1.65-1.58,3.71-2.73,6-3.28V24h79.82v8.67
+c2.29,0.55,4.35,1.69,6,3.28V13C95.91,8.04,91.87,4,86.91,4z
+M18.73,18.5c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,18.5,18.73,18.5z M54.31,15.97H27.59v-3.94h26.72V15.97z" />
+    <path
+        android:pathData="M 0 0 H 100 V 132 H 0 V 0 Z" />
+</vector>
\ No newline at end of file
index df46271..c062b6d 100644 (file)
@@ -30,6 +30,7 @@
         android:padding="16dp"
         android:clickable="true"
         android:background="?android:attr/selectableItemBackground"
+        android:contentDescription="@*android:string/action_bar_up_description"
         android:src="?android:attr/homeAsUpIndicator" />
 
     <TextView
index 3a7c1d1..567e009 100644 (file)
@@ -18,7 +18,6 @@
     android:id="@+id/recents_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@drawable/recents_tv_background_gradient"
     android:clipChildren="false"
     android:clipToPadding="false"
     android:layoutDirection="rtl">
index c5b1a7a..54e97da 100644 (file)
@@ -59,7 +59,7 @@
         <ImageView
                 android:id="@+id/card_view_thumbnail"
                 android:layout_width="match_parent"
-                android:layout_height="@dimen/recents_tv_card_height"
+                android:layout_height="@dimen/recents_tv_screenshot_height"
                 android:scaleType="centerCrop"
                 android:gravity="center"
                 android:layout_alignParentTop="true"
index 75195c4..7460201 100644 (file)
@@ -43,6 +43,7 @@
             android:singleLine="true"
             android:ellipsize="start"
             android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+            android:textIsSelectable="true"
             android:imeOptions="actionSend|flagNoExtractUi" />
 
     <FrameLayout
@@ -62,6 +63,7 @@
                 android:paddingBottom="12dp"
                 android:id="@+id/remote_input_send"
                 android:src="@drawable/ic_send"
+                android:contentDescription="@*android:string/ime_action_send"
                 android:tint="@color/remote_input_send"
                 android:tintMode="src_in"
                 android:background="@drawable/ripple_drawable" />
index d65ab04..eeed0cf 100644 (file)
     <color name="default_remote_input_background">@*android:color/notification_default_color</color>
     <color name="remote_input_hint">#4dffffff</color>
 
+    <color name="remote_input_accent">#eeeeee</color>
+
     <color name="qs_tile_tint_unavailable">#40ffffff</color>
     <color name="qs_tile_tint_inactive">#4dffffff</color>
     <color name="qs_tile_tint_active">#ffffffff</color>
index b589110..6b153d1 100644 (file)
@@ -19,7 +19,7 @@
 <resources>
     <!-- Dimens for recents card in the recents view on tv -->
     <dimen name="recents_tv_card_width">268dip</dimen>
-    <dimen name="recents_tv_card_height">151dip</dimen>
+    <dimen name="recents_tv_screenshot_height">151dip</dimen>
     <dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
     <dimen name="recents_tv_banner_width">114dip</dimen>
     <dimen name="recents_tv_banner_height">64dip</dimen>
index 420a939..5295ccb 100644 (file)
     <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
     <string name="drag_to_add_tiles">Drag to add tiles</string>
 
+    <!-- Label for area where tiles can be dragged in to [CHAR LIMIT=60] -->
+    <string name="drag_to_remove_tiles">Drag here to remove</string>
+
     <!-- Button to edit the tile ordering of quick settings [CHAR LIMIT=60] -->
     <string name="qs_edit">Edit</string>
 
index 2660926..b0c1e95 100644 (file)
         <item name="android:colorControlActivated">@color/system_accent_color</item>
     </style>
 
-    <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault">
-        <item name="android:colorControlActivated">@android:color/white</item>
+    <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
+        <item name="android:colorAccent">@color/remote_input_accent</item>
     </style>
 
     <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog">
index 1fcc9e4..6a72e54 100644 (file)
@@ -15,4 +15,5 @@ limitations under the License.
 -->
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <item format="float" type="integer" name="unselected_scale">1.0</item>
+    <item format="float" type="integer" name="selected_scale">1.1</item>
 </resources>
index 358674c..aa3f6e5 100644 (file)
@@ -535,31 +535,43 @@ public class ExpandHelper implements Gefingerpoken {
         boolean nowExpanded;
         int naturalHeight = mScaler.getNaturalHeight();
         if (wasClosed) {
-            nowExpanded = (force || currentHeight > mOldHeight);
+            nowExpanded = (force || currentHeight > mOldHeight && velocity >= 0);
         } else {
-            nowExpanded = !force && currentHeight >= mOldHeight;
+            nowExpanded = !force && (currentHeight >= mOldHeight || velocity > 0);
         }
         nowExpanded |= mNaturalHeight == mSmallSize;
         if (mScaleAnimation.isRunning()) {
             mScaleAnimation.cancel();
         }
-        mCallback.setUserExpandedChild(mResizedView, nowExpanded);
         mCallback.expansionStateChanged(false);
         float targetHeight = nowExpanded ? naturalHeight : mSmallSize;
         if (targetHeight != currentHeight) {
             mScaleAnimation.setFloatValues(targetHeight);
             mScaleAnimation.setupStartValues();
             final View scaledView = mResizedView;
+            final boolean expand = nowExpanded;
             mScaleAnimation.addListener(new AnimatorListenerAdapter() {
+                public boolean mCancelled;
+
                 @Override
                 public void onAnimationEnd(Animator animation) {
+                    if (!mCancelled) {
+                        mCallback.setUserExpandedChild(scaledView, expand);
+                    }
                     mCallback.setUserLockedChild(scaledView, false);
                     mScaleAnimation.removeListener(this);
                 }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    mCancelled = true;
+                }
             });
+            velocity = nowExpanded == velocity >= 0 ? velocity : 0;
             mFlingAnimationUtils.apply(mScaleAnimation, currentHeight, targetHeight, velocity);
             mScaleAnimation.start();
         } else {
+            mCallback.setUserExpandedChild(mResizedView, nowExpanded);
             mCallback.setUserLockedChild(mResizedView, false);
         }
 
index 72a59d7..aeca840 100644 (file)
@@ -128,6 +128,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
     public void hide(int x, int y) {
         if (isShown) {
             isShown = false;
+            mToolbar.dismissPopupMenus();
             setCustomizing(false);
             save();
             mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
index d9b3b3f..57db3a6 100644 (file)
@@ -28,6 +28,7 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
+import android.widget.TextView;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSIconView;
 import com.android.systemui.qs.QSTileView;
@@ -153,7 +154,12 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
 
     @Override
     public void onBindViewHolder(final Holder holder, int position) {
-        if (holder.getItemViewType() == TYPE_EDIT) return;
+        if (holder.getItemViewType() == TYPE_EDIT) {
+            ((TextView) holder.itemView.findViewById(android.R.id.title)).setText(
+                    mCurrentDrag != null ? R.string.drag_to_remove_tiles
+                    : R.string.drag_to_add_tiles);
+            return;
+        }
 
         TileInfo info = mTiles.get(position);
         holder.mTileView.onStateChanged(info.state);
@@ -250,11 +256,13 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
             super.onSelectedChanged(viewHolder, actionState);
             if (mCurrentDrag != null) {
                 mCurrentDrag.stopDrag();
+                mCurrentDrag = null;
             }
             if (viewHolder != null) {
                 mCurrentDrag = (Holder) viewHolder;
                 mCurrentDrag.startDrag();
             }
+            notifyItemChanged(mDividerIndex);
         }
 
         @Override
index d864df8..9be24de 100644 (file)
@@ -66,6 +66,7 @@ import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskGrouping;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.views.TaskCardView;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskStackView;
 import com.android.systemui.recents.views.TaskStackViewScroller;
@@ -166,6 +167,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
     boolean mCanReuseTaskStackViews = true;
     boolean mDraggingInRecents;
     boolean mLaunchedWhileDocking;
+    private boolean mIsRunningOnTv;
 
     // Task launching
     Rect mSearchBarBounds = new Rect();
@@ -230,8 +232,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
         UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
         if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
             mRecentsIntentActivityName = RECENTS_TV_ACTIVITY;
+            mIsRunningOnTv = true;
         } else {
             mRecentsIntentActivityName = RECENTS_ACTIVITY;
+            mIsRunningOnTv = false;
         }
     }
 
@@ -793,6 +797,22 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
         }
     }
 
+    /**
+     * Creates the activity options for an app->recents transition on TV.
+     */
+    private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
+            ActivityManager.RunningTaskInfo topTask) {
+        Bitmap thumbnail = mThumbnailTransitionBitmapCache;
+        Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
+        if (thumbnail != null) {
+            return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
+                    null, (int) rect.left, (int) rect.top,
+                    (int) rect.width(), (int) rect.height(), mHandler, null);
+        }
+        // If both the screenshot and thumbnail fails, then just fall back to the default transition
+        return getUnknownTransitionActivityOptions();
+    }
+
     private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask,
             TaskViewTransform toTransform) {
         Bitmap thumbnail;
@@ -872,6 +892,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
             boolean isTopTaskHome, boolean animate) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
 
+        // If we are on TV, divert to a different helper method
+        if (mIsRunningOnTv) {
+            setUpAndStartTvRecents(topTask, isTopTaskHome, animate);
+            return;
+        }
         // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
         // should always preload the tasks now. If we are dragging in recents, reload them as
         // the stacks might have changed.
@@ -947,6 +972,90 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
     }
 
     /**
+     * Used to set up the animations of Tv Recents, then start the Recents Activity.
+     * TODO: Add the Transitions for Home -> Recents TV
+     * TODO: Shift Transition code to separate class under /tv directory and access
+     *              from here
+     */
+    private void setUpAndStartTvRecents(ActivityManager.RunningTaskInfo topTask,
+                                      boolean isTopTaskHome, boolean animate) {
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+
+        // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
+        // should always preload the tasks now. If we are dragging in recents, reload them as
+        // the stacks might have changed.
+        if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) {
+            // Create a new load plan if preloadRecents() was never triggered
+            sInstanceLoadPlan = loader.createLoadPlan(mContext);
+        }
+        if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
+            loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome);
+        }
+        TaskStack stack = sInstanceLoadPlan.getTaskStack();
+
+        // Update the header bar if necessary
+        updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
+
+        // Prepare the dummy stack for the transition
+        TaskStackLayoutAlgorithm.VisibilityReport stackVr =
+                mDummyStackView.computeStackVisibilityReport();
+
+        if (!animate) {
+            ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
+            startRecentsActivity(topTask, opts, false /* fromHome */,
+                    false /* fromSearchHome */, false /* fromThumbnail*/, stackVr);
+            return;
+        }
+
+        boolean hasRecentTasks = stack.getTaskCount() > 0;
+        boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
+
+        if (useThumbnailTransition) {
+            // Try starting with a thumbnail transition
+            ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask);
+            if (opts != null) {
+                startRecentsActivity(topTask, opts, false /* fromHome */,
+                        false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
+            } else {
+                // Fall through below to the non-thumbnail transition
+                useThumbnailTransition = false;
+            }
+        }
+
+        if (!useThumbnailTransition) {
+            // If there is no thumbnail transition, but is launching from home into recents, then
+            // use a quick home transition and do the animation from home
+            if (hasRecentTasks) {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                String homeActivityPackage = ssp.getHomeActivityPackageName();
+                String searchWidgetPackage = null;
+                if (RecentsDebugFlags.Static.EnableSearchBar) {
+                    searchWidgetPackage = Prefs.getString(mContext,
+                            Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null);
+                } else {
+                    AppWidgetProviderInfo searchWidgetInfo = ssp.resolveSearchAppWidget();
+                    if (searchWidgetInfo != null) {
+                        searchWidgetPackage = searchWidgetInfo.provider.getPackageName();
+                    }
+                }
+
+                // Determine whether we are coming from a search owned home activity
+                boolean fromSearchHome = (homeActivityPackage != null) &&
+                        homeActivityPackage.equals(searchWidgetPackage);
+                ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome);
+                startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome,
+                        false /* fromThumbnail */, stackVr);
+            } else {
+                // Otherwise we do the normal fade from an unknown source
+                ActivityOptions opts = getUnknownTransitionActivityOptions();
+                startRecentsActivity(topTask, opts, true /* fromHome */,
+                        false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
+            }
+        }
+        mLastToggleTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
      * Starts the recents activity.
      */
     private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
index 48a1904..365b29d 100644 (file)
@@ -29,6 +29,7 @@ import com.android.systemui.R;
 
 public class ViewFocusAnimator implements View.OnFocusChangeListener {
     private final float mUnselectedScale;
+    private final float mSelectedScale;
     private final float mSelectedScaleDelta;
     private final float mUnselectedZ;
     private final float mSelectedZDelta;
@@ -49,8 +50,9 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
         TypedValue out = new TypedValue();
         res.getValue(R.integer.unselected_scale, out, true);
         mUnselectedScale = out.getFloat();
-        mSelectedScaleDelta = res.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1) -
-                mUnselectedScale;
+        res.getValue(R.integer.selected_scale, out, true);
+        mSelectedScale = out.getFloat();
+        mSelectedScaleDelta = mSelectedScale - mUnselectedScale;
 
         mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z);
         mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta);
index ef8d48e..bd3143f 100644 (file)
 package com.android.systemui.recents.tv.views;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -121,10 +119,10 @@ public class RecentsTvTransitionHelper {
             };
         }
         try {
-            Rect taskRect = taskView.getGlobalRect();
+            Rect taskRect = taskView.getFocusedThumbnailRect();
             WindowManagerGlobal.getWindowManagerService()
-                    .overridePendingAppTransitionThumb(task.thumbnail, taskRect.left,
-                            taskRect.top, callback, true);
+                    .overridePendingAppTransitionAspectScaledThumb(task.thumbnail, taskRect.left,
+                            taskRect.top, taskRect.width(), taskRect.height(), callback, true);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to override transition: " + e);
         }
index 7d8a3ce..5775b60 100644 (file)
 package com.android.systemui.recents.tv.views;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.WindowManager;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -71,15 +76,46 @@ public class TaskCardView extends LinearLayout {
         mThumbnailView.getFocusedRect(r);
     }
 
-    public Rect getFocusedRect() {
+    public Rect getFocusedThumbnailRect() {
         Rect r = new Rect();
-        getFocusedRect(r);
+        mThumbnailView.getGlobalVisibleRect(r);
+        TypedValue out = new TypedValue();
+        getContext().getResources().getValue(R.integer.selected_scale, out, true);
+        float deltaScale = (out.getFloat() - 1.0f) / 2;
+        r.set((int) (r.left - r.left * deltaScale),
+                (int) (r.top - r.top * deltaScale),
+                (int) (r.right + r.right * deltaScale),
+                (int) (r.bottom + r.bottom * deltaScale));
         return r;
     }
 
-    public Rect getGlobalRect() {
-        Rect r = new Rect();
-        getGlobalVisibleRect(r);
-        return r;
+    public static Rect getStartingCardThumbnailRect(Context context) {
+        Resources res = context.getResources();
+
+        TypedValue out = new TypedValue();
+        res.getValue(R.integer.selected_scale, out, true);
+        float scale = out.getFloat();
+
+        int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width);
+        int widthDelta = (int) (width * scale - width);
+        int height = (int) (res.getDimensionPixelOffset(
+                R.dimen.recents_tv_screenshot_height) * scale);
+        int padding = res.getDimensionPixelOffset(R.dimen.recents_tv_grid_row_padding);
+
+        int headerHeight = (int) ((res.getDimensionPixelOffset(
+                R.dimen.recents_tv_card_extra_badge_size) +
+                res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom)) * scale);
+
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        Point size = new Point();
+        display.getSize(size);
+        int screenWidth = size.x;
+        int screenHeight = size.y;
+
+        return new Rect(screenWidth - width - padding - widthDelta / 2,
+                screenHeight / 2 - height / 2 + headerHeight / 2,
+                screenWidth - padding + widthDelta / 2,
+                screenHeight / 2 + height / 2 + headerHeight / 2);
     }
 }
index 143f160..bb4a771 100644 (file)
@@ -20,6 +20,7 @@ import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -31,6 +32,7 @@ import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -138,6 +140,8 @@ public abstract class BaseStatusBar extends SystemUI implements
     protected static final boolean ENABLE_HEADS_UP = true;
     protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
 
+    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+
     // Should match the values in PhoneWindowManager
     public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
     public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
@@ -146,6 +150,8 @@ public abstract class BaseStatusBar extends SystemUI implements
             "com.android.systemui.statusbar.banner_action_cancel";
     private static final String BANNER_ACTION_SETUP =
             "com.android.systemui.statusbar.banner_action_setup";
+    private static final String WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION
+            = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
 
     protected CommandQueue mCommandQueue;
     protected IStatusBarService mBarService;
@@ -199,6 +205,9 @@ public abstract class BaseStatusBar extends SystemUI implements
     private UserManager mUserManager;
     private int mDensity;
 
+    private KeyguardManager mKeyguardManager;
+    private LockPatternUtils mLockPatternUtils;
+
     // UI-specific methods
 
     /**
@@ -499,6 +508,20 @@ public abstract class BaseStatusBar extends SystemUI implements
 
                     );
                 }
+            } else if (WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION.equals(action)) {
+                final IntentSender intentSender = (IntentSender) intent
+                        .getParcelableExtra(Intent.EXTRA_INTENT);
+                final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
+                try {
+                    mContext.startIntentSender(intentSender, null, 0, 0, 0);
+                } catch (IntentSender.SendIntentException e) {
+                    /* ignore */
+                }
+                try {
+                    mBarService.onNotificationClick(notificationKey);
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
             }
         }
     };
@@ -661,6 +684,8 @@ public abstract class BaseStatusBar extends SystemUI implements
         mDensity = currentConfig.densityDpi;
 
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mLockPatternUtils = new LockPatternUtils(mContext);
 
         // Connect in to the status bar manager service
         mCommandQueue = new CommandQueue(this);
@@ -723,10 +748,14 @@ public abstract class BaseStatusBar extends SystemUI implements
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_PRESENT);
-        filter.addAction(BANNER_ACTION_CANCEL);
-        filter.addAction(BANNER_ACTION_SETUP);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
+        IntentFilter internalFilter = new IntentFilter();
+        internalFilter.addAction(WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
+        internalFilter.addAction(BANNER_ACTION_CANCEL);
+        internalFilter.addAction(BANNER_ACTION_SETUP);
+        mContext.registerReceiver(mBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
+
         IntentFilter allUsersFilter = new IntentFilter();
         allUsersFilter.addAction(
                 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -739,8 +768,7 @@ public abstract class BaseStatusBar extends SystemUI implements
         if (0 != Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) {
             Log.d(TAG, "user hasn't seen notification about hidden notifications");
-            final LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
-            if (!lockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
+            if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
                 Log.d(TAG, "insecure lockscreen, skipping notification");
                 Settings.Secure.putInt(mContext.getContentResolver(),
                         Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
@@ -1079,6 +1107,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                         });
                         a.start();
                         guts.setExposed(true);
+                        row.closeRemoteInput();
                         mStackScroller.onHeightChanged(null, true /* needsAnimation */);
                         mNotificationGutsExposed = guts;
                     }
@@ -1680,7 +1709,6 @@ public abstract class BaseStatusBar extends SystemUI implements
                             ActivityManagerNative.getDefault().resumeAppSwitches();
                         } catch (RemoteException e) {
                         }
-
                         try {
                             intent.send();
                         } catch (PendingIntent.CanceledException e) {
@@ -1773,8 +1801,22 @@ public abstract class BaseStatusBar extends SystemUI implements
                                 ActivityManagerNative.getDefault().resumeAppSwitches();
                             } catch (RemoteException e) {
                             }
-
                             if (intent != null) {
+                                // If we are launching a work activity and require to launch
+                                // separate work challenge, we defer the activity action and cancel
+                                // notification until work challenge is unlocked.
+                                if (intent.isActivity()) {
+                                    final int userId = intent.getCreatorUserHandle()
+                                            .getIdentifier();
+                                    if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+                                            && mKeyguardManager.isDeviceLocked(userId)) {
+                                        // Show work challenge, do not run pendingintent and
+                                        // remove notification
+                                        startWorkChallenge(userId, intent.getIntentSender(),
+                                                notificationKey);
+                                        return;
+                                    }
+                                }
                                 try {
                                     intent.send();
                                 } catch (PendingIntent.CanceledException e) {
@@ -1809,6 +1851,23 @@ public abstract class BaseStatusBar extends SystemUI implements
             }, afterKeyguardGone);
         }
 
+        public void startWorkChallenge(int userId, IntentSender intendSender,
+                String notificationKey) {
+            final Intent callBackIntent = new Intent(
+                    WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
+            callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
+            callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
+            callBackIntent.setPackage(mContext.getPackageName());
+
+            final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
+                    null, userId);
+            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            newIntent.putExtra(Intent.EXTRA_INTENT, PendingIntent
+                    .getBroadcast(mContext, 0, callBackIntent, 0).getIntentSender());
+            mContext.startActivity(newIntent);
+        }
+
         public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
             Notification notification = sbn.getNotification();
             if (notification.contentIntent != null || notification.fullScreenIntent != null) {
@@ -1856,15 +1915,16 @@ public abstract class BaseStatusBar extends SystemUI implements
 
     /**
      * The LEDs are turned off when the notification panel is shown, even just a little bit.
+     * See also NotificationStackScrollLayout.setIsExpanded() for another place where we
+     * attempt to do this.
      */
     protected void handleVisibleToUserChanged(boolean visibleToUser) {
         try {
             if (visibleToUser) {
                 boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
                 boolean clearNotificationEffects =
-                    ((mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD) ||
-                            (!pinnedHeadsUp && (mState == StatusBarState.SHADE
-                                    || mState == StatusBarState.SHADE_LOCKED)));
+                        !isPanelFullyCollapsed() &&
+                        (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
                 int notificationLoad = mNotificationData.getActiveNotifications().size();
                 if (pinnedHeadsUp && isPanelFullyCollapsed())  {
                     notificationLoad = 1;
index 246f15e..22bb8eb 100644 (file)
@@ -579,6 +579,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
         }
     }
 
+    public void closeRemoteInput() {
+        mPrivateLayout.closeRemoteInput();
+        mPublicLayout.closeRemoteInput();
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
index 3b87577..c2df292 100644 (file)
@@ -69,6 +69,9 @@ public class NotificationContentView extends FrameLayout {
     private View mHeadsUpChild;
     private HybridNotificationView mSingleLineView;
 
+    private RemoteInputView mExpandedRemoteInput;
+    private RemoteInputView mHeadsUpRemoteInput;
+
     private NotificationViewWrapper mContractedWrapper;
     private NotificationViewWrapper mExpandedWrapper;
     private NotificationViewWrapper mHeadsUpWrapper;
@@ -743,15 +746,19 @@ public class NotificationContentView extends FrameLayout {
 
         View bigContentView = mExpandedChild;
         if (bigContentView != null) {
-            applyRemoteInput(bigContentView, entry, hasRemoteInput);
+            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput);
+        } else {
+            mExpandedRemoteInput = null;
         }
         View headsUpContentView = mHeadsUpChild;
         if (headsUpContentView != null) {
-            applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
+            mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
+        } else {
+            mHeadsUpRemoteInput = null;
         }
     }
 
-    private void applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
+    private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
         View actionContainerCandidate = view.findViewById(
                 com.android.internal.R.id.actions_container);
         if (actionContainerCandidate instanceof FrameLayout) {
@@ -777,7 +784,20 @@ public class NotificationContentView extends FrameLayout {
                     color = mContext.getColor(R.color.default_remote_input_background);
                 }
                 riv.setBackgroundColor(color);
+
+                return riv;
             }
+            return existing;
+        }
+        return null;
+    }
+
+    public void closeRemoteInput() {
+        if (mHeadsUpRemoteInput != null) {
+            mHeadsUpRemoteInput.close();
+        }
+        if (mExpandedRemoteInput != null) {
+            mExpandedRemoteInput.close();
         }
     }
 
index e53f044..99896f8 100644 (file)
@@ -36,7 +36,6 @@ import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Display;
-import android.view.Gravity;
 import android.view.IDockedStackListener.Stub;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -46,7 +45,6 @@ import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.LinearLayout;
-
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.stackdivider.Divider;
@@ -54,7 +52,6 @@ import com.android.systemui.statusbar.policy.DeadZone;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
 
 public class NavigationBarView extends LinearLayout {
     final static boolean DEBUG = false;
@@ -100,6 +97,7 @@ public class NavigationBarView extends LinearLayout {
     private boolean mDockedStackExists;
 
     private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
+    private int mDensity;
 
     private class NavTransitionListener implements TransitionListener {
         private boolean mBackTransitioning;
@@ -190,6 +188,7 @@ public class NavigationBarView extends LinearLayout {
         mShowMenu = false;
         mGestureHelper = new NavigationBarGestureHelper(context);
 
+        mDensity = context.getResources().getConfiguration().densityDpi;
         getIcons(context);
 
         mBarTransitions = new NavigationBarTransitions(this);
@@ -599,6 +598,10 @@ public class NavigationBarView extends LinearLayout {
             // we are switching to.
             setNavigationIconHints(mNavigationIconHints, true);
         }
+        if (mDensity != newConfig.densityDpi) {
+            mDensity = newConfig.densityDpi;
+            getIcons(getContext());
+        }
     }
 
     /**
index eb5b57e..95f26d4 100644 (file)
 
 package com.android.systemui.statusbar.phone;
 
+import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
 import android.app.StatusBarManager;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.media.session.MediaSessionLegacyHelper;
+import android.net.Uri;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.util.AttributeSet;
+import android.view.ActionMode;
+import android.view.InputQueue;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.SurfaceHolder;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.widget.FrameLayout;
 
+import com.android.internal.view.FloatingActionMode;
+import com.android.internal.widget.FloatingToolbar;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.statusbar.BaseStatusBar;
@@ -57,6 +75,13 @@ public class StatusBarWindowView extends FrameLayout {
     private final Paint mTransparentSrcPaint = new Paint();
     private FalsingManager mFalsingManager;
 
+    // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
+    // DecorView, but since this is a special window we have to roll our own.
+    private View mFloatingActionModeOriginatingView;
+    private ActionMode mFloatingActionMode;
+    private FloatingToolbar mFloatingToolbar;
+    private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
+
     public StatusBarWindowView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setMotionEventSplittingEnabled(false);
@@ -301,5 +326,341 @@ public class StatusBarWindowView extends FrameLayout {
             a.recycle();
         }
     }
+
+    @Override
+    public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback,
+            int type) {
+        if (type == ActionMode.TYPE_FLOATING) {
+            return startActionMode(originalView, callback, type);
+        }
+        return super.startActionModeForChild(originalView, callback, type);
+    }
+
+    private ActionMode createFloatingActionMode(
+            View originatingView, ActionMode.Callback2 callback) {
+        if (mFloatingActionMode != null) {
+            mFloatingActionMode.finish();
+        }
+        cleanupFloatingActionModeViews();
+        final FloatingActionMode mode =
+                new FloatingActionMode(mContext, callback, originatingView);
+        mFloatingActionModeOriginatingView = originatingView;
+        mFloatingToolbarPreDrawListener =
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        mode.updateViewLocationInWindow();
+                        return true;
+                    }
+                };
+        return mode;
+    }
+
+    private void setHandledFloatingActionMode(ActionMode mode) {
+        mFloatingActionMode = mode;
+        mFloatingToolbar = new FloatingToolbar(mContext, mFakeWindow);
+        ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
+        mFloatingActionMode.invalidate();  // Will show the floating toolbar if necessary.
+        mFloatingActionModeOriginatingView.getViewTreeObserver()
+                .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
+    }
+
+    private void cleanupFloatingActionModeViews() {
+        if (mFloatingToolbar != null) {
+            mFloatingToolbar.dismiss();
+            mFloatingToolbar = null;
+        }
+        if (mFloatingActionModeOriginatingView != null) {
+            if (mFloatingToolbarPreDrawListener != null) {
+                mFloatingActionModeOriginatingView.getViewTreeObserver()
+                        .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
+                mFloatingToolbarPreDrawListener = null;
+            }
+            mFloatingActionModeOriginatingView = null;
+        }
+    }
+
+    private ActionMode startActionMode(
+            View originatingView, ActionMode.Callback callback, int type) {
+        ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
+        ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback);
+        if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
+            setHandledFloatingActionMode(mode);
+        } else {
+            mode = null;
+        }
+        return mode;
+    }
+
+    private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
+        private final ActionMode.Callback mWrapped;
+
+        public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
+            mWrapped = wrapped;
+        }
+
+        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+            return mWrapped.onCreateActionMode(mode, menu);
+        }
+
+        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+            requestFitSystemWindows();
+            return mWrapped.onPrepareActionMode(mode, menu);
+        }
+
+        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            return mWrapped.onActionItemClicked(mode, item);
+        }
+
+        public void onDestroyActionMode(ActionMode mode) {
+            mWrapped.onDestroyActionMode(mode);
+            if (mode == mFloatingActionMode) {
+                cleanupFloatingActionModeViews();
+                mFloatingActionMode = null;
+            }
+            requestFitSystemWindows();
+        }
+
+        @Override
+        public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+            if (mWrapped instanceof ActionMode.Callback2) {
+                ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
+            } else {
+                super.onGetContentRect(mode, view, outRect);
+            }
+        }
+    }
+
+    /**
+     * Minimal window to satisfy FloatingToolbar.
+     */
+    private Window mFakeWindow = new Window(mContext) {
+        @Override
+        public void takeSurface(SurfaceHolder.Callback2 callback) {
+        }
+
+        @Override
+        public void takeInputQueue(InputQueue.Callback callback) {
+        }
+
+        @Override
+        public boolean isFloating() {
+            return false;
+        }
+
+        @Override
+        public void alwaysReadCloseOnTouchAttr() {
+        }
+
+        @Override
+        public void setContentView(@LayoutRes int layoutResID) {
+        }
+
+        @Override
+        public void setContentView(View view) {
+        }
+
+        @Override
+        public void setContentView(View view, ViewGroup.LayoutParams params) {
+        }
+
+        @Override
+        public void addContentView(View view, ViewGroup.LayoutParams params) {
+        }
+
+        @Override
+        public void clearContentView() {
+        }
+
+        @Override
+        public View getCurrentFocus() {
+            return null;
+        }
+
+        @Override
+        public LayoutInflater getLayoutInflater() {
+            return null;
+        }
+
+        @Override
+        public void setTitle(CharSequence title) {
+        }
+
+        @Override
+        public void setTitleColor(@ColorInt int textColor) {
+        }
+
+        @Override
+        public void openPanel(int featureId, KeyEvent event) {
+        }
+
+        @Override
+        public void closePanel(int featureId) {
+        }
+
+        @Override
+        public void togglePanel(int featureId, KeyEvent event) {
+        }
+
+        @Override
+        public void invalidatePanelMenu(int featureId) {
+        }
+
+        @Override
+        public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
+            return false;
+        }
+
+        @Override
+        public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
+            return false;
+        }
+
+        @Override
+        public void closeAllPanels() {
+        }
+
+        @Override
+        public boolean performContextMenuIdentifierAction(int id, int flags) {
+            return false;
+        }
+
+        @Override
+        public void onConfigurationChanged(Configuration newConfig) {
+        }
+
+        @Override
+        public void setBackgroundDrawable(Drawable drawable) {
+        }
+
+        @Override
+        public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
+        }
+
+        @Override
+        public void setFeatureDrawableUri(int featureId, Uri uri) {
+        }
+
+        @Override
+        public void setFeatureDrawable(int featureId, Drawable drawable) {
+        }
+
+        @Override
+        public void setFeatureDrawableAlpha(int featureId, int alpha) {
+        }
+
+        @Override
+        public void setFeatureInt(int featureId, int value) {
+        }
+
+        @Override
+        public void takeKeyEvents(boolean get) {
+        }
+
+        @Override
+        public boolean superDispatchKeyEvent(KeyEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchTouchEvent(MotionEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchTrackballEvent(MotionEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchGenericMotionEvent(MotionEvent event) {
+            return false;
+        }
+
+        @Override
+        public View getDecorView() {
+            return StatusBarWindowView.this;
+        }
+
+        @Override
+        public View peekDecorView() {
+            return null;
+        }
+
+        @Override
+        public Bundle saveHierarchyState() {
+            return null;
+        }
+
+        @Override
+        public void restoreHierarchyState(Bundle savedInstanceState) {
+        }
+
+        @Override
+        protected void onActive() {
+        }
+
+        @Override
+        public void setChildDrawable(int featureId, Drawable drawable) {
+        }
+
+        @Override
+        public void setChildInt(int featureId, int value) {
+        }
+
+        @Override
+        public boolean isShortcutKey(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        @Override
+        public void setVolumeControlStream(int streamType) {
+        }
+
+        @Override
+        public int getVolumeControlStream() {
+            return 0;
+        }
+
+        @Override
+        public int getStatusBarColor() {
+            return 0;
+        }
+
+        @Override
+        public void setStatusBarColor(@ColorInt int color) {
+        }
+
+        @Override
+        public int getNavigationBarColor() {
+            return 0;
+        }
+
+        @Override
+        public void setNavigationBarColor(@ColorInt int color) {
+        }
+
+        @Override
+        public void setDecorCaptionShade(int decorCaptionShade) {
+        }
+
+        @Override
+        public void setResizingCaptionDrawable(Drawable drawable) {
+        }
+
+        @Override
+        public void onMultiWindowChanged() {
+        }
+
+        @Override
+        public void reportActivityRelaunched() {
+        }
+    };
+
 }
 
index f03d9e9..c6b1cdf 100644 (file)
@@ -69,18 +69,22 @@ public class HotspotControllerImpl implements HotspotController {
 
     @Override
     public void addCallback(Callback callback) {
-        if (callback == null || mCallbacks.contains(callback)) return;
-        if (DEBUG) Log.d(TAG, "addCallback " + callback);
-        mCallbacks.add(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        synchronized (mCallbacks) {
+            if (callback == null || mCallbacks.contains(callback)) return;
+            if (DEBUG) Log.d(TAG, "addCallback " + callback);
+            mCallbacks.add(callback);
+            mReceiver.setListening(!mCallbacks.isEmpty());
+        }
     }
 
     @Override
     public void removeCallback(Callback callback) {
         if (callback == null) return;
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
-        mCallbacks.remove(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        synchronized (mCallbacks) {
+            mCallbacks.remove(callback);
+            mReceiver.setListening(!mCallbacks.isEmpty());
+        }
     }
 
     @Override
@@ -110,8 +114,10 @@ public class HotspotControllerImpl implements HotspotController {
     }
 
     private void fireCallback(boolean isEnabled) {
-        for (Callback callback : mCallbacks) {
-            callback.onHotspotChanged(isEnabled);
+        synchronized (mCallbacks) {
+            for (Callback callback : mCallbacks) {
+                callback.onHotspotChanged(isEnabled);
+            }
         }
     }
 
index 29b0f4b..3a0336b 100644 (file)
@@ -29,8 +29,10 @@ import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
@@ -44,6 +46,7 @@ import android.widget.TextView;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.stack.LongPressCancelable;
 
 /**
  * Host for the remote input.
@@ -64,6 +67,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
     private RemoteInputController mController;
 
     private NotificationData.Entry mEntry;
+    private LongPressCancelable mLongPressCancelable;
 
     public RemoteInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -226,6 +230,30 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
         updateSendButton();
     }
 
+    public void close() {
+        mEditText.defocusIfNeeded();
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (mLongPressCancelable == null) {
+                ViewParent p = getParent();
+                while (p != null) {
+                    if (p instanceof LongPressCancelable) {
+                        mLongPressCancelable = (LongPressCancelable) p;
+                        break;
+                    }
+                    p = p.getParent();
+                }
+            }
+            if (mLongPressCancelable != null) {
+                mLongPressCancelable.requestDisallowLongPress();
+            }
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
     /**
      * An EditText that changes appearance based on whether it's focusable and becomes
      * un-focusable whenever the user navigates away from it or it becomes invisible.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
new file mode 100644 (file)
index 0000000..05f0c07
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.stack;
+
+/**
+ * Interface for container layouts that listen for long presses. A child that
+ * wants to handle long press can use this to cancel the parents long press logic.
+ */
+public interface LongPressCancelable {
+    /**
+     * Request that the view does not perform long press for the current touch.
+     */
+    void requestDisallowLongPress();
+}
index d9b78a2..686a712 100644 (file)
@@ -83,7 +83,7 @@ import java.util.HashSet;
 public class NotificationStackScrollLayout extends ViewGroup
         implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
         ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
-        SettingsIconRowListener {
+        SettingsIconRowListener, LongPressCancelable {
 
     public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
     private static final String TAG = "StackScroller";
@@ -2627,6 +2627,11 @@ public class NotificationStackScrollLayout extends ViewGroup
         }
     }
 
+    @Override
+    public void requestDisallowLongPress() {
+        removeLongPressCallback();
+    }
+
     public void removeLongPressCallback() {
         mSwipeHelper.removeLongPressCallback();
     }
@@ -2691,6 +2696,16 @@ public class NotificationStackScrollLayout extends ViewGroup
         if (changed) {
             if (!mIsExpanded) {
                 mGroupManager.collapseAllGroups();
+            } else {
+                // XXX: HACK: we should not be clearing notification effects from way down here.
+                // But at the moment we don't have a reliable way to know when the window is
+                // actually exposed to the air, so
+                if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+                    if (DEBUG) {
+                        Log.v(TAG, "clearing notification effects from scroller");
+                    }
+                    mPhoneStatusBar.clearNotificationEffects();
+                }
             }
             updateNotificationAnimationStates();
             updateChronometers();
index 88f8381..51531e3 100644 (file)
@@ -8,8 +8,8 @@
     <application
         android:label="@string/app_label"
         android:process="com.android.proxyhandler"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <service android:name=".ProxyService"
             android:exported="true">
index b4b40ae..9ce81ed 100644 (file)
@@ -56,6 +56,7 @@ import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -174,6 +175,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
 
     private final PackageManager mPackageManager;
 
+    private final PowerManager mPowerManager;
+
     private final WindowManagerInternal mWindowManagerService;
 
     private final SecurityPolicy mSecurityPolicy;
@@ -232,6 +235,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
     public AccessibilityManagerService(Context context) {
         mContext = context;
         mPackageManager = mContext.getPackageManager();
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mSecurityPolicy = new SecurityPolicy();
@@ -1013,7 +1017,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                 PackageManager.GET_SERVICES
                         | PackageManager.GET_META_DATA
                         | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
-                        | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                 mCurrentUserId);
 
         for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -1801,7 +1806,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
     private KeyEventDispatcher getKeyEventDispatcher() {
         if (mKeyEventDispatcher == null) {
             mKeyEventDispatcher = new KeyEventDispatcher(
-                    mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock);
+                    mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock,
+                    mPowerManager);
         }
         return mKeyEventDispatcher;
     }
@@ -2702,6 +2708,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
+                // Regardless of whether or not the action succeeds, it was generated by an
+                // accessibility service that is driven by user actions, so note user activity.
+                mPowerManager.userActivity(SystemClock.uptimeMillis(),
+                        PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
+
                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
@@ -2723,6 +2734,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
             }
             final long identity = Binder.clearCallingIdentity();
             try {
+                mPowerManager.userActivity(SystemClock.uptimeMillis(),
+                        PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
                 switch (action) {
                     case AccessibilityService.GLOBAL_ACTION_BACK: {
                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
index 3469565..e03c16e 100644 (file)
 package com.android.server.accessibility;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Pools;
@@ -69,6 +71,7 @@ public class KeyEventDispatcher {
     private final Handler mHandlerToSendKeyEventsToInputFilter;
     private final int mMessageTypeForSendKeyEvent;
     private final Handler mKeyEventTimeoutHandler;
+    private final PowerManager mPowerManager;
 
     /**
      * @param handlerToSendKeyEventsToInputFilter The handler to which to post {@code KeyEvent}s
@@ -77,9 +80,12 @@ public class KeyEventDispatcher {
      * message that carries a {@code KeyEvent} to be sent to the input filter
      * @param lock The lock used for all synchronization in this package. This lock must be held
      * when calling {@code notifyKeyEventLocked}
+     * @param powerManager The power manager to alert to user activity if a KeyEvent is processed
+     * by a service
      */
     public KeyEventDispatcher(Handler handlerToSendKeyEventsToInputFilter,
-                              int messageTypeForSendKeyEvent, Object lock) {
+            int messageTypeForSendKeyEvent, Object lock,
+            PowerManager powerManager) {
         if (InputEventConsistencyVerifier.isInstrumentationEnabled()) {
             mSentEventsVerifier = new InputEventConsistencyVerifier(
                     this, 0, KeyEventDispatcher.class.getSimpleName());
@@ -91,6 +97,7 @@ public class KeyEventDispatcher {
         mKeyEventTimeoutHandler =
                 new Handler(mHandlerToSendKeyEventsToInputFilter.getLooper(), new Callback());
         mLock = lock;
+        mPowerManager = powerManager;
     }
 
     /**
@@ -165,7 +172,16 @@ public class KeyEventDispatcher {
             PendingKeyEvent pendingEvent =
                     removeEventFromListLocked(mPendingEventsMap.get(service), sequence);
             if (pendingEvent != null) {
-                pendingEvent.handled |= handled;
+                if (handled && !pendingEvent.handled) {
+                    pendingEvent.handled = handled;
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        mPowerManager.userActivity(pendingEvent.event.getEventTime(),
+                                PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
+                }
                 removeReferenceToPendingEventLocked(pendingEvent);
             }
         }
@@ -241,7 +257,7 @@ public class KeyEventDispatcher {
             int policyFlags = pendingEvent.policyFlags | WindowManagerPolicy.FLAG_PASS_TO_USER;
             mHandlerToSendKeyEventsToInputFilter
                     .obtainMessage(mMessageTypeForSendKeyEvent, policyFlags, 0, pendingEvent.event)
-                            .sendToTarget();
+                    .sendToTarget();
         } else {
             pendingEvent.event.recycle();
         }
index a4f85db..8febecc 100644 (file)
@@ -2487,7 +2487,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
             // from a profile that is still locked, so let them see those
             // widgets.
             if (isProfileWithUnlockedParent(userId)) {
-                flags |= PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+                flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
             }
 
             // Widgets referencing shared libraries need to have their
index aaa2211..99c5dd6 100644 (file)
@@ -7,7 +7,8 @@ LOCAL_MODULE := services.core
 LOCAL_SRC_FILES += \
     $(call all-java-files-under,java) \
     java/com/android/server/EventLogTags.logtags \
-    java/com/android/server/am/EventLogTags.logtags
+    java/com/android/server/am/EventLogTags.logtags \
+    ../../../../system/netd/server/binder/android/net/INetd.aidl
 
 LOCAL_JAVA_LIBRARIES := services.net telephony-common
 LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
index bfe9e8e..a94c8b8 100644 (file)
@@ -121,6 +121,8 @@ public class AppOpsService extends IAppOpsService.Stub {
      *       - SparseArray w/ mapping:
      *          AppOp code --> Set of packages that are not restricted for this code
      *
+     * For efficiency, a core assumption here is that the number of per-package exemptions stored
+     * here will be relatively small.  If this changes, this data structure should be revisited.
      */
     private final ArrayMap<IBinder, SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>>>
             mOpUserRestrictions = new ArrayMap<>();
@@ -445,8 +447,12 @@ public class AppOpsService extends IAppOpsService.Stub {
             int[] ops) {
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return Collections.emptyList();
+        }
         synchronized (this) {
-            Ops pkgOps = getOpsLocked(uid, packageName, false);
+            Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false);
             if (pkgOps == null) {
                 return null;
             }
@@ -464,7 +470,7 @@ public class AppOpsService extends IAppOpsService.Stub {
 
     private void pruneOp(Op op, int uid, String packageName) {
         if (op.time == 0 && op.rejectTime == 0) {
-            Ops ops = getOpsLocked(uid, packageName, false);
+            Ops ops = getOpsRawLocked(uid, packageName, false);
             if (ops != null) {
                 ops.remove(op.op);
                 if (ops.size() <= 0) {
@@ -878,8 +884,12 @@ public class AppOpsService extends IAppOpsService.Stub {
     public int checkOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
         synchronized (this) {
-            if (isOpRestricted(uid, code, packageName)) {
+            if (isOpRestricted(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             code = AppOpsManager.opToSwitch(code);
@@ -890,7 +900,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                     return uidMode;
                 }
             }
-            Op op = getOpLocked(code, uid, packageName, false);
+            Op op = getOpLocked(code, uid, resolvedPackageName, false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
             }
@@ -966,6 +976,7 @@ public class AppOpsService extends IAppOpsService.Stub {
 
     @Override
     public int checkPackage(int uid, String packageName) {
+        Preconditions.checkNotNull(packageName);
         synchronized (this) {
             if (getOpsRawLocked(uid, packageName, true) != null) {
                 return AppOpsManager.MODE_ALLOWED;
@@ -979,26 +990,39 @@ public class AppOpsService extends IAppOpsService.Stub {
     public int noteProxyOperation(int code, String proxyPackageName,
             int proxiedUid, String proxiedPackageName) {
         verifyIncomingOp(code);
-        final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(),
-                proxyPackageName, -1, null);
+        final int proxyUid = Binder.getCallingUid();
+        String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
+        if (resolveProxyPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        final int proxyMode = noteOperationUnchecked(code, proxyUid,
+                resolveProxyPackageName, -1, null);
         if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
             return proxyMode;
         }
-        return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
-                Binder.getCallingUid(), proxyPackageName);
+        String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
+        if (resolveProxiedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
+                proxyMode, resolveProxyPackageName);
     }
 
     @Override
     public int noteOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
-        return noteOperationUnchecked(code, uid, packageName, 0, null);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null);
     }
 
     private int noteOperationUnchecked(int code, int uid, String packageName,
             int proxyUid, String proxyPackageName) {
         synchronized (this) {
-            Ops ops = getOpsLocked(uid, packageName, true);
+            Ops ops = getOpsRawLocked(uid, packageName, true);
             if (ops == null) {
                 if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
@@ -1046,16 +1070,20 @@ public class AppOpsService extends IAppOpsService.Stub {
     public int startOperation(IBinder token, int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return  AppOpsManager.MODE_IGNORED;
+        }
         ClientState client = (ClientState)token;
         synchronized (this) {
-            Ops ops = getOpsLocked(uid, packageName, true);
+            Ops ops = getOpsRawLocked(uid, resolvedPackageName, true);
             if (ops == null) {
                 if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
-                        + " package " + packageName);
+                        + " package " + resolvedPackageName);
                 return AppOpsManager.MODE_ERRORED;
             }
             Op op = getOpLocked(ops, code, true);
-            if (isOpRestricted(uid, code, packageName)) {
+            if (isOpRestricted(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             final int switchCode = AppOpsManager.opToSwitch(code);
@@ -1065,7 +1093,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
-                            + packageName);
+                            + resolvedPackageName);
                     op.rejectTime = System.currentTimeMillis();
                     return uidMode;
                 }
@@ -1073,12 +1101,13 @@ public class AppOpsService extends IAppOpsService.Stub {
             final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
             if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
                 if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
-                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
+                        + switchCode + " (" + code + ") uid " + uid + " package "
+                        + resolvedPackageName);
                 op.rejectTime = System.currentTimeMillis();
                 return switchOp.mode;
             }
             if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
-                    + " package " + packageName);
+                    + " package " + resolvedPackageName);
             if (op.nesting == 0) {
                 op.time = System.currentTimeMillis();
                 op.rejectTime = 0;
@@ -1096,9 +1125,16 @@ public class AppOpsService extends IAppOpsService.Stub {
     public void finishOperation(IBinder token, int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
-        ClientState client = (ClientState)token;
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return;
+        }
+        if (!(token instanceof ClientState)) {
+            return;
+        }
+        ClientState client = (ClientState) token;
         synchronized (this) {
-            Op op = getOpLocked(code, uid, packageName, true);
+            Op op = getOpLocked(code, uid, resolvedPackageName, true);
             if (op == null) {
                 return;
             }
@@ -1114,6 +1150,9 @@ public class AppOpsService extends IAppOpsService.Stub {
 
     @Override
     public int permissionToOpCode(String permission) {
+        if (permission == null) {
+            return AppOpsManager.OP_NONE;
+        }
         return AppOpsManager.permissionToOpCode(permission);
     }
 
@@ -1163,15 +1202,6 @@ public class AppOpsService extends IAppOpsService.Stub {
         return uidState;
     }
 
-    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
-        if (uid == 0) {
-            packageName = "root";
-        } else if (uid == Process.SHELL_UID) {
-            packageName = "com.android.shell";
-        }
-        return getOpsRawLocked(uid, packageName, edit);
-    }
-
     private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
         UidState uidState = getUidStateLocked(uid, edit);
         if (uidState == null) {
@@ -1257,7 +1287,7 @@ public class AppOpsService extends IAppOpsService.Stub {
     }
 
     private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
-        Ops ops = getOpsLocked(uid, packageName, edit);
+        Ops ops = getOpsRawLocked(uid, packageName, edit);
         if (ops == null) {
             return null;
         }
@@ -1304,15 +1334,18 @@ public class AppOpsService extends IAppOpsService.Stub {
             }
 
             if (opRestrictions[code]) {
-                if (opExceptions != null && opExceptions.get(code) != null &&
-                        opExceptions.get(code).contains(packageName)) {
-                    continue; // AppOps code is restricted, but this package is exempt
+
+                if (opExceptions != null) {
+                    ArraySet<String> ex = opExceptions.get(code);
+                    if (ex != null && ex.contains(packageName)) {
+                        continue; // AppOps code is restricted, but this package is exempt
+                    }
                 }
 
                 if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
                     // If we are the system, bypass user restrictions for certain codes
                     synchronized (this) {
-                        Ops ops = getOpsLocked(uid, packageName, true);
+                        Ops ops = getOpsRawLocked(uid, packageName, true);
                         if ((ops != null) && ops.isPrivileged) {
                             return false;
                         }
@@ -1577,7 +1610,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                         out.startTag(null, "uid");
                         out.attribute(null, "n", Integer.toString(pkg.getUid()));
                         synchronized (this) {
-                            Ops ops = getOpsLocked(pkg.getUid(), pkg.getPackageName(), false);
+                            Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false);
                             // Should always be present as the list of PackageOps is generated
                             // from Ops.
                             if (ops != null) {
@@ -2098,6 +2131,7 @@ public class AppOpsService extends IAppOpsService.Stub {
     @Override
     public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
         checkSystemUid("setUserRestrictions");
+        Preconditions.checkNotNull(restrictions);
         Preconditions.checkNotNull(token);
         final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
         for (int i = 0; i < opRestrictions.length; ++i) {
@@ -2143,9 +2177,8 @@ public class AppOpsService extends IAppOpsService.Stub {
             final SparseArray<ArraySet<String>> opExceptions =
                     getUserPackageExemptionsForToken(token, userHandle);
 
-            // If exceptionPackages is not null, update the exception packages for this AppOps code
             ArraySet<String> exceptions = opExceptions.get(code);
-            if (exceptionPackages != null) {
+            if (exceptionPackages != null && exceptionPackages.length > 0) {
                 if (exceptions == null) {
                     exceptions = new ArraySet<>(exceptionPackages.length);
                     opExceptions.put(code, exceptions);
@@ -2153,7 +2186,11 @@ public class AppOpsService extends IAppOpsService.Stub {
                     exceptions.clear();
                 }
 
-                exceptions.addAll(Arrays.asList(exceptionPackages));
+                for (String p : exceptionPackages) {
+                    exceptions.add(p);
+                }
+            } else {
+                opExceptions.remove(code);
             }
         }
 
@@ -2219,14 +2256,23 @@ public class AppOpsService extends IAppOpsService.Stub {
 
             if (restrictions != null) {
                 final boolean[] opRestrictions = restrictions.first;
+                final SparseArray<ArraySet<String>> opExceptions = restrictions.second;
+                boolean stillHasRestrictions = false;
                 if (opRestrictions != null) {
-                    for (boolean restriction : opRestrictions) {
+                    for (int i = 0; i < opRestrictions.length; i++) {
+                        boolean restriction = opRestrictions[i];
                         if (restriction) {
-                            return;
+                            stillHasRestrictions = true;
+                        } else {
+                            opExceptions.remove(i);
                         }
                     }
                 }
 
+                if (stillHasRestrictions) {
+                    return;
+                }
+
                 // No restrictions set for this client
                 perTokenRestrictions.remove(userHandle);
                 if (perTokenRestrictions.size() <= 0) {
@@ -2300,6 +2346,15 @@ public class AppOpsService extends IAppOpsService.Stub {
         }
     }
 
+    private static String resolvePackageName(int uid, String packageName)  {
+        if (uid == 0) {
+            return "root";
+        } else if (uid == Process.SHELL_UID) {
+            return "com.android.shell";
+        }
+        return packageName;
+    }
+
     private static String[] getPackagesForUid(int uid) {
         String[] packageNames = null;
         try {
index 9b8f2d2..00a49bd 100644 (file)
@@ -456,6 +456,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     class SettingsObserver extends ContentObserver {
         int mUserId;
         boolean mRegistered = false;
+        @NonNull
         String mLastEnabled = "";
 
         /**
index 4536e04..65a22b9 100644 (file)
@@ -809,7 +809,9 @@ class MountService extends IMountService.Stub
                 if (user.isSystemOnly()) continue;
 
                 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.id);
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.id);
                 if (provider != null) {
                     final IActivityManager am = ActivityManagerNative.getDefault();
                     try {
index 329f716..07c10b0 100644 (file)
@@ -49,6 +49,7 @@ import android.annotation.NonNull;
 import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.INetd;
 import android.net.INetworkManagementEventObserver;
 import android.net.InterfaceConfiguration;
 import android.net.IpPrefix;
@@ -122,7 +123,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
     private static final String TAG = "NetworkManagement";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     private static final String NETD_TAG = "NetdConnector";
-    private static final String NETD_SOCKET_NAME = "netd";
+    private static final String NETD_SERVICE_NAME = "netd";
 
     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
 
@@ -188,6 +189,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
     private final Handler mFgHandler;
     private final Handler mDaemonHandler;
 
+    private INetd mNetdService;
+
     private IBatteryStats mBatteryStats;
 
     private final Thread mThread;
@@ -306,7 +309,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
     }
 
     public static NetworkManagementService create(Context context) throws InterruptedException {
-        return create(context, NETD_SOCKET_NAME);
+        return create(context, NETD_SERVICE_NAME);
     }
 
     public void systemReady() {
@@ -515,6 +518,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub
      * existing in-memory rules.
      */
     private void prepareNativeDaemon() {
+        boolean nativeServiceAvailable = false;
+        try {
+            mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME));
+            nativeServiceAvailable = mNetdService.isAlive();
+        } catch (RemoteException e) {}
+        if (!nativeServiceAvailable) {
+            Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME);
+        }
+
         mBandwidthControlEnabled = false;
 
         // only enable bandwidth control when support exists
index 306e933..3eb20a0 100644 (file)
@@ -28,6 +28,7 @@ import com.android.internal.textservice.ITextServicesSessionListener;
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
@@ -464,9 +465,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
             return null;
         }
         synchronized (mSpellCheckerMap) {
-            final String subtypeHashCodeStr = mSettings.getSelectedSpellCheckerSubtype();
+            final int subtypeHashCode =
+                    mSettings.getSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE);
             if (DBG) {
-                Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr);
+                Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCode);
             }
             final SpellCheckerInfo sci = getCurrentSpellChecker(null);
             if (sci == null || sci.getSubtypeCount() == 0) {
@@ -475,17 +477,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                 }
                 return null;
             }
-            final int hashCode;
-            if (!TextUtils.isEmpty(subtypeHashCodeStr)) {
-                hashCode = Integer.valueOf(subtypeHashCodeStr);
-            } else {
-                hashCode = 0;
-            }
-            if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
+            if (subtypeHashCode == SpellCheckerSubtype.SUBTYPE_ID_NONE
+                    && !allowImplicitlySelectedSubtype) {
                 return null;
             }
             String candidateLocale = null;
-            if (hashCode == 0) {
+            if (subtypeHashCode == 0) {
                 // Spell checker language settings == "auto"
                 final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
                 if (imm != null) {
@@ -507,7 +504,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
             SpellCheckerSubtype candidate = null;
             for (int i = 0; i < sci.getSubtypeCount(); ++i) {
                 final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
-                if (hashCode == 0) {
+                if (subtypeHashCode == 0) {
                     final String scsLocale = scs.getLocale();
                     if (candidateLocale.equals(scsLocale)) {
                         return scs;
@@ -518,7 +515,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
                             candidate = scs;
                         }
                     }
-                } else if (scs.hashCode() == hashCode) {
+                } else if (scs.hashCode() == subtypeHashCode) {
                     if (DBG) {
                         Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale
                                 + ", " + scs.getLocale());
@@ -1096,12 +1093,15 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
             }
         }
 
-        private String getString(final String key) {
+        @Nullable
+        private String getString(@NonNull final String key, @Nullable final String defaultValue) {
+            final String result;
             if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
-                final String result = mCopyOnWriteDataStore.get(key);
-                return result != null ? result : "";
+                result = mCopyOnWriteDataStore.get(key);
+            } else {
+                result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
             }
-            return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+            return result != null ? result : defaultValue;
         }
 
         private void putInt(final String key, final int value) {
@@ -1149,24 +1149,31 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
             return mCurrentUserId;
         }
 
-        public void putSelectedSpellChecker(String sciId) {
-            putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+        public void putSelectedSpellChecker(@Nullable String sciId) {
+            if (TextUtils.isEmpty(sciId)) {
+                // OK to coalesce to null, since getSelectedSpellChecker() can take care of the
+                // empty data scenario.
+                putString(Settings.Secure.SELECTED_SPELL_CHECKER, null);
+            } else {
+                putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+            }
         }
 
         public void putSelectedSpellCheckerSubtype(int hashCode) {
-            putString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode));
+            putInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, hashCode);
         }
 
         public void setSpellCheckerEnabled(boolean enabled) {
             putBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, enabled);
         }
 
+        @NonNull
         public String getSelectedSpellChecker() {
-            return getString(Settings.Secure.SELECTED_SPELL_CHECKER);
+            return getString(Settings.Secure.SELECTED_SPELL_CHECKER, "");
         }
 
-        public String getSelectedSpellCheckerSubtype() {
-            return getString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE);
+        public int getSelectedSpellCheckerSubtype(final int defaultValue) {
+            return getInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, defaultValue);
         }
 
         public boolean isSpellCheckerEnabled() {
index d4dd505..322df04 100644 (file)
@@ -597,7 +597,7 @@ public class AccountManagerService
         if (sharedAccounts == null || sharedAccounts.length == 0) return;
         Account[] accounts = getAccountsAsUser(null, userId, mContext.getOpPackageName());
         int parentUserId = UserManager.isSplitSystemUser()
-                ? mUserManager.getUserInfo(userId).restrictedProfileParentId
+                ? getUserManager().getUserInfo(userId).restrictedProfileParentId
                 : UserHandle.USER_SYSTEM;
         if (parentUserId < 0) {
             Log.w(TAG, "User " + userId + " has shared accounts, but no parent user");
@@ -1061,7 +1061,7 @@ public class AccountManagerService
         for (UserInfo user : users) {
             if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) {
                 addSharedAccountAsUser(account, user.id);
-                if (mUserManager.isUserUnlocked(user.id)) {
+                if (getUserManager().isUserUnlocked(user.id)) {
                     mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
                             MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account));
                 }
@@ -1270,7 +1270,7 @@ public class AccountManagerService
                          * Owner or system user account was renamed, rename the account for
                          * those users with which the account was shared.
                          */
-                        List<UserInfo> users = mUserManager.getUsers(true);
+                        List<UserInfo> users = getUserManager().getUsers(true);
                         for (UserInfo user : users) {
                             if (user.isRestricted()
                                     && (user.restrictedProfileParentId == parentUserId)) {
@@ -1286,7 +1286,7 @@ public class AccountManagerService
     }
 
     private boolean canHaveProfile(final int parentUserId) {
-        final UserInfo userInfo = mUserManager.getUserInfo(parentUserId);
+        final UserInfo userInfo = getUserManager().getUserInfo(parentUserId);
         return userInfo != null && userInfo.canHaveProfile();
     }
 
@@ -1477,7 +1477,7 @@ public class AccountManagerService
             int parentUserId = accounts.userId;
             if (canHaveProfile(parentUserId)) {
                 // Remove from any restricted profiles that are sharing this account.
-                List<UserInfo> users = mUserManager.getUsers(true);
+                List<UserInfo> users = getUserManager().getUsers(true);
                 for (UserInfo user : users) {
                     if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) {
                         removeSharedAccountAsUser(account, user.id, callingUid);
@@ -3825,7 +3825,7 @@ public class AccountManagerService
 
             final ActivityManager am = mContext.getSystemService(ActivityManager.class);
             if (am.isUserRunningAndLocked(mAccounts.userId)
-                    && !authenticatorInfo.componentInfo.encryptionAware) {
+                    && !authenticatorInfo.componentInfo.directBootAware) {
                 Slog.w(TAG, "Blocking binding to authenticator " + authenticatorInfo.componentName
                         + " which isn't encryption aware");
                 return false;
@@ -4730,7 +4730,7 @@ public class AccountManagerService
                 || callingUid == Process.myUid()) {
             return unfiltered;
         }
-        UserInfo user = mUserManager.getUserInfo(userAccounts.userId);
+        UserInfo user = getUserManager().getUserInfo(userAccounts.userId);
         if (user != null && user.isRestricted()) {
             String[] packages = mPackageManager.getPackagesForUid(callingUid);
             // If any of the packages is a white listed package, return the full set,
index 95dbd0f..4f0f770 100644 (file)
@@ -267,7 +267,7 @@ import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEME
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.GET_PROVIDERS;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -1910,7 +1910,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                     mRecentTasks.loadUserRecentsLocked(userId);
                 }
                 if (userId == UserHandle.USER_SYSTEM) {
-                    startPersistentApps(PackageManager.MATCH_ENCRYPTION_UNAWARE);
+                    startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 }
                 installEncryptionUnawareProviders(userId);
                 break;
@@ -6913,6 +6913,14 @@ public final class ActivityManagerService extends ActivityManagerNative
             }
         }
 
+        // We're going to be splicing together extras before sending, so we're
+        // okay poking into any contained extras.
+        if (intents != null) {
+            for (int i = 0; i < intents.length; i++) {
+                intents[i].setDefusable(true);
+            }
+        }
+
         final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
         final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
         final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
@@ -10953,7 +10961,7 @@ public final class ActivityManagerService extends ActivityManagerNative
         // We're only interested in providers that are encryption unaware, and
         // we don't care about uninstalled apps, since there's no way they're
         // running at this point.
-        final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE;
+        final int matchFlags = GET_PROVIDERS | MATCH_DIRECT_BOOT_UNAWARE;
 
         synchronized (this) {
             final int NP = mProcessNames.getMap().size();
@@ -12874,7 +12882,7 @@ public final class ActivityManagerService extends ActivityManagerNative
         synchronized (this) {
             // Only start up encryption-aware persistent apps; once user is
             // unlocked we'll come back around and start unaware apps
-            startPersistentApps(PackageManager.MATCH_ENCRYPTION_AWARE);
+            startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
 
             // Start up initial activity.
             mBooting = true;
index fa62c98..efa7420 100644 (file)
@@ -620,7 +620,8 @@ class ActivityStarter {
                         && userManager.isUserUnlocked(parent.getUserHandle())
                         && !userManager.isUserUnlocked(userInfo.getUserHandle())) {
                     rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
-                            PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                            PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 }
             }
         }
index d2aa966..39fbeb5 100644 (file)
@@ -4,7 +4,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
 import android.app.AppGlobals;
-import android.auditing.SecurityLog;
+import android.app.admin.SecurityLog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
index e7580f4..b4df689 100644 (file)
@@ -205,7 +205,6 @@ public class AudioService extends IAudioService.Stub {
     private static final int MSG_SET_FORCE_USE = 8;
     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
     private static final int MSG_SET_ALL_VOLUMES = 10;
-    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
     private static final int MSG_REPORT_NEW_ROUTES = 12;
     private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
     private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
@@ -217,7 +216,6 @@ public class AudioService extends IAudioService.Stub {
     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
     private static final int MSG_SYSTEM_READY = 21;
     private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
-    private static final int MSG_PERSIST_MICROPHONE_MUTE = 23;
     private static final int MSG_UNMUTE_STREAM = 24;
     private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
     private static final int MSG_INDICATE_SYSTEM_READY = 26;
@@ -665,6 +663,7 @@ public class AudioService extends IAudioService.Stub {
         // array initialized by updateStreamVolumeAlias()
         updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
         readPersistedSettings();
+        readUserRestrictions();
         mSettingsObserver = new SettingsObserver();
         createStreamStates();
 
@@ -1111,14 +1110,27 @@ public class AudioService extends IAudioService.Stub {
                 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
                 UserHandle.USER_CURRENT);
 
+        updateMasterMono(cr);
+
+        // Each stream will read its own persisted settings
+
+        // Broadcast the sticky intents
+        broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
+        broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
+
+        // Broadcast vibrate settings
+        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
+        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
+
+        // Load settings for the volume controller
+        mVolumeController.loadSettings(cr);
+    }
+
+    private void readUserRestrictions() {
         final int currentUser = getCurrentUserId();
 
-        // In addition to checking the system setting, also check the current user restriction.
-        // Because of the delay before persisting VOLUME_MASTER_MUTE, there's a window where
-        // DISALLOW_ADJUST_VOLUME will be ignored when it's set right before switching users.
-        boolean masterMute = (System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
-                0, UserHandle.USER_CURRENT) == 1)
-                || mUserManagerInternal.getUserRestriction(
+        // Check the current user restriction.
+        boolean masterMute = mUserManagerInternal.getUserRestriction(
                     currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
         if (mUseFixedVolume) {
             masterMute = false;
@@ -1131,29 +1143,12 @@ public class AudioService extends IAudioService.Stub {
         AudioSystem.setMasterMute(masterMute);
         broadcastMasterMuteStatus(masterMute);
 
-        boolean microphoneMute =
-                (System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1)
-                || mUserManagerInternal.getUserRestriction(
-                        currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+        boolean microphoneMute = mUserManagerInternal.getUserRestriction(
+                currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
         if (DEBUG_VOL) {
             Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
         }
         AudioSystem.muteMicrophone(microphoneMute);
-
-        updateMasterMono(cr);
-
-        // Each stream will read its own persisted settings
-
-        // Broadcast the sticky intents
-        broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
-        broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
-
-        // Broadcast vibrate settings
-        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
-        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
-
-        // Load settings for the volume controller
-        mVolumeController.loadSettings(cr);
     }
 
     private int rescaleIndex(int index, int srcStream, int dstStream) {
@@ -1295,7 +1290,7 @@ public class AudioService extends IAudioService.Stub {
             // Check if the ringer mode handles this adjustment. If it does we don't
             // need to adjust the volume further.
             final int result = checkForRingerModeChange(aliasIndex, direction, step,
-                    streamState.mIsMuted, caller);
+                    streamState.mIsMuted);
             adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
             // If suppressing a volume adjustment in silent mode, display the UI hint
             if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
@@ -1911,20 +1906,12 @@ public class AudioService extends IAudioService.Stub {
             if (mute != AudioSystem.getMasterMute()) {
                 setSystemAudioMute(mute);
                 AudioSystem.setMasterMute(mute);
-                // Post a persist master volume msg
-                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
-                        : 0, userId, null, PERSIST_DELAY);
                 sendMasterMuteUpdate(mute, flags);
 
                 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
                 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
                 sendBroadcastToAll(intent);
             }
-        } else {
-            // If not the current user just persist the setting which will be loaded
-            // on user switch.
-            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
-                    : 0, userId, null, PERSIST_DELAY);
         }
     }
 
@@ -2017,8 +2004,6 @@ public class AudioService extends IAudioService.Stub {
             AudioSystem.muteMicrophone(on);
         }
         // Post a persist microphone msg.
-        sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
-                : 0, userId, null, PERSIST_DELAY);
     }
 
     @Override
@@ -2607,6 +2592,7 @@ public class AudioService extends IAudioService.Stub {
     private void readAudioSettings(boolean userSwitch) {
         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
         readPersistedSettings();
+        readUserRestrictions();
 
         // restore volume settings
         int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -3375,8 +3361,7 @@ public class AudioService extends IAudioService.Stub {
      * adjusting volume. If so, this will set the proper ringer mode and volume
      * indices on the stream states.
      */
-    private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
-            String caller) {
+    private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
         final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
         int result = FLAG_ADJUST_VOLUME;
         int ringerMode = getRingerModeInternal();
@@ -3465,11 +3450,6 @@ public class AudioService extends IAudioService.Stub {
             break;
         }
 
-        if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
-                && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
-            throw new SecurityException("Not allowed to change Do Not Disturb state");
-        }
-
         setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
 
         mPrevVolDirection = direction;
@@ -4545,16 +4525,6 @@ public class AudioService extends IAudioService.Stub {
                     persistVolume((VolumeStreamState) msg.obj, msg.arg1);
                     break;
 
-                case MSG_PERSIST_MASTER_VOLUME_MUTE:
-                    if (mUseFixedVolume) {
-                        return;
-                    }
-                    Settings.System.putIntForUser(mContentResolver,
-                                                 Settings.System.VOLUME_MASTER_MUTE,
-                                                 msg.arg1,
-                                                 msg.arg2);
-                    break;
-
                 case MSG_PERSIST_RINGER_MODE:
                     // note that the value persisted is the current ringer mode, not the
                     // value of ringer mode as of the time the request was made to persist
@@ -4677,15 +4647,11 @@ public class AudioService extends IAudioService.Stub {
                             Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
                             UserHandle.USER_CURRENT);
                     break;
-                case MSG_PERSIST_MICROPHONE_MUTE:
-                    Settings.System.putIntForUser(mContentResolver,
-                                                 Settings.System.MICROPHONE_MUTE,
-                                                 msg.arg1,
-                                                 msg.arg2);
-                    break;
+
                 case MSG_UNMUTE_STREAM:
                     onUnmuteStream(msg.arg1, msg.arg2);
                     break;
+
                 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
                     onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
                     break;
index 033a243..3c04b78 100644 (file)
@@ -1109,7 +1109,8 @@ public class InputManagerService extends IInputManager.Stub
         final PackageManager pm = mContext.getPackageManager();
         Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
         for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
-                PackageManager.GET_META_DATA | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE)) {
+                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE)) {
             final ActivityInfo activityInfo = resolveInfo.activityInfo;
             final int priority = resolveInfo.priority;
             visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
@@ -1125,7 +1126,8 @@ public class InputManagerService extends IInputManager.Stub
                 ActivityInfo receiver = pm.getReceiverInfo(
                         new ComponentName(d.packageName, d.receiverName),
                         PackageManager.GET_META_DATA
-                                | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                                | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor);
             } catch (NameNotFoundException ex) {
             }
index cee4619..9fd7f90 100644 (file)
@@ -311,10 +311,10 @@ public final class JobSchedulerService extends com.android.server.SystemService
             }
 
             toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
-        }
-        startTrackingJob(jobStatus, toCancel);
-        if (toCancel != null) {
-            cancelJobImpl(toCancel);
+            if (toCancel != null) {
+                cancelJobImpl(toCancel);
+            }
+            startTrackingJob(jobStatus, toCancel);
         }
         mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
         return JobScheduler.RESULT_SUCCESS;
@@ -1219,7 +1219,8 @@ public final class JobSchedulerService extends com.android.server.SystemService
             final ComponentName service = job.getService();
             try {
                 ServiceInfo si = pm.getServiceInfo(service,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                         UserHandle.getUserId(uid));
                 if (si == null) {
                     throw new IllegalArgumentException("No such service " + service);
index 3acd2ca..56edcca 100644 (file)
@@ -2509,8 +2509,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
         // update rules for all installed applications
         final List<UserInfo> users = mUserManager.getUsers();
         final List<ApplicationInfo> apps = pm.getInstalledApplications(
-                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS
-                        | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_DISABLED_COMPONENTS
+                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
 
         final int usersSize = users.size();
         final int appsSize = apps.size();
index 3baf894..575de16 100644 (file)
@@ -160,6 +160,7 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
@@ -276,9 +277,6 @@ public class NotificationManagerService extends SystemService {
     // Persistent storage for notification policy
     private AtomicFile mPolicyFile;
 
-    // Temporary holder for <blocked-packages> config coming from old policy files.
-    private HashSet<String> mBlockedPackages = new HashSet<String>();
-
     private static final int DB_VERSION = 1;
 
     private static final String TAG_NOTIFICATION_POLICY = "notification-policy";
@@ -354,27 +352,7 @@ public class NotificationManagerService extends SystemService {
         final XmlPullParser parser = Xml.newPullParser();
         parser.setInput(stream, StandardCharsets.UTF_8.name());
 
-        int type;
-        String tag;
-        int version = DB_VERSION;
-        while ((type = parser.next()) != END_DOCUMENT) {
-            tag = parser.getName();
-            if (type == START_TAG) {
-                if (TAG_NOTIFICATION_POLICY.equals(tag)) {
-                    version = Integer.parseInt(
-                            parser.getAttributeValue(null, ATTR_VERSION));
-                } else if (TAG_BLOCKED_PKGS.equals(tag)) {
-                    while ((type = parser.next()) != END_DOCUMENT) {
-                        tag = parser.getName();
-                        if (TAG_PACKAGE.equals(tag)) {
-                            mBlockedPackages.add(
-                                    parser.getAttributeValue(null, ATTR_NAME));
-                        } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
-                            break;
-                        }
-                    }
-                }
-            }
+        while (parser.next() != END_DOCUMENT) {
             mZenModeHelper.readXml(parser, forRestore);
             mRankingHelper.readXml(parser, forRestore);
         }
@@ -383,7 +361,6 @@ public class NotificationManagerService extends SystemService {
     private void loadPolicyFile() {
         if (DBG) Slog.d(TAG, "loadPolicyFile");
         synchronized(mPolicyFile) {
-            mBlockedPackages.clear();
 
             FileInputStream infile = null;
             try {
@@ -941,7 +918,7 @@ public class NotificationManagerService extends SystemService {
         final File systemDir = new File(Environment.getDataDirectory(), "system");
         mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
 
-        importOldBlockDb();
+        syncBlockDb();
 
         // This is a MangedServices object that keeps track of the listeners.
         mListeners = new NotificationListeners();
@@ -1041,22 +1018,43 @@ public class NotificationManagerService extends SystemService {
     }
 
     /**
-     * Read the old XML-based app block database and import those blockages into the AppOps system.
+     * Make sure the XML config and the the AppOps system agree about blocks.
      */
-    private void importOldBlockDb() {
+    private void syncBlockDb() {
         loadPolicyFile();
 
-        PackageManager pm = getContext().getPackageManager();
-        for (String pkg : mBlockedPackages) {
-            PackageInfo info = null;
-            try {
-                info = pm.getPackageInfo(pkg, 0);
-                setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false);
-            } catch (NameNotFoundException e) {
-                // forget you
+        // sync bans from ranker into app opps
+        Map<Integer, String> packageBans = mRankingHelper.getPackageBans();
+        for(Entry<Integer, String> ban : packageBans.entrySet()) {
+            final int uid = ban.getKey();
+            final String packageName = ban.getValue();
+            setNotificationsEnabledForPackageImpl(packageName, uid, false);
+        }
+
+        // sync bans from app opps into ranker
+        packageBans.clear();
+        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
+            final int userId = user.getUserHandle().getIdentifier();
+            final PackageManager packageManager = getContext().getPackageManager();
+            List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId);
+            final int packageCount = packages.size();
+            for (int p = 0; p < packageCount; p++) {
+                final String packageName = packages.get(p).packageName;
+                try {
+                    final int uid = packageManager.getPackageUidAsUser(packageName, userId);
+                    if (!checkNotificationOp(packageName, uid)) {
+                        packageBans.put(uid, packageName);
+                    }
+                } catch (NameNotFoundException e) {
+                    // forget you
+                }
             }
         }
-        mBlockedPackages.clear();
+        for (Entry<Integer, String> ban : packageBans.entrySet()) {
+            mRankingHelper.setImportance(ban.getValue(), ban.getKey(), IMPORTANCE_NONE);
+        }
+
+        savePolicyFile();
     }
 
     @Override
@@ -1261,6 +1259,8 @@ public class NotificationManagerService extends SystemService {
             checkCallerIsSystem();
 
             setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
+            mRankingHelper.setEnabled(pkg, uid, enabled);
+            savePolicyFile();
         }
 
         /**
@@ -2034,21 +2034,8 @@ public class NotificationManagerService extends SystemService {
         JSONObject dump = new JSONObject();
         try {
             dump.put("service", "Notification Manager");
-            JSONArray bans = new JSONArray();
-            try {
-                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
-                for (Integer userId : packageBans.keySet()) {
-                    for (String packageName : packageBans.get(userId)) {
-                        JSONObject ban = new JSONObject();
-                        ban.put("userId", userId);
-                        ban.put("packageName", packageName);
-                        bans.put(ban);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                // pass
-            }
-            dump.put("bans", bans);
+            dump.put("bans", mRankingHelper.dumpBansJson(filter));
+            dump.put("ranking", mRankingHelper.dumpJson(filter));
             dump.put("stats", mUsageStats.dumpJson(filter));
         } catch (JSONException e) {
             e.printStackTrace();
@@ -2175,45 +2162,7 @@ public class NotificationManagerService extends SystemService {
                     r.dump(pw, "      ", getContext(), filter.redact);
                 }
             }
-
-            try {
-                pw.println("\n  Banned Packages:");
-                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
-                for (Integer userId : packageBans.keySet()) {
-                    for (String packageName : packageBans.get(userId)) {
-                        pw.println("    " + userId + ": " + packageName);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                // pass
-            }
-        }
-    }
-
-    private ArrayMap<Integer, ArrayList<String>> getPackageBans(DumpFilter filter)
-            throws NameNotFoundException {
-        ArrayMap<Integer, ArrayList<String>> packageBans = new ArrayMap<>();
-        ArrayList<String> packageNames = new ArrayList<>();
-        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
-            final int userId = user.getUserHandle().getIdentifier();
-            final PackageManager packageManager = getContext().getPackageManager();
-            List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId);
-            final int packageCount = packages.size();
-            for (int p = 0; p < packageCount; p++) {
-                final String packageName = packages.get(p).packageName;
-                if (filter == null || filter.matches(packageName)) {
-                    final int uid = packageManager.getPackageUidAsUser(packageName, userId);
-                    if (!checkNotificationOp(packageName, uid)) {
-                        packageNames.add(packageName);
-                    }
-                }
-            }
-            if (!packageNames.isEmpty()) {
-                packageBans.put(userId, packageNames);
-                packageNames = new ArrayList<>();
-            }
         }
-        return packageBans;
     }
 
     /**
@@ -2298,6 +2247,11 @@ public class NotificationManagerService extends SystemService {
         // Sanitize inputs
         notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
                 Notification.PRIORITY_MAX);
+        if (notification.extras != null) {
+            // If the remote side sent us bad parcelables, they won't get the
+            // results they want, which is their loss.
+            notification.extras.setDefusable(true);
+        }
 
         // setup local book-keeping
         final StatusBarNotification n = new StatusBarNotification(
@@ -3598,6 +3552,9 @@ public class NotificationManagerService extends SystemService {
         public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
             if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
                     + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)));
+            if (mRankerServicePackageName == null) {
+                return;
+            }
 
             if (pkgList != null && (pkgList.length > 0)) {
                 for (String pkgName : pkgList) {
@@ -3610,6 +3567,10 @@ public class NotificationManagerService extends SystemService {
 
         protected void registerRanker() {
             // Find the updatable ranker and register it.
+            if (mRankerServicePackageName == null) {
+                Slog.w(TAG, "could not start ranker service: no package specified!");
+                return;
+            }
             Set<ComponentName> rankerComponents = queryPackageForServices(
                     mRankerServicePackageName, UserHandle.USER_SYSTEM, null);
             Iterator<ComponentName> iterator = rankerComponents.iterator();
index fd96a78..4a41705 100644 (file)
@@ -25,6 +25,11 @@ import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.server.notification.NotificationManagerService.DumpFilter;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -33,6 +38,8 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
 
 public class RankingHelper implements RankingConfig {
     private static final String TAG = "RankingHelper";
@@ -358,6 +365,14 @@ public class RankingHelper implements RankingConfig {
         updateConfig();
     }
 
+    public void setEnabled(String packageName, int uid, boolean enabled) {
+        boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE;
+        if (wasEnabled == enabled) {
+            return;
+        }
+        setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE);
+    }
+
     public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
         if (filter == null) {
             final int N = mSignalExtractors.length;
@@ -398,17 +413,97 @@ public class RankingHelper implements RankingConfig {
                 }
                 if (r.priority != DEFAULT_PRIORITY) {
                     pw.print(" priority=");
-                    pw.print(Ranking.importanceToString(r.priority));
+                    pw.print(Notification.priorityToString(r.priority));
                 }
                 if (r.visibility != DEFAULT_VISIBILITY) {
                     pw.print(" visibility=");
-                    pw.print(Ranking.importanceToString(r.visibility));
+                    pw.print(Notification.visibilityToString(r.visibility));
                 }
                 pw.println();
             }
         }
     }
 
+    public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) {
+        JSONObject ranking = new JSONObject();
+        JSONArray records = new JSONArray();
+        try {
+            ranking.put("noUid", mRestoredWithoutUids.size());
+        } catch (JSONException e) {
+           // pass
+        }
+        final int N = mRecords.size();
+        for (int i = 0; i < N; i++) {
+            final Record r = mRecords.valueAt(i);
+            if (filter == null || filter.matches(r.pkg)) {
+                JSONObject record = new JSONObject();
+                try {
+                    record.put("userId", UserHandle.getUserId(r.uid));
+                    record.put("packageName", r.pkg);
+                    if (r.importance != DEFAULT_IMPORTANCE) {
+                        record.put("importance", Ranking.importanceToString(r.importance));
+                    }
+                    if (r.priority != DEFAULT_PRIORITY) {
+                        record.put("priority", Notification.priorityToString(r.priority));
+                    }
+                    if (r.visibility != DEFAULT_VISIBILITY) {
+                        record.put("visibility", Notification.visibilityToString(r.visibility));
+                    }
+                } catch (JSONException e) {
+                   // pass
+                }
+                records.put(record);
+            }
+        }
+        try {
+            ranking.put("records", records);
+        } catch (JSONException e) {
+            // pass
+        }
+        return ranking;
+    }
+
+    /**
+     * Dump only the ban information as structured JSON for the stats collector.
+     *
+     * This is intentionally redundant with {#link dumpJson} because the old
+     * scraper will expect this format.
+     *
+     * @param filter
+     * @return
+     */
+    public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) {
+        JSONArray bans = new JSONArray();
+        Map<Integer, String> packageBans = getPackageBans();
+        for(Entry<Integer, String> ban : packageBans.entrySet()) {
+            final int userId = UserHandle.getUserId(ban.getKey());
+            final String packageName = ban.getValue();
+            if (filter == null || filter.matches(packageName)) {
+                JSONObject banJson = new JSONObject();
+                try {
+                    banJson.put("userId", userId);
+                    banJson.put("packageName", packageName);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+                bans.put(banJson);
+            }
+        }
+        return bans;
+    }
+
+    public Map<Integer, String> getPackageBans() {
+        final int N = mRecords.size();
+        ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
+        for (int i = 0; i < N; i++) {
+            final Record r = mRecords.valueAt(i);
+            if (r.importance == Ranking.IMPORTANCE_NONE) {
+                packageBans.put(r.uid, r.pkg);
+            }
+        }
+        return packageBans;
+    }
+
     public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
         if (queryReplace || pkgList == null || pkgList.length == 0
                 || mRestoredWithoutUids.isEmpty()) {
index 27c8293..13a96ae 100644 (file)
@@ -59,7 +59,8 @@ final class DefaultPermissionGrantPolicy {
     private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
-    private static final int DEFAULT_FLAGS = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+    private static final int DEFAULT_FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE
+            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 
     private static final String AUDIO_MIME_TYPE = "audio/mpeg";
 
index 5b0ceca..863a5ed 100644 (file)
@@ -218,7 +218,8 @@ public class LauncherAppsService extends SystemService {
             int packageUid = -1;
             try {
                 packageUid = mPm.getPackageUidAsUser(callingPackage,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
                         UserHandle.getUserId(getCallingUid()));
             } catch (NameNotFoundException e) {
@@ -256,7 +257,9 @@ public class LauncherAppsService extends SystemService {
             long ident = Binder.clearCallingIdentity();
             try {
                 List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return new ParceledListSlice<>(apps);
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -274,7 +277,9 @@ public class LauncherAppsService extends SystemService {
             long ident = Binder.clearCallingIdentity();
             try {
                 ResolveInfo app = mPm.resolveActivityAsUser(intent,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return app;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -293,7 +298,9 @@ public class LauncherAppsService extends SystemService {
             try {
                 IPackageManager pm = AppGlobals.getPackageManager();
                 PackageInfo info = pm.getPackageInfo(packageName,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return info != null && info.applicationInfo.enabled;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -421,7 +428,9 @@ public class LauncherAppsService extends SystemService {
             try {
                 IPackageManager pm = AppGlobals.getPackageManager();
                 ActivityInfo info = pm.getActivityInfo(component,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return info != null;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -445,7 +454,9 @@ public class LauncherAppsService extends SystemService {
             try {
                 IPackageManager pm = AppGlobals.getPackageManager();
                 ActivityInfo info = pm.getActivityInfo(component,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 if (!info.exported) {
                     throw new SecurityException("Cannot launch non-exported components "
                             + component);
@@ -455,7 +466,9 @@ public class LauncherAppsService extends SystemService {
                 // as calling startActivityAsUser ignores the category and just
                 // resolves based on the component if present.
                 List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 final int size = apps.size();
                 for (int i = 0; i < size; ++i) {
                     ActivityInfo activityInfo = apps.get(i).activityInfo;
index b624087..c2e0992 100644 (file)
@@ -61,10 +61,9 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
@@ -2565,7 +2564,8 @@ public class PackageManagerService extends IPackageManager.Stub {
         final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
 
         final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
         } else {
@@ -2580,7 +2580,8 @@ public class PackageManagerService extends IPackageManager.Stub {
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
 
         final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
         } else {
@@ -2592,7 +2593,8 @@ public class PackageManagerService extends IPackageManager.Stub {
         final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
 
         final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         ResolveInfo best = null;
         final int N = matches.size();
         for (int i = 0; i < N; i++) {
@@ -2627,7 +2629,8 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
         final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
 
         final int N = resolvers.size();
         if (N == 0) {
@@ -2672,7 +2675,8 @@ public class PackageManagerService extends IPackageManager.Stub {
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
 
         final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         if (matches.size() == 0) {
             return null;
         } else if (matches.size() == 1) {
@@ -2886,8 +2890,8 @@ public class PackageManagerService extends IPackageManager.Stub {
                 throw new SecurityException("Package " + packageName + " is currently frozen!");
             }
 
-            if (!userKeyUnlocked && !(ps.pkg.applicationInfo.isEncryptionAware()
-                    || ps.pkg.applicationInfo.isPartiallyEncryptionAware())) {
+            if (!userKeyUnlocked && !(ps.pkg.applicationInfo.isDirectBootAware()
+                    || ps.pkg.applicationInfo.isPartiallyDirectBootAware())) {
                 throw new SecurityException("Package " + packageName + " is not encryption aware!");
             }
         }
@@ -3255,17 +3259,17 @@ public class PackageManagerService extends IPackageManager.Stub {
      * Update given flags based on encryption status of current user.
      */
     private int updateFlags(int flags, int userId) {
-        if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
-                | PackageManager.MATCH_ENCRYPTION_AWARE)) != 0) {
+        if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                | PackageManager.MATCH_DIRECT_BOOT_AWARE)) != 0) {
             // Caller expressed an explicit opinion about what encryption
             // aware/unaware components they want to see, so fall through and
             // give them what they want
         } else {
             // Caller expressed no opinion, so match based on user state
             if (isUserKeyUnlocked(userId)) {
-                flags |= PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+                flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
             } else {
-                flags |= PackageManager.MATCH_ENCRYPTION_AWARE;
+                flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE;
             }
         }
         return flags;
@@ -3280,8 +3284,8 @@ public class PackageManagerService extends IPackageManager.Stub {
                 | PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS)) != 0) {
             // Caller is asking for component details, so they'd better be
             // asking for specific encryption matching behavior, or be triaged
-            if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
-                    | PackageManager.MATCH_ENCRYPTION_AWARE
+            if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
                     | PackageManager.MATCH_DEBUG_TRIAGED_MISSING)) == 0) {
                 triaged = false;
             }
@@ -3318,8 +3322,8 @@ public class PackageManagerService extends IPackageManager.Stub {
         boolean triaged = true;
         // Caller is asking for component details, so they'd better be
         // asking for specific encryption matching behavior, or be triaged
-        if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
-                | PackageManager.MATCH_ENCRYPTION_AWARE
+        if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                | PackageManager.MATCH_DIRECT_BOOT_AWARE
                 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING)) == 0) {
             triaged = false;
         }
@@ -6126,10 +6130,10 @@ public class PackageManagerService extends IPackageManager.Stub {
                 final PackageParser.Package p = i.next();
                 if (p.applicationInfo == null) continue;
 
-                final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
-                        && !p.applicationInfo.isEncryptionAware();
-                final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
-                        && p.applicationInfo.isEncryptionAware();
+                final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
+                        && !p.applicationInfo.isDirectBootAware();
+                final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
+                        && p.applicationInfo.isDirectBootAware();
 
                 if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
                         && (!mSafeMode || isSystemApp(p))
@@ -8289,8 +8293,8 @@ public class PackageManagerService extends IPackageManager.Stub {
                 a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
                 a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
                 a.info.dataDir = pkg.applicationInfo.dataDir;
-                a.info.deviceEncryptedDataDir = pkg.applicationInfo.deviceEncryptedDataDir;
-                a.info.credentialEncryptedDataDir = pkg.applicationInfo.credentialEncryptedDataDir;
+                a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir;
+                a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir;
 
                 // TODO: Update instrumentation.nativeLibraryDir as well ? Does it
                 // need other information about the application, like the ABI and what not ?
@@ -16459,10 +16463,22 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
     }
 
-    ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
-            int userId) {
+    private Intent getHomeIntent() {
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_HOME);
+        return intent;
+    }
+
+    private IntentFilter getHomeFilter() {
+        IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
+        filter.addCategory(Intent.CATEGORY_HOME);
+        filter.addCategory(Intent.CATEGORY_DEFAULT);
+        return filter;
+    }
+
+    ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+            int userId) {
+        Intent intent  = getHomeIntent();
         List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
                 PackageManager.GET_META_DATA, userId);
         ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
@@ -16481,6 +16497,32 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
     }
 
     @Override
+    public void setHomeActivity(ComponentName comp, int userId) {
+        ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
+        getHomeActivitiesAsUser(homeActivities, userId);
+
+        boolean found = false;
+
+        final int size = homeActivities.size();
+        final ComponentName[] set = new ComponentName[size];
+        for (int i = 0; i < size; i++) {
+            final ResolveInfo candidate = homeActivities.get(i);
+            final ActivityInfo info = candidate.activityInfo;
+            final ComponentName activityName = new ComponentName(info.packageName, info.name);
+            set[i] = activityName;
+            if (!found && activityName.equals(comp)) {
+                found = true;
+            }
+        }
+        if (!found) {
+            throw new IllegalArgumentException("Component " + comp + " cannot be home on user "
+                    + userId);
+        }
+        replacePreferredActivity(getHomeFilter(), IntentFilter.MATCH_CATEGORY_EMPTY,
+                set, comp, userId);
+    }
+
+    @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {
         if (!sUserManager.exists(userId)) return;
@@ -16624,6 +16666,22 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         }
     }
 
+    @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        if (!sUserManager.exists(userId)) {
+            return;
+        }
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission*/,
+                false /* checkShell */, "flushPackageRestrictions");
+        synchronized (mPackages) {
+            mSettings.writePackageRestrictionsLPr(userId);
+            mDirtyUsers.remove(userId);
+            if (mDirtyUsers.isEmpty()) {
+                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+            }
+        }
+    }
+
     private void sendPackageChangedBroadcast(String packageName,
             boolean killFlag, ArrayList<String> componentNames, int packageUid) {
         if (DEBUG_INSTALL)
@@ -18332,13 +18390,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
 
     /**
      * For system apps on non-FBE devices, this method migrates any existing
-     * CE/DE data to match the {@code forceDeviceEncrypted} flag requested by
-     * the app.
+     * CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag
+     * requested by the app.
      */
     private boolean maybeMigrateAppData(String volumeUuid, int userId, PackageParser.Package pkg) {
         if (pkg.isSystemApp() && !StorageManager.isFileEncryptedNativeOrEmulated()
-                && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
-            final int storageTarget = pkg.applicationInfo.isForceDeviceEncrypted()
+                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+            final int storageTarget = pkg.applicationInfo.isDefaultToDeviceProtectedStorage()
                     ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
             synchronized (mInstallLock) {
                 try {
index d77168c..319fc37 100644 (file)
@@ -117,6 +117,8 @@ class PackageManagerShellCommand extends ShellCommand {
                     return runSuspend(true);
                 case "unsuspend":
                     return runSuspend(false);
+                case "set-home-activity":
+                    return runSetHomeActivity();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -963,6 +965,39 @@ class PackageManagerShellCommand extends ShellCommand {
         return params;
     }
 
+    private int runSetHomeActivity() {
+        final PrintWriter pw = getOutPrintWriter();
+        int userId = UserHandle.USER_SYSTEM;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        String component = getNextArg();
+        ComponentName componentName =
+                component != null ? ComponentName.unflattenFromString(component) : null;
+
+        if (componentName == null) {
+            pw.println("Error: component name not specified or invalid");
+            return 1;
+        }
+
+        try {
+            mInterface.setHomeActivity(componentName, userId);
+            return 0;
+        } catch (RemoteException e) {
+            pw.println(e.toString());
+            return 1;
+        }
+    }
+
     private static String checkAbiArgument(String abi) {
         if (TextUtils.isEmpty(abi)) {
             throw new IllegalArgumentException("Missing ABI argument");
@@ -1303,6 +1338,8 @@ class PackageManagerShellCommand extends ShellCommand {
         pw.println("    Suspends the specified package (as user).");
         pw.println("  unsuspend [--user USER_ID] TARGET-PACKAGE");
         pw.println("    Unsuspends the specified package (as user).");
+        pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
+        pw.println("    set the default home activity (aka launcher).");
         pw.println();
         Intent.printIntentArgsHelp(pw , "");
     }
index 4c77f28..e66ec3c 100644 (file)
@@ -3048,7 +3048,8 @@ final class Settings {
             tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), "  ");
         }
         Intent intent = new Intent();
-        int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+        int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
+                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
         intent.setAction(tmpPa.getAction(0));
         for (int i=0; i<tmpPa.countCategories(); i++) {
             String cat = tmpPa.getCategory(i);
@@ -4175,10 +4176,10 @@ final class Settings {
         ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
         ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
         ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS, "HAS_DOMAIN_URLS",
-        ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED, "FORCE_DEVICE_ENCRYPTED",
-        ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE, "ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE, "DEFAULT_TO_DEVICE_PROTECTED_STORAGE",
+        ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE, "DIRECT_BOOT_AWARE",
         ApplicationInfo.PRIVATE_FLAG_AUTOPLAY, "AUTOPLAY",
-        ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE, "PARTIALLY_ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE, "PARTIALLY_DIRECT_BOOT_AWARE",
         ApplicationInfo.PRIVATE_FLAG_EPHEMERAL, "EPHEMERAL",
         ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
         ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES, "RESIZEABLE_ACTIVITIES",
index 0641749..39aa455 100644 (file)
@@ -159,6 +159,8 @@ public class ShortcutService extends IShortcutService.Stub {
     static final String TAG_EXTRAS = "extras";
     static final String TAG_SHORTCUT = "shortcut";
     static final String TAG_LAUNCHER = "launcher";
+    static final String TAG_PIN = "pin";
+    static final String TAG_LAUNCHER_PINS = "launcher-pins";
 
     static final String ATTR_VALUE = "value";
     static final String ATTR_NAME = "name";
@@ -174,6 +176,7 @@ public class ShortcutService extends IShortcutService.Stub {
     static final String ATTR_FLAGS = "flags";
     static final String ATTR_ICON_RES = "icon-res";
     static final String ATTR_BITMAP_PATH = "bitmap-path";
+    static final String ATTR_PACKAGE_NAME = "package-name";
 
     @VisibleForTesting
     interface ConfigConstants {
@@ -723,7 +726,7 @@ public class ShortcutService extends IShortcutService.Stub {
     /** Return the per-user state. */
     @GuardedBy("mLock")
     @NonNull
-    private UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) {
+    UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) {
         UserShortcuts userPackages = mUsers.get(userId);
         if (userPackages == null) {
             userPackages = loadUserLocked(userId);
@@ -738,15 +741,16 @@ public class ShortcutService extends IShortcutService.Stub {
     /** Return the per-user per-package state. */
     @GuardedBy("mLock")
     @NonNull
-    private PackageShortcuts getPackageShortcutsLocked(
+    PackageShortcuts getPackageShortcutsLocked(
             @NonNull String packageName, @UserIdInt int userId) {
-        final UserShortcuts userPackages = getUserShortcutsLocked(userId);
-        PackageShortcuts shortcuts = userPackages.getPackages().get(packageName);
-        if (shortcuts == null) {
-            shortcuts = new PackageShortcuts(userId, packageName);
-            userPackages.getPackages().put(packageName, shortcuts);
-        }
-        return shortcuts;
+        return getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
+    }
+
+    @GuardedBy("mLock")
+    @NonNull
+    LauncherShortcuts getLauncherShortcuts(
+            @NonNull String packageName, @UserIdInt int userId) {
+        return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName);
     }
 
     // === Caller validation ===
@@ -981,12 +985,11 @@ public class ShortcutService extends IShortcutService.Stub {
     // Test overrides it.
     int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) {
         try {
-
-            // TODO Is MATCH_UNINSTALLED_PACKAGES correct to get SD card app info?
-
             return mContext.getPackageManager().getPackageUidAsUser(packageName,
-                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                            | PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+                    PackageManager.MATCH_DIRECT_BOOT_AWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                            | PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                    userId);
         } catch (NameNotFoundException e) {
             return -1;
         }
@@ -1057,7 +1060,7 @@ public class ShortcutService extends IShortcutService.Stub {
         validatePersistableBundleForXml(shortcut.getIntentPersistableExtras());
         validatePersistableBundleForXml(shortcut.getExtras());
 
-        shortcut.setFlags(0);
+        shortcut.replaceFlags(0);
     }
 
     // KXmlSerializer is strict and doesn't allow certain characters, so we disallow those
@@ -1129,8 +1132,7 @@ public class ShortcutService extends IShortcutService.Stub {
             // Then, add/update all.  We need to make sure to take over "pinned" flag.
             for (int i = 0; i < size; i++) {
                 final ShortcutInfo newShortcut = newShortcuts.get(i);
-                newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
-                ps.updateShortcutWithCapping(this, newShortcut);
+                ps.addDynamicShortcut(this, newShortcut);
             }
         }
         userPackageChanged(packageName, userId);
@@ -1194,8 +1196,7 @@ public class ShortcutService extends IShortcutService.Stub {
             fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
 
             // Add it.
-            newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
-            ps.updateShortcutWithCapping(this, newShortcut);
+            ps.addDynamicShortcut(this, newShortcut);
         }
         userPackageChanged(packageName, userId);
 
@@ -1251,7 +1252,8 @@ public class ShortcutService extends IShortcutService.Stub {
 
         final ArrayList<ShortcutInfo> ret = new ArrayList<>();
 
-        getPackageShortcutsLocked(packageName, userId).findAll(ret, query, cloneFlags);
+        getPackageShortcutsLocked(packageName, userId).findAll(this, ret, query, cloneFlags,
+                /* callingLauncher= */ null);
 
         return new ParceledListSlice<>(ret);
     }
@@ -1406,25 +1408,27 @@ public class ShortcutService extends IShortcutService.Stub {
 
             synchronized (mLock) {
                 if (packageName != null) {
-                    getShortcutsInnerLocked(packageName, changedSince, componentName, queryFlags,
-                            userId, ret, cloneFlag);
+                    getShortcutsInnerLocked(
+                            callingPackage, packageName, changedSince,
+                            componentName, queryFlags, userId, ret, cloneFlag);
                 } else {
                     final ArrayMap<String, PackageShortcuts> packages =
                             getUserShortcutsLocked(userId).getPackages();
                     for (int i = packages.size() - 1; i >= 0; i--) {
                         getShortcutsInnerLocked(
-                                packages.keyAt(i),
-                                changedSince, componentName, queryFlags, userId, ret, cloneFlag);
+                                callingPackage, packages.keyAt(i), changedSince,
+                                componentName, queryFlags, userId, ret, cloneFlag);
                     }
                 }
             }
             return ret;
         }
 
-        private void getShortcutsInnerLocked(@Nullable String packageName,long changedSince,
+        private void getShortcutsInnerLocked(@NonNull String callingPackage,
+                @Nullable String packageName,long changedSince,
                 @Nullable ComponentName componentName, int queryFlags,
                 int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
-            getPackageShortcutsLocked(packageName, userId).findAll(ret,
+            getPackageShortcutsLocked(packageName, userId).findAll(ShortcutService.this, ret,
                     (ShortcutInfo si) -> {
                         if (si.getLastChangedTimestamp() < changedSince) {
                             return false;
@@ -1435,12 +1439,12 @@ public class ShortcutService extends IShortcutService.Stub {
                         }
                         final boolean matchDynamic =
                                 ((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
-                                && si.isDynamic();
+                                        && si.isDynamic();
                         final boolean matchPinned =
                                 ((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0)
                                         && si.isPinned();
                         return matchDynamic || matchPinned;
-                    }, cloneFlag);
+                    }, cloneFlag, callingPackage);
         }
 
         @Override
@@ -1453,9 +1457,10 @@ public class ShortcutService extends IShortcutService.Stub {
             final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size());
             final ArraySet<String> idSet = new ArraySet<>(ids);
             synchronized (mLock) {
-                getPackageShortcutsLocked(packageName, userId).findAll(ret,
+                getPackageShortcutsLocked(packageName, userId).findAll(
+                        ShortcutService.this, ret,
                         (ShortcutInfo si) -> idSet.contains(si.getId()),
-                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage);
             }
             return ret;
         }
@@ -1468,8 +1473,8 @@ public class ShortcutService extends IShortcutService.Stub {
             Preconditions.checkNotNull(shortcutIds, "shortcutIds");
 
             synchronized (mLock) {
-                getPackageShortcutsLocked(packageName, userId).replacePinned(
-                        ShortcutService.this, callingPackage, shortcutIds);
+                getLauncherShortcuts(callingPackage, userId).pinShortcuts(
+                        ShortcutService.this, packageName, shortcutIds);
             }
             userPackageChanged(packageName, userId);
         }
@@ -1812,6 +1817,14 @@ public class ShortcutService extends IShortcutService.Stub {
         Binder.restoreCallingIdentity(token);
     }
 
+    final void wtf(String message) {
+        Slog.wtf(TAG, message, /* exception= */ null);
+    }
+
+    void wtf(String message, Exception e) {
+        Slog.wtf(TAG, message, e);
+    }
+
     File injectSystemDataPath() {
         return Environment.getDataSystemDirectory();
     }
@@ -1887,6 +1900,8 @@ class UserShortcuts {
 
     private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>();
 
+    private final ArrayMap<String, LauncherShortcuts> mLaunchers = new ArrayMap<>();
+
     private ComponentName mLauncherComponent;
 
     public UserShortcuts(int userId) {
@@ -1897,13 +1912,41 @@ class UserShortcuts {
         return mPackages;
     }
 
+    public ArrayMap<String, LauncherShortcuts> getLaunchers() {
+        return mLaunchers;
+    }
+
+    public PackageShortcuts getPackageShortcuts(@NonNull String packageName) {
+        PackageShortcuts ret = mPackages.get(packageName);
+        if (ret == null) {
+            ret = new PackageShortcuts(mUserId, packageName);
+            mPackages.put(packageName, ret);
+        }
+        return ret;
+    }
+
+    public LauncherShortcuts getLauncherShortcuts(@NonNull String packageName) {
+        LauncherShortcuts ret = mLaunchers.get(packageName);
+        if (ret == null) {
+            ret = new LauncherShortcuts(mUserId, packageName);
+            mLaunchers.put(packageName, ret);
+        }
+        return ret;
+    }
+
     public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
         out.startTag(null, ShortcutService.TAG_USER);
 
         ShortcutService.writeTagValue(out, ShortcutService.TAG_LAUNCHER,
                 mLauncherComponent);
 
-        for (int i = 0; i < mPackages.size(); i++) {
+        final int lsize = mLaunchers.size();
+        for (int i = 0; i < lsize; i++) {
+            mLaunchers.valueAt(i).saveToXml(out);
+        }
+
+        final int psize = mPackages.size();
+        for (int i = 0; i < psize; i++) {
             mPackages.valueAt(i).saveToXml(out);
         }
 
@@ -1924,16 +1967,26 @@ class UserShortcuts {
             final int depth = parser.getDepth();
             final String tag = parser.getName();
             switch (tag) {
-                case ShortcutService.TAG_LAUNCHER:
+                case ShortcutService.TAG_LAUNCHER: {
                     ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
                             parser, ShortcutService.ATTR_VALUE);
                     continue;
-                case ShortcutService.TAG_PACKAGE:
+                }
+                case ShortcutService.TAG_PACKAGE: {
                     final PackageShortcuts shortcuts = PackageShortcuts.loadFromXml(parser, userId);
 
                     // Don't use addShortcut(), we don't need to save the icon.
                     ret.getPackages().put(shortcuts.mPackageName, shortcuts);
                     continue;
+                }
+
+                case ShortcutService.TAG_LAUNCHER_PINS: {
+                    final LauncherShortcuts shortcuts =
+                            LauncherShortcuts.loadFromXml(parser, userId);
+
+                    ret.getLaunchers().put(shortcuts.mPackageName, shortcuts);
+                    continue;
+                }
             }
             throw ShortcutService.throwForInvalidTag(depth, tag);
         }
@@ -1970,12 +2023,166 @@ class UserShortcuts {
         pw.print(mLauncherComponent);
         pw.println();
 
+        for (int i = 0; i < mLaunchers.size(); i++) {
+            mLaunchers.valueAt(i).dump(s, pw, prefix + "  ");
+        }
+
         for (int i = 0; i < mPackages.size(); i++) {
             mPackages.valueAt(i).dump(s, pw, prefix + "  ");
         }
     }
 }
 
+class LauncherShortcuts {
+    private static final String TAG = ShortcutService.TAG;
+
+    @UserIdInt
+    final int mUserId;
+
+    @NonNull
+    final String mPackageName;
+
+    /**
+     * Package name -> IDs.
+     */
+    final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
+
+    LauncherShortcuts(@UserIdInt int userId, @NonNull String packageName) {
+        mUserId = userId;
+        mPackageName = packageName;
+    }
+
+    public void pinShortcuts(@NonNull ShortcutService s, @NonNull String packageName,
+            @NonNull List<String> ids) {
+        final int idSize = ids.size();
+        if (idSize == 0) {
+            mPinnedShortcuts.remove(packageName);
+        } else {
+            final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName);
+
+            // Pin shortcuts.  Make sure only pin the ones that were visible to the caller.
+            // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
+
+            final PackageShortcuts packageShortcuts =
+                    s.getPackageShortcutsLocked(packageName, mUserId);
+            final ArraySet<String> newSet = new ArraySet<>();
+
+            for (int i = 0; i < idSize; i++) {
+                final String id = ids.get(i);
+                final ShortcutInfo si = packageShortcuts.findShortcutById(id);
+                if (si == null) {
+                    continue;
+                }
+                if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) {
+                    newSet.add(id);
+                }
+            }
+            mPinnedShortcuts.put(packageName, newSet);
+        }
+        s.getPackageShortcutsLocked(packageName, mUserId).refreshPinnedFlags(s);
+    }
+
+    /**
+     * Return the pinned shortcut IDs for the publisher package.
+     */
+    public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) {
+        return mPinnedShortcuts.get(packageName);
+    }
+
+    /**
+     * Persist.
+     */
+    public void saveToXml(XmlSerializer out) throws IOException {
+        out.startTag(null, ShortcutService.TAG_LAUNCHER_PINS);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_PACKAGE_NAME,
+                mPackageName);
+
+        final int size = mPinnedShortcuts.size();
+        for (int i = 0; i < size; i++) {
+            out.startTag(null, ShortcutService.TAG_PACKAGE);
+            ShortcutService.writeAttr(out, ShortcutService.ATTR_PACKAGE_NAME,
+                    mPinnedShortcuts.keyAt(i));
+
+            final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+            final int idSize = ids.size();
+            for (int j = 0; j < idSize; j++) {
+                ShortcutService.writeTagValue(out, ShortcutService.TAG_PIN, ids.valueAt(j));
+            }
+            out.endTag(null, ShortcutService.TAG_PACKAGE);
+        }
+
+        out.endTag(null, ShortcutService.TAG_LAUNCHER_PINS);
+    }
+
+    /**
+     * Load.
+     */
+    public static LauncherShortcuts loadFromXml(XmlPullParser parser, int userId)
+            throws IOException, XmlPullParserException {
+        final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
+                ShortcutService.ATTR_PACKAGE_NAME);
+
+        final LauncherShortcuts ret = new LauncherShortcuts(userId, launcherPackageName);
+
+        ArraySet<String> ids = null;
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            final int depth = parser.getDepth();
+            final String tag = parser.getName();
+            switch (tag) {
+                case ShortcutService.TAG_PACKAGE: {
+                    final String packageName = ShortcutService.parseStringAttribute(parser,
+                            ShortcutService.ATTR_PACKAGE_NAME);
+                    ids = new ArraySet<>();
+                    ret.mPinnedShortcuts.put(packageName, ids);
+                    continue;
+                }
+                case ShortcutService.TAG_PIN: {
+                    ids.add(ShortcutService.parseStringAttribute(parser,
+                            ShortcutService.ATTR_VALUE));
+                    continue;
+                }
+            }
+            throw ShortcutService.throwForInvalidTag(depth, tag);
+        }
+        return ret;
+    }
+
+    public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+        pw.println();
+
+        pw.print(prefix);
+        pw.print("Launcher: ");
+        pw.print(mPackageName);
+        pw.println();
+
+        final int size = mPinnedShortcuts.size();
+        for (int i = 0; i < size; i++) {
+            pw.println();
+
+            pw.print(prefix);
+            pw.print("  ");
+            pw.print("Package: ");
+            pw.println(mPinnedShortcuts.keyAt(i));
+
+            final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+            final int idSize = ids.size();
+
+            for (int j = 0; j < idSize; j++) {
+                pw.print(prefix);
+                pw.print("    ");
+                pw.print(ids.valueAt(j));
+                pw.println();
+            }
+        }
+    }
+}
+
 /**
  * All the information relevant to shortcuts from a single package (per-user).
  */
@@ -2039,27 +2246,34 @@ class PackageShortcuts {
      *
      * It checks the max number of dynamic shortcuts.
      */
-    public void updateShortcutWithCapping(@NonNull ShortcutService s,
+    public void addDynamicShortcut(@NonNull ShortcutService s,
             @NonNull ShortcutInfo newShortcut) {
+        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+
         final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
 
-        int oldFlags = 0;
-        int newDynamicCount = mDynamicShortcutCount;
+        final boolean wasPinned;
+        final int newDynamicCount;
 
-        if (oldShortcut != null) {
-            oldFlags = oldShortcut.getFlags();
+        if (oldShortcut == null) {
+            wasPinned = false;
+            newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
+        } else {
+            wasPinned = oldShortcut.isPinned();
             if (oldShortcut.isDynamic()) {
-                newDynamicCount--;
+                newDynamicCount = mDynamicShortcutCount; // not adding a dynamic shortcut.
+            } else {
+                newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
             }
         }
-        if (newShortcut.isDynamic()) {
-            newDynamicCount++;
-        }
+
         // Make sure there's still room.
         s.enforceMaxDynamicShortcuts(newDynamicCount);
 
         // Okay, make it dynamic and add.
-        newShortcut.addFlags(oldFlags);
+        if (wasPinned) {
+            newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+        }
 
         addShortcut(s, newShortcut);
         mDynamicShortcutCount = newDynamicCount;
@@ -2088,6 +2302,9 @@ class PackageShortcuts {
         }
     }
 
+    /**
+     * Remove all dynamic shortcuts.
+     */
     public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -2096,6 +2313,9 @@ class PackageShortcuts {
         mDynamicShortcutCount = 0;
     }
 
+    /**
+     * Remove a dynamic shortcut by ID.
+     */
     public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
         final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
 
@@ -2112,24 +2332,40 @@ class PackageShortcuts {
         }
     }
 
-    public void replacePinned(@NonNull ShortcutService s, String launcherPackage,
-            List<String> shortcutIds) {
-
-        // TODO Should be per launcherPackage.
-
+    /**
+     * Called after a launcher updates the pinned set.  For each shortcut in this package,
+     * set FLAG_PINNED if any launcher has pinned it.  Otherwise, clear it.
+     *
+     * <p>Then remove all shortcuts that are not dynamic and no longer pinned either.
+     */
+    public void refreshPinnedFlags(@NonNull ShortcutService s) {
         // First, un-pin all shortcuts
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
         }
 
-        // Then pin ALL
-        for (int i = shortcutIds.size() - 1; i >= 0; i--) {
-            final ShortcutInfo shortcut = mShortcuts.get(shortcutIds.get(i));
-            if (shortcut != null) {
-                shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+        // Then, for the pinned set for each launcher, set the pin flag one by one.
+        final ArrayMap<String, LauncherShortcuts> launchers =
+                s.getUserShortcutsLocked(mUserId).getLaunchers();
+
+        for (int l = launchers.size() - 1; l >= 0; l--) {
+            final LauncherShortcuts launcherShortcuts = launchers.valueAt(l);
+            final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(mPackageName);
+
+            if (pinned == null || pinned.size() == 0) {
+                continue;
+            }
+            for (int i = pinned.size() - 1; i >= 0; i--) {
+                final ShortcutInfo si = mShortcuts.get(pinned.valueAt(i));
+                if (si == null) {
+                    s.wtf("Shortcut not found");
+                } else {
+                    si.addFlags(ShortcutInfo.FLAG_PINNED);
+                }
             }
         }
 
+        // Lastly, remove the ones that are no longer pinned nor dynamic.
         removeOrphans(s);
     }
 
@@ -2173,12 +2409,40 @@ class PackageShortcuts {
     /**
      * Find all shortcuts that match {@code query}.
      */
-    public void findAll(@NonNull List<ShortcutInfo> result,
-            @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
+    public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
+            @Nullable Predicate<ShortcutInfo> query, int cloneFlag,
+            @Nullable String callingLauncher) {
+
+        // Set of pinned shortcuts by the calling launcher.
+        final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
+                : s.getLauncherShortcuts(callingLauncher, mUserId)
+                    .getPinnedShortcutIds(mPackageName);
+
         for (int i = 0; i < mShortcuts.size(); i++) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
-            if (query == null || query.test(si)) {
-                result.add(si.clone(cloneFlag));
+
+            // If it's called by non-launcher (i.e. publisher, always include -> true.
+            // Otherwise, only include non-dynamic pinned one, if the calling launcher has pinned
+            // it.
+            final boolean isPinnedByCaller = (callingLauncher == null)
+                    || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId()));
+            if (!si.isDynamic()) {
+                if (!si.isPinned()) {
+                    s.wtf("Shortcut not pinned here");
+                    continue;
+                }
+                if (!isPinnedByCaller) {
+                    continue;
+                }
+            }
+            final ShortcutInfo clone = si.clone(cloneFlag);
+            // Fix up isPinned for the caller.  Note we need to do it before the "test" callback,
+            // since it may check isPinned.
+            if (!isPinnedByCaller) {
+                clone.clearFlags(ShortcutInfo.FLAG_PINNED);
+            }
+            if (query == null || query.test(clone)) {
+                result.add(clone);
             }
         }
     }
@@ -2188,6 +2452,8 @@ class PackageShortcuts {
     }
 
     public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+        pw.println();
+
         pw.print(prefix);
         pw.print("Package: ");
         pw.print(mPackageName);
index 57ae523..a47f250 100644 (file)
@@ -138,16 +138,18 @@ class ShortcutManager {
                     ComponentName componentName = new ComponentName(packageName, className);
                     try {
                         info = packageManager.getActivityInfo(componentName,
-                                PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                                | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                                        | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                     } catch (PackageManager.NameNotFoundException e) {
                         String[] packages = packageManager.canonicalToCurrentPackageNames(
                                 new String[] { packageName });
                         componentName = new ComponentName(packages[0], className);
                         try {
                             info = packageManager.getActivityInfo(componentName,
-                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                                    | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                                    PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                                            | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                         } catch (PackageManager.NameNotFoundException e1) {
                             Log.w(TAG, "Unable to add bookmark: " + packageName
                                     + "/" + className, e);
index cd771ba..1695615 100644 (file)
@@ -645,15 +645,23 @@ final class WindowState implements WindowManagerPolicy.WindowState {
         final boolean fullscreenTask = !inMultiWindowMode();
         final boolean windowsAreFloating = task != null && task.isFloating();
 
-        if (fullscreenTask || (isChildWindow()
-                && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) {
+        // If the task has temp inset bounds set, we have to make sure all its windows uses
+        // the temp inset frame. Otherwise different display frames get applied to the main
+        // window and the child window, making them misaligned.
+        if (fullscreenTask) {
+            mInsetFrame.setEmpty();
+        } else {
+            task.getTempInsetBounds(mInsetFrame);
+        }
+
+        if (mInsetFrame.isEmpty()  && (fullscreenTask
+                || (isChildWindow() && (mAttrs.privateFlags
+                        & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0))) {
             // We use the parent frame as the containing frame for fullscreen and child windows
             mContainingFrame.set(pf);
             mDisplayFrame.set(df);
-            mInsetFrame.setEmpty();
         } else {
             task.getBounds(mContainingFrame);
-            task.getTempInsetBounds(mInsetFrame);
             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
 
                 // If the bounds are frozen, we still want to translate the window freely and only
index 252bc1e..41eafe7 100644 (file)
@@ -711,8 +711,6 @@ class WindowStateAnimator {
 
         // Start a new transaction and apply position & offset.
         final int layerStack = w.getDisplayContent().getDisplay().getLayerStack();
-        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
-                "POS " + mTmpSize.left + ", " + mTmpSize.top, false);
         mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
         mLastHidden = true;
 
index fb07512..11f3771 100644 (file)
@@ -119,6 +119,8 @@ class WindowSurfaceController {
             mSurfaceY = top;
 
             try {
+                if (SHOW_TRANSACTIONS) logSurface(
+                        "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
                 mSurfaceControl.setPosition(left, top);
                 mSurfaceControl.setLayerStack(layerStack);
 
@@ -205,6 +207,9 @@ class WindowSurfaceController {
             mSurfaceY = top;
 
             try {
+                if (SHOW_TRANSACTIONS) logSurface(
+                        "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null);
+
                 mSurfaceControl.setPosition(left, top);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Error positioning surface of " + this
index 16e73fc..5302253 100644 (file)
@@ -21,13 +21,14 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.TEXT;
 
-import com.google.android.collect.Sets;
-
 import android.Manifest.permission;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accounts.AccountManager;
@@ -50,10 +51,10 @@ import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
+import android.app.admin.SecurityLog;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.app.admin.SystemUpdatePolicy;
 import android.app.backup.IBackupManager;
-import android.auditing.SecurityLog;
-import android.auditing.SecurityLog.SecurityEvent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -142,6 +143,7 @@ import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
 import com.android.server.pm.UserRestrictionsUtils;
+import com.google.android.collect.Sets;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -484,9 +486,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                 new MonitoringCertNotificationTask().execute(intent);
             }
             if (Intent.ACTION_USER_ADDED.equals(action)) {
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
                 removeUserData(userHandle);
             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
                 synchronized (DevicePolicyManagerService.this) {
@@ -1273,10 +1275,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                     final String adminPackage = aa.info.getPackageName();
                     if (packageName == null || packageName.equals(adminPackage)) {
                         if (mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) == null
-                                || mIPackageManager.getReceiverInfo(
-                                    aa.info.getComponent(),
-                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-                                    userHandle) == null) {
+                                || mIPackageManager.getReceiverInfo(aa.info.getComponent(),
+                                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                                        userHandle) == null) {
                             removed = true;
                             policy.mAdminList.remove(i);
                             policy.mAdminMap.remove(aa.info.getComponent());
@@ -1672,7 +1674,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
             if (mOwners.hasDeviceOwner()) {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true");
                 Slog.i(LOG_TAG, "Set ro.device_owner property to true");
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
                 if (mInjector.securityLogGetLoggingEnabledProperty()) {
                     mSecurityLogMonitor.start();
                 }
@@ -2097,8 +2099,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
         try {
             ai = mIPackageManager.getReceiverInfo(adminName,
                     PackageManager.GET_META_DATA |
-                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
-                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, userHandle);
+                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS |
+                    PackageManager.MATCH_DIRECT_BOOT_AWARE |
+                    PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
         } catch (RemoteException e) {
             // shouldn't happen.
         }
@@ -5612,7 +5615,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
             mOwners.clearDeviceOwner();
             mOwners.writeDeviceOwner();
             updateDeviceOwnerLocked();
-            disableDeviceLoggingIfNotCompliant();
+            disableSecurityLoggingIfNotCompliant();
             // Reactivate backup service.
             long ident = mInjector.binderClearCallingIdentity();
             try {
@@ -7194,11 +7197,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
 
             try {
                 int parentUserId = getProfileParentId(userId);
-                List<ResolveInfo> activitiesToEnable = mIPackageManager.queryIntentActivities(
-                        intent,
-                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-                        parentUserId).getList();
+                List<ResolveInfo> activitiesToEnable = mIPackageManager
+                        .queryIntentActivities(intent,
+                                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                                parentUserId)
+                        .getList();
 
                 if (VERBOSE_LOG) {
                     Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
@@ -8598,15 +8603,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
         return false;
     }
 
-    private synchronized void disableDeviceLoggingIfNotCompliant() {
+    private synchronized void disableSecurityLoggingIfNotCompliant() {
         if (!isDeviceOwnerManagedSingleUserDevice()) {
             mInjector.securityLogSetLoggingEnabledProperty(false);
-            Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device.");
+            Slog.w(LOG_TAG, "Security logging turned off as it's no longer a single user device.");
         }
     }
 
     @Override
-    public void setDeviceLoggingEnabled(ComponentName admin, boolean enabled) {
+    public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
@@ -8624,7 +8629,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     }
 
     @Override
-    public boolean getDeviceLoggingEnabled(ComponentName admin) {
+    public boolean isSecurityLoggingEnabled(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         synchronized (this) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -8633,7 +8638,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrievePreviousDeviceLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
@@ -8648,7 +8653,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrieveDeviceLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
index cacc671..79702a8 100644 (file)
@@ -17,8 +17,8 @@
 package com.android.server.devicepolicy;
 
 import android.app.admin.DeviceAdminReceiver;
-import android.auditing.SecurityLog;
-import android.auditing.SecurityLog.SecurityEvent;
+import android.app.admin.SecurityLog;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.util.Log;
 import android.util.Slog;
 
index 19c073c..5975405 100644 (file)
@@ -28,6 +28,7 @@ import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources.Theme;
+import android.os.BaseBundle;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FactoryTest;
@@ -35,7 +36,6 @@ import android.os.FileUtils;
 import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.PowerManager;
-import android.os.RecoverySystem;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -53,6 +53,7 @@ import com.android.internal.R;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.os.ZygoteInit;
+import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
 import com.android.server.am.ActivityManagerService;
@@ -69,10 +70,9 @@ import com.android.server.hdmi.HdmiControlService;
 import com.android.server.input.InputManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
-import com.android.internal.widget.ILockSettings;
+import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.MediaRouterService;
 import com.android.server.media.MediaSessionService;
-import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.projection.MediaProjectionManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
@@ -271,6 +271,10 @@ public final class SystemServer {
             // explicitly specifying a user.
             Environment.setUserRequired(true);
 
+            // Within the system server, any incoming Bundles should be defused
+            // to avoid throwing BadParcelableException.
+            BaseBundle.setShouldDefuse(true);
+
             // Ensure binder calls into the system always run at foreground priority.
             BinderInternal.disableBackgroundScheduling(true);
 
index 69f12eb..34f2e2e 100644 (file)
@@ -161,9 +161,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
                 assertNull("BUG: only one idle handler allowed", mIdleHandler);
                 mIdleHandler = new IdleHandler() {
                     public boolean queueIdle() {
-                        cv.open();
-                        mIdleHandler = null;
-                        return false;  // Remove the handler.
+                        synchronized (queue) {
+                            cv.open();
+                            mIdleHandler = null;
+                            return false;  // Remove the handler.
+                        }
                     }
                 };
                 queue.addIdleHandler(mIdleHandler);
index 6bcaf4d..5c51139 100644 (file)
@@ -57,6 +57,7 @@ import android.test.InstrumentationTestCase;
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
+import android.util.SparseArray;
 
 import com.android.frameworks.servicestests.R;
 import com.android.internal.util.Preconditions;
@@ -250,6 +251,12 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
             r.run();
             mContext.injectRestoreCallingIdentity(token);
         }
+
+        @Override
+        void wtf(String message, Exception e) {
+            // During tests, WTF is fatal.
+            fail(message + "  exception: " + e);
+        }
     }
 
     /** ShortcutManager with injection override methods. */
@@ -1752,68 +1759,320 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
 
     public void testPinShortcutAndGetPinnedShortcuts() {
         // Create some shortcuts.
-        setCaller(CALLING_PACKAGE_1);
-        final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
-        final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
+            final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+        });
 
-        setCaller(CALLING_PACKAGE_2);
-        final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
-        final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
-        final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
+            final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
+            final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+        });
 
-        setCaller(CALLING_PACKAGE_3);
-        final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2)));
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s3_2)));
+        });
 
         // Pin some.
-        setCaller(LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    Arrays.asList("s2", "s3"), getCallingUser());
 
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                Arrays.asList("s2", "s3"), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    Arrays.asList("s3", "s4", "s5"), getCallingUser());
 
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                Arrays.asList("s3", "s4", "s5"), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
+                    Arrays.asList("s3"), getCallingUser());  // Note ID doesn't exist
+        });
 
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
-                Arrays.asList("s3"), getCallingUser());  // Note ID doesn't exist
+        // Delete some.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+            mManager.deleteDynamicShortcut("s2");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+        });
+
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+            mManager.deleteDynamicShortcut("s3");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+        });
+
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+            mManager.deleteDynamicShortcut("s2");
+            assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+        });
+
+        // Get pinned shortcuts from launcher
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s2");
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3", "s4");
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+                    /* none */);
+        });
+    }
+
+    public void testPinShortcutAndGetPinnedShortcuts_multi() {
+        // Create some shortcuts.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        dumpsysOnLogcat();
+
+        // Pin some.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    Arrays.asList("s3", "s4"), getCallingUser());
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    Arrays.asList("s1", "s2", "s4"), getCallingUser());
+        });
+
+        dumpsysOnLogcat();
 
         // Delete some.
-        setCaller(CALLING_PACKAGE_1);
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
-        mManager.deleteDynamicShortcut("s2");
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+            mManager.deleteDynamicShortcut("s3");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+        });
 
-        setCaller(CALLING_PACKAGE_2);
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
-        mManager.deleteDynamicShortcut("s3");
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+        dumpsysOnLogcat();
 
-        setCaller(CALLING_PACKAGE_3);
-        assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
-        mManager.deleteDynamicShortcut("s2");
-        assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
+            mManager.deleteDynamicShortcut("s1");
+            mManager.deleteDynamicShortcut("s3");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
+        });
+
+        dumpsysOnLogcat();
 
         // Get pinned shortcuts from launcher
-        setCaller(LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2");
+
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2", "s3");
+
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+        });
 
-        // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
-        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
-                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
-                "s2");
+        dumpsysOnLogcat();
 
-        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
-                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
-                "s3", "s4");
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            // Launcher2 still has no pinned ones.
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+                    /* none */);
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+                    /* none */);
 
-        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
-                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
-                /* none */);
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s2");
+
+            // Now pin some.
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    Arrays.asList("s1", "s2"), getCallingUser());
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    Arrays.asList("s1", "s2"), getCallingUser());
+
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+
+            // S1 was not visible to it, so shouldn't be pinned.
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s2");
+        });
+
+        // Re-initialize and load from the files.
+        initService();
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2");
+        });
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s2");
+        });
+
+        // Delete all dynamic.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            mManager.deleteAllDynamicShortcuts();
+
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            mManager.deleteAllDynamicShortcuts();
+
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2", "s1");
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2");
+
+            // from all packages.
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, null,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2", "s3");
+
+            // Update pined.  Note s2 and s3 are actually available, but not visible to this
+            // launcher, so still can't be pinned.
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+                    getCallingUser());
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+        });
+        // Re-publish s1.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
+        });
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+
+            // Now "s1" is visible, so can be pinned.
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+                    getCallingUser());
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s3");
+        });
+
+        // Now clear pinned shortcuts.  First, from launcher 1.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2");
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2");
+        });
+
+        // Clear all pins from launcher 2.
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
     }
 
     public void testCreateShortcutIntent() {
@@ -1880,8 +2139,11 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
     }
 
     public void testLauncherCallback() throws Throwable {
-        LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
 
+        // TODO Add "multi" version -- run the test with two launchers and make sure the callback
+        // argument only contains the ones that are actually visible to each launcher.
+
+        LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
 
         // Set listeners
 
index ea437d0..86518b5 100644 (file)
@@ -444,6 +444,11 @@ public class CarrierConfigManager {
     public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
 
     /**
+     * Flag specifying whether ICCID is showed in SIM Status screen, default to false.
+     */
+    public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
+
+    /**
      * Flag specifying whether an additional (client initiated) intent needs to be sent on System
      * update
      */
@@ -680,6 +685,7 @@ public class CarrierConfigManager {
         sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false);
         sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true);
         sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
+        sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false);
         sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
index 84cffe1..b739ead 100644 (file)
@@ -151,7 +151,7 @@ public class MockContext extends Context {
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
         throw new UnsupportedOperationException();
     }
 
@@ -258,7 +258,7 @@ public class MockContext extends Context {
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
         throw new UnsupportedOperationException();
     }
 
@@ -726,26 +726,26 @@ public class MockContext extends Context {
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
+    public Context createDeviceProtectedStorageContext() {
         throw new UnsupportedOperationException();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public Context createCredentialEncryptedStorageContext() {
+    public Context createCredentialProtectedStorageContext() {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
+    public boolean isDeviceProtectedStorage() {
         throw new UnsupportedOperationException();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public boolean isCredentialEncryptedStorage() {
+    public boolean isCredentialProtectedStorage() {
         throw new UnsupportedOperationException();
     }
 }
index e851c8d..91e891f 100644 (file)
@@ -758,6 +758,12 @@ public class MockPackageManager extends PackageManager {
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void addPreferredActivity(IntentFilter filter,
             int match, ComponentName[] set, ComponentName activity) {
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml
new file mode 100644 (file)
index 0000000..d5d86d8
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 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 android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml
new file mode 100644 (file)
index 0000000..9754e4b
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 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 android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
index 495d620..5856f49 100644 (file)
@@ -35,6 +35,8 @@ import java.text.DecimalFormat;
 public class VectorDrawablePerformance extends Activity {
     private static final String LOGCAT = "VectorDrawable1";
     protected int[] icon = {
+            R.drawable.vector_icon_filltype_nonzero,
+            R.drawable.vector_icon_filltype_evenodd,
             R.drawable.vector_icon_gradient_1,
             R.drawable.vector_icon_gradient_2,
             R.drawable.vector_icon_gradient_3,
index fb2213c..c16de7b 100755 (executable)
@@ -67,6 +67,20 @@ def assert_font_supports_any_of_chars(font, chars):
     sys.exit('None of characters in %s were found in %s' % (chars, font))
 
 
+def assert_font_supports_all_of_chars(font, chars):
+    best_cmap = get_best_cmap(font)
+    for char in chars:
+        assert char in best_cmap, (
+            'U+%04X was not found in %s' % (char, font))
+
+
+def assert_font_supports_none_of_chars(font, chars):
+    best_cmap = get_best_cmap(font)
+    for char in chars:
+        assert char not in best_cmap, (
+            'U+%04X was found in %s' % (char, font))
+
+
 def check_hyphens(hyphens_dir):
     # Find all the scripts that need automatic hyphenation
     scripts = set()
@@ -141,6 +155,93 @@ def parse_fonts_xml(fonts_xml_path):
                 _script_to_font_map[script].add((font_file, index))
 
 
+def check_emoji_availability():
+    emoji_fonts = [font[5] for font in _fallback_chain if 'Zsye' in font[1]]
+    emoji_chars = _emoji_properties['Emoji']
+    for emoji_font in emoji_fonts:
+        assert_font_supports_all_of_chars(emoji_font, emoji_chars)
+
+
+def check_emoji_defaults():
+    default_emoji_chars = _emoji_properties['Emoji_Presentation']
+    missing_text_chars = _emoji_properties['Emoji'] - default_emoji_chars
+    emoji_font_seen = False
+    for name, scripts, variant, weight, style, font in _fallback_chain:
+        if 'Zsye' in scripts:
+            emoji_font_seen = True
+            # No need to check the emoji font
+            continue
+        # For later fonts, we only check them if they have a script
+        # defined, since the defined script may get them to a higher
+        # score even if they appear after the emoji font.
+        if emoji_font_seen and not scripts:
+            continue
+
+        # Check default emoji-style characters
+        assert_font_supports_none_of_chars(font, sorted(default_emoji_chars))
+
+        # Mark default text-style characters appearing in fonts above the emoji
+        # font as seen
+        if not emoji_font_seen:
+            missing_text_chars -= set(get_best_cmap(font))
+
+    # Noto does not have monochrome symbols for Unicode 7.0 wingdings and
+    # webdings
+    missing_text_chars -= _chars_by_age['7.0']
+    # TODO: Remove these after b/26113320 is fixed
+    missing_text_chars -= {
+        0x263A, # WHITE SMILING FACE
+        0x270C, # VICTORY HAND
+        0x2744, # SNOWFLAKE
+        0x2764, # HEAVY BLACK HEART
+    }
+    assert missing_text_chars == set(), (
+        'Text style version of some emoji characters are missing.')
+
+
+# Setting reverse to true returns a dictionary that maps the values to sets of
+# characters, useful for some binary properties. Otherwise, we get a
+# dictionary that maps characters to the property values, assuming there's only
+# one property in the file.
+def parse_unicode_datafile(file_path, reverse=False):
+    if reverse:
+        output_dict = collections.defaultdict(set)
+    else:
+        output_dict = {}
+    with open(file_path) as datafile:
+        for line in datafile:
+            if '#' in line:
+                line = line[:line.index('#')]
+            line = line.strip()
+            if not line:
+                continue
+            char_range, prop = line.split(';')
+            char_range = char_range.strip()
+            prop = prop.strip()
+            if '..' in char_range:
+                char_start, char_end = char_range.split('..')
+            else:
+                char_start = char_end = char_range
+            char_start = int(char_start, 16)
+            char_end = int(char_end, 16)
+            char_range = xrange(char_start, char_end+1)
+            if reverse:
+                output_dict[prop].update(char_range)
+            else:
+                for char in char_range:
+                    assert char not in output_dict
+                    output_dict[char] = prop
+    return output_dict
+
+
+def parse_ucd(ucd_path):
+    global _emoji_properties, _chars_by_age
+    _emoji_properties = parse_unicode_datafile(
+        path.join(ucd_path, 'emoji-data.txt'), reverse=True)
+    _chars_by_age = parse_unicode_datafile(
+        path.join(ucd_path, 'DerivedAge.txt'), reverse=True)
+
+
 def main():
     target_out = sys.argv[1]
     global _fonts_dir
@@ -152,6 +253,11 @@ def main():
     hyphens_dir = path.join(target_out, 'usr', 'hyphen-data')
     check_hyphens(hyphens_dir)
 
+    ucd_path = sys.argv[2]
+    parse_ucd(ucd_path)
+    check_emoji_availability()
+    check_emoji_defaults()
+
 
 if __name__ == '__main__':
     main()
index c7ae6fc..b3f1ee1 100644 (file)
@@ -1258,7 +1258,7 @@ public final class BridgeContext extends Context {
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
         // pass
         return false;
     }
@@ -1451,7 +1451,7 @@ public final class BridgeContext extends Context {
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
         // pass
         return false;
     }
@@ -1838,24 +1838,24 @@ public final class BridgeContext extends Context {
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
+    public Context createDeviceProtectedStorageContext() {
         // pass
         return null;
     }
 
     @Override
-    public Context createCredentialEncryptedStorageContext() {
+    public Context createCredentialProtectedStorageContext() {
         // pass
         return null;
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
+    public boolean isDeviceProtectedStorage() {
         return false;
     }
 
     @Override
-    public boolean isCredentialEncryptedStorage() {
+    public boolean isCredentialProtectedStorage() {
         return false;
     }
 }
index 4039cdf..42c0ae0 100644 (file)
@@ -715,6 +715,10 @@ public class BridgePackageManager extends PackageManager {
     }
 
     @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+    }
+
+    @Override
     public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle userHandle) {
         return false;