Merge "Added a unit test for TaskPersister" into nyc-dev
diff --git a/Android.mk b/Android.mk
index 165aed9..cf6d946 100644
--- a/Android.mk
+++ b/Android.mk
@@ -42,7 +42,7 @@
# 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 \
diff --git a/api/current.txt b/api/current.txt
index 419120f..889ed59 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -443,6 +443,7 @@
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 @@
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 @@
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
@@ -575,7 +576,6 @@
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
@@ -3537,7 +3537,6 @@
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();
@@ -4219,7 +4218,6 @@
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);
@@ -5853,7 +5851,6 @@
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);
@@ -5902,6 +5899,7 @@
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);
@@ -5911,8 +5909,8 @@
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);
@@ -5924,7 +5922,6 @@
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);
@@ -5957,6 +5954,7 @@
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);
@@ -6042,6 +6040,27 @@
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();
@@ -6246,6 +6265,8 @@
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();
@@ -6259,8 +6280,6 @@
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
@@ -6582,31 +6601,6 @@
}
-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 {
@@ -7980,7 +7974,7 @@
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();
@@ -8038,10 +8032,10 @@
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[]);
@@ -8176,7 +8170,7 @@
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();
@@ -8228,9 +8222,9 @@
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);
@@ -9321,10 +9315,9 @@
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;
@@ -9361,8 +9354,8 @@
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;
}
@@ -9833,11 +9826,10 @@
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
@@ -19268,7 +19260,6 @@
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
@@ -29377,10 +29368,6 @@
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);
@@ -29942,7 +29929,7 @@
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";
}
@@ -37919,7 +37906,7 @@
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();
@@ -37970,9 +37957,9 @@
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);
@@ -42599,7 +42586,7 @@
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);
@@ -43696,7 +43683,7 @@
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);
@@ -57462,6 +57449,10 @@
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[]);
diff --git a/api/removed.txt b/api/removed.txt
index 8ac2d63..9b5d3ab 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -17,12 +17,40 @@
}
+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 @@
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();
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 6f0370c..947aa90 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -538,6 +538,7 @@
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 @@
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 @@
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
@@ -670,7 +671,6 @@
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
@@ -3654,7 +3654,6 @@
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();
@@ -4351,7 +4350,6 @@
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);
@@ -5992,7 +5990,6 @@
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();
@@ -6048,6 +6045,7 @@
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);
@@ -6058,8 +6056,8 @@
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);
@@ -6072,7 +6070,6 @@
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);
@@ -6105,6 +6102,7 @@
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);
@@ -6199,6 +6197,27 @@
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();
@@ -6512,6 +6531,8 @@
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();
@@ -6525,8 +6546,6 @@
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
@@ -6849,31 +6868,6 @@
}
-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 {
@@ -8278,8 +8272,8 @@
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();
@@ -8337,11 +8331,11 @@
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[]);
@@ -8485,8 +8479,8 @@
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();
@@ -8538,10 +8532,10 @@
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);
@@ -9644,10 +9638,10 @@
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;
@@ -9684,8 +9678,8 @@
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;
}
@@ -9935,6 +9929,7 @@
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);
@@ -10221,11 +10216,10 @@
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
@@ -20438,7 +20432,6 @@
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
@@ -24714,8 +24707,6 @@
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();
@@ -24767,39 +24758,6 @@
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);
@@ -25726,9 +25684,11 @@
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;
}
@@ -31428,6 +31388,7 @@
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
@@ -31720,10 +31681,6 @@
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);
@@ -32284,9 +32241,9 @@
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";
}
@@ -40663,8 +40620,8 @@
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();
@@ -40715,10 +40672,10 @@
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);
@@ -45354,7 +45311,7 @@
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);
@@ -46452,7 +46409,7 @@
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);
@@ -48706,12 +48663,13 @@
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
@@ -48856,7 +48814,9 @@
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);
@@ -60554,6 +60514,10 @@
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[]);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index caeecf5..8bf59df 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -15,12 +15,40 @@
}
+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 @@
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();
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index ba57039..908a50e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -443,6 +443,7 @@
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 @@
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 @@
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
@@ -575,7 +576,6 @@
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
@@ -3537,7 +3537,6 @@
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();
@@ -4219,7 +4218,6 @@
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);
@@ -5857,7 +5855,6 @@
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);
@@ -5906,6 +5903,7 @@
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);
@@ -5915,8 +5913,8 @@
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);
@@ -5928,7 +5926,6 @@
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);
@@ -5961,6 +5958,7 @@
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);
@@ -6046,6 +6044,27 @@
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();
@@ -6250,6 +6269,8 @@
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();
@@ -6263,8 +6284,6 @@
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
@@ -6586,31 +6605,6 @@
}
-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 {
@@ -7985,7 +7979,7 @@
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();
@@ -8044,10 +8038,10 @@
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[]);
@@ -8182,7 +8176,7 @@
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();
@@ -8235,9 +8229,9 @@
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);
@@ -9330,10 +9324,9 @@
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;
@@ -9370,8 +9363,8 @@
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;
}
@@ -9843,11 +9836,10 @@
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
@@ -19298,7 +19290,6 @@
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();
@@ -19316,7 +19307,6 @@
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);
@@ -29444,10 +29434,6 @@
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);
@@ -30009,7 +29995,7 @@
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";
}
@@ -37991,7 +37977,7 @@
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();
@@ -38043,9 +38029,9 @@
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);
@@ -42673,7 +42659,7 @@
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);
@@ -43770,7 +43756,7 @@
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);
@@ -57536,6 +57522,10 @@
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[]);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 8ac2d63..9b5d3ab 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -17,12 +17,40 @@
}
+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 @@
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();
}
}
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 8bcbf51..7590325 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -305,7 +305,7 @@
}
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);
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 75680e6..4019a56 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -688,7 +688,7 @@
/** {@hide} */
public boolean isEncryptionAware() {
- return mResolveInfo.serviceInfo.encryptionAware;
+ return mResolveInfo.serviceInfo.directBootAware;
}
/**
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a0a599e..cc1d68e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -744,7 +744,7 @@
Activity mParent;
boolean mCalled;
/*package*/ boolean mResumed;
- private boolean mStopped;
+ /*package*/ boolean mStopped;
boolean mFinished;
boolean mStartedActivity;
private boolean mDestroyed;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 060ac5e..dbc6c84 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -379,6 +379,33 @@
? "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 @@
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 @@
// 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);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index cefb22d..5ef03d1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2025,6 +2025,15 @@
}
@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 {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4fccbc9..63a6829 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -400,7 +400,7 @@
*
* @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 @@
}
@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 @@
}
@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;
}
}
@@ -1905,17 +1905,17 @@
}
@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);
}
@@ -1926,13 +1926,13 @@
}
@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
@@ -1944,10 +1944,10 @@
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();
}
@@ -2013,13 +2013,13 @@
// 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;
}
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index c68fd65..e090aa4 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -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.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.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 @@
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 @@
mSharedLibraries = null;
mDataDir = null;
mDataDirFile = null;
- mDeviceEncryptedDataDirFile = null;
- mCredentialEncryptedDataDirFile = null;
+ mDeviceProtectedDataDirFile = null;
+ mCredentialProtectedDataDirFile = null;
mLibDir = null;
mBaseClassLoader = null;
mSecurityViolation = false;
@@ -303,8 +302,8 @@
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 @@
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) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 132b6dd..e9d0846 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3197,6 +3197,7 @@
}
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 @@
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 @@
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 @@
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;
}
}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 3be2cdc..dd70b5d 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -268,7 +268,7 @@
"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 @@
}
/**
- * 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) {
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9094912..b7d9b80 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -25,7 +25,7 @@
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 @@
}
/**
- * 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 setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+ try {
+ mService.setSecurityLoggingEnabled(admin, enabled);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * 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 security logging is enabled by device owner, {@code false} otherwise.
+ * @throws SecurityException if {@code admin} is not a device owner.
+ */
+ public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) {
try {
- mService.setDeviceLoggingEnabled(admin, enabled);
+ return mService.isSecurityLoggingEnabled(admin);
} 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.
- *
- * @param admin Which device owner this request is associated with.
- * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise.
- * @throws SecurityException if {@code admin} is not a device owner.
+ * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+ * @hide
*/
public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
- try {
- return mService.getDeviceLoggingEnabled(admin);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
+ return isSecurityLoggingEnabled(admin);
}
/**
- * 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.
+ * 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 @@
}
/**
+ * 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 @@
* @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 @@
}
/**
+ * 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}.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c38496d..3ba5bd8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -290,10 +290,10 @@
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);
diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
similarity index 98%
rename from core/java/android/auditing/SecurityLog.java
rename to core/java/android/app/admin/SecurityLog.java
index 13823a2..001a81d 100644
--- a/core/java/android/auditing/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -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 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
diff --git a/core/java/android/auditing/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
similarity index 93%
rename from core/java/android/auditing/SecurityLogTags.logtags
rename to core/java/android/app/admin/SecurityLogTags.logtags
index ccc3799..39371c7 100644
--- a/core/java/android/auditing/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -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)
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index aeb3156..801c951 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -18,7 +18,6 @@
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.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 @@
// 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 @@
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 @@
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 @@
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();
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index cdc80e3..478024d 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -19,7 +19,7 @@
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 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 @@
// 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 @@
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();
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index bbfec41..828ac38 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -73,9 +73,32 @@
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 @@
* 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 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 @@
* 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) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c4dfdcf..ca19b9b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -695,20 +695,26 @@
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 @@
@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 @@
/**
* 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 @@
/**
* 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>
- * 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.
+ * 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.
* <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 @@
/**
* 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();
+ }
}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 323c9bf..b2df207 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -33,8 +33,8 @@
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 @@
}
@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 @@
}
@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 @@
}
@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();
}
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 58d75f7..104feb5 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -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.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 @@
* 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 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 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 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
/** @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;
}
/**
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 63a163d..5cd15dd 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -66,10 +66,14 @@
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 @@
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 @@
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 @@
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 @@
descriptionRes = source.readInt();
enabled = (source.readInt() != 0);
exported = (source.readInt() != 0);
- encryptionAware = (source.readInt() != 0);
+ encryptionAware = directBootAware = (source.readInt() != 0);
}
-
+
/**
* @hide
*/
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4899fe5..dabc652 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -316,6 +316,11 @@
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.
*/
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index 44bdf4e..cbeed35 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -62,9 +62,9 @@
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 @@
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 @@
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 @@
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 @@
ai.splitSourceDirs = splitSourceDirs;
ai.splitPublicSourceDirs = splitPublicSourceDirs;
ai.dataDir = dataDir;
- ai.deviceEncryptedDataDir = deviceEncryptedDataDir;
- ai.credentialEncryptedDataDir = credentialEncryptedDataDir;
+ ai.deviceProtectedDataDir = deviceProtectedDataDir;
+ ai.credentialProtectedDataDir = credentialProtectedDataDir;
ai.nativeLibraryDir = nativeLibraryDir;
}
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 8724d5e..d865f345 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -160,7 +160,8 @@
* as defined in {@link #hasShortcutHostPermission()}, will receive it.
*
* @param packageName The name of the package that has the shortcuts.
- * @param shortcuts all shortcuts from the package (dynamic and/or pinned).
+ * @param shortcuts all shortcuts from the package (dynamic and/or pinned). Only "key"
+ * information will be provided, as defined in {@link ShortcutInfo#hasKeyFieldsOnly()}.
* @param user The UserHandle of the profile that generated the change.
*/
public void onShortcutsChanged(@NonNull String packageName,
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 56dcdb7..ed8143e 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1057,8 +1057,13 @@
}
/** {@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} */
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c1017fb..1079f97 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -48,6 +48,7 @@
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 @@
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 @@
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 @@
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 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_DIRECT_BOOT_UNAWARE = 0x00040000;
+
+ /**
+ * 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;
-
- /**
- * Querying flag: include only components which are encryption aware in the
- * returned info, regardless of the current user state.
- */
+ /** @removed */
+ @Deprecated
public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
-
- /**
- * Querying flag: include both encryption aware and unaware components in
- * the returned info, regardless of the current user state.
- */
+ /** @removed */
+ @Deprecated
public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = MATCH_ENCRYPTION_AWARE
| MATCH_ENCRYPTION_UNAWARE;
@@ -401,7 +426,8 @@
* </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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
@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 @@
* @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 @@
* 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 @@
* @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 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 @@
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
@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 @@
* @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 @@
/**
* 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 @@
* @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 @@
*
* @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 @@
* @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 @@
@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 @@
* @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 @@
* 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 @@
* @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 @@
*
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
/**
* 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 @@
* @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 @@
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 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 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
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7d7be9a..db7ca2a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2865,13 +2865,13 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
}
}
- 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 @@
}
}
- 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();
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 38e0044..e85311d 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -23,8 +23,8 @@
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 @@
}
}
- 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;
}
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index bb28bde..6162d1a 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -365,7 +365,8 @@
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);
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index e41136c..ae75e3f 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -46,8 +46,6 @@
* if necessary, and persisted.
*
* We will disallow byte[] icons, because they can easily go over binder size limit.
- *
- * TODO Move save/load to this class
*/
public class ShortcutInfo implements Parcelable {
/* @hide */
@@ -524,7 +522,7 @@
}
/** @hide*/
- public void setFlags(@ShortcutFlags int flags) {
+ public void replaceFlags(@ShortcutFlags int flags) {
mFlags = flags;
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 04e64af..ffd9d89 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1099,6 +1099,11 @@
if (oldHandler == null) {
updateCallbackLocked(callback, handler);
}
+
+ // If not connected to camera service, schedule a reconnect to camera service.
+ if (mCameraService == null) {
+ scheduleCameraServiceReconnectionLocked();
+ }
}
}
@@ -1123,6 +1128,11 @@
if (oldHandler == null) {
updateTorchCallbackLocked(callback, handler);
}
+
+ // If not connected to camera service, schedule a reconnect to camera service.
+ if (mCameraService == null) {
+ scheduleCameraServiceReconnectionLocked();
+ }
}
}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 2dfb061..8582150 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -43,6 +43,16 @@
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 @@
* 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 @@
} else {
rssiCurve = null;
}
+ meteredHint = in.readByte() != 0;
}
@Override
@@ -81,6 +110,7 @@
} else {
out.writeByte((byte) 0);
}
+ out.writeByte((byte) (meteredHint ? 1 : 0));
}
@Override
@@ -90,18 +120,20 @@
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 =
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e1c7ad77..6df2a9d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -477,10 +477,10 @@
* 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();
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index f334e77..1097cad 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -51,7 +51,7 @@
*/
public Bundle() {
super();
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -62,7 +62,7 @@
*/
Bundle(Parcel parcelledData) {
super(parcelledData);
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
if (mParcelledData.hasFileDescriptors()) {
mFlags |= FLAG_HAS_FDS;
}
@@ -70,7 +70,7 @@
/* package */ Bundle(Parcel parcelledData, int length) {
super(parcelledData, length);
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
if (mParcelledData.hasFileDescriptors()) {
mFlags |= FLAG_HAS_FDS;
}
@@ -85,7 +85,7 @@
*/
public Bundle(ClassLoader loader) {
super(loader);
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -96,7 +96,7 @@
*/
public Bundle(int capacity) {
super(capacity);
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -118,7 +118,7 @@
*/
public Bundle(PersistableBundle b) {
super(b);
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -196,7 +196,7 @@
@Override
public void clear() {
super.clear();
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -1122,7 +1122,7 @@
*/
public void readFromParcel(Parcel parcel) {
super.readFromParcelInner(parcel);
- mFlags = FLAG_HAS_FDS_KNOWN;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
if (mParcelledData.hasFileDescriptors()) {
mFlags |= FLAG_HAS_FDS;
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1b79497..dd73e53 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -605,6 +605,30 @@
*/
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 @@
}
}
- 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) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 2a4507c..cb4caea 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -318,6 +318,13 @@
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
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index e2675b1..92e1862 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -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 @@
}
}
- /**
- * 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 @@
}
}
- /**
- * 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 @@
* 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 @@
/**
* 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());
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index ebb12fd..c36680c 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -113,8 +113,8 @@
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 @@
/**
* 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 @@
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;
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 2445bc2..1ec00db 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -38,6 +38,8 @@
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 @@
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 @@
}
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 @@
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 @@
}
private void onStopSample() {
- if (mRingtone != null) {
- mRingtone.stop();
+ synchronized (this) {
+ if (mRingtone != null) {
+ mRingtone.stop();
+ }
}
}
@@ -274,7 +287,9 @@
}
public boolean isSamplePlaying() {
- return mRingtone != null && mRingtone.isPlaying();
+ synchronized (this) {
+ return mRingtone != null && mRingtone.isPlaying();
+ }
}
public void startSample() {
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index def303a..b06d503 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -44,7 +44,8 @@
* Only the system, the default SMS application, and the default phone app
* (See {@link android.telecom.TelecomManager#getDefaultDialerPackage()}), and carrier apps
* (See {@link android.service.carrier.CarrierService}) can read, and write to the blockednumber
- * provider.
+ * provider. However, {@link #canCurrentUserBlockNumbers(Context)} can be accessed by any
+ * application.
* </p>
*
* <h3> Data </h3>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 049d585..5fc2899 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2093,7 +2093,7 @@
*/
public static void clearConfiguration(Configuration inoutConfig) {
inoutConfig.fontScale = 0;
- if (!inoutConfig.userSetLocale) {
+ if (!inoutConfig.userSetLocale && !inoutConfig.getLocales().isEmpty()) {
inoutConfig.setLocales(LocaleList.getEmptyLocaleList());
}
}
diff --git a/core/java/android/speech/tts/AudioPlaybackQueueItem.java b/core/java/android/speech/tts/AudioPlaybackQueueItem.java
index d4fea53..ed7534d 100644
--- a/core/java/android/speech/tts/AudioPlaybackQueueItem.java
+++ b/core/java/android/speech/tts/AudioPlaybackQueueItem.java
@@ -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 @@
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;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index fc075de..1eaa7cf 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -19,7 +19,7 @@
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 @@
/**
* 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 @@
/** 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 @@
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),
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index bfe5c3f..a1bc2d1 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -247,23 +247,22 @@
*/
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 @@
}
}
- 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 @@
}
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);
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index 93a156b..e9153dd 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -1013,7 +1013,7 @@
* @return This instance.
*/
public MeasureBuilder setIntegerPart(long integerPart) {
- return setNumber(String.valueOf(integerPart));
+ return setIntegerPart(String.valueOf(integerPart));
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 55393b1..a7bf73a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10210,44 +10210,38 @@
* 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 @@
// 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 @@
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 @@
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 @@
/*
* 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 @@
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 @@
}
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 @@
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;
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 36a5db1..816d9c4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1291,20 +1291,19 @@
}
@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
@@ -4995,6 +4994,8 @@
if (child.hasFocus()) {
requestChildFocus(child, child.findFocus());
}
+ dispatchVisibilityAggregated(isAttachedToWindow() && getWindowVisibility() == VISIBLE
+ && isShown());
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fecf892..a2295ce 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1472,7 +1472,7 @@
if (viewVisibilityChanged) {
mAttachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility);
- host.dispatchVisibilityAggregated(host, viewVisibility);
+ host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
endDragResizing();
destroyHardwareResources();
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9f05990..63f3744 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -566,8 +566,8 @@
* @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 */
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index df33698..35d3bf9 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -50,7 +50,10 @@
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;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2eb258f..b16508e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -32,6 +32,7 @@
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 @@
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)}.
*
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 3d72260..0751ab0 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -106,6 +106,9 @@
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 @@
* 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 @@
if (!sPackageInfo.packageName.equals(packageName))
return LIBLOAD_WRONG_PACKAGE_NAME;
- return loadNativeLibrary();
+ return loadNativeLibrary(clazzLoader);
}
static WebViewFactoryProvider getProvider() {
@@ -333,15 +337,16 @@
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 @@
}
// 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 @@
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 @@
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);
}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 94d231c..e5b65e7 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -28,6 +28,7 @@
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 void onFinishTemporaryDetach();
public void onActivityResult(int requestCode, int resultCode, Intent data);
+
+ public Handler getHandler(Handler originalHandler);
+
+ public View findFocus(View originalFocusedView);
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 4bcb406..942cbcb 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1827,7 +1827,7 @@
return;
}
- Layout layout = getActiveLayout();
+ Layout layout = mTextView.getLayout();
final int offset = mTextView.getSelectionStart();
final int line = layout.getLineForOffset(offset);
final int top = layout.getLineTop(line);
@@ -2192,27 +2192,35 @@
mCursorDrawable[cursorIndex] = mTextView.getContext().getDrawable(
mTextView.mCursorDrawableRes);
final Drawable drawable = mCursorDrawable[cursorIndex];
- final int left = clampCursorHorizontalPosition(drawable, horizontal);
+ final int left = clampHorizontalPosition(drawable, horizontal);
final int width = drawable.getIntrinsicWidth();
drawable.setBounds(left, top - mTempRect.top, left + width,
bottom + mTempRect.bottom);
}
/**
- * Return clamped position for the cursor. If the cursor is within the boundaries of the view,
- * then it is offset with the left padding of the cursor drawable. If the cursor is at
+ * Return clamped position for the drawable. If the drawable is within the boundaries of the
+ * view, then it is offset with the left padding of the cursor drawable. If the drawable is at
* the beginning or the end of the text then its drawable edge is aligned with left or right of
- * the view boundary.
+ * the view boundary. If the drawable is null, horizontal parameter is aligned to left or right
+ * of the view.
*
- * @param drawable Cursor drawable.
- * @param horizontal Horizontal position for the cursor.
- * @return The clamped horizontal position for the cursor.
+ * @param drawable Drawable. Can be null.
+ * @param horizontal Horizontal position for the drawable.
+ * @return The clamped horizontal position for the drawable.
*/
- private final int clampCursorHorizontalPosition(final Drawable drawable, float
- horizontal) {
+ private int clampHorizontalPosition(@Nullable final Drawable drawable, float horizontal) {
horizontal = Math.max(0.5f, horizontal - 0.5f);
if (mTempRect == null) mTempRect = new Rect();
- drawable.getPadding(mTempRect);
+
+ int drawableWidth = 0;
+ if (drawable != null) {
+ drawable.getPadding(mTempRect);
+ drawableWidth = drawable.getIntrinsicWidth();
+ } else {
+ mTempRect.setEmpty();
+ }
+
int scrollX = mTextView.getScrollX();
float horizontalDiff = horizontal - scrollX;
int viewClippedWidth = mTextView.getWidth() - mTextView.getCompoundPaddingLeft()
@@ -2221,9 +2229,11 @@
final int left;
if (horizontalDiff >= (viewClippedWidth - 1f)) {
// at the rightmost position
- final int cursorWidth = drawable.getIntrinsicWidth();
- left = viewClippedWidth + scrollX - (cursorWidth - mTempRect.right);
- } else if (Math.abs(horizontalDiff) <= 1f) {
+ left = viewClippedWidth + scrollX - (drawableWidth - mTempRect.right);
+ } else if (Math.abs(horizontalDiff) <= 1f ||
+ (TextUtils.isEmpty(mTextView.getText())
+ && (TextView.VERY_WIDE - scrollX) <= (viewClippedWidth + 1f)
+ && horizontal <= 1f)) {
// at the leftmost position
left = scrollX - mTempRect.left;
} else {
@@ -3772,10 +3782,10 @@
+ mHandleHeight);
} else {
// We have a single cursor.
- Layout layout = getActiveLayout();
+ Layout layout = mTextView.getLayout();
int line = layout.getLineForOffset(mTextView.getSelectionStart());
- float primaryHorizontal =
- layout.getPrimaryHorizontal(mTextView.getSelectionStart());
+ float primaryHorizontal = clampHorizontalPosition(null,
+ layout.getPrimaryHorizontal(mTextView.getSelectionStart()));
mSelectionBounds.set(
primaryHorizontal,
layout.getLineTop(line),
@@ -4152,7 +4162,7 @@
prepareCursorControllers();
return;
}
- layout = getActiveLayout();
+ layout = mTextView.getLayout();
boolean offsetChanged = offset != mPreviousOffset;
if (offsetChanged || parentScrolled) {
@@ -4322,19 +4332,6 @@
public void onDetached() {}
}
- /**
- * Returns the active layout (hint or text layout). Note that the text layout can be null.
- */
- private Layout getActiveLayout() {
- Layout layout = mTextView.getLayout();
- Layout hintLayout = mTextView.getHintLayout();
- if (TextUtils.isEmpty(layout.getText()) && hintLayout != null &&
- !TextUtils.isEmpty(hintLayout.getText())) {
- layout = hintLayout;
- }
- return layout;
- }
-
private class InsertionHandleView extends HandleView {
private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000;
private static final int RECENT_CUT_COPY_DURATION = 15 * 1000; // seconds
@@ -4431,7 +4428,7 @@
final Drawable drawable = mCursorCount > 0 ? mCursorDrawable[0] : null;
if (drawable != null) {
final float horizontal = layout.getPrimaryHorizontal(offset);
- return clampCursorHorizontalPosition(drawable, horizontal) + mTempRect.left;
+ return clampHorizontalPosition(drawable, horizontal) + mTempRect.left;
}
return super.getCursorHorizontalPosition(layout, offset);
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 71b5ce9..222a040 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -913,7 +913,9 @@
if (mDrawable != null) {
mDrawable.setCallback(null);
unscheduleDrawable(mDrawable);
- mDrawable.setVisible(false, false);
+ if (isAttachedToWindow()) {
+ mDrawable.setVisible(false, false);
+ }
}
mDrawable = d;
@@ -924,8 +926,9 @@
if (d.isStateful()) {
d.setState(getDrawableState());
}
- d.setVisible(isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown(),
- true);
+ if (isAttachedToWindow()) {
+ d.setVisible(getWindowVisibility() == VISIBLE && isShown(), true);
+ }
d.setLevel(mLevel);
mDrawableWidth = d.getIntrinsicWidth();
mDrawableHeight = d.getIntrinsicHeight();
@@ -1501,10 +1504,10 @@
}
@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);
}
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index dd0f91e..e9fa26c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -617,6 +617,7 @@
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 @@
}
@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;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fbedbda..3195097 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -285,8 +285,8 @@
private static final RectF TEMP_RECTF = new RectF();
- // XXX should be much larger
- private static final int VERY_WIDE = 1024*1024;
+ /** @hide */
+ static final int VERY_WIDE = 1024 * 1024; // XXX should be much larger
private static final int ANIMATED_SCROLL_GAP = 250;
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
@@ -6552,7 +6552,7 @@
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 @@
}
boolean canShare() {
- return canCopy() && isDeviceProvisioned();
+ if (!getContext().canStartActivityForResult() || !isDeviceProvisioned()) {
+ return false;
+ }
+ return canCopy();
}
boolean isDeviceProvisioned() {
@@ -9669,16 +9672,10 @@
}
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() {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 90ee05e..f3ae688 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -854,7 +854,8 @@
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 @@
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 @@
// 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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
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);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8de9c09..d11787d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -107,7 +107,7 @@
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;
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index df48d6d..fbd8fb5 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2073,11 +2073,7 @@
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);
}
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8ef1a22..c6db0ed 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -36,7 +36,7 @@
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 \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 95323f7..7ff38fd5 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -109,7 +109,7 @@
* 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 @@
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),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index fb9b1e5..4001283 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -73,6 +73,9 @@
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
index 0000000..da47c4c
--- /dev/null
+++ b/core/jni/android_app_admin_SecurityLog.cpp
@@ -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
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 3e4e352..1bc4285 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -200,7 +200,7 @@
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 @@
}
return nativeToJavaStatus(
- lpRecorder->start((AudioSystem::sync_event_t)event, triggerSession));
+ lpRecorder->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index c699339..7496124 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -389,7 +389,7 @@
}
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)
{
@@ -1540,7 +1540,7 @@
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
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 302cf63..024c21d 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -235,7 +235,7 @@
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;
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index a9003c1..a7ac5b8 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -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 @@
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 @@
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 @@
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;
};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6444c6c..97a51d5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2959,8 +2959,8 @@
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"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index d0d1d5a..5716823 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -109,13 +109,6 @@
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
@@ -579,10 +572,10 @@
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
@@ -1262,7 +1255,6 @@
<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
@@ -1306,8 +1298,8 @@
<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
@@ -1686,7 +1678,7 @@
<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
@@ -1770,7 +1762,7 @@
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. -->
@@ -1810,7 +1802,7 @@
<attr name="enabled" />
<attr name="exported" />
<attr name="singleUser" />
- <attr name="encryptionAware" />
+ <attr name="directBootAware" />
</declare-styleable>
<!-- The <code>activity</code> tag declares an
@@ -1883,7 +1875,7 @@
<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
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4e8740a..3c5b4c0 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2679,8 +2679,8 @@
<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" />
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index a65a813..e636bc0 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -993,7 +993,7 @@
</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 @@
</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>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 5970a22..a361eda 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -223,6 +223,7 @@
<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 -->
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index bfa2b10..b780778 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -111,7 +111,7 @@
<!-- accessibility test permissions -->
<uses-permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT" />
- <application android:theme="@style/Theme">
+ <application android:theme="@style/Theme" android:supportsRtl="true">
<uses-library android:name="android.test.runner" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
<meta-data
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index cbf17a4..ec8cd71 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -37,6 +37,8 @@
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 @@
/**
* test IPrintManager.getPrintJobInfo
*/
+ @LargeTest
public void testGetPrintJobInfo() throws Exception {
startPrinting();
@@ -274,6 +277,7 @@
/**
* test IPrintManager.getPrintJobInfos
*/
+ @LargeTest
public void testGetPrintJobInfos() throws Exception {
startPrinting();
@@ -301,6 +305,7 @@
/**
* test IPrintManager.print
*/
+ @LargeTest
public void testPrint() throws Exception {
final String name = "dummy print job";
@@ -354,6 +359,7 @@
/**
* test IPrintManager.cancelPrintJob
*/
+ @LargeTest
public void testCancelPrintJob() throws Exception {
startPrinting();
@@ -377,6 +383,7 @@
/**
* test IPrintManager.restartPrintJob
*/
+ @LargeTest
public void testRestartPrintJob() throws Exception {
startPrinting();
@@ -399,6 +406,7 @@
/**
* test IPrintManager.addPrintJobStateChangeListener
*/
+ @MediumTest
public void testAddPrintJobStateChangeListener() throws Exception {
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
@@ -424,6 +432,7 @@
/**
* test IPrintManager.removePrintJobStateChangeListener
*/
+ @MediumTest
public void testRemovePrintJobStateChangeListener() throws Exception {
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
@@ -447,6 +456,7 @@
/**
* test IPrintManager.addPrintServicesChangeListener
*/
+ @MediumTest
public void testAddPrintServicesChangeListener() throws Exception {
final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
@@ -465,6 +475,7 @@
/**
* test IPrintManager.removePrintServicesChangeListener
*/
+ @MediumTest
public void testRemovePrintServicesChangeListener() throws Exception {
final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
@@ -488,6 +499,7 @@
/**
* test IPrintManager.getPrintServices
*/
+ @MediumTest
public void testGetPrintServices() throws Exception {
List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
PrintManager.ALL_SERVICES, mUserId);
@@ -509,6 +521,7 @@
/**
* 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 @@
/**
* test IPrintManager.createPrinterDiscoverySession
*/
+ @MediumTest
public void testCreatePrinterDiscoverySession() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
@@ -573,6 +587,7 @@
/**
* test IPrintManager.startPrinterDiscovery
*/
+ @LargeTest
public void testStartPrinterDiscovery() throws Exception {
startPrinting();
@@ -615,6 +630,7 @@
/**
* test IPrintManager.stopPrinterDiscovery
*/
+ @MediumTest
public void testStopPrinterDiscovery() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
@@ -638,6 +654,7 @@
/**
* test IPrintManager.validatePrinters
*/
+ @LargeTest
public void testValidatePrinters() throws Exception {
startPrinting();
@@ -678,6 +695,7 @@
/**
* test IPrintManager.startPrinterStateTracking
*/
+ @LargeTest
public void testStartPrinterStateTracking() throws Exception {
startPrinting();
@@ -699,6 +717,7 @@
/**
* test IPrintManager.getCustomPrinterIcon
*/
+ @LargeTest
public void testGetCustomPrinterIcon() throws Exception {
startPrinting();
@@ -720,6 +739,7 @@
/**
* test IPrintManager.stopPrinterStateTracking
*/
+ @LargeTest
public void testStopPrinterStateTracking() throws Exception {
startPrinting();
@@ -746,6 +766,7 @@
/**
* test IPrintManager.destroyPrinterDiscoverySession
*/
+ @MediumTest
public void testDestroyPrinterDiscoverySession() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
diff --git a/core/tests/coretests/src/android/widget/EditorCursorTest.java b/core/tests/coretests/src/android/widget/EditorCursorTest.java
index 04c8b8c..6d650ff 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorTest.java
@@ -16,16 +16,34 @@
package android.widget;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
+import android.view.Choreographer;
import android.view.ViewGroup;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnLeft;
+import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnRight;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.isEmptyString;
+import static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.Matchers.sameInstance;
+
public class EditorCursorTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
+
+ private final static String LTR_STRING = "aaaaaaaaaaaaaaaaaaaaaa";
+ private final static String LTR_HINT = "hint";
+ private final static String RTL_STRING = "Ù…Ø±ØØ¨Ø§ الروبوت Ù…Ø±ØØ¨Ø§ الروبوت Ù…Ø±ØØ¨Ø§ الروبوت";
+ private final static String RTL_HINT = "الروبوت";
+ private final static int CURSOR_BLINK_MS = 500;
+
private EditText mEditText;
- private final String RTL_STRING = "Ù…Ø±ØØ¨Ø§ الروبوت Ù…Ø±ØØ¨Ø§ الروبوت Ù…Ø±ØØ¨Ø§ الروبوت";
public EditorCursorTest() {
super(TextViewActivity.class);
@@ -55,110 +73,160 @@
@Override
public void run() {
getActivity().setContentView(layout);
- mEditText.requestFocus();
}
});
getInstrumentation().waitForIdleSync();
+ onView(sameInstance(mEditText)).perform(click());
}
@SmallTest
- public void testCursorIsInViewBoundariesWhenOnRightForLtr() throws Exception {
+ public void testCursorIsInViewBoundariesWhenOnRightForLtr() {
// Asserts that when an EditText has LTR text, and cursor is at the end (right),
// cursor is drawn to the right edge of the view
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mEditText.setText("aaaaaaaaaaaaaaaaaaaaaa");
- int length = mEditText.getText().length();
- mEditText.setSelection(length, length);
- }
- });
- getInstrumentation().waitForIdleSync();
+ setEditTextText(LTR_STRING, LTR_STRING.length());
- Editor editor = mEditText.getEditorForTesting();
- Drawable drawable = editor.getCursorDrawable()[0];
- Rect drawableBounds = drawable.getBounds();
- Rect drawablePadding = new Rect();
- drawable.getPadding(drawablePadding);
-
- // right edge of the view including the scroll
- int maxRight = mEditText.getWidth() - mEditText.getCompoundPaddingRight()
- - mEditText.getCompoundPaddingLeft() + +mEditText.getScrollX();
- int diff = drawableBounds.right - drawablePadding.right - maxRight;
- assertTrue(diff >= 0 && diff <= 1);
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
}
@SmallTest
- public void testCursorIsInViewBoundariesWhenOnLeftForLtr() throws Exception {
+ public void testCursorIsInViewBoundariesWhenOnLeftForLtr() {
// Asserts that when an EditText has LTR text, and cursor is at the beginning,
// cursor is drawn to the left edge of the view
+ setEditTextText(LTR_STRING, 0);
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mEditText.setText("aaaaaaaaaaaaaaaaaaaaaa");
- mEditText.setSelection(0, 0);
- }
- });
- getInstrumentation().waitForIdleSync();
-
- Drawable drawable = mEditText.getEditorForTesting().getCursorDrawable()[0];
- Rect drawableBounds = drawable.getBounds();
- Rect drawablePadding = new Rect();
- drawable.getPadding(drawablePadding);
-
- int diff = drawableBounds.left + drawablePadding.left;
- assertTrue(diff >= 0 && diff <= 1);
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
}
@SmallTest
- public void testCursorIsInViewBoundariesWhenOnRightForRtl() throws Exception {
+ public void testCursorIsInViewBoundariesWhenOnRightForRtl() {
// Asserts that when an EditText has RTL text, and cursor is at the end,
// cursor is drawn to the left edge of the view
+ setEditTextText(RTL_STRING, 0);
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mEditText.setText(RTL_STRING);
- mEditText.setSelection(0, 0);
- }
- });
- getInstrumentation().waitForIdleSync();
-
- Drawable drawable = mEditText.getEditorForTesting().getCursorDrawable()[0];
- Rect drawableBounds = drawable.getBounds();
- Rect drawablePadding = new Rect();
- drawable.getPadding(drawablePadding);
-
- int maxRight = mEditText.getWidth() - mEditText.getCompoundPaddingRight()
- - mEditText.getCompoundPaddingLeft() + mEditText.getScrollX();
-
- int diff = drawableBounds.right - drawablePadding.right - maxRight;
- assertTrue(diff >= 0 && diff <= 1);
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
}
@SmallTest
- public void testCursorIsInViewBoundariesWhenOnLeftForRtl() throws Exception {
+ public void testCursorIsInViewBoundariesWhenOnLeftForRtl() {
// Asserts that when an EditText has RTL text, and cursor is at the beginning,
// cursor is drawn to the right edge of the view
+ setEditTextText(RTL_STRING, RTL_STRING.length());
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+ }
+
+ /* Tests for cursor positioning with hint */
+ @SmallTest
+ public void testCursorIsOnLeft_withFirstStrongLtrAlgorithm() {
+ setEditTextHint(null, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+ assertThat(mEditText.getHint(), nullValue());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+ setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+ setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+ }
+
+ @SmallTest
+ public void testCursorIsOnRight_withFirstStrongRtlAlgorithm() {
+ setEditTextHint(null, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+ assertThat(mEditText.getHint(), nullValue());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+ setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+ setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+ }
+
+ @SmallTest
+ public void testCursorIsOnLeft_withLtrAlgorithm() {
+ setEditTextHint(null, TextView.TEXT_DIRECTION_LTR, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+ assertThat(mEditText.getHint(), nullValue());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+ setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_LTR, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+ setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_LTR, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+ }
+
+ @SmallTest
+ public void testCursorIsOnRight_withRtlAlgorithm() {
+ setEditTextHint(null, TextView.TEXT_DIRECTION_RTL, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+ assertThat(mEditText.getHint(), nullValue());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+ setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_RTL, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+ setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_RTL, 0);
+ assertThat(mEditText.getText().toString(), isEmptyString());
+
+ onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+ }
+
+ private void setEditTextProperties(final String text, final String hint,
+ final Integer textDirection, final Integer selection) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
- mEditText.setText(RTL_STRING);
- int length = mEditText.getText().length();
- mEditText.setSelection(length, length);
+ if (textDirection != null) mEditText.setTextDirection(textDirection);
+ if (text != null) mEditText.setText(text);
+ if (hint != null) mEditText.setHint(hint);
+ if (selection != null) mEditText.setSelection(selection);
}
});
getInstrumentation().waitForIdleSync();
- Drawable drawable = mEditText.getEditorForTesting().getCursorDrawable()[0];
- Rect drawableBounds = drawable.getBounds();
- Rect drawablePadding = new Rect();
- drawable.getPadding(drawablePadding);
-
- int diff = drawableBounds.left - mEditText.getScrollX() + drawablePadding.left;
- assertTrue(diff >= 0 && diff <= 1);
+ // wait for cursor to be drawn. updateCursorPositions function is called during draw() and
+ // only when cursor is visible during blink.
+ final CountDownLatch latch = new CountDownLatch(1);
+ mEditText.postOnAnimationDelayed(new Runnable() {
+ @Override
+ public void run() {
+ latch.countDown();
+ }
+ }, CURSOR_BLINK_MS);
+ try {
+ assertThat("Problem while waiting for the cursor to blink",
+ latch.await(10, TimeUnit.SECONDS), equalTo(true));
+ } catch (Exception e) {
+ fail("Problem while waiting for the cursor to blink");
+ }
}
+ private void setEditTextHint(final String hint, final int textDirection, final int selection) {
+ setEditTextProperties(null, hint, textDirection, selection);
+ }
+
+ private void setEditTextText(final String text, final Integer selection) {
+ setEditTextProperties(text, null, null, selection);
+ }
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 4a4727f..91d57e7 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -16,8 +16,10 @@
package android.widget;
+import static android.support.test.espresso.action.ViewActions.longClick;
import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.onFloatingToolBarItem;
import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex;
@@ -49,6 +51,7 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.text.Selection;
import android.text.Spannable;
+import android.text.InputType;
import android.view.KeyEvent;
import static org.hamcrest.Matchers.anyOf;
@@ -234,6 +237,33 @@
}
@SmallTest
+ public void testToolbarAppearsAfterSelection_withFirstStringLtrAlgorithmAndRtlHint()
+ throws Exception {
+ // after the hint layout change, the floating toolbar was not visible in the case below
+ // this test tests that the floating toolbar is displayed on the screen and is visible to
+ // user.
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ textView.post(new Runnable() {
+ @Override
+ public void run() {
+ textView.setTextDirection(TextView.TEXT_DIRECTION_FIRST_STRONG_LTR);
+ textView.setInputType(InputType.TYPE_CLASS_TEXT);
+ textView.setSingleLine(true);
+ textView.setHint("الروبوت");
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ onView(withId(R.id.textview)).perform(typeTextIntoFocusedView("test"));
+ onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1));
+ onFloatingToolBarItem(withText(com.android.internal.R.string.cut)).perform(click());
+ onView(withId(R.id.textview)).perform(longClick());
+ sleepForFloatingToolbarPopup();
+
+ assertFloatingToolbarIsDisplayed();
+ }
+
+ @SmallTest
public void testToolbarAndInsertionHandle() throws Exception {
final String text = "text";
onView(withId(R.id.textview)).perform(click());
diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
index f02fe00..0f7f359 100644
--- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
+++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
@@ -54,6 +54,16 @@
}
/**
+ * Creates a {@link ViewInteraction} for the floating bar menu item with the given matcher.
+ *
+ * @param matcher The matcher for the menu item.
+ */
+ public static ViewInteraction onFloatingToolBarItem(Matcher<View> matcher) {
+ return onView(matcher)
+ .inRoot(withDecorView(hasDescendant(withTagValue(is(TAG)))));
+ }
+
+ /**
* Asserts that the floating toolbar is displayed on screen.
*
* @throws AssertionError if the assertion fails
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
index 37c7425..6e44cd8 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
@@ -19,15 +19,23 @@
import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
import static com.android.internal.util.Preconditions.checkNotNull;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.number.IsCloseTo.closeTo;
+import android.annotation.IntDef;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.support.test.espresso.NoMatchingViewException;
import android.support.test.espresso.ViewAssertion;
import android.view.View;
+import android.widget.EditText;
import android.widget.TextView;
import junit.framework.AssertionFailedError;
import org.hamcrest.Matcher;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A collection of assertions on a {@link android.widget.TextView}.
*/
@@ -113,6 +121,22 @@
}
/**
+ * Returns a {@link ViewAssertion} that asserts that the EditText insertion pointer is on
+ * the left edge.
+ */
+ public static ViewAssertion hasInsertionPointerOnLeft() {
+ return new CursorPositionAssertion(CursorPositionAssertion.LEFT);
+ }
+
+ /**
+ * Returns a {@link ViewAssertion} that asserts that the EditText insertion pointer is on
+ * the right edge.
+ */
+ public static ViewAssertion hasInsertionPointerOnRight() {
+ return new CursorPositionAssertion(CursorPositionAssertion.RIGHT);
+ }
+
+ /**
* A {@link ViewAssertion} to check the selected text in a {@link TextView}.
*/
private static final class TextSelectionAssertion implements ViewAssertion {
@@ -142,4 +166,54 @@
}
}
}
+
+ /**
+ * {@link ViewAssertion} to check that EditText cursor is on a given position.
+ */
+ static class CursorPositionAssertion implements ViewAssertion {
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({LEFT, RIGHT})
+ public @interface CursorEdgePositionType {}
+ public static final int LEFT = 0;
+ public static final int RIGHT = 1;
+
+ private final int mPosition;
+
+ private CursorPositionAssertion(@CursorEdgePositionType int position) {
+ this.mPosition = position;
+ }
+
+ @Override
+ public void check(View view, NoMatchingViewException exception) {
+ if (!(view instanceof EditText)) {
+ throw new AssertionFailedError("View should be an instance of EditText");
+ }
+ EditText editText = (EditText) view;
+ Drawable drawable = editText.getEditorForTesting().getCursorDrawable()[0];
+ Rect drawableBounds = drawable.getBounds();
+ Rect drawablePadding = new Rect();
+ drawable.getPadding(drawablePadding);
+
+ final int diff;
+ final String positionStr;
+ switch (mPosition) {
+ case LEFT:
+ positionStr = "left";
+ diff = drawableBounds.left - editText.getScrollX() + drawablePadding.left;
+ break;
+ case RIGHT:
+ positionStr = "right";
+ int maxRight = editText.getWidth() - editText.getCompoundPaddingRight()
+ - editText.getCompoundPaddingLeft() + editText.getScrollX();
+ diff = drawableBounds.right - drawablePadding.right - maxRight;
+ break;
+ default:
+ throw new AssertionFailedError("Unknown position for cursor assertion");
+ }
+
+ assertThat("Cursor should be on the " + positionStr, Double.valueOf(diff),
+ closeTo(0f, 1f));
+ }
+ }
}
diff --git a/docs/html/guide/topics/graphics/hardware-accel.jd b/docs/html/guide/topics/graphics/hardware-accel.jd
index e3f1d9e..ca7255b 100644
--- a/docs/html/guide/topics/graphics/hardware-accel.jd
+++ b/docs/html/guide/topics/graphics/hardware-accel.jd
@@ -284,7 +284,7 @@
</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 @@
<td colspan="5" class="s5">Xfermode</td>
</tr>
<tr>
- <td class="label_neg">AvoidXfermode</td>
- <td class="value_neg">✗</td>
- </tr>
- <tr>
- <td class="label_neg">PixelXorXfermode</td>
- <td class="value_neg">✗</td>
- </tr>
- <tr>
<td class="label_neg">PorterDuff.Mode.DARKEN (framebuffer)</td>
<td class="value_neg">✗</td>
</tr>
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3e86e6f..3973f2f 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -17,10 +17,13 @@
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 @@
public final class Outline {
private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
- /** @hide */
- public Path mPath;
+ private static final int MODE_EMPTY = 0;
+ private static final int MODE_RECT = 1;
+ private static final int MODE_CONVEX_PATH = 2;
/** @hide */
- public Rect mRect;
+ @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 final Path mPath = new Path();
+
+ /** @hide */
+ public final Rect mRect = new Rect();
/** @hide */
public float mRadius = RADIUS_UNDEFINED;
/** @hide */
@@ -63,8 +83,9 @@
* @see #isEmpty()
*/
public void setEmpty() {
- mPath = null;
- mRect = null;
+ mMode = MODE_EMPTY;
+ mPath.rewind();
+ mRect.setEmpty();
mRadius = RADIUS_UNDEFINED;
}
@@ -77,7 +98,7 @@
* @see #setEmpty()
*/
public boolean isEmpty() {
- return mRect == null && mPath == null;
+ return mMode == MODE_EMPTY;
}
@@ -90,7 +111,7 @@
* @see {@link android.view.View#setClipToOutline(boolean)}
*/
public boolean canClip() {
- return !isEmpty() && mRect != null;
+ return mMode != MODE_CONVEX_PATH;
}
/**
@@ -122,19 +143,9 @@
* @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 @@
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 @@
* 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 @@
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 @@
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 @@
* 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);
}
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 330dc29..eac9359 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -92,6 +92,8 @@
*/
bool init();
+ bool isInitialized() { return mInitialized; }
+
/**
* Flush the cache.
*
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index fd5856a..50b21a4 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -646,7 +646,9 @@
}
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));
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 114347d..cdbbbab 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -197,7 +197,12 @@
}
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;
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a496b49..c539d63 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -484,6 +484,8 @@
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 @@
#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 */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index cb61e51..6706c30 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -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 @@
}
}
+ // 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 @@
void freePrefetechedLayers();
+ void waitOnFences();
+
EGLint mLastFrameWidth = 0;
EGLint mLastFrameHeight = 0;
@@ -213,6 +221,16 @@
// 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 */
diff --git a/libs/hwui/tests/scripts/prep_volantis.sh b/libs/hwui/tests/scripts/prep_volantis.sh
index 09d4869..0572ee55 100755
--- a/libs/hwui/tests/scripts/prep_volantis.sh
+++ b/libs/hwui/tests/scripts/prep_volantis.sh
@@ -49,6 +49,6 @@
# 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"
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index f147fd4..31555f2 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -316,6 +316,61 @@
<< "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:
diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h
index 6cb23e5..0a7acb0 100644
--- a/libs/hwui/thread/Barrier.h
+++ b/libs/hwui/thread/Barrier.h
@@ -33,11 +33,6 @@
mCondition.signal(mType);
}
- void close() {
- Mutex::Autolock l(mLock);
- mOpened = false;
- }
-
void wait() const {
Mutex::Autolock l(mLock);
while (!mOpened) {
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 11fecfb..a7eb73f 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -47,7 +47,6 @@
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 @@
}
/**
- * 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 @@
gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
gnssMeasurement.mMultipathIndicator = parcel.readInt();
gnssMeasurement.mSnrInDb = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0);
return gnssMeasurement;
}
@@ -845,7 +824,6 @@
parcel.writeDouble(mCarrierPhaseUncertainty);
parcel.writeInt(mMultipathIndicator);
parcel.writeDouble(mSnrInDb);
- parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0));
}
@Override
@@ -880,10 +858,6 @@
mPseudorangeRateMetersPerSecond,
"PseudorangeRateUncertaintyMetersPerSecond",
mPseudorangeRateUncertaintyMetersPerSecond));
- builder.append(String.format(
- format,
- "PseudorangeRateIsCorrected",
- isPseudorangeRateCorrected()));
builder.append(String.format(
format,
@@ -943,7 +917,6 @@
resetCarrierPhaseUncertainty();
setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
resetSnrInDb();
- setPseudorangeRateCorrected(false);
}
private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index ac255c8..e5c0f27 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -286,18 +286,11 @@
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;
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d179171..3c42161 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1076,9 +1076,6 @@
* <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.
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 0f82cfc..ca306cc 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -228,7 +228,7 @@
/**
* Audio session ID
*/
- private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+ private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
/**
* AudioAttributes
*/
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index c5d1120..e1dab09 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -295,7 +295,7 @@
/**
* 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 @@
int bufferSizeInBytes, int mode)
throws IllegalArgumentException {
this(streamType, sampleRateInHz, channelConfig, audioFormat,
- bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE);
+ bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);
}
/**
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 26061e4..346f083 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -508,7 +508,8 @@
* 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
*/
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 89e4577..3eb3359 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -302,7 +302,6 @@
* 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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* 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 @@
* @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 @@
*
* @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 @@
* 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");
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index e9d62de..2fb1a3b 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -906,14 +906,16 @@
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) {
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index fa69135..10efe18 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -351,7 +351,7 @@
priority,
effectCallback,
&lpJniStorage->mCallbackData,
- sessionId,
+ (audio_session_t) sessionId,
0);
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
@@ -819,7 +819,7 @@
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) {
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 3d3adba..f1a8c6f 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -388,7 +388,7 @@
0,
android_media_visualizer_effect_callback,
lpJniStorage,
- sessionId);
+ (audio_session_t) sessionId);
if (lpVisualizer == 0) {
ALOGE("Error creating Visualizer");
goto setup_failure;
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 76c701a..5cfe300 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -105,6 +105,14 @@
/*****************************************************************************/
+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(
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index ccf1501..55d000c 100644
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -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
index 0000000..3f12906
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/Android.mk
@@ -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
index 0000000..1c3ed80
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
@@ -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
index 0000000..d6e8a96
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
@@ -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
index 0000000..21fc52e
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
@@ -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();
+ }
+ }
+}
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index 86087c3..ebb3969 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -21,4 +21,8 @@
<!-- Intentionally unset. Vendors should set this in an overlay. -->
<string name="trusted_quick_viewer_package" translatable="false"></string>
<bool name="list_divider_inset_left">true</bool>
+ <!-- Indicates if the home directory should be hidden in the roots list, that is presented
+ in the drawer/left side panel ) -->
+ <bool name="home_root_hidden">true</bool>
+
</resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index e7406e68..0d098e6 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -211,13 +211,29 @@
<!-- Text in the button asking user to deny access to a given directory. -->
<string name="deny">Deny</string>
<!-- Dialog text shown to users when asking if they want to delete files (a confirmation). -->
- <plurals name="delete_confirmation_message">
- <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
- <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
- </plurals>
<!-- Label text showing user how many items are selected. Can be one or more elements. -->
<plurals name="elements_selected">
<item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> selected</item>
<item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
</plurals>
+
+ <!-- Dialog text shown to users when asking if they want to delete a file (a confirmation) -->
+ <string name="delete_filename_confirmation_message">Delete \"<xliff:g id="name" example="cat.jpg">%1$s</xliff:g>\"?</string>
+ <!-- Dialog text shown to users when asking if they want to delete a folder (a confirmation) -->
+ <string name="delete_foldername_confirmation_message">Delete folder \"<xliff:g id="name" example="Photos">%1$s</xliff:g>\" and its contents?</string>
+ <!-- Dialog text shown to users when asking if they want to delete files (a confirmation). -->
+ <plurals name="delete_files_confirmation_message">
+ <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
+ <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
+ </plurals>
+ <!-- Dialog text shown to users when asking if they want to delete folders (a confirmation). -->
+ <plurals name="delete_folders_confirmation_message">
+ <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> folder and its contents?</item>
+ <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> folders and their contents?</item>
+ </plurals>
+ <!-- Dialog text shown to users when asking if they want to delete mixed type items: files and folders (a confirmation). -->
+ <plurals name="delete_items_confirmation_message">
+ <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> item?</item>
+ <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> items?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index c51cbb3..fe61094 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -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.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 @@
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 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 @@
}
}
+ /**
+ * 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;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 9f83c04..54e6287 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -317,7 +317,10 @@
for (final RootInfo root : roots) {
final RootItem item = new RootItem(root);
- if (root.isLibrary()) {
+
+ if (root.isHome() && isHomeRootHidden(context)) {
+ continue;
+ } else if (root.isLibrary()) {
if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
libraries.add(item);
} else {
@@ -367,6 +370,13 @@
}
}
+ /*
+ * Indicates if the home directory should be hidden in the roots list.
+ */
+ private boolean isHomeRootHidden(Context context) {
+ return context.getResources().getBoolean(R.bool.home_root_hidden);
+ }
+
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Item item = getItem(position);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index b539421..6f1863e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -86,6 +86,11 @@
*/
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 @@
/**
* 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);
@@ -147,6 +151,14 @@
return sCollator.compare(lhs, rhs);
}
+ /**
+ * Compare two strings against each other using system default collator in a
+ * case-insensitive mode.
+ */
+ public static int compareToIgnoreCase(String lhs, String rhs) {
+ return sCollator.compare(lhs, rhs);
+ }
+
public static boolean isHardwareKeyboardAvailable(Context context) {
return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 63a834f..60e4b9a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -688,6 +688,39 @@
}.execute(selected);
}
+ private String generateDeleteMessage(final List<DocumentInfo> docs) {
+ String message;
+ int dirsCount = 0;
+
+ for (DocumentInfo doc : docs) {
+ if (doc.isDirectory()) {
+ ++dirsCount;
+ }
+ }
+
+ if (docs.size() == 1) {
+ // Deleteing 1 file xor 1 folder in cwd
+ message = dirsCount == 0
+ ? getActivity().getString(R.string.delete_filename_confirmation_message,
+ docs.get(0).displayName)
+ : getActivity().getString(R.string.delete_foldername_confirmation_message,
+ docs.get(0).displayName);
+ } else if (dirsCount == 0) {
+ // Deleting only files in cwd
+ message = Shared.getQuantityString(getActivity(),
+ R.plurals.delete_files_confirmation_message, docs.size());
+ } else if (dirsCount == docs.size()) {
+ // Deleting only folders in cwd
+ message = Shared.getQuantityString(getActivity(),
+ R.plurals.delete_folders_confirmation_message, docs.size());
+ } else {
+ // Deleting mixed items (files and folders) in cwd
+ message = Shared.getQuantityString(getActivity(),
+ R.plurals.delete_items_confirmation_message, docs.size());
+ }
+ return message;
+ }
+
private void deleteDocuments(final Selection selected) {
assert(!selected.isEmpty());
@@ -698,11 +731,7 @@
TextView message =
(TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null);
- message.setText(
- Shared.getQuantityString(
- getActivity(),
- R.plurals.delete_confirmation_message,
- docs.size()));
+ message.setText(generateDeleteMessage(docs));
// This "insta-hides" files that are being deleted, because
// the delete operation may be not execute immediately (it
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index c5ee592..179cb9b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -20,8 +20,6 @@
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.os.Bundle;
@@ -48,6 +46,7 @@
@VisibleForTesting
public class Model {
private static final String TAG = "Model";
+ private static final String EMPTY = "";
private boolean mIsLoading;
private List<UpdateListener> mUpdateListeners = new ArrayList<>();
@@ -62,6 +61,13 @@
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 mSizeIndex = -1;
+ private int mLastModifiedIndex = -1;
+
@Nullable String info;
@Nullable String error;
@Nullable DocumentInfo doc;
@@ -72,20 +78,6 @@
*
* @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;
}
@@ -127,6 +119,14 @@
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);
+ mLastModifiedIndex = mCursor.getColumnIndex(Document.COLUMN_LAST_MODIFIED);
+ mSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE);
+
doc = result.doc;
updateModelData();
@@ -173,22 +173,24 @@
for (int pos = 0; pos < mCursorCount; ++pos) {
mCursor.moveToNext();
positions[pos] = pos;
- mIds[pos] = createModelId(mCursor);
- mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
+ // 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.
+ mIds[pos] = createModelId(
+ getStringOrEmpty(mAuthorityIndex), getStringOrEmpty(mDocIdIndex));
+
+ mimeType = getStringOrEmpty(mMimeTypeIndex);
isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
- switch(mSortOrder) {
+ switch (mSortOrder) {
case SORT_ORDER_DISPLAY_NAME:
- final String displayName = getCursorString(
- mCursor, Document.COLUMN_DISPLAY_NAME);
- displayNames[pos] = displayName;
+ displayNames[pos] = getStringOrEmpty(mDisplayNameIndex);
break;
case SORT_ORDER_LAST_MODIFIED:
- longValues[pos] = getLastModified(mCursor);
+ longValues[pos] = getLastModified();
break;
case SORT_ORDER_SIZE:
- longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE);
+ longValues[pos] = getDocSize();
break;
}
}
@@ -244,7 +246,7 @@
} else {
final String lhs = pivotValue;
final String rhs = sortKey[mid];
- compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
+ compare = Shared.compareToIgnoreCase(lhs, rhs);
}
if (compare < 0) {
@@ -365,13 +367,42 @@
}
/**
- * @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.
+ * @return Value of the string column, or an empty string if no value, or empty value.
*/
- long getLastModified(Cursor cursor) {
- long l = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED);
- return (l == -1) ? Long.MAX_VALUE : l;
+ private String getStringOrEmpty(int columnIndex) {
+ if (columnIndex == -1)
+ return EMPTY;
+ final String result = mCursor.getString(columnIndex);
+ return result != null ? result : EMPTY;
+ }
+
+ /**
+ * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
+ * or missing timestamp - these will be replaced with MAX_LONG so that such files get sorted to
+ * the top when sorting by date.
+ */
+ private long getLastModified() {
+ if (mLastModifiedIndex == -1)
+ return Long.MAX_VALUE;
+ try {
+ final long result = mCursor.getLong(mLastModifiedIndex);
+ return result > 0 ? result : Long.MAX_VALUE;
+ } catch (NumberFormatException e) {
+ return Long.MAX_VALUE;
+ }
+ }
+
+ /**
+ * @return Size for the given document. If the size is unknown or invalid, returns 0.
+ */
+ private long getDocSize() {
+ if (mSizeIndex == -1)
+ return 0;
+ try {
+ return mCursor.getLong(mSizeIndex);
+ } catch (NumberFormatException e) {
+ return 0;
+ }
}
public @Nullable Cursor getItem(String modelId) {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index e4afc3d..f294919 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -58,18 +58,23 @@
public void testRootsListed() throws Exception {
initTestFiles();
- bots.roots.openRoot(ROOT_0_ID);
-
// Should also have Drive, but that requires pre-configuration of devices
// We omit for now.
- bots.roots.assertHasRoots(
+ bots.roots.assertRootsPresent(
"Images",
"Videos",
"Audio",
"Downloads",
- "Documents",
ROOT_0_ID,
ROOT_1_ID);
+
+ // Separate logic for "Documents" root, which presence depends on the config setting
+ boolean homeRootHidden = context.getResources().getBoolean(R.bool.home_root_hidden);
+ if (homeRootHidden) {
+ bots.roots.assertRootsAbsent("Documents");
+ } else {
+ bots.roots.assertRootsPresent("Documents");
+ }
}
public void testFilesListed() throws Exception {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
index 356fd01..096af10 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
@@ -69,7 +69,7 @@
mDevice.waitForIdle();
}
- public void assertHasRoots(String... labels) throws UiObjectNotFoundException {
+ public void assertRootsPresent(String... labels) throws UiObjectNotFoundException {
List<String> missing = new ArrayList<>();
for (String label : labels) {
if (!findRoot(label).exists()) {
@@ -82,6 +82,18 @@
}
}
+ public void assertRootsAbsent(String... labels) throws UiObjectNotFoundException {
+ List<String> unexpected = new ArrayList<>();
+ for (String label : labels) {
+ if (findRoot(label).exists()) {
+ unexpected.add(label);
+ }
+ }
+ if (!unexpected.isEmpty()) {
+ Assert.fail("Unexpected roots " + unexpected);
+ }
+ }
+
public void assertHasFocus() {
assertHasFocus(ROOTS_LIST_ID);
}
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 519db66..c2ca998 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -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"/>
diff --git a/packages/ExtShared/AndroidManifest.xml b/packages/ExtShared/AndroidManifest.xml
index e2e81d0..04d865e 100644
--- a/packages/ExtShared/AndroidManifest.xml
+++ b/packages/ExtShared/AndroidManifest.xml
@@ -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"/>
diff --git a/packages/FakeOemFeatures/AndroidManifest.xml b/packages/FakeOemFeatures/AndroidManifest.xml
index fe74ad8..a66521d 100644
--- a/packages/FakeOemFeatures/AndroidManifest.xml
+++ b/packages/FakeOemFeatures/AndroidManifest.xml
@@ -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" />
diff --git a/packages/FusedLocation/AndroidManifest.xml b/packages/FusedLocation/AndroidManifest.xml
index ed84c0d..a8319ab 100644
--- a/packages/FusedLocation/AndroidManifest.xml
+++ b/packages/FusedLocation/AndroidManifest.xml
@@ -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" />
diff --git a/packages/InputDevices/AndroidManifest.xml b/packages/InputDevices/AndroidManifest.xml
index 07885ea..9507c9f 100644
--- a/packages/InputDevices/AndroidManifest.xml
+++ b/packages/InputDevices/AndroidManifest.xml
@@ -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">
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index 54972b4..165fe05 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -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>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
similarity index 83%
rename from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
rename to packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
index 55f55b0..83488cd 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
@@ -14,12 +14,15 @@
* 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.");
+ }
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 4582226..68c1992 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -30,6 +30,8 @@
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 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 @@
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.");
}
- 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]);
+ 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 MtpObjectInfo infoWithHandle =
new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
final String documentId = mDatabase.putNewDocument(
@@ -351,9 +388,12 @@
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);
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 0202343..6fb2a78 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -33,7 +33,6 @@
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 @@
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/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
similarity index 75%
copy from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
copy to packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
index 55f55b0..db7d777 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
@@ -14,12 +14,15 @@
* 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.
+ * Exception thrown when sendObjectInfo failed.
*/
-public class BusyDeviceException extends IOException {
+class SendObjectInfoFailure extends IOException {
+ SendObjectInfoFailure() {
+ super("Failed to MtpDevice#sendObjectInfo.");
+ }
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index afcb457..9c1880a 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -30,8 +30,6 @@
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;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 606f4eb7..645e182 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -20,6 +20,8 @@
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 @@
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();
+ }
+ });
}
}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index e4c2cbc..1aee490 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -687,7 +687,7 @@
<!-- 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>
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 7a1c741..ce69c5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -103,16 +103,6 @@
}
@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) {
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index ba991fb..6c06d05 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -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"
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5b865f9..0c35573 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -113,8 +113,8 @@
<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"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 334035c..073cf14 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -167,8 +167,8 @@
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/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index df46271..c062b6d 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -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
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index 3a7c1d1..567e009 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -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">
diff --git a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
index c5b1a7a..54e97da 100644
--- a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
+++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
@@ -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"
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 75195c4..7460201 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -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" />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d65ab04..eeed0cf 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -155,6 +155,8 @@
<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>
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index b589110..6b153d1 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -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>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 420a939..5295ccb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1432,6 +1432,9 @@
<!-- 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>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2660926..b0c1e95 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -201,8 +201,8 @@
<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">
diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml
index 1fcc9e4..6a72e54 100644
--- a/packages/SystemUI/res/values/values_tv.xml
+++ b/packages/SystemUI/res/values/values_tv.xml
@@ -15,4 +15,5 @@
-->
<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>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 358674c..aa3f6e5 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -535,31 +535,43 @@
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);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 72a59d7..aeca840 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -128,6 +128,7 @@
public void hide(int x, int y) {
if (isShown) {
isShown = false;
+ mToolbar.dismissPopupMenus();
setCustomizing(false);
save();
mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index d9b3b3f..57db3a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -28,6 +28,7 @@
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 @@
@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 @@
super.onSelectedChanged(viewHolder, actionState);
if (mCurrentDrag != null) {
mCurrentDrag.stopDrag();
+ mCurrentDrag = null;
}
if (viewHolder != null) {
mCurrentDrag = (Holder) viewHolder;
mCurrentDrag.startDrag();
}
+ notifyItemChanged(mDividerIndex);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index d864df8..9be24de 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -66,6 +66,7 @@
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 @@
boolean mCanReuseTaskStackViews = true;
boolean mDraggingInRecents;
boolean mLaunchedWhileDocking;
+ private boolean mIsRunningOnTv;
// Task launching
Rect mSearchBarBounds = new Rect();
@@ -230,8 +232,10 @@
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 @@
}
}
+ /**
+ * 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 @@
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 @@
}
/**
+ * 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,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
index 48a1904..365b29d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -29,6 +29,7 @@
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 @@
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);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
index ef8d48e..bd3143f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
@@ -16,10 +16,8 @@
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 @@
};
}
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);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 7d8a3ce..5775b60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -16,8 +16,13 @@
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 @@
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);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 143f160..bb4a771 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -20,6 +20,7 @@
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.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 @@
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 @@
"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 @@
private UserManager mUserManager;
private int mDensity;
+ private KeyguardManager mKeyguardManager;
+ private LockPatternUtils mLockPatternUtils;
+
// UI-specific methods
/**
@@ -499,6 +508,20 @@
);
}
+ } 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 @@
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 @@
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 @@
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 @@
});
a.start();
guts.setExposed(true);
+ row.closeRemoteInput();
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
mNotificationGutsExposed = guts;
}
@@ -1680,7 +1709,6 @@
ActivityManagerNative.getDefault().resumeAppSwitches();
} catch (RemoteException e) {
}
-
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
@@ -1773,8 +1801,22 @@
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 @@
}, 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 @@
/**
* 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;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 246f15e..22bb8eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -579,6 +579,11 @@
}
}
+ public void closeRemoteInput() {
+ mPrivateLayout.closeRemoteInput();
+ mPublicLayout.closeRemoteInput();
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 3b87577..c2df292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -69,6 +69,9 @@
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 @@
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 @@
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();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index e53f044..99896f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -36,7 +36,6 @@
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.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 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 @@
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 @@
mShowMenu = false;
mGestureHelper = new NavigationBarGestureHelper(context);
+ mDensity = context.getResources().getConfiguration().densityDpi;
getIcons(context);
mBarTransitions = new NavigationBarTransitions(this);
@@ -599,6 +598,10 @@
// we are switching to.
setNavigationIconHints(mNavigationIconHints, true);
}
+ if (mDensity != newConfig.densityDpi) {
+ mDensity = newConfig.densityDpi;
+ getIcons(getContext());
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index eb5b57e..95f26d4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -16,24 +16,42 @@
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 @@
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 @@
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() {
+ }
+ };
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index f03d9e9..c6b1cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -69,18 +69,22 @@
@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 @@
}
private void fireCallback(boolean isEnabled) {
- for (Callback callback : mCallbacks) {
- callback.onHotspotChanged(isEnabled);
+ synchronized (mCallbacks) {
+ for (Callback callback : mCallbacks) {
+ callback.onHotspotChanged(isEnabled);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 29b0f4b..3a0336b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -29,8 +29,10 @@
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 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 @@
private RemoteInputController mController;
private NotificationData.Entry mEntry;
+ private LongPressCancelable mLongPressCancelable;
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -226,6 +230,30 @@
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
index 0000000..05f0c07
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
@@ -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();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index d9b78a2..686a712 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -83,7 +83,7 @@
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 @@
}
}
+ @Override
+ public void requestDisallowLongPress() {
+ removeLongPressCallback();
+ }
+
public void removeLongPressCallback() {
mSwipeHelper.removeLongPressCallback();
}
@@ -2691,6 +2696,16 @@
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();
diff --git a/packages/services/Proxy/AndroidManifest.xml b/packages/services/Proxy/AndroidManifest.xml
index 88f8381..51531e3 100644
--- a/packages/services/Proxy/AndroidManifest.xml
+++ b/packages/services/Proxy/AndroidManifest.xml
@@ -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">
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index b4b40ae..9ce81ed2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -56,6 +56,7 @@
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 @@
private final PackageManager mPackageManager;
+ private final PowerManager mPowerManager;
+
private final WindowManagerInternal mWindowManagerService;
private final SecurityPolicy mSecurityPolicy;
@@ -232,6 +235,7 @@
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 @@
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 @@
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 @@
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 @@
}
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);
diff --git a/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java b/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java
index 3469565..e03c16e 100644
--- a/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java
@@ -17,8 +17,10 @@
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 @@
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 @@
* 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 @@
mKeyEventTimeoutHandler =
new Handler(mHandlerToSendKeyEventsToInputFilter.getLooper(), new Callback());
mLock = lock;
+ mPowerManager = powerManager;
}
/**
@@ -165,7 +172,16 @@
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 @@
int policyFlags = pendingEvent.policyFlags | WindowManagerPolicy.FLAG_PASS_TO_USER;
mHandlerToSendKeyEventsToInputFilter
.obtainMessage(mMessageTypeForSendKeyEvent, policyFlags, 0, pendingEvent.event)
- .sendToTarget();
+ .sendToTarget();
} else {
pendingEvent.event.recycle();
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index a4f85db..8febecc 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2487,7 +2487,8 @@
// 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
diff --git a/services/core/Android.mk b/services/core/Android.mk
index aaa2211..99c5dd6 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -7,7 +7,8 @@
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
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index e7db2a8..a94c8b8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -447,8 +447,12 @@
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;
}
@@ -466,7 +470,7 @@
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) {
@@ -880,8 +884,12 @@
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);
@@ -892,7 +900,7 @@
return uidMode;
}
}
- Op op = getOpLocked(code, uid, packageName, false);
+ Op op = getOpLocked(code, uid, resolvedPackageName, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -968,6 +976,7 @@
@Override
public int checkPackage(int uid, String packageName) {
+ Preconditions.checkNotNull(packageName);
synchronized (this) {
if (getOpsRawLocked(uid, packageName, true) != null) {
return AppOpsManager.MODE_ALLOWED;
@@ -981,26 +990,39 @@
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);
@@ -1048,16 +1070,20 @@
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);
@@ -1067,7 +1093,7 @@
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;
}
@@ -1075,12 +1101,13 @@
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;
@@ -1098,9 +1125,16 @@
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;
}
@@ -1116,6 +1150,9 @@
@Override
public int permissionToOpCode(String permission) {
+ if (permission == null) {
+ return AppOpsManager.OP_NONE;
+ }
return AppOpsManager.permissionToOpCode(permission);
}
@@ -1165,15 +1202,6 @@
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) {
@@ -1259,7 +1287,7 @@
}
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;
}
@@ -1317,7 +1345,7 @@
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;
}
@@ -1582,7 +1610,7 @@
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) {
@@ -2103,6 +2131,7 @@
@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) {
@@ -2317,6 +2346,15 @@
}
}
+ 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 {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 9b8f2d2..00a49bd 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -456,6 +456,7 @@
class SettingsObserver extends ContentObserver {
int mUserId;
boolean mRegistered = false;
+ @NonNull
String mLastEnabled = "";
/**
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 4536e04..65a22b9 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -809,7 +809,9 @@
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 {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 329f716..07c10b0 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -49,6 +49,7 @@
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 @@
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 @@
private final Handler mFgHandler;
private final Handler mDaemonHandler;
+ private INetd mNetdService;
+
private IBatteryStats mBatteryStats;
private final Thread mThread;
@@ -306,7 +309,7 @@
}
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 @@
* 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
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 306e933..3eb20a0 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -28,6 +28,7 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
}
- 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 @@
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() {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d4dd505..322df04 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -597,7 +597,7 @@
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 @@
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 @@
* 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 @@
}
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 @@
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 @@
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 @@
|| 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,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6361db5..4f0f770 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -267,7 +267,7 @@
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 @@
mRecentTasks.loadUserRecentsLocked(userId);
}
if (userId == UserHandle.USER_SYSTEM) {
- startPersistentApps(PackageManager.MATCH_ENCRYPTION_UNAWARE);
+ startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
installEncryptionUnawareProviders(userId);
break;
@@ -10961,7 +10961,7 @@
// 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();
@@ -12882,7 +12882,7 @@
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;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index fa62c98..efa7420 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -620,7 +620,8 @@
&& 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);
}
}
}
diff --git a/services/core/java/com/android/server/am/ProcessStartLogger.java b/services/core/java/com/android/server/am/ProcessStartLogger.java
index d2aa966..39fbeb5 100644
--- a/services/core/java/com/android/server/am/ProcessStartLogger.java
+++ b/services/core/java/com/android/server/am/ProcessStartLogger.java
@@ -4,7 +4,7 @@
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;
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index d41e3d8..fb1cda7 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -113,6 +113,7 @@
// on file when we loaded them.
if (mPersistedTaskIds.get(userId) == null) {
mPersistedTaskIds.put(userId, mTaskPersister.loadPersistedTaskIdsForUser(userId));
+ Slog.i(TAG, "Loaded persisted task ids for user " + userId);
}
}
@@ -143,6 +144,12 @@
TaskRecord task = get(i);
if (task.isPersistable && (task.stack == null || !task.stack.isHomeStack())) {
// Set of persisted taskIds for task.userId should not be null here
+ // TODO Investigate why it can happen. For now initialize with an empty set
+ if (mPersistedTaskIds.get(task.userId) == null) {
+ Slog.wtf(TAG, "No task ids found for userId " + task.userId + ". task=" + task
+ + " mPersistedTaskIds=" + mPersistedTaskIds);
+ mPersistedTaskIds.put(task.userId, new SparseBooleanArray());
+ }
mPersistedTaskIds.get(task.userId).put(task.taskId, true);
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5320221..f471af6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1290,7 +1290,7 @@
// 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) {
@@ -1384,8 +1384,13 @@
synchronized (mHdmiPlaybackClient) {
int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
KeyEvent.KEYCODE_VOLUME_UP;
- mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
- mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
+ mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
}
@@ -3361,8 +3366,7 @@
* 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();
@@ -3451,11 +3455,6 @@
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;
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
index 8195319..d62a0b3 100644
--- a/services/core/java/com/android/server/connectivity/ApfFilter.java
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -90,7 +90,7 @@
}
private static final String TAG = "ApfFilter";
- private static final boolean VDBG = true;
+ private static final boolean VDBG = false;
private final ConnectivityService mConnectivityService;
private final NetworkAgentInfo mNai;
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 033a243..3c04b78 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1109,7 +1109,8 @@
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 @@
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) {
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index cee46195..9fd7f90 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -311,10 +311,10 @@
}
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 @@
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);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 3acd2ca..56edcca 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2509,8 +2509,9 @@
// 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();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 703d812..575de16 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -160,6 +160,7 @@
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 @@
// 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 @@
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 @@
private void loadPolicyFile() {
if (DBG) Slog.d(TAG, "loadPolicyFile");
synchronized(mPolicyFile) {
- mBlockedPackages.clear();
FileInputStream infile = null;
try {
@@ -941,7 +918,7 @@
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 @@
}
/**
- * 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 @@
checkCallerIsSystem();
setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
+ mRankingHelper.setEnabled(pkg, uid, enabled);
+ savePolicyFile();
}
/**
@@ -2034,21 +2034,8 @@
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,47 +2162,9 @@
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;
- }
-
/**
* The private API only accessible to the system process.
*/
@@ -3603,6 +3552,9 @@
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) {
@@ -3615,6 +3567,10 @@
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();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index fd96a78..4a41705 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -25,6 +25,11 @@
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.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 @@
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 @@
}
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()) {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 27c8293..13a96ae 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -59,7 +59,8 @@
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";
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 5b0ceca..2f0532a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -218,7 +218,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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;
@@ -537,7 +550,7 @@
}
}
- void postToPackageMonitor(Runnable r) {
+ void postToPackageMonitorHandler(Runnable r) {
mPackageMonitor.getRegisteredHandler().post(r);
}
@@ -681,7 +694,7 @@
@Override
public void onShortcutChanged(@NonNull String packageName,
@UserIdInt int userId) {
- postToPackageMonitor(() -> onShortcutChangedInner(packageName, userId));
+ postToPackageMonitorHandler(() -> onShortcutChangedInner(packageName, userId));
}
private void onShortcutChangedInner(@NonNull String packageName,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 067b59c..c2e0992 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -61,10 +61,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
| 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 @@
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 @@
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 @@
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 ?
@@ -16662,6 +16666,22 @@
}
}
+ @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)
@@ -18370,13 +18390,13 @@
/**
* 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 {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4c77f28..e66ec3c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3048,7 +3048,8 @@
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 @@
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",
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 0641749..e831bb1 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -44,6 +44,7 @@
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
+import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
@@ -96,20 +97,18 @@
/**
* TODO:
*
- * - Detect when already registered instances are passed to APIs again, which might break
- * internal bitmap handling.
+ * - Default launcher check does take a few ms. Worth caching.
*
* - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
* -> Need to scan all packages when a user starts too.
* -> Clear data -> remove all dynamic? but not the pinned?
*
- * - Pinned per each launcher package (multiple launchers)
- *
- * - Make save async (should we?)
- *
* - Scan and remove orphan bitmaps (just in case).
*
* - Backup & restore
+ *
+ * - Detect when already registered instances are passed to APIs again, which might break
+ * internal bitmap handling.
*/
public class ShortcutService extends IShortcutService.Stub {
static final String TAG = "ShortcutService";
@@ -138,7 +137,8 @@
@VisibleForTesting
static final int DEFAULT_ICON_PERSIST_QUALITY = 100;
- private static final int SAVE_DELAY_MS = 5000; // in milliseconds.
+ @VisibleForTesting
+ static final int DEFAULT_SAVE_DELAY_MS = 3000;
@VisibleForTesting
static final String FILENAME_BASE_STATE = "shortcut_service.xml";
@@ -151,33 +151,19 @@
static final String DIRECTORY_BITMAPS = "bitmaps";
- static final String TAG_ROOT = "root";
- static final String TAG_USER = "user";
- static final String TAG_PACKAGE = "package";
- static final String TAG_LAST_RESET_TIME = "last_reset_time";
- static final String TAG_INTENT_EXTRAS = "intent-extras";
- static final String TAG_EXTRAS = "extras";
- static final String TAG_SHORTCUT = "shortcut";
- static final String TAG_LAUNCHER = "launcher";
+ private static final String TAG_ROOT = "root";
+ private static final String TAG_LAST_RESET_TIME = "last_reset_time";
- static final String ATTR_VALUE = "value";
- static final String ATTR_NAME = "name";
- static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
- static final String ATTR_CALL_COUNT = "call-count";
- static final String ATTR_LAST_RESET = "last-reset";
- static final String ATTR_ID = "id";
- static final String ATTR_ACTIVITY = "activity";
- static final String ATTR_TITLE = "title";
- static final String ATTR_INTENT = "intent";
- static final String ATTR_WEIGHT = "weight";
- static final String ATTR_TIMESTAMP = "timestamp";
- static final String ATTR_FLAGS = "flags";
- static final String ATTR_ICON_RES = "icon-res";
- static final String ATTR_BITMAP_PATH = "bitmap-path";
+ private static final String ATTR_VALUE = "value";
@VisibleForTesting
interface ConfigConstants {
/**
+ * Key name for the save delay, in milliseconds. (int)
+ */
+ String KEY_SAVE_DELAY_MILLIS = "save_delay_ms";
+
+ /**
* Key name for the throttling reset interval, in seconds. (long)
*/
String KEY_RESET_INTERVAL_SEC = "reset_interval_sec";
@@ -254,12 +240,22 @@
private CompressFormat mIconPersistFormat;
private int mIconPersistQuality;
+ private int mSaveDelayMillis;
+
private final PackageManagerInternal mPackageManagerInternal;
+ @GuardedBy("mLock")
+ private List<Integer> mDirtyUserIds = new ArrayList<>();
+
public ShortcutService(Context context) {
+ this(context, BackgroundThread.get().getLooper());
+ }
+
+ @VisibleForTesting
+ ShortcutService(Context context, Looper looper) {
mContext = Preconditions.checkNotNull(context);
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
- mHandler = new Handler(BackgroundThread.get().getLooper());
+ mHandler = new Handler(looper);
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
}
@@ -287,7 +283,7 @@
@Override
public void onCleanupUser(int userHandle) {
synchronized (mService.mLock) {
- mService.onCleanupUserInner(userHandle);
+ mService.onCleanupUserLocked(userHandle);
}
}
@@ -318,7 +314,10 @@
}
/** lifecycle event */
- void onCleanupUserInner(int userId) {
+ void onCleanupUserLocked(int userId) {
+ // Save all dirty information.
+ saveDirtyInfo();
+
// Unload
mUsers.delete(userId);
}
@@ -364,6 +363,9 @@
result = false;
}
+ mSaveDelayMillis = (int) parser.getLong(ConfigConstants.KEY_SAVE_DELAY_MILLIS,
+ DEFAULT_SAVE_DELAY_MS);
+
mResetInterval = parser.getLong(
ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
* 1000L;
@@ -505,7 +507,7 @@
void saveBaseStateLocked() {
final AtomicFile file = getBaseStateFile();
if (DEBUG) {
- Slog.i(TAG, "Saving to " + file.getBaseFile());
+ Slog.d(TAG, "Saving to " + file.getBaseFile());
}
FileOutputStream outs = null;
@@ -538,7 +540,7 @@
final AtomicFile file = getBaseStateFile();
if (DEBUG) {
- Slog.i(TAG, "Loading from " + file.getBaseFile());
+ Slog.d(TAG, "Loading from " + file.getBaseFile());
}
try (FileInputStream in = file.openRead()) {
XmlPullParser parser = Xml.newPullParser();
@@ -583,7 +585,7 @@
private void saveUserLocked(@UserIdInt int userId) {
final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
if (DEBUG) {
- Slog.i(TAG, "Saving to " + path);
+ Slog.d(TAG, "Saving to " + path);
}
path.mkdirs();
final AtomicFile file = new AtomicFile(path);
@@ -616,7 +618,7 @@
private UserShortcuts loadUserLocked(@UserIdInt int userId) {
final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
if (DEBUG) {
- Slog.i(TAG, "Loading from " + path);
+ Slog.d(TAG, "Loading from " + path);
}
final AtomicFile file = new AtomicFile(path);
@@ -625,7 +627,7 @@
in = file.openRead();
} catch (FileNotFoundException e) {
if (DEBUG) {
- Slog.i(TAG, "Not found " + path);
+ Slog.d(TAG, "Not found " + path);
}
return null;
}
@@ -646,7 +648,7 @@
Slog.d(TAG, String.format("depth=%d type=%d name=%s",
depth, type, tag));
}
- if ((depth == 1) && TAG_USER.equals(tag)) {
+ if ((depth == 1) && UserShortcuts.TAG_ROOT.equals(tag)) {
ret = UserShortcuts.loadFromXml(parser, userId);
continue;
}
@@ -661,29 +663,58 @@
}
}
- // TODO Actually make it async.
private void scheduleSaveBaseState() {
- synchronized (mLock) {
- saveBaseStateLocked();
- }
+ scheduleSave(UserHandle.USER_NULL); // Special case -- use USER_NULL for base state.
}
- // TODO Actually make it async.
void scheduleSaveUser(@UserIdInt int userId) {
+ scheduleSave(userId);
+ }
+
+ // In order to re-schedule, we need to reuse the same instance, so keep it in final.
+ private final Runnable mSaveDirtyInfoRunner = this::saveDirtyInfo;
+
+ private void scheduleSave(@UserIdInt int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "Scheduling to save for " + userId);
+ }
synchronized (mLock) {
- saveUserLocked(userId);
+ if (!mDirtyUserIds.contains(userId)) {
+ mDirtyUserIds.add(userId);
+ }
+ }
+ // If already scheduled, remove that and re-schedule in N seconds.
+ mHandler.removeCallbacks(mSaveDirtyInfoRunner);
+ mHandler.postDelayed(mSaveDirtyInfoRunner, mSaveDelayMillis);
+ }
+
+ @VisibleForTesting
+ void saveDirtyInfo() {
+ if (DEBUG) {
+ Slog.d(TAG, "saveDirtyInfo");
+ }
+ synchronized (mLock) {
+ for (int i = mDirtyUserIds.size() - 1; i >= 0; i--) {
+ final int userId = mDirtyUserIds.get(i);
+ if (userId == UserHandle.USER_NULL) { // USER_NULL for base state.
+ saveBaseStateLocked();
+ } else {
+ saveUserLocked(userId);
+ }
+ }
+ mDirtyUserIds.clear();
}
}
/** Return the last reset time. */
long getLastResetTimeLocked() {
- updateTimes();
+ updateTimesLocked();
return mRawLastResetTime;
}
/** Return the next reset time. */
long getNextResetTimeLocked() {
- updateTimes();
+ updateTimesLocked();
return mRawLastResetTime + mResetInterval;
}
@@ -694,7 +725,7 @@
/**
* Update the last reset time.
*/
- private void updateTimes() {
+ private void updateTimesLocked() {
final long now = injectCurrentTimeMillis();
@@ -706,13 +737,14 @@
} else if (now < mRawLastResetTime) {
// Clock rewound.
if (isClockValid(now)) {
+ Slog.w(TAG, "Clock rewound");
// TODO Randomize??
mRawLastResetTime = now;
}
} else {
- // TODO Do it properly.
- while ((mRawLastResetTime + mResetInterval) <= now) {
- mRawLastResetTime += mResetInterval;
+ if ((mRawLastResetTime + mResetInterval) <= now) {
+ final long offset = mRawLastResetTime % mResetInterval;
+ mRawLastResetTime = ((now / mResetInterval) * mResetInterval) + offset;
}
}
if (prevLastResetTime != mRawLastResetTime) {
@@ -723,7 +755,7 @@
/** 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 +770,16 @@
/** 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 +1014,11 @@
// 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 +1089,7 @@
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 +1161,7 @@
// 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 +1225,7 @@
fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
// Add it.
- newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
- ps.updateShortcutWithCapping(this, newShortcut);
+ ps.addDynamicShortcut(this, newShortcut);
}
userPackageChanged(packageName, userId);
@@ -1251,7 +1281,8 @@
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 +1437,27 @@
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 +1468,12 @@
}
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 +1486,10 @@
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 +1502,8 @@
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 +1846,14 @@
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();
}
@@ -1882,11 +1924,18 @@
class UserShortcuts {
private static final String TAG = ShortcutService.TAG;
+ static final String TAG_ROOT = "user";
+ private static final String TAG_LAUNCHER = "launcher";
+
+ private static final String ATTR_VALUE = "value";
+
@UserIdInt
final int mUserId;
private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>();
+ private final ArrayMap<String, LauncherShortcuts> mLaunchers = new ArrayMap<>();
+
private ComponentName mLauncherComponent;
public UserShortcuts(int userId) {
@@ -1897,17 +1946,45 @@
return mPackages;
}
- public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
- out.startTag(null, ShortcutService.TAG_USER);
+ public ArrayMap<String, LauncherShortcuts> getLaunchers() {
+ return mLaunchers;
+ }
- ShortcutService.writeTagValue(out, ShortcutService.TAG_LAUNCHER,
+ 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, TAG_ROOT);
+
+ ShortcutService.writeTagValue(out, 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);
}
- out.endTag(null, ShortcutService.TAG_USER);
+ out.endTag(null, TAG_ROOT);
}
public static UserShortcuts loadFromXml(XmlPullParser parser, int userId)
@@ -1924,16 +2001,26 @@
final int depth = parser.getDepth();
final String tag = parser.getName();
switch (tag) {
- case ShortcutService.TAG_LAUNCHER:
+ case TAG_LAUNCHER: {
ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
- parser, ShortcutService.ATTR_VALUE);
+ parser, ATTR_VALUE);
continue;
- case ShortcutService.TAG_PACKAGE:
+ }
+ case PackageShortcuts.TAG_ROOT: {
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 LauncherShortcuts.TAG_ROOT: {
+ final LauncherShortcuts shortcuts =
+ LauncherShortcuts.loadFromXml(parser, userId);
+
+ ret.getLaunchers().put(shortcuts.mPackageName, shortcuts);
+ continue;
+ }
}
throw ShortcutService.throwForInvalidTag(depth, tag);
}
@@ -1970,18 +2057,199 @@
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;
+
+ static final String TAG_ROOT = "launcher-pins";
+
+ private static final String TAG_PACKAGE = "package";
+ private static final String TAG_PIN = "pin";
+
+ private static final String ATTR_VALUE = "value";
+ private static final String ATTR_PACKAGE_NAME = "package-name";
+
+ @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, TAG_ROOT);
+ ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
+ mPackageName);
+
+ final int size = mPinnedShortcuts.size();
+ for (int i = 0; i < size; i++) {
+ out.startTag(null, TAG_PACKAGE);
+ ShortcutService.writeAttr(out, 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, TAG_PIN, ids.valueAt(j));
+ }
+ out.endTag(null, TAG_PACKAGE);
+ }
+
+ out.endTag(null, TAG_ROOT);
+ }
+
+ /**
+ * Load.
+ */
+ public static LauncherShortcuts loadFromXml(XmlPullParser parser, int userId)
+ throws IOException, XmlPullParserException {
+ final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
+ 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 TAG_PACKAGE: {
+ final String packageName = ShortcutService.parseStringAttribute(parser,
+ ATTR_PACKAGE_NAME);
+ ids = new ArraySet<>();
+ ret.mPinnedShortcuts.put(packageName, ids);
+ continue;
+ }
+ case TAG_PIN: {
+ ids.add(ShortcutService.parseStringAttribute(parser,
+ 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).
*/
class PackageShortcuts {
private static final String TAG = ShortcutService.TAG;
+ static final String TAG_ROOT = "package";
+ private static final String TAG_INTENT_EXTRAS = "intent-extras";
+ private static final String TAG_EXTRAS = "extras";
+ private static final String TAG_SHORTCUT = "shortcut";
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
+ private static final String ATTR_CALL_COUNT = "call-count";
+ private static final String ATTR_LAST_RESET = "last-reset";
+ private static final String ATTR_ID = "id";
+ private static final String ATTR_ACTIVITY = "activity";
+ private static final String ATTR_TITLE = "title";
+ private static final String ATTR_INTENT = "intent";
+ private static final String ATTR_WEIGHT = "weight";
+ private static final String ATTR_TIMESTAMP = "timestamp";
+ private static final String ATTR_FLAGS = "flags";
+ private static final String ATTR_ICON_RES = "icon-res";
+ private static final String ATTR_BITMAP_PATH = "bitmap-path";
+
@UserIdInt
final int mUserId;
@@ -2039,27 +2307,34 @@
*
* 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 +2363,9 @@
}
}
+ /**
+ * 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 +2374,9 @@
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 +2393,40 @@
}
}
- 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);
}
@@ -2141,12 +2438,19 @@
final long now = s.injectCurrentTimeMillis();
if (ShortcutService.isClockValid(now) && mLastResetTime > now) {
- // Clock rewound. // TODO Test it
+ Slog.w(TAG, "Clock rewound");
+ // Clock rewound.
mLastResetTime = now;
+ mApiCallCount = 0;
+ return mApiCallCount;
}
// If not reset yet, then reset.
if (mLastResetTime < last) {
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format("My last reset=%d, now=%d, last=%d: resetting",
+ mLastResetTime, now, last));
+ }
mApiCallCount = 0;
mLastResetTime = last;
}
@@ -2173,12 +2477,40 @@
/**
* 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 +2520,8 @@
}
public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.println();
+
pw.print(prefix);
pw.print("Package: ");
pw.print(mPackageName);
@@ -2235,58 +2569,58 @@
}
public void saveToXml(@NonNull XmlSerializer out) throws IOException, XmlPullParserException {
- out.startTag(null, ShortcutService.TAG_PACKAGE);
+ out.startTag(null, TAG_ROOT);
- ShortcutService.writeAttr(out, ShortcutService.ATTR_NAME, mPackageName);
- ShortcutService.writeAttr(out, ShortcutService.ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
- ShortcutService.writeAttr(out, ShortcutService.ATTR_CALL_COUNT, mApiCallCount);
- ShortcutService.writeAttr(out, ShortcutService.ATTR_LAST_RESET, mLastResetTime);
+ ShortcutService.writeAttr(out, ATTR_NAME, mPackageName);
+ ShortcutService.writeAttr(out, ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
+ ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
+ ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
final int size = mShortcuts.size();
for (int j = 0; j < size; j++) {
saveShortcut(out, mShortcuts.valueAt(j));
}
- out.endTag(null, ShortcutService.TAG_PACKAGE);
+ out.endTag(null, TAG_ROOT);
}
private static void saveShortcut(XmlSerializer out, ShortcutInfo si)
throws IOException, XmlPullParserException {
- out.startTag(null, ShortcutService.TAG_SHORTCUT);
- ShortcutService.writeAttr(out, ShortcutService.ATTR_ID, si.getId());
+ out.startTag(null, TAG_SHORTCUT);
+ ShortcutService.writeAttr(out, ATTR_ID, si.getId());
// writeAttr(out, "package", si.getPackageName()); // not needed
- ShortcutService.writeAttr(out, ShortcutService.ATTR_ACTIVITY, si.getActivityComponent());
+ ShortcutService.writeAttr(out, ATTR_ACTIVITY, si.getActivityComponent());
// writeAttr(out, "icon", si.getIcon()); // We don't save it.
- ShortcutService.writeAttr(out, ShortcutService.ATTR_TITLE, si.getTitle());
- ShortcutService.writeAttr(out, ShortcutService.ATTR_INTENT, si.getIntentNoExtras());
- ShortcutService.writeAttr(out, ShortcutService.ATTR_WEIGHT, si.getWeight());
- ShortcutService.writeAttr(out, ShortcutService.ATTR_TIMESTAMP,
+ ShortcutService.writeAttr(out, ATTR_TITLE, si.getTitle());
+ ShortcutService.writeAttr(out, ATTR_INTENT, si.getIntentNoExtras());
+ ShortcutService.writeAttr(out, ATTR_WEIGHT, si.getWeight());
+ ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
si.getLastChangedTimestamp());
- ShortcutService.writeAttr(out, ShortcutService.ATTR_FLAGS, si.getFlags());
- ShortcutService.writeAttr(out, ShortcutService.ATTR_ICON_RES, si.getIconResourceId());
- ShortcutService.writeAttr(out, ShortcutService.ATTR_BITMAP_PATH, si.getBitmapPath());
+ ShortcutService.writeAttr(out, ATTR_FLAGS, si.getFlags());
+ ShortcutService.writeAttr(out, ATTR_ICON_RES, si.getIconResourceId());
+ ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
- ShortcutService.writeTagExtra(out, ShortcutService.TAG_INTENT_EXTRAS,
+ ShortcutService.writeTagExtra(out, TAG_INTENT_EXTRAS,
si.getIntentPersistableExtras());
- ShortcutService.writeTagExtra(out, ShortcutService.TAG_EXTRAS, si.getExtras());
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
- out.endTag(null, ShortcutService.TAG_SHORTCUT);
+ out.endTag(null, TAG_SHORTCUT);
}
public static PackageShortcuts loadFromXml(XmlPullParser parser, int userId)
throws IOException, XmlPullParserException {
final String packageName = ShortcutService.parseStringAttribute(parser,
- ShortcutService.ATTR_NAME);
+ ATTR_NAME);
final PackageShortcuts ret = new PackageShortcuts(userId, packageName);
ret.mDynamicShortcutCount =
- ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_DYNAMIC_COUNT);
+ ShortcutService.parseIntAttribute(parser, ATTR_DYNAMIC_COUNT);
ret.mApiCallCount =
- ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_CALL_COUNT);
+ ShortcutService.parseIntAttribute(parser, ATTR_CALL_COUNT);
ret.mLastResetTime =
- ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_LAST_RESET);
+ ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
final int outerDepth = parser.getDepth();
int type;
@@ -2298,7 +2632,7 @@
final int depth = parser.getDepth();
final String tag = parser.getName();
switch (tag) {
- case ShortcutService.TAG_SHORTCUT:
+ case TAG_SHORTCUT:
final ShortcutInfo si = parseShortcut(parser, packageName);
// Don't use addShortcut(), we don't need to save the icon.
@@ -2325,17 +2659,17 @@
int iconRes;
String bitmapPath;
- id = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_ID);
+ id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
activityComponent = ShortcutService.parseComponentNameAttribute(parser,
- ShortcutService.ATTR_ACTIVITY);
- title = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_TITLE);
- intent = ShortcutService.parseIntentAttribute(parser, ShortcutService.ATTR_INTENT);
- weight = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_WEIGHT);
+ ATTR_ACTIVITY);
+ title = ShortcutService.parseStringAttribute(parser, ATTR_TITLE);
+ intent = ShortcutService.parseIntentAttribute(parser, ATTR_INTENT);
+ weight = (int) ShortcutService.parseLongAttribute(parser, ATTR_WEIGHT);
lastChangedTimestamp = (int) ShortcutService.parseLongAttribute(parser,
- ShortcutService.ATTR_TIMESTAMP);
- flags = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_FLAGS);
- iconRes = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_ICON_RES);
- bitmapPath = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_BITMAP_PATH);
+ ATTR_TIMESTAMP);
+ flags = (int) ShortcutService.parseLongAttribute(parser, ATTR_FLAGS);
+ iconRes = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES);
+ bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH);
final int outerDepth = parser.getDepth();
int type;
@@ -2351,10 +2685,10 @@
depth, type, tag));
}
switch (tag) {
- case ShortcutService.TAG_INTENT_EXTRAS:
+ case TAG_INTENT_EXTRAS:
intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
continue;
- case ShortcutService.TAG_EXTRAS:
+ case TAG_EXTRAS:
extras = PersistableBundle.restoreFromXml(parser);
continue;
}
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index 57ae523..a47f250 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -138,16 +138,18 @@
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);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 16e73fc..5302253 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,13 +21,14 @@
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.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.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 @@
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 @@
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 @@
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 @@
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 @@
mOwners.clearDeviceOwner();
mOwners.writeDeviceOwner();
updateDeviceOwnerLocked();
- disableDeviceLoggingIfNotCompliant();
+ disableSecurityLoggingIfNotCompliant();
// Reactivate backup service.
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -7194,11 +7197,13 @@
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 @@
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 @@
}
@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 @@
}
@Override
- public ParceledListSlice<SecurityEvent> retrievePreviousDeviceLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
Preconditions.checkNotNull(admin);
ensureDeviceOwnerManagingSingleUser(admin);
@@ -8648,7 +8653,7 @@
}
@Override
- public ParceledListSlice<SecurityEvent> retrieveDeviceLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
Preconditions.checkNotNull(admin);
ensureDeviceOwnerManagingSingleUser(admin);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index cacc671..79702a8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -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;
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 69f12eb..34f2e2e 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -161,9 +161,11 @@
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);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index 6bcaf4d..ad86fd0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -57,6 +57,7 @@
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;
@@ -165,8 +166,8 @@
private final class ShortcutServiceTestable extends ShortcutService {
final ServiceContext mContext;
- public ShortcutServiceTestable(ServiceContext context) {
- super(context);
+ public ShortcutServiceTestable(ServiceContext context, Looper looper) {
+ super(context, looper);
mContext = context;
}
@@ -247,9 +248,20 @@
@Override
void postToHandler(Runnable r) {
final long token = mContext.injectClearCallingIdentity();
- r.run();
+ super.postToHandler(r);
+ try {
+ runTestOnUiThread(() -> {});
+ } catch (Throwable e) {
+ fail("runTestOnUiThread failed: " + e);
+ }
mContext.injectRestoreCallingIdentity(token);
}
+
+ @Override
+ void wtf(String message, Exception e) {
+ // During tests, WTF is fatal.
+ fail(message + " exception: " + e);
+ }
}
/** ShortcutManager with injection override methods. */
@@ -295,7 +307,7 @@
}
@Override
- void postToPackageMonitor(Runnable r) {
+ void postToPackageMonitorHandler(Runnable r) {
final long token = mContext.injectClearCallingIdentity();
r.run();
mContext.injectRestoreCallingIdentity(token);
@@ -361,7 +373,7 @@
private static final int USER_10 = 10;
private static final int USER_11 = 11;
- private static final long START_TIME = 1234560000000L;
+ private static final long START_TIME = 1440000000101L;
private static final long INTERVAL = 10000;
@@ -417,7 +429,7 @@
LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
// Instantiate targets.
- mService = new ShortcutServiceTestable(mServiceContext);
+ mService = new ShortcutServiceTestable(mServiceContext, Looper.getMainLooper());
mManager = new ShortcutManagerTestable(mClientContext, mService);
mInternal = LocalServices.getService(ShortcutServiceInternal.class);
@@ -502,6 +514,7 @@
* For debugging, dump the main state file on logcat.
*/
private void dumpBaseStateFile() {
+ mService.saveDirtyInfo();
dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
+ "/system/" + ShortcutService.FILENAME_BASE_STATE);
}
@@ -510,6 +523,7 @@
* For debugging, dump per-user state file on logcat.
*/
private void dumpUserFile(int userId) {
+ mService.saveDirtyInfo();
dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
+ "/user-" + userId
+ "/" + ShortcutService.FILENAME_USER_PACKAGES);
@@ -883,6 +897,8 @@
dumpBaseStateFile();
+ mService.saveDirtyInfo();
+
// Restore.
initService();
@@ -1118,51 +1134,102 @@
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(2, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
mInjectedCurrentTimeLillis++;
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(1, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
mInjectedCurrentTimeLillis++;
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(0, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Reached the max
mInjectedCurrentTimeLillis++;
assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(0, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Still throttled
mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(0, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Now it should work.
mInjectedCurrentTimeLillis++;
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1))); // fail
assertEquals(2, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
mInjectedCurrentTimeLillis++;
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(1, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
mInjectedCurrentTimeLillis++;
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(0, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
mInjectedCurrentTimeLillis++;
assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(0, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
// 4 days later...
mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL;
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(2, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
- // Make sure getRemainingCallCount() itself gets reset withou calling setDynamicShortcuts().
+ mInjectedCurrentTimeLillis++;
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+ assertEquals(1, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
+
+ // Make sure getRemainingCallCount() itself gets reset without calling setDynamicShortcuts().
mInjectedCurrentTimeLillis = START_TIME + 8 * INTERVAL;
assertEquals(3, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
+
+ mInjectedCurrentTimeLillis++;
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+ assertEquals(2, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
+ }
+
+ public void testThrottling_rewind() {
+ final ShortcutInfo si1 = makeShortcut("shortcut1");
+
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+ assertEquals(2, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+
+ mInjectedCurrentTimeLillis = 12345; // Clock reset!
+
+ // Since the clock looks invalid, the counter shouldn't have reset.
+ assertEquals(2, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+
+ // Forward again. Still haven't reset yet.
+ mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
+ assertEquals(2, mManager.getRemainingCallCount());
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+
+ // Now rewind -- this will reset the counters.
+ mInjectedCurrentTimeLillis = START_TIME - 100000;
+ assertEquals(3, mManager.getRemainingCallCount());
+
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+ assertEquals(2, mManager.getRemainingCallCount());
+
+ // Forward again, should be reset now.
+ mInjectedCurrentTimeLillis += INTERVAL;
+ assertEquals(3, mManager.getRemainingCallCount());
}
public void testThrottling_perPackage() {
@@ -1284,6 +1351,7 @@
"none");
// Re-initialize and load from the files.
+ mService.saveDirtyInfo();
initService();
// Load from launcher.
@@ -1752,68 +1820,321 @@
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.
- setCaller(CALLING_PACKAGE_1);
- assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
- mManager.deleteDynamicShortcut("s2");
- assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+ mManager.deleteDynamicShortcut("s2");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+ });
- setCaller(CALLING_PACKAGE_2);
- assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
- mManager.deleteDynamicShortcut("s3");
- assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ mManager.deleteDynamicShortcut("s3");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ });
- setCaller(CALLING_PACKAGE_3);
- assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
- mManager.deleteDynamicShortcut("s2");
- assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ mManager.deleteDynamicShortcut("s2");
+ assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ });
// Get pinned shortcuts from launcher
- setCaller(LAUNCHER_1);
+ 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");
- // 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_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 */);
+ });
+ }
- 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.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+ mManager.deleteDynamicShortcut("s3");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+ });
+
+ dumpsysOnLogcat();
+
+ 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
+ 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");
+ });
+
+ dumpsysOnLogcat();
+
+ 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(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.
+ mService.saveDirtyInfo();
+ 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 +2201,11 @@
}
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
@@ -2008,6 +2332,7 @@
dumpUserFile(0);
// Restore.
+ mService.saveDirtyInfo();
initService();
assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -2104,6 +2429,7 @@
mService, new ComponentName("pkg1", "class"));
// Restore.
+ mService.saveDirtyInfo();
initService();
// Before the load, the map should be empty.
@@ -2152,7 +2478,7 @@
assertNull(mService.getShortcutsForTest().get(USER_10).getLauncherComponent());
// Try stopping the user
- mService.onCleanupUserInner(USER_10);
+ mService.onCleanupUserLocked(USER_10);
// Now it's unloaded.
assertEquals(1, mService.getShortcutsForTest().size());
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 2ab0525..a965342 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -44,6 +44,7 @@
public static final boolean ERROR = isLoggable(android.util.Log.ERROR);
private static MessageDigest sMessageDigest;
+ private static final Object sMessageDigestLock = new Object();
private Log() {}
@@ -57,7 +58,9 @@
} catch (NoSuchAlgorithmException e) {
md = null;
}
- sMessageDigest = md;
+ synchronized (sMessageDigestLock) {
+ sMessageDigest = md;
+ }
return null;
}
}.execute();
@@ -187,13 +190,15 @@
}
private static String secureHash(byte[] input) {
- if (sMessageDigest != null) {
- sMessageDigest.reset();
- sMessageDigest.update(input);
- byte[] result = sMessageDigest.digest();
- return encodeHex(result);
- } else {
- return "Uninitialized SHA1";
+ synchronized (sMessageDigestLock) {
+ if (sMessageDigest != null) {
+ sMessageDigest.reset();
+ sMessageDigest.update(input);
+ byte[] result = sMessageDigest.digest();
+ return encodeHex(result);
+ } else {
+ return "Uninitialized SHA1";
+ }
}
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 84cffe1..b739ead 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -151,7 +151,7 @@
}
@Override
- public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+ public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
throw new UnsupportedOperationException();
}
@@ -258,7 +258,7 @@
}
@Override
- public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+ public boolean moveDatabaseFrom(Context sourceContext, String name) {
throw new UnsupportedOperationException();
}
@@ -726,26 +726,26 @@
}
@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();
}
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index e851c8d..91e891f 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -758,6 +758,12 @@
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/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index fb172d4..c16de7b 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -164,6 +164,7 @@
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:
@@ -176,32 +177,39 @@
if emoji_font_seen and not scripts:
continue
- if font[1] is None:
- emoji_to_skip = set()
- else:
- # CJK font, skip checking the following characters for now.
- # See b/26153752
- emoji_to_skip = ({
- 0x26BD, # SOCCER BALL
- 0x26BE, # BASEBALL
- 0x1F18E, # NEGATIVE SQUARED AB
- 0x1F201, # SQUARED KATAKANA KOKO
- 0x1F21A, # SQUARED CJK UNIFIED IDEOGRAPH-7121
- 0x1F22F, # SQUARED CJK UNIFIED IDEOGRAPH-6307
- } | set(xrange(0x1F191, 0x1F19A+1))
- | set(xrange(0x1F232, 0x1F236+1))
- | set(xrange(0x1F238, 0x1F23A+1))
- | set(xrange(0x1F250, 0x1F251+1)))
+ # Check default emoji-style characters
+ assert_font_supports_none_of_chars(font, sorted(default_emoji_chars))
- assert_font_supports_none_of_chars(font,
- sorted(default_emoji_chars - emoji_to_skip))
+ # 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.')
-def parse_ucd(ucd_path):
- global _emoji_properties
- _emoji_properties = collections.defaultdict(set)
- with open(path.join(ucd_path, 'emoji-data.txt')) as emoji_data_txt:
- for line in emoji_data_txt:
+# 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()
@@ -216,7 +224,22 @@
char_start = char_end = char_range
char_start = int(char_start, 16)
char_end = int(char_end, 16)
- _emoji_properties[prop].update(xrange(char_start, char_end+1))
+ 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():
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index c7ae6fc..b3f1ee1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1258,7 +1258,7 @@
}
@Override
- public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+ public boolean moveDatabaseFrom(Context sourceContext, String name) {
// pass
return false;
}
@@ -1451,7 +1451,7 @@
}
@Override
- public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+ public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
// pass
return false;
}
@@ -1838,24 +1838,24 @@
}
@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;
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 4039cdf..42c0ae0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -715,6 +715,10 @@
}
@Override
+ public void flushPackageRestrictionsAsUser(int userId) {
+ }
+
+ @Override
public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
UserHandle userHandle) {
return false;