# 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 \
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
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
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
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillColor = 16843780; // 0x1010404
field public static final int fillEnabled = 16843343; // 0x101024f
+ field public static final int fillType = 16844064; // 0x1010520
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
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
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();
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);
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);
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);
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);
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);
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);
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();
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();
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
}
-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 {
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();
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[]);
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();
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);
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;
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;
}
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
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
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);
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";
}
field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+ field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
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();
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);
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);
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);
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[]);
}
+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 {
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();
}
}
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
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
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
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillColor = 16843780; // 0x1010404
field public static final int fillEnabled = 16843343; // 0x101024f
+ field public static final int fillType = 16844064; // 0x1010520
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
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
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();
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);
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();
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);
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);
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);
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);
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();
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();
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
}
-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 {
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();
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[]);
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();
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);
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;
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;
}
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);
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
}
public final class ContextHubManager {
- method public java.lang.Integer[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
+ method public int[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
method public int[] getContextHubHandles();
method public android.hardware.location.ContextHubInfo getContextHubInfo(int);
method public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2
}
- public abstract class ContextHubManager.ContextHubCallback {
- ctor public ContextHubManager.ContextHubCallback();
+ public static abstract class ContextHubManager.ContextHubCallback {
+ ctor protected ContextHubManager.ContextHubCallback();
+ method public abstract void onMessageReceipt(int, int, android.hardware.location.ContextHubMessage);
}
public class ContextHubMessage {
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
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();
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);
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;
}
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
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);
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";
}
field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+ field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
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();
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);
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);
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);
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
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);
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[]);
}
+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 {
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();
}
}
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
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
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
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillColor = 16843780; // 0x1010404
field public static final int fillEnabled = 16843343; // 0x101024f
+ field public static final int fillType = 16844064; // 0x1010520
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
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
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();
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);
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);
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);
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);
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);
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);
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();
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();
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
}
-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 {
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();
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[]);
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();
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);
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;
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;
}
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
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();
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);
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);
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";
}
field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+ field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
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();
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);
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);
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);
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[]);
}
+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 {
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();
}
}
}
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);
/** {@hide} */
public boolean isEncryptionAware() {
- return mResolveInfo.serviceInfo.encryptionAware;
+ return mResolveInfo.serviceInfo.directBootAware;
}
/**
Activity mParent;
boolean mCalled;
/*package*/ boolean mResumed;
- private boolean mStopped;
+ /*package*/ boolean mStopped;
boolean mFinished;
boolean mStartedActivity;
private boolean mDestroyed;
/** @hide */
public ActivityOptions(Bundle opts) {
+ // If the remote side sent us bad parcelables, they won't get the
+ // results they want, which is their loss.
+ opts.setDefusable(true);
+
mPackageName = opts.getString(KEY_PACKAGE_NAME);
try {
mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT);
? "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 {
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) {
// 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);
}
@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 {
*
* @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) {
}
@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
}
@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;
}
}
}
}
try {
- return ActivityManagerNative.getDefault().registerReceiver(
+ final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
+ if (intent != null) {
+ intent.setExtrasClassLoader(getClassLoader());
+ intent.prepareToEnterProcess();
+ }
+ return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@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);
}
}
@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
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();
}
// 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;
}
}
package android.app;
-import android.text.TextUtils;
-import android.util.ArrayMap;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
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;
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 {
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;
mSharedLibraries = null;
mDataDir = null;
mDataDirFile = null;
- mDeviceEncryptedDataDirFile = null;
- mCredentialEncryptedDataDirFile = null;
+ mDeviceProtectedDataDirFile = null;
+ mCredentialProtectedDataDirFile = null;
mLibDir = null;
mBaseClassLoader = null;
mSecurityViolation = false;
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,
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) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
+
+ @Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
+ intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
}
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);
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++) {
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);
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;
}
}
"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)
}
/**
- * 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) {
}
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;
}
/**
- * Called by device owner to control the device logging feature. Logging can only be enabled on
- * single user devices where the sole user is managed by the device owner.
- * <p>
- * Device logs contain various information intended for security auditing purposes. See
- * {@link SecurityEvent} for details.
- * <p>
- * There must be only one user on the device, managed by the device owner. Otherwise a
- * {@link SecurityException} will be thrown.
+ * Called by device owner to control the security logging feature. Logging can only be
+ * enabled on single user devices where the sole user is managed by the device owner.
+ *
+ * <p> Security logs contain various information intended for security auditing purposes.
+ * See {@link SecurityEvent} for details.
+ *
+ * <p>There must be only one user on the device, managed by the device owner.
+ * Otherwise a {@link SecurityException} will be thrown.
*
* @param admin Which device owner this request is associated with.
- * @param enabled whether device logging should be enabled or not.
+ * @param enabled whether security logging should be enabled or not.
* @throws SecurityException if {@code admin} is not a device owner.
- * @see #retrieveDeviceLogs
+ * @see #retrieveSecurityLogs
*/
- public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+ public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
try {
- mService.setDeviceLoggingEnabled(admin, enabled);
+ mService.setSecurityLoggingEnabled(admin, enabled);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
- * Return whether device logging is enabled or not by the device owner.
- * <p>
- * Can only be called by the device owner, otherwise a {@link SecurityException} will be thrown.
+ * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+ * @hide
+ */
+ public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+ setSecurityLoggingEnabled(admin, enabled);
+ }
+
+ /**
+ * Return whether security logging is enabled or not by the device owner.
+ *
+ * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
+ * thrown.
*
* @param admin Which device owner this request is associated with.
- * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise.
+ * @return {@code true} if security logging is enabled by device owner, {@code false} otherwise.
* @throws SecurityException if {@code admin} is not a device owner.
*/
- public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
+ public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) {
try {
- return mService.getDeviceLoggingEnabled(admin);
+ return mService.isSecurityLoggingEnabled(admin);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
- * Called by device owner to retrieve all new device logging entries since the last call to this
- * API after device boots.
- * <p>
- * Access to the logs is rate limited and it will only return new logs after the device owner
- * has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
- * <p>
- * There must be only one user on the device, managed by the device owner. Otherwise a
- * {@link SecurityException} will be thrown.
+ * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+ * @hide
+ */
+ public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
+ return isSecurityLoggingEnabled(admin);
+ }
+
+ /**
+ * Called by device owner to retrieve all new security logging entries since the last call to
+ * this API after device boots.
+ *
+ * <p> Access to the logs is rate limited and it will only return new logs after the device
+ * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
+ *
+ * <p>There must be only one user on the device, managed by the device owner.
+ * Otherwise a {@link SecurityException} will be thrown.
*
* @param admin Which device owner this request is associated with.
- * @return the new batch of device logs which is a list of {@link SecurityEvent}, or
- * {@code null} if rate limitation is exceeded or if logging is currently disabled.
+ * @return the new batch of security logs which is a list of {@link SecurityEvent},
+ * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
* @throws SecurityException if {@code admin} is not a device owner.
*/
- public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
+ public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
try {
- ParceledListSlice<SecurityEvent> list = mService.retrieveDeviceLogs(admin);
+ ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
if (list != null) {
return list.getList();
} else {
}
/**
+ * 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.
*
* @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();
}
/**
+ * 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}.
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);
* limitations under the License.
*/
-package android.auditing;
+package android.app.admin;
import android.annotation.IntDef;
import android.os.Parcel;
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
# 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)
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;
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
// 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();
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();
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();
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();
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;
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
// 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();
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();
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.
* job does not recur periodically.
*/
public long getIntervalMillis() {
- return intervalMillis >= MIN_PERIOD_MILLIS ? intervalMillis : MIN_PERIOD_MILLIS;
+ return intervalMillis >= getMinimumPeriod() ? intervalMillis : getMinimumPeriod();
}
/**
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;
}
* 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) {
}
}
+ /** {@hide} */
+ public void prepareToEnterProcess() {
+ final int size = mItems.size();
+ for (int i = 0; i < size; i++) {
+ final Item item = mItems.get(i);
+ if (item.mIntent != null) {
+ item.mIntent.prepareToEnterProcess();
+ }
+ }
+ }
+
/** @hide */
public void fixUris(int contentUserHint) {
final int size = mItems.size();
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.
@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
/**
* 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
/**
* Return a new Context object for the current Context but whose storage
- * APIs are backed by device-encrypted storage.
+ * APIs are backed by device-protected storage.
+ * <p>
+ * When a device is encrypted, data stored in this location is encrypted
+ * with a key tied to the physical device, and it can be accessed
+ * immediately after the device has booted successfully, both
+ * <em>before and after</em> the user has authenticated with their
+ * credentials (such as a lock pattern or PIN).
* <p>
- * Data stored in device-encrypted storage is typically encrypted with a key
- * tied to the physical device, and it can be accessed when the device has
- * booted successfully, both <em>before and after</em> the user has
- * authenticated with their credentials (such as a lock pattern or PIN).
- * Because device-encrypted data is available before user authentication,
- * you should carefully consider what data you store using this Context.
+ * Because device-protected data is available without user authentication,
+ * you should carefully limit the data you store using this Context. For
+ * example, storing sensitive authentication tokens or passwords in the
+ * device-protected area is strongly discouraged.
* <p>
* If the underlying device does not have the ability to store
- * device-encrypted and credential-encrypted data using different keys, then
- * both storage areas will become available at the same time. They remain
- * two distinct storage areas, and only the window of availability changes.
+ * device-protected and credential-protected data using different keys, then
+ * both storage areas will become available at the same time. They remain as
+ * two distinct storage locations on disk, and only the window of
+ * availability changes.
* <p>
* Each call to this method returns a new instance of a Context object;
* Context objects are not shared, however common state (ClassLoader, other
* Resources for the same configuration) may be so the Context itself can be
* fairly lightweight.
*
- * @see #isDeviceEncryptedStorage()
+ * @see #isDeviceProtectedStorage()
*/
- public abstract Context createDeviceEncryptedStorageContext();
+ public abstract Context createDeviceProtectedStorageContext();
+
+ /** @removed */
+ @Deprecated
+ public Context createDeviceEncryptedStorageContext() {
+ return createDeviceProtectedStorageContext();
+ }
/**
* Return a new Context object for the current Context but whose storage
- * APIs are backed by credential-encrypted storage.
+ * APIs are backed by credential-protected storage. This is the default
+ * storage area for apps unless
+ * {@link android.R.attr#defaultToDeviceProtectedStorage} was requested.
* <p>
- * Data stored in credential-encrypted storage is typically encrypted with a
- * key tied to user credentials, and they can be accessed
+ * When a device is encrypted, data stored in this location is encrypted
+ * with a key tied to user credentials, which can be accessed
* <em>only after</em> the user has entered their credentials (such as a
* lock pattern or PIN).
* <p>
* If the underlying device does not have the ability to store
- * device-encrypted and credential-encrypted data using different keys, then
- * both storage areas will become available at the same time. They remain
- * two distinct storage areas, and only the window of availability changes.
+ * device-protected and credential-protected data using different keys, then
+ * both storage areas will become available at the same time. They remain as
+ * two distinct storage locations on disk, and only the window of
+ * availability changes.
* <p>
* Each call to this method returns a new instance of a Context object;
* Context objects are not shared, however common state (ClassLoader, other
* Resources for the same configuration) may be so the Context itself can be
* fairly lightweight.
*
- * @see #isCredentialEncryptedStorage()
+ * @see #isCredentialProtectedStorage()
* @hide
*/
@SystemApi
- public abstract Context createCredentialEncryptedStorageContext();
+ public abstract Context createCredentialProtectedStorageContext();
+
+ /** @removed */
+ @Deprecated
+ public Context createCredentialEncryptedStorageContext() {
+ return createCredentialProtectedStorageContext();
+ }
/**
* Gets the display adjustments holder for this context. This information
/**
* 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();
+ }
}
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;
}
@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
}
@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
}
@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();
}
}
return mExtras != null && mExtras.hasFileDescriptors();
}
- /** @hide */
+ /** {@hide} */
public void setAllowFds(boolean allowFds) {
if (mExtras != null) {
mExtras.setAllowFds(allowFds);
}
}
+ /** {@hide} */
+ public void setDefusable(boolean defusable) {
+ if (mExtras != null) {
+ mExtras.setDefusable(defusable);
+ }
+ }
+
/**
* Retrieve extended data from the intent.
*
* @hide
*/
public void prepareToEnterProcess() {
+ // We just entered destination process, so we should be able to read all
+ // parcelables inside.
+ setDefusable(true);
+
+ if (mSelector != null) {
+ mSelector.prepareToEnterProcess();
+ }
+ if (mClipData != null) {
+ mClipData.prepareToEnterProcess();
+ }
+
if (mContentUserHint != UserHandle.USER_CURRENT) {
if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
fixUris(mContentUserHint);
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;
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;
* 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
*/
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
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
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;
/**
}
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));
}
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;
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);
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();
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;
}
}
}
/** @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;
}
/**
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() {
descriptionRes = orig.descriptionRes;
enabled = orig.enabled;
exported = orig.exported;
- encryptionAware = orig.encryptionAware;
+ encryptionAware = directBootAware = orig.directBootAware;
}
@Override public CharSequence loadLabel(PackageManager pm) {
pw.println(prefix + "processName=" + processName);
}
pw.println(prefix + "enabled=" + enabled + " exported=" + exported
- + " encryptionAware=" + encryptionAware);
+ + " directBootAware=" + directBootAware);
if (descriptionRes != 0) {
pw.println(prefix + "description=" + descriptionRes);
}
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) {
descriptionRes = source.readInt();
enabled = (source.readInt() != 0);
exported = (source.readInt() != 0);
- encryptionAware = (source.readInt() != 0);
+ encryptionAware = directBootAware = (source.readInt() != 0);
}
-
+
/**
* @hide
*/
*/
ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates);
+ void setHomeActivity(in ComponentName className, int userId);
+
/**
* As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
*/
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.
*/
boolean isPackageDeviceAdminOnAnyUser(String packageName);
List<String> getPreviousCodePaths(in String packageName);
-
}
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.
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;
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);
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;
ai.splitSourceDirs = splitSourceDirs;
ai.splitPublicSourceDirs = splitPublicSourceDirs;
ai.dataDir = dataDir;
- ai.deviceEncryptedDataDir = deviceEncryptedDataDir;
- ai.credentialEncryptedDataDir = credentialEncryptedDataDir;
+ ai.deviceProtectedDataDir = deviceProtectedDataDir;
+ ai.credentialProtectedDataDir = credentialProtectedDataDir;
ai.nativeLibraryDir = nativeLibraryDir;
}
}
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.ExceptionUtils;
-import android.util.Log;
import com.android.internal.util.IndentingPrintWriter;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
* Return list of all known install sessions, regardless of the installer.
*/
public @NonNull List<SessionInfo> getAllSessions() {
- final ApplicationInfo info = mContext.getApplicationInfo();
- if ("com.google.android.googlequicksearchbox".equals(info.packageName)
- && info.versionCode <= 300400110) {
- Log.d(TAG, "Ignoring callback request from old prebuilt");
- return Collections.EMPTY_LIST;
- }
-
try {
return mInstaller.getAllSessions(mUserId).getList();
} catch (RemoteException e) {
* calling thread.
*/
public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
- // TODO: remove this temporary guard once we have new prebuilts
- final ApplicationInfo info = mContext.getApplicationInfo();
- if ("com.google.android.googlequicksearchbox".equals(info.packageName)
- && info.versionCode <= 300400110) {
- Log.d(TAG, "Ignoring callback request from old prebuilt");
- return;
- }
-
synchronized (mDelegates) {
final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
handler.getLooper());
}
/** {@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} */
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;
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
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,
})
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,
})
public static final int MATCH_ALL = 0x00020000;
/**
- * Querying flag: include only components which are encryption unaware in
+ * Querying flag: match components which are direct boot <em>unaware</em> in
* the returned info, regardless of the current user state.
+ * <p>
+ * When neither {@link #MATCH_DIRECT_BOOT_AWARE} nor
+ * {@link #MATCH_DIRECT_BOOT_UNAWARE} are specified, the default behavior is
+ * to match only runnable components based on the user state. For example,
+ * when a user is started but credentials have not been presented yet, the
+ * user is running "locked" and only {@link #MATCH_DIRECT_BOOT_AWARE}
+ * components are returned. Once the user credentials have been presented,
+ * the user is running "unlocked" and both {@link #MATCH_DIRECT_BOOT_AWARE}
+ * and {@link #MATCH_DIRECT_BOOT_UNAWARE} components are returned.
+ *
+ * @see UserManager#isUserUnlocked()
*/
- public static final int MATCH_ENCRYPTION_UNAWARE = 0x00040000;
-
- /**
- * Querying flag: include only components which are encryption aware in the
- * returned info, regardless of the current user state.
- */
- public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
+ public static final int MATCH_DIRECT_BOOT_UNAWARE = 0x00040000;
/**
- * Querying flag: include both encryption aware and unaware components in
+ * Querying flag: match components which are direct boot <em>aware</em> in
* the returned info, regardless of the current user state.
+ * <p>
+ * When neither {@link #MATCH_DIRECT_BOOT_AWARE} nor
+ * {@link #MATCH_DIRECT_BOOT_UNAWARE} are specified, the default behavior is
+ * to match only runnable components based on the user state. For example,
+ * when a user is started but credentials have not been presented yet, the
+ * user is running "locked" and only {@link #MATCH_DIRECT_BOOT_AWARE}
+ * components are returned. Once the user credentials have been presented,
+ * the user is running "unlocked" and both {@link #MATCH_DIRECT_BOOT_AWARE}
+ * and {@link #MATCH_DIRECT_BOOT_UNAWARE} components are returned.
+ *
+ * @see UserManager#isUserUnlocked()
*/
+ public static final int MATCH_DIRECT_BOOT_AWARE = 0x00080000;
+
+ /** @removed */
+ @Deprecated
+ public static final int MATCH_ENCRYPTION_UNAWARE = 0x00040000;
+ /** @removed */
+ @Deprecated
+ public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
+ /** @removed */
+ @Deprecated
public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = MATCH_ENCRYPTION_AWARE
| MATCH_ENCRYPTION_UNAWARE;
* </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;
* 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
* @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
*/
* 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
* @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
*/
@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
* @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
*/
* 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
* @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
*/
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
* @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
* @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,
*
* @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
* @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
*/
@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
* @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,
/**
* 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
* @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
*/
*
* @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
* @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
*/
@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
* @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
* 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
* @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
*/
*
* @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
* @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
*/
*
* @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
* @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,
* @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
* @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(
* @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
* @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
*/
*
* @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
* @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
*/
*
* @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
* @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,
/**
* 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
* @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
*/
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);
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
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
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,
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;
}
}
- 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();
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) {
}
}
- 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();
}
}
- 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();
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;
}
}
- 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;
}
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);
}
}
/** @hide*/
- public void setFlags(@ShortcutFlags int flags) {
+ public void replaceFlags(@ShortcutFlags int flags) {
mFlags = flags;
}
private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
+ private static final Object sLock = new Object();
private static boolean sSensorModuleInitialized = false;
- private static InjectEventQueue mInjectEventQueue = null;
-
- private final Object mLock = new Object();
+ private static InjectEventQueue sInjectEventQueue = null;
private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
/** {@hide} */
public SystemSensorManager(Context context, Looper mainLooper) {
- mMainLooper = mainLooper;
- mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
- mContext = context;
- mNativeInstance = nativeCreate(context.getOpPackageName());
-
- synchronized(mLock) {
+ synchronized(sLock) {
if (!sSensorModuleInitialized) {
sSensorModuleInitialized = true;
nativeClassInit();
}
+ }
- // initialize the sensor list
- for (int index = 0;;++index) {
- Sensor sensor = new Sensor();
- if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
- mFullSensorsList.add(sensor);
- mHandleToSensor.put(sensor.getHandle(), sensor);
- }
+ mMainLooper = mainLooper;
+ mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
+ mContext = context;
+ mNativeInstance = nativeCreate(context.getOpPackageName());
+
+ // initialize the sensor list
+ for (int index = 0;;++index) {
+ Sensor sensor = new Sensor();
+ if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
+ mFullSensorsList.add(sensor);
+ mHandleToSensor.put(sensor.getHandle(), sensor);
}
}
}
protected boolean initDataInjectionImpl(boolean enable) {
- synchronized (mLock) {
+ synchronized (sLock) {
if (enable) {
boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance);
// The HAL does not support injection OR SensorService hasn't been set in DI mode.
return false;
}
// Initialize a client for data_injection.
- if (mInjectEventQueue == null) {
- mInjectEventQueue = new InjectEventQueue(mMainLooper, this,
+ if (sInjectEventQueue == null) {
+ sInjectEventQueue = new InjectEventQueue(mMainLooper, this,
mContext.getPackageName());
}
} else {
// If data injection is being disabled clean up the native resources.
- if (mInjectEventQueue != null) {
- mInjectEventQueue.dispose();
- mInjectEventQueue = null;
+ if (sInjectEventQueue != null) {
+ sInjectEventQueue.dispose();
+ sInjectEventQueue = null;
}
}
return true;
protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
long timestamp) {
- synchronized (mLock) {
- if (mInjectEventQueue == null) {
+ synchronized (sLock) {
+ if (sInjectEventQueue == null) {
Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
return false;
}
- int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
+ int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
timestamp);
// If there are any errors in data injection clean up the native resources.
if (ret != 0) {
- mInjectEventQueue.dispose();
- mInjectEventQueue = null;
+ sInjectEventQueue.dispose();
+ sInjectEventQueue = null;
}
return ret == 0;
}
*
* <p>In particular these formats are converted:
* <ul>
- * <li>ImageFormat.JPEG => HAL_DATASPACE_JFIF
+ * <li>ImageFormat.JPEG => HAL_DATASPACE_V0_JFIF
* <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH
* <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH
* <li>others => HAL_DATASPACE_UNKNOWN
static int imageFormatToDataspace(int format) {
switch (format) {
case ImageFormat.JPEG:
- return HAL_DATASPACE_JFIF;
+ return HAL_DATASPACE_V0_JFIF;
case ImageFormat.DEPTH_POINT_CLOUD:
case ImageFormat.DEPTH16:
return HAL_DATASPACE_DEPTH;
private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159;
+ private static final int HAL_DATASPACE_STANDARD_SHIFT = 16;
+ private static final int HAL_DATASPACE_TRANSFER_SHIFT = 22;
+ private static final int HAL_DATASPACE_RANGE_SHIFT = 27;
+
private static final int HAL_DATASPACE_UNKNOWN = 0x0;
- private static final int HAL_DATASPACE_JFIF = 0x101;
+ private static final int HAL_DATASPACE_V0_JFIF =
+ (2 << HAL_DATASPACE_STANDARD_SHIFT) |
+ (3 << HAL_DATASPACE_TRANSFER_SHIFT) |
+ (1 << HAL_DATASPACE_RANGE_SHIFT);
+
private static final int HAL_DATASPACE_DEPTH = 0x1000;
private static final long DURATION_20FPS_NS = 50000000L;
*/
package android.hardware.location;
-import android.Manifest;
import android.annotation.SystemApi;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.ServiceConnection;
-import android.hardware.location.ContextHubService;
-import android.hardware.location.NanoAppInstanceInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.ServiceManager;
import android.util.Log;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
/**
- * A class that exposes the Context hubs on a device to
- * applicaions.
+ * A class that exposes the Context hubs on a device to applications.
*
- * Please not that this class is not expected to be used by
- * unbundled applications. Also, calling applications are
- * expected to have LOCTION_HARDWARE premissions to use this
- * class.
+ * Please note that this class is not expected to be used by unbundled applications. Also, calling
+ * applications are expected to have LOCATION_HARDWARE permissions to use this class.
*
* @hide
*/
public final class ContextHubManager {
private static final String TAG = "ContextHubManager";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
- private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
- + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
- private final Context mContext;
private final Looper mMainLooper;
private IContextHubService mContextHubService;
- private boolean mContextHubConnected;
private ContextHubCallback mCallback;
private Handler mCallbackHandler;
/**
- * A special context hub identifer meaning any possible hub on
- * the system.
+ * A special context hub identifier meaning any possible hub on the system.
*/
public static final int ANY_HUB = -1;
/**
public static final int MSG_DATA_SEND = 3;
/**
- * an interface to receive asynchronous communication from the context hub
+ * An interface to receive asynchronous communication from the context hub.
*/
- public abstract class ContextHubCallback {
+ public abstract static class ContextHubCallback {
+ protected ContextHubCallback() {}
+
/**
- * callback function called on message receipt from context hub
+ * Callback function called on message receipt from context hub.
*
- * @param hubId id of the hub of the message
- * @param nanoAppId identifier for the app that sent the message
- * @param msg the context hub message
+ * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
+ * @param nanoAppHandle Handle (unique identifier) for the app that sent the message.
+ * @param message The context hub message.
*
* @see ContextHubMessage
*/
- abstract void onMessageReceipt(int hubId, int nanoAppId, ContextHubMessage msg);
+ public abstract void onMessageReceipt(
+ int hubHandle,
+ int nanoAppHandle,
+ ContextHubMessage message);
}
/**
try {
retVal = getBinder().getContextHubHandles();
} catch (RemoteException e) {
- Log.e(TAG, "Could not fetch context hub handles :" + e.toString());
+ Log.e(TAG, "Could not fetch context hub handles : " + e);
}
return retVal;
}
/**
* Get more information about a specific hub.
*
- * @param contexthubHandle Handle of context hub
- *
- * @return ContextHubInfo returned information about the hub
+ * @param hubHandle Handle (system-wide unique identifier) of a context hub.
+ * @return ContextHubInfo Information about the requested context hub.
*
* @see ContextHubInfo
*/
- public ContextHubInfo getContextHubInfo(int contexthubHandle) {
+ public ContextHubInfo getContextHubInfo(int hubHandle) {
ContextHubInfo retVal = null;
try {
- retVal = getBinder().getContextHubInfo(contexthubHandle);
+ retVal = getBinder().getContextHubInfo(hubHandle);
} catch (RemoteException e) {
- Log.e(TAG, "Could not fetch context hub info :" + e.toString());
+ Log.e(TAG, "Could not fetch context hub info :" + e);
}
return retVal;
}
/**
- * Load a nanoapp on a specified context hub
+ * Load a nano app on a specified context hub.
*
* @param hubHandle handle of context hub to load the app on.
* @param app the nanoApp to load on the hub
try {
retVal = getBinder().loadNanoApp(hubHandle, app);
} catch (RemoteException e) {
- Log.e(TAG, "Could not fetch load nanoApp :" + e.toString());
+ Log.e(TAG, "Could not fetch load nanoApp :" + e);
}
return retVal;
/**
* Unload a specified nanoApp
*
- * @param nanoAppInstanceHandle handle of the nanoApp to load
+ * @param nanoAppHandle handle of the nanoApp to load
*
- * @return int 0 on success, -1 otherewise
+ * @return int 0 on success, -1 otherwise
*/
- public int unloadNanoApp(int nanoAppInstanceHandle) {
+ public int unloadNanoApp(int nanoAppHandle) {
int retVal = -1;
try {
- retVal = getBinder().unloadNanoApp(nanoAppInstanceHandle);
+ retVal = getBinder().unloadNanoApp(nanoAppHandle);
} catch (RemoteException e) {
- Log.e(TAG, "Could not fetch unload nanoApp :" + e.toString());
+ Log.e(TAG, "Could not fetch unload nanoApp :" + e);
}
return retVal;
/**
* get information about the nano app instance
*
- * @param nanoAppInstanceHandle handle of the nanoAppInstance
- *
- * @return NanoAppInstanceInfo Inforamtion about the nano app
- * instance.
+ * @param nanoAppHandle handle of the nanoAppInstance
+ * @return NanoAppInstanceInfo Information about the nano app instance.
*
* @see NanoAppInstanceInfo
*/
- public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) {
+ public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
NanoAppInstanceInfo retVal = null;
try {
- retVal = getBinder().getNanoAppInstanceInfo(nanoAppInstanceHandle);
+ retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
} catch (RemoteException e) {
- Log.e(TAG, "Could not fetch nanoApp info :" + e.toString());
+ Log.e(TAG, "Could not fetch nanoApp info :" + e);
}
return retVal;
*
* @see NanoAppFilter
*
- * @return Integer[] Array of handles to any found nano apps
+ * @return int[] Array of handles to any found nano apps
*/
- public Integer[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
- int[] temp;
- Integer[] retVal = null;
-
+ public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
+ int[] retVal = null;
try {
- temp = getBinder().findNanoAppOnHub(hubHandle, filter);
- retVal = new Integer[temp.length];
- for (int i = 0; i < temp.length; i++) {
- retVal[i] = temp[i];
- }
+ retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
} catch (RemoteException e) {
- Log.e(TAG, "Could not query nanoApp instance :" + e.toString());
+ Log.e(TAG, "Could not query nanoApp instance :" + e);
}
-
return retVal;
}
/**
- * Send a message to a spcific nano app instance on a context
- * hub
- *
+ * Send a message to a specific nano app instance on a context hub.
*
* @param hubHandle handle of the hub to send the message to
* @param nanoAppHandle handle of the nano app to send to
- * @param msg Message to be sent
+ * @param message Message to be sent
*
* @see ContextHubMessage
*
/**
* Set a callback to receive messages from the context hub
*
- *
* @param callback Callback object
*
* @see ContextHubCallback
/**
* Set a callback to receive messages from the context hub
*
- *
* @param callback Callback object
- * @param hander Hander object
+ * @param handler Handler object
*
* @see ContextHubCallback
*
}
/**
- * Unregister a callback for receive messages from the context
- * hub
+ * Unregister a callback for receive messages from the context hub.
*
* @see ContextHubCallback
*
return 0;
}
- private void checkPermissions() {
- mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
- }
-
private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
@Override
public void onMessageReceipt(final int hubId, final int nanoAppId,
- final ContextHubMessage message) throws RemoteException {
+ final ContextHubMessage message) {
if (mCallback != null) {
synchronized(this) {
final ContextHubCallback callback = mCallback;
/** @hide */
public ContextHubManager(Context context, Looper mainLooper) {
- checkPermissions();
- mContext = context;
mMainLooper = mainLooper;
IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
try {
getBinder().registerCallback(mClientCallback);
} catch (RemoteException e) {
- Log.e(TAG, "Could not register callback:" + e.toString());
+ Log.e(TAG, "Could not register callback:" + e);
}
} else {
package android.hardware.location;
-import android.app.Service;
+import android.Manifest;
import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class ContextHubService extends IContextHubService.Stub {
private static final String TAG = "ContextHubService";
+ private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+ private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+ + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
public static final String CONTEXTHUB_SERVICE = "contexthub_service";
@Override
public int registerCallback(IContextHubCallback callback) throws RemoteException{
+ checkPermissions();
mCallback = callback;
return 0;
}
@Override
public int[] getContextHubHandles() throws RemoteException {
+ checkPermissions();
int [] returnArray = new int[mContextHubInfo.length];
for (int i = 0; i < returnArray.length; ++i) {
@Override
public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
+ checkPermissions();
contextHubHandle -= 1;
if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
return null; // null means fail
@Override
public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
+ checkPermissions();
contextHubHandle -= 1;
if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
return nativeSendMessage(msgHeader, app.getAppBinary());
}
- @Override
- public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+ @Override
+ public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+ checkPermissions();
NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
if (info == null) {
- return -1; //means failed
+ return -1; //means failed
}
// Call Native interface here
msgHeader[2] = info.getHandle();
return nativeSendMessage(msgHeader, null);
- }
+ }
@Override
- public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) throws RemoteException {
+ public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
+ throws RemoteException {
+ checkPermissions();
// This assumes that all the nanoAppInfo is current. This is reasonable
// for the use cases for tightly controlled nanoApps.
if (mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
@Override
public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
+ checkPermissions();
ArrayList<Integer> foundInstances = new ArrayList<Integer>();
for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
}
@Override
- public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException {
+ public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
+ throws RemoteException {
+ checkPermissions();
int[] msgHeader = new int[8];
msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
msgHeader[1] = hubHandle;
return nativeSendMessage(msgHeader, msg.getData());
}
+
+ private void checkPermissions() {
+ mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+ }
}
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.
* 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) {
} else {
rssiCurve = null;
}
+ meteredHint = in.readByte() != 0;
}
@Override
} else {
out.writeByte((byte) 0);
}
+ out.writeByte((byte) (meteredHint ? 1 : 0));
}
@Override
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 =
*/
package android.os;
+
import android.util.AndroidRuntimeException;
/**
- * The object you are calling has died, because its hosting process
- * no longer exists.
+ * Exception thrown when a {@link Parcelable} is malformed or otherwise invalid.
+ * <p>
+ * This is typically encountered when a custom {@link Parcelable} object is
+ * passed to another process that doesn't have the same {@link Parcelable} class
+ * in its {@link ClassLoader}.
*/
public class BadParcelableException extends AndroidRuntimeException {
public BadParcelableException(String msg) {
import java.util.Set;
/**
- * A mapping from String values to various types.
+ * A mapping from String keys to values of various types. In most cases, you
+ * should work directly with either the {@link Bundle} or
+ * {@link PersistableBundle} subclass.
*/
public class BaseBundle {
private static final String TAG = "Bundle";
// Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
+ /**
+ * Flag indicating that this Bundle is okay to "defuse." That is, it's okay
+ * for system processes to ignore any {@link BadParcelableException}
+ * encountered when unparceling it, leaving an empty bundle in its place.
+ * <p>
+ * This should <em>only</em> be set when the Bundle reaches its final
+ * destination, otherwise a system process may clobber contents that were
+ * destined for an app that could have unparceled them.
+ */
+ static final int FLAG_DEFUSABLE = 1 << 0;
+
+ private static volatile boolean sShouldDefuse = false;
+
+ /**
+ * Set global variable indicating that any Bundles parsed in this process
+ * should be "defused." That is, any {@link BadParcelableException}
+ * encountered will be suppressed and logged, leaving an empty Bundle
+ * instead of crashing.
+ *
+ * @hide
+ */
+ public static void setShouldDefuse(boolean shouldDefuse) {
+ sShouldDefuse = shouldDefuse;
+ }
+
+ /** {@hide} */
static final Parcel EMPTY_PARCEL;
static {
*/
private ClassLoader mClassLoader;
+ /** {@hide} */
+ int mFlags;
+
/**
* Constructs a new, empty Bundle that uses a specific ClassLoader for
* instantiating Parcelable and Serializable objects.
return;
}
+ if (sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {
+ Log.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may "
+ + "clobber all data inside!", new Throwable());
+ }
+
if (mParcelledData == EMPTY_PARCEL) {
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ ": empty");
mMap.erase();
mMap.ensureCapacity(N);
}
- mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
- mParcelledData.recycle();
- mParcelledData = null;
+ try {
+ mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
+ } catch (BadParcelableException e) {
+ if (sShouldDefuse) {
+ Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
+ mMap.erase();
+ } else {
+ throw e;
+ }
+ } finally {
+ mParcelledData.recycle();
+ mParcelledData = null;
+ }
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ " final map: " + mMap);
}
return;
}
- int magic = parcel.readInt();
+ final int magic = parcel.readInt();
if (magic != BUNDLE_MAGIC) {
- //noinspection ThrowableInstanceNeverThrown
throw new IllegalStateException("Bad magic number for Bundle: 0x"
+ Integer.toHexString(magic));
}
* 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();
import java.util.List;
/**
- * A mapping from String values to various Parcelable types.
+ * A mapping from String keys to various {@link Parcelable} values.
*
+ * @see PersistableBundle
*/
public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
+ private static final int FLAG_HAS_FDS = 1 << 8;
+ private static final int FLAG_HAS_FDS_KNOWN = 1 << 9;
+ private static final int FLAG_ALLOW_FDS = 1 << 10;
+
public static final Bundle EMPTY;
+
static final Parcel EMPTY_PARCEL;
static {
EMPTY_PARCEL = BaseBundle.EMPTY_PARCEL;
}
- private boolean mHasFds = false;
- private boolean mFdsKnown = true;
- private boolean mAllowFds = true;
-
/**
* Constructs a new, empty Bundle.
*/
public Bundle() {
super();
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
*/
Bundle(Parcel parcelledData) {
super(parcelledData);
-
- mHasFds = mParcelledData.hasFileDescriptors();
- mFdsKnown = true;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+ if (mParcelledData.hasFileDescriptors()) {
+ mFlags |= FLAG_HAS_FDS;
+ }
}
/* package */ Bundle(Parcel parcelledData, int length) {
super(parcelledData, length);
-
- mHasFds = mParcelledData.hasFileDescriptors();
- mFdsKnown = true;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+ if (mParcelledData.hasFileDescriptors()) {
+ mFlags |= FLAG_HAS_FDS;
+ }
}
/**
*/
public Bundle(ClassLoader loader) {
super(loader);
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
*/
public Bundle(int capacity) {
super(capacity);
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
*/
public Bundle(Bundle b) {
super(b);
-
- mHasFds = b.mHasFds;
- mFdsKnown = b.mFdsKnown;
+ mFlags = b.mFlags;
}
/**
*/
public Bundle(PersistableBundle b) {
super(b);
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
return super.getClassLoader();
}
- /** @hide */
+ /** {@hide} */
public boolean setAllowFds(boolean allowFds) {
- boolean orig = mAllowFds;
- mAllowFds = allowFds;
+ final boolean orig = (mFlags & FLAG_ALLOW_FDS) != 0;
+ if (allowFds) {
+ mFlags |= FLAG_ALLOW_FDS;
+ } else {
+ mFlags &= ~FLAG_ALLOW_FDS;
+ }
return orig;
}
/**
+ * Mark if this Bundle is okay to "defuse." That is, it's okay for system
+ * processes to ignore any {@link BadParcelableException} encountered when
+ * unparceling it, leaving an empty bundle in its place.
+ * <p>
+ * This should <em>only</em> be set when the Bundle reaches its final
+ * destination, otherwise a system process may clobber contents that were
+ * destined for an app that could have unparceled them.
+ *
+ * @hide
+ */
+ public void setDefusable(boolean defusable) {
+ if (defusable) {
+ mFlags |= FLAG_DEFUSABLE;
+ } else {
+ mFlags &= ~FLAG_DEFUSABLE;
+ }
+ }
+
+ /**
* Clones the current Bundle. The internal map is cloned, but the keys and
* values to which it refers are copied by reference.
*/
@Override
public void clear() {
super.clear();
-
- mHasFds = false;
- mFdsKnown = true;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
bundle.unparcel();
mMap.putAll(bundle.mMap);
- // fd state is now known if and only if both bundles already knew
- mHasFds |= bundle.mHasFds;
- mFdsKnown = mFdsKnown && bundle.mFdsKnown;
+ // FD state is now known if and only if both bundles already knew
+ if ((bundle.mFlags & FLAG_HAS_FDS) != 0) {
+ mFlags |= FLAG_HAS_FDS;
+ }
+ if ((bundle.mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
+ }
}
/**
* Reports whether the bundle contains any parcelled file descriptors.
*/
public boolean hasFileDescriptors() {
- if (!mFdsKnown) {
+ if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
boolean fdFound = false; // keep going until we find one or run out of data
if (mParcelledData != null) {
}
}
- mHasFds = fdFound;
- mFdsKnown = true;
+ if (fdFound) {
+ mFlags |= FLAG_HAS_FDS;
+ }
+ mFlags |= FLAG_HAS_FDS_KNOWN;
}
- return mHasFds;
+ return (mFlags & FLAG_HAS_FDS) != 0;
}
/**
public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
unparcel();
mMap.put(key, value);
- mFdsKnown = false;
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
unparcel();
mMap.put(key, value);
- mFdsKnown = false;
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
@Nullable ArrayList<? extends Parcelable> value) {
unparcel();
mMap.put(key, value);
- mFdsKnown = false;
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/** {@hide} */
public void putParcelableList(String key, List<? extends Parcelable> value) {
unparcel();
mMap.put(key, value);
- mFdsKnown = false;
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
@Nullable SparseArray<? extends Parcelable> value) {
unparcel();
mMap.put(key, value);
- mFdsKnown = false;
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
*/
@Override
public void writeToParcel(Parcel parcel, int flags) {
- final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
+ final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0);
try {
super.writeToParcelInner(parcel, flags);
} finally {
*/
public void readFromParcel(Parcel parcel) {
super.readFromParcelInner(parcel);
- mHasFds = mParcelledData.hasFileDescriptors();
- mFdsKnown = true;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+ if (mParcelledData.hasFileDescriptors()) {
+ mFlags |= FLAG_HAS_FDS;
+ }
}
@Override
}
return "Bundle[" + mMap.toString() + "]";
}
-
}
*/
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;
}
}
- 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) {
import android.annotation.Nullable;
import android.util.ArrayMap;
+
import com.android.internal.util.XmlUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
/**
- * A mapping from String values to various types that can be saved to persistent and later
- * restored.
+ * A mapping from String keys to values of various types. The set of types
+ * supported by this class is purposefully restricted to simple objects that can
+ * safely be persisted to and restored from disk.
*
+ * @see Bundle
*/
public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable,
XmlUtils.WriteMapCallback {
*/
public PersistableBundle() {
super();
+ mFlags = FLAG_DEFUSABLE;
}
/**
*/
public PersistableBundle(int capacity) {
super(capacity);
+ mFlags = FLAG_DEFUSABLE;
}
/**
*/
public PersistableBundle(PersistableBundle b) {
super(b);
+ mFlags = b.mFlags;
}
*/
private PersistableBundle(ArrayMap<String, Object> map) {
super();
+ mFlags = FLAG_DEFUSABLE;
// First stuff everything in.
putAll(map);
/* package */ PersistableBundle(Parcel parcelledData, int length) {
super(parcelledData, length);
+ mFlags = FLAG_DEFUSABLE;
}
/**
}
return "PersistableBundle[" + mMap.toString() + "]";
}
-
}
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
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package android.os;
import android.Manifest;
}
}
- /**
- * 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 {
}
}
- /**
- * 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 {
* 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());
/**
* 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());
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;
/**
* 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.
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;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
+import com.android.internal.annotations.GuardedBy;
+
/**
* Turns a {@link SeekBar} into a volume control.
* @hide
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;
}
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);
+ }
}
}
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);
+ }
}
}
}
}
private void onStopSample() {
- if (mRingtone != null) {
- mRingtone.stop();
+ synchronized (this) {
+ if (mRingtone != null) {
+ mRingtone.stop();
+ }
}
}
}
public boolean isSamplePlaying() {
- return mRingtone != null && mRingtone.isPlaying();
+ synchronized (this) {
+ return mRingtone != null && mRingtone.isPlaying();
+ }
}
public void startSample() {
*/
public static void clearConfiguration(Configuration inoutConfig) {
inoutConfig.fontScale = 0;
- if (!inoutConfig.userSetLocale) {
+ if (!inoutConfig.userSetLocale && !inoutConfig.getLocales().isEmpty()) {
inoutConfig.setLocales(LocaleList.getEmptyLocaleList());
}
}
public static final String VOLUME_MASTER = "volume_master";
/**
- * Master volume mute (int 1 = mute, 0 = not muted).
- *
- * @hide
- */
- public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
-
- private static final Validator VOLUME_MASTER_MUTE_VALIDATOR = sBooleanValidator;
-
- /**
- * Microphone mute (int 1 = mute, 0 = not muted).
- *
- * @hide
- */
- public static final String MICROPHONE_MUTE = "microphone_mute";
-
- private static final Validator MICROPHONE_MUTE_VALIDATOR = sBooleanValidator;
-
- /**
* Master mono (int 1 = mono, 0 = normal).
*
* @hide
PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
PRIVATE_SETTINGS.add(VOLUME_MASTER);
- PRIVATE_SETTINGS.add(VOLUME_MASTER_MUTE);
- PRIVATE_SETTINGS.add(MICROPHONE_MUTE);
PRIVATE_SETTINGS.add(MASTER_MONO);
PRIVATE_SETTINGS.add(NOTIFICATIONS_USE_RING_VOLUME);
PRIVATE_SETTINGS.add(VIBRATE_IN_SILENT);
VALIDATORS.put(ADVANCED_SETTINGS, ADVANCED_SETTINGS_VALIDATOR);
VALIDATORS.put(SCREEN_AUTO_BRIGHTNESS_ADJ, SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR);
VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR);
- VALIDATORS.put(VOLUME_MASTER_MUTE, VOLUME_MASTER_MUTE_VALIDATOR);
- VALIDATORS.put(MICROPHONE_MUTE, MICROPHONE_MUTE_VALIDATOR);
VALIDATORS.put(MASTER_MONO, MASTER_MONO_VALIDATOR);
VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR);
VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR);
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;
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;
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;
/**
* 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;
/** 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;
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),
*/
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
}
}
- 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;
}
}
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);
* @return This instance.
*/
public MeasureBuilder setIntegerPart(long integerPart) {
- return setNumber(String.valueOf(integerPart));
+ return setIntegerPart(String.valueOf(integerPart));
}
/**
* 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);
}
}
// to change animation states.
if (mParent != null && getWindowVisibility() == VISIBLE &&
((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
- dispatchVisibilityAggregated(this, newVisibility);
+ dispatchVisibilityAggregated(newVisibility == VISIBLE);
}
notifySubtreeAccessibilityStateChangedIfNeeded();
}
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);
}
}
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);
}
}
}
/*
* 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) {
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();
}
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;
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;
}
}
@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
if (viewVisibilityChanged) {
mAttachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility);
- host.dispatchVisibilityAggregated(host, viewVisibility);
+ host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
endDragResizing();
destroyHardwareResources();
* @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 */
sWindowManagerService = getWindowManagerService();
ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
} catch (RemoteException e) {
- Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
+ throw e.rethrowFromSystemServer();
}
}
return sWindowManagerService;
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
- Log.e(TAG, "Failed to open window session", e);
+ throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
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;
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;
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)}.
*
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:
* 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;
if (!sPackageInfo.packageName.equals(packageName))
return LIBLOAD_WRONG_PACKAGE_NAME;
- return loadNativeLibrary();
+ return loadNativeLibrary(clazzLoader);
}
static WebViewFactoryProvider getProvider() {
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,
}
// 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;
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) {
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);
}
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;
public void onFinishTemporaryDetach();
public void onActivityResult(int requestCode, int resultCode, Intent data);
+
+ public Handler getHandler(Handler originalHandler);
+
+ public View findFocus(View originalFocusedView);
}
interface ScrollDelegate {
boolean handled = false;
int action = event.getAction();
if (KeyEvent.isConfirmKey(keyCode)
- && event.hasNoModifiers() && action == KeyEvent.ACTION_UP) {
+ && event.hasNoModifiers() && action != KeyEvent.ACTION_UP) {
handled = resurrectSelectionIfNeeded();
if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) {
keyPressed();
}
@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);
}
}
private void swapCurrentDrawable(Drawable newDrawable) {
final Drawable oldDrawable = mCurrentDrawable;
mCurrentDrawable = newDrawable;
+
if (oldDrawable != mCurrentDrawable) {
if (oldDrawable != null) {
oldDrawable.setVisible(false, false);
}
@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;
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 {
}
boolean canShare() {
- return canCopy() && isDeviceProvisioned();
+ if (!getContext().canStartActivityForResult() || !isDeviceProvisioned()) {
+ return false;
+ }
+ return canCopy();
}
boolean isDeviceProvisioned() {
}
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() {
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];
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,
// 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 {
}
}
- 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) {
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);
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() {
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);
}
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);
}
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;
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);
}
}
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 \
* 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);
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),
case SkEncodedFormat::kWBMP_SkEncodedFormat:
mimeType = "image/vnd.wap.wbmp";
break;
+ case SkEncodedFormat::kRAW_SkEncodedFormat:
+ mimeType = "image/x-adobe-dng";
+ break;
default:
mimeType = nullptr;
break;
--- /dev/null
+/*
+ * 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
static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha,
jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit,
- jint strokeLineCap, jint strokeLineJoin) {
+ jint strokeLineCap, jint strokeLineJoin, jint fillType) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha,
trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap,
- strokeLineJoin);
+ strokeLineJoin, fillType);
}
static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
{"nDraw", "(JJJLandroid/graphics/Rect;ZZ)V", (void*)draw},
{"nCreateFullPath", "!()J", (void*)createEmptyFullPath},
{"nCreateFullPath", "!(J)J", (void*)createFullPath},
- {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
+ {"nUpdateFullPathProperties", "!(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
{"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient},
{"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient},
{"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties},
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;
}
return nativeToJavaStatus(
- lpRecorder->start((AudioSystem::sync_event_t)event, triggerSession));
+ lpRecorder->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
}
jfieldID mRule;
jfieldID mFormat;
jfieldID mRouteFlags;
- jfieldID mRegistrationId;
+ jfieldID mDeviceType;
+ jfieldID mDeviceAddress;
jfieldID mMixType;
jfieldID mCallbackFlags;
} gAudioMixFields;
}
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)
{
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
{
nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
+ nAudioMix->mDeviceType = (audio_devices_t)
+ env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
- jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
- gAudioMixFields.mRegistrationId);
- const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
- nAudioMix->mRegistrationId = String8(nRegistrationId);
- env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
- env->DeleteLocalRef(jRegistrationId);
+ jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
+ gAudioMixFields.mDeviceAddress);
+ const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
+ nAudioMix->mDeviceAddress = String8(nDeviceAddress);
+ env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
+ env->DeleteLocalRef(jDeviceAddress);
nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
"Landroid/media/AudioFormat;");
gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
- gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId",
+ gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
+ gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
"Ljava/lang/String;");
gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
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;
#include <DamageAccumulator.h>
#include <Matrix.h>
#include <RenderNode.h>
+#include <renderthread/CanvasContext.h>
#include <TreeInfo.h>
#include <Paint.h>
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();
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:
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;
};
PublicFormat f) {
switch(f) {
case PublicFormat::JPEG:
- return HAL_DATASPACE_JFIF;
+ return HAL_DATASPACE_V0_JFIF;
case PublicFormat::DEPTH_POINT_CLOUD:
case PublicFormat::DEPTH16:
return HAL_DATASPACE_DEPTH;
case PublicFormat::YUV_420_888:
case PublicFormat::NV21:
case PublicFormat::YV12:
- return HAL_DATASPACE_JFIF;
+ return HAL_DATASPACE_V0_JFIF;
default:
// Most formats map to UNKNOWN
return HAL_DATASPACE_UNKNOWN;
switch (dataSpace) {
case HAL_DATASPACE_DEPTH:
return PublicFormat::DEPTH_POINT_CLOUD;
- case HAL_DATASPACE_JFIF:
+ case HAL_DATASPACE_V0_JFIF:
return PublicFormat::JPEG;
default:
// Assume otherwise-marked blobs are also JPEG
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"
</attr>
<!-- sets the Miter limit for a stroked path -->
<attr name="strokeMiterLimit" format="float"/>
+ <!-- sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
+ For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty -->
+ <attr name="fillType" format="enum">
+ <enum name="nonZero" value="0"/>
+ <enum name="evenOdd" value="1"/>
+ </attr>
</declare-styleable>
<!-- Defines the clip path used in VectorDrawables. -->
included in the system image. Third-party apps cannot use it.</em> -->
<attr name="allowClearUserData" format="boolean" />
- <!-- Option to let applications specify that user data should
- never be encrypted if an Encrypted File System solution
- is enabled. Specifically, this is an "opt-out" feature, meaning
- that, by default, user data will be encrypted if the EFS feature
- is enabled. -->
- <attr name="neverEncrypt" format="boolean" />
-
<!-- Option to indicate this application is only for testing purposes.
For example, it may expose functionality or data outside of itself
that would cause a security hole, but is useful for testing. This
single integer, with higher numbers considered to be better. -->
<attr name="priority" format="integer" />
- <!-- Indicate if this component is aware of encryption lifecycle, and can be
+ <!-- Indicate if this component is aware of direct boot lifecycle, and can be
safely run before the user has entered their credentials (such as a lock
pattern or PIN). -->
- <attr name="encryptionAware" format="boolean" />
+ <attr name="directBootAware" format="boolean" />
<!-- Specify how an activity should be launched. See the
<a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
<attr name="restoreNeedsApplication" />
<attr name="restoreAnyVersion" />
<attr name="backupInForeground" />
- <attr name="neverEncrypt" />
<!-- Request that your application's processes be created with
a large Dalvik heap. This applies to <em>all</em> processes
created for the application. It only applies to the first
<attr name="usesCleartextTraffic" />
<attr name="multiArch" />
<attr name="extractNativeLibs" />
- <attr name="forceDeviceEncrypted" format="boolean" />
- <attr name="encryptionAware" />
+ <attr name="defaultToDeviceProtectedStorage" format="boolean" />
+ <attr name="directBootAware" />
<attr name="resizeableActivity" />
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
<attr name="enabled" />
<attr name="exported" />
<attr name="singleUser" />
- <attr name="encryptionAware" />
+ <attr name="directBootAware" />
</declare-styleable>
<!-- Attributes that can be supplied in an AndroidManifest.xml
with it is through the Service API (binding and starting). -->
<attr name="isolatedProcess" format="boolean" />
<attr name="singleUser" />
- <attr name="encryptionAware" />
+ <attr name="directBootAware" />
<!-- If the service is an {@link android.R.attr#isolatedProcess} service, this permits a
client to bind to the service as if it were running it its own package. The service
must also be {@link android.R.attr#exported} if this flag is set. -->
<attr name="enabled" />
<attr name="exported" />
<attr name="singleUser" />
- <attr name="encryptionAware" />
+ <attr name="directBootAware" />
</declare-styleable>
<!-- The <code>activity</code> tag declares an
<attr name="supportsPictureInPicture" />
<attr name="lockTaskMode" />
<attr name="showForAllUsers" />
- <attr name="encryptionAware" />
+ <attr name="directBootAware" />
<!-- @hide This activity is always focusable regardless of if it is in a task/stack whose
activities are normally not focusable.
For example, {@link android.R.attr#supportsPictureInPicture} activities are placed
<public type="attr" name="contextPopupMenuStyle" />
<public type="attr" name="textAppearancePopupMenuHeader" />
<public type="attr" name="windowBackgroundFallback" />
- <public type="attr" name="forceDeviceEncrypted" />
- <public type="attr" name="encryptionAware" />
+ <public type="attr" name="defaultToDeviceProtectedStorage" />
+ <public type="attr" name="directBootAware" />
<public type="attr" name="preferenceFragmentStyle" />
<public type="attr" name="canControlMagnification" />
<public type="attr" name="languageTag" />
<public type="attr" name="canRecord" />
<public type="attr" name="tunerCount" />
<public type="attr" name="nfcAntennaPositionDrawable" />
+ <public type="attr" name="fillType" />
<public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
<public type="style" name="Widget.Material.SeekBar.Discrete" />
</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>
</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>
<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 -->
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;
/**
* test IPrintManager.getPrintJobInfo
*/
+ @LargeTest
public void testGetPrintJobInfo() throws Exception {
startPrinting();
/**
* test IPrintManager.getPrintJobInfos
*/
+ @LargeTest
public void testGetPrintJobInfos() throws Exception {
startPrinting();
/**
* test IPrintManager.print
*/
+ @LargeTest
public void testPrint() throws Exception {
final String name = "dummy print job";
/**
* test IPrintManager.cancelPrintJob
*/
+ @LargeTest
public void testCancelPrintJob() throws Exception {
startPrinting();
/**
* test IPrintManager.restartPrintJob
*/
+ @LargeTest
public void testRestartPrintJob() throws Exception {
startPrinting();
/**
* test IPrintManager.addPrintJobStateChangeListener
*/
+ @MediumTest
public void testAddPrintJobStateChangeListener() throws Exception {
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
/**
* test IPrintManager.removePrintJobStateChangeListener
*/
+ @MediumTest
public void testRemovePrintJobStateChangeListener() throws Exception {
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
/**
* test IPrintManager.addPrintServicesChangeListener
*/
+ @MediumTest
public void testAddPrintServicesChangeListener() throws Exception {
final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
/**
* test IPrintManager.removePrintServicesChangeListener
*/
+ @MediumTest
public void testRemovePrintServicesChangeListener() throws Exception {
final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
/**
* test IPrintManager.getPrintServices
*/
+ @MediumTest
public void testGetPrintServices() throws Exception {
List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
PrintManager.ALL_SERVICES, mUserId);
/**
* test IPrintManager.setPrintServiceEnabled
*/
+ @MediumTest
public void testSetPrintServiceEnabled() throws Exception {
final ComponentName printService = mIPrintManager.getPrintServices(
PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
/**
* test IPrintManager.createPrinterDiscoverySession
*/
+ @MediumTest
public void testCreatePrinterDiscoverySession() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
/**
* test IPrintManager.startPrinterDiscovery
*/
+ @LargeTest
public void testStartPrinterDiscovery() throws Exception {
startPrinting();
/**
* test IPrintManager.stopPrinterDiscovery
*/
+ @MediumTest
public void testStopPrinterDiscovery() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
/**
* test IPrintManager.validatePrinters
*/
+ @LargeTest
public void testValidatePrinters() throws Exception {
startPrinting();
/**
* test IPrintManager.startPrinterStateTracking
*/
+ @LargeTest
public void testStartPrinterStateTracking() throws Exception {
startPrinting();
/**
* test IPrintManager.getCustomPrinterIcon
*/
+ @LargeTest
public void testGetCustomPrinterIcon() throws Exception {
startPrinting();
/**
* test IPrintManager.stopPrinterStateTracking
*/
+ @LargeTest
public void testStopPrinterStateTracking() throws Exception {
startPrinting();
/**
* test IPrintManager.destroyPrinterDiscoverySession
*/
+ @MediumTest
public void testDestroyPrinterDiscoverySession() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
.PHONY: fontchain_lint
fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml
PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \
- python $(FONTCHAIN_LINTER) $(TARGET_OUT)
\ No newline at end of file
+ python $(FONTCHAIN_LINTER) $(TARGET_OUT) external/unicode
</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>
<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>
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>
public final class Outline {
private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
+ private static final int MODE_EMPTY = 0;
+ private static final int MODE_RECT = 1;
+ private static final int MODE_CONVEX_PATH = 2;
+
/** @hide */
- public Path mPath;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = false,
+ value = {
+ MODE_EMPTY,
+ MODE_RECT,
+ MODE_CONVEX_PATH,
+ })
+ public @interface Mode {}
+
+ @Mode
+ private int mMode = MODE_EMPTY;
/** @hide */
- public Rect mRect;
+ public final Path mPath = new Path();
+
+ /** @hide */
+ public final Rect mRect = new Rect();
/** @hide */
public float mRadius = RADIUS_UNDEFINED;
/** @hide */
* @see #isEmpty()
*/
public void setEmpty() {
- mPath = null;
- mRect = null;
+ mMode = MODE_EMPTY;
+ mPath.rewind();
+ mRect.setEmpty();
mRadius = RADIUS_UNDEFINED;
}
* @see #setEmpty()
*/
public boolean isEmpty() {
- return mRect == null && mPath == null;
+ return mMode == MODE_EMPTY;
}
* @see {@link android.view.View#setClipToOutline(boolean)}
*/
public boolean canClip() {
- return !isEmpty() && mRect != null;
+ return mMode != MODE_CONVEX_PATH;
}
/**
* @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;
}
return;
}
- if (mRect == null) mRect = new Rect();
+ mMode = MODE_RECT;
mRect.set(left, top, right, bottom);
mRadius = radius;
- mPath = null;
+ mPath.rewind();
}
/**
* 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);
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;
}
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;
}
* 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);
}
}
private static final int STROKE_LINE_CAP_INDEX = 8;
private static final int STROKE_LINE_JOIN_INDEX = 9;
private static final int STROKE_MITER_LIMIT_INDEX = 10;
- private static final int TOTAL_PROPERTY_COUNT = 11;
+ private static final int FILL_TYPE_INDEX = 11;
+ private static final int TOTAL_PROPERTY_COUNT = 12;
+ // Property map for animatable attributes.
private final static HashMap<String, Integer> sPropertyMap
= new HashMap<String, Integer> () {
{
int strokeLineCap = properties.getInt(STROKE_LINE_CAP_INDEX * 4);
int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4);
float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4);
+ int fillType = properties.getInt(FILL_TYPE_INDEX * 4);
Shader fillGradient = null;
Shader strokeGradient = null;
// Account for any configuration changes.
R.styleable.VectorDrawablePath_trimPathOffset, trimPathOffset);
trimPathStart = a.getFloat(
R.styleable.VectorDrawablePath_trimPathStart, trimPathStart);
+ fillType = a.getInt(R.styleable.VectorDrawablePath_fillType, fillType);
nUpdateFullPathProperties(mNativePtr, strokeWidth, strokeColor, strokeAlpha,
fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset,
- strokeMiterLimit, strokeLineCap, strokeLineJoin);
+ strokeMiterLimit, strokeLineCap, strokeLineJoin, fillType);
}
@Override
private static native void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
- int strokeLineJoin);
+ int strokeLineJoin, int fillType);
private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr);
private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr);
*/
bool init();
+ bool isInitialized() { return mInitialized; }
+
/**
* Flush the cache.
*
}
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));
}
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;
}
void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
- float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) {
+ float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
+ int fillType) {
mProperties.strokeWidth = strokeWidth;
mProperties.strokeColor = strokeColor;
mProperties.strokeAlpha = strokeAlpha;
mProperties.strokeMiterLimit = strokeMiterLimit;
mProperties.strokeLineCap = strokeLineCap;
mProperties.strokeLineJoin = strokeLineJoin;
+ mProperties.fillType = fillType;
// If any trim property changes, mark trim dirty and update the trim path
setTrimPathStart(trimPathStart);
return SkColorSetA(color, alphaBytes * alpha);
}
-void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale,
+void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale,
const SkMatrix& matrix){
// Draw path's fill, if fill color or gradient is valid
bool needsFill = false;
if (needsFill) {
mPaint.setStyle(SkPaint::Style::kFill_Style);
mPaint.setAntiAlias(true);
+ SkPath::FillType ft = static_cast<SkPath::FillType>(mProperties.fillType);
+ renderPath.setFillType(ft);
outCanvas->drawPath(renderPath, mPaint);
}
}
}
-void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
float strokeScale, const SkMatrix& matrix){
outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
}
protected:
virtual const SkPath& getUpdatedPath();
- virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
+ virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
float strokeScale, const SkMatrix& matrix) = 0;
Data mData;
SkPath mSkPath;
int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
float strokeMiterLimit = 4;
+ int fillType = 0; /* non-zero or kWinding_FillType in Skia */
};
FullPath(const FullPath& path); // for cloning
void updateProperties(float strokeWidth, SkColor strokeColor,
float strokeAlpha, SkColor fillColor, float fillAlpha,
float trimPathStart, float trimPathEnd, float trimPathOffset,
- float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
+ float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType);
// TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
float getStrokeWidth() {
return mProperties.strokeWidth;
protected:
const SkPath& getUpdatedPath() override;
- void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+ void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
float strokeScale, const SkMatrix& matrix) override;
private:
StrokeLineCap,
StrokeLineJoin,
StrokeMiterLimit,
+ FillType,
Count,
};
// Applies trimming to the specified path.
ClipPath(const Data& nodes) : Path(nodes) {}
protected:
- void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+ void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
float strokeScale, const SkMatrix& matrix) override;
};
bool drew = mCanvas->finish();
#endif
+ waitOnFences();
+
GL_CHECKPOINT(LOW);
// Even if we decided to cancel the frame, from the perspective of jank
#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 */
#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"
#include <utils/Functor.h>
#include <gui/Surface.h>
+#include <functional>
#include <set>
#include <string>
#include <vector>
}
}
+ // 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
void freePrefetechedLayers();
+ void waitOnFences();
+
EGLint mLastFrameWidth = 0;
EGLint mLastFrameHeight = 0;
// 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 */
# 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"
<< "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:
#include <gtest/gtest.h>
-#include "BakedOpRenderer.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "Rect.h"
mCondition.signal(mType);
}
- void close() {
- Mutex::Autolock l(mLock);
- mOpened = false;
- }
-
void wait() const {
Mutex::Autolock l(mLock);
while (!mOpened) {
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
}
/**
- * 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.
*/
gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
gnssMeasurement.mMultipathIndicator = parcel.readInt();
gnssMeasurement.mSnrInDb = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0);
return gnssMeasurement;
}
parcel.writeDouble(mCarrierPhaseUncertainty);
parcel.writeInt(mMultipathIndicator);
parcel.writeDouble(mSnrInDb);
- parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0));
}
@Override
mPseudorangeRateMetersPerSecond,
"PseudorangeRateUncertaintyMetersPerSecond",
mPseudorangeRateUncertaintyMetersPerSecond));
- builder.append(String.format(
- format,
- "PseudorangeRateIsCorrected",
- isPseudorangeRateCorrected()));
builder.append(String.format(
format,
resetCarrierPhaseUncertainty();
setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
resetSnrInDb();
- setPseudorangeRateCorrected(false);
}
private void setFlag(int flag) {
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;
}
* <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.
/**
* Audio session ID
*/
- private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+ private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
/**
* AudioAttributes
*/
/**
* Audio session ID
*/
- private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+ private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
/**
* Reference to the app-ops service.
*/
int bufferSizeInBytes, int mode)
throws IllegalArgumentException {
this(streamType, sampleRateInHz, channelConfig, audioFormat,
- bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE);
+ bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);
}
/**
* 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
*/
private AudioMixingRule mRule;
private AudioFormat mFormat;
private int mRouteFlags;
- private String mRegistrationId;
private int mMixType = MIX_TYPE_INVALID;
// written by AudioPolicy
int mMixState = MIX_STATE_DISABLED;
int mCallbackFlags;
+ String mDeviceAddress;
// initialized in constructor, read by AudioPolicyConfig
- final int mDeviceId;
- final String mDeviceAddress;
+ final int mDeviceSystemType; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
/**
* All parameters are guaranteed valid through the Builder.
*/
private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags,
- int deviceId, String deviceAddress) {
+ int deviceType, String deviceAddress) {
mRule = rule;
mFormat = format;
mRouteFlags = routeFlags;
- mRegistrationId = null;
mMixType = rule.getTargetMixType();
mCallbackFlags = callbackFlags;
- mDeviceId = deviceId;
- mDeviceAddress = deviceAddress;
+ mDeviceSystemType = deviceType;
+ mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress;
}
// CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined
}
void setRegistration(String regId) {
- mRegistrationId = regId;
+ mDeviceAddress = regId;
}
/** @hide */
public String getRegistration() {
- return mRegistrationId;
+ return mDeviceAddress;
}
/** @hide */
private AudioFormat mFormat = null;
private int mRouteFlags = 0;
private int mCallbackFlags = 0;
- private int mDeviceId = -1;
+ // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
+ private int mDeviceSystemType = AudioSystem.DEVICE_NONE;
private String mDeviceAddress = null;
/**
/**
* @hide
* Only used by AudioPolicyConfig, not a public API.
- * @param deviceId
+ * @param deviceType an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
* @param address
* @return the same Builder instance.
*/
- Builder setDevice(int deviceId, String address) {
- mDeviceId = deviceId;
+ Builder setDevice(int deviceType, String address) {
+ mDeviceSystemType = deviceType;
mDeviceAddress = address;
return this;
}
if (!device.isSink()) {
throw new IllegalArgumentException("Unsupported device type on mix, not a sink");
}
- mDeviceId = device.getId();
+ mDeviceSystemType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
mDeviceAddress = device.getAddress();
return this;
}
}
mFormat = new AudioFormat.Builder().setSampleRate(rate).build();
}
- if (mDeviceId != -1) {
+ if ((mDeviceSystemType != AudioSystem.DEVICE_NONE)
+ && (mDeviceSystemType != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)
+ && (mDeviceSystemType != AudioSystem.DEVICE_IN_REMOTE_SUBMIX)) {
if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) {
throw new IllegalArgumentException(
"Can't have audio device without flag ROUTE_FLAG_RENDER");
throw new IllegalArgumentException(
"Can't have flag ROUTE_FLAG_RENDER without an audio device");
}
+ if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_LOOP_BACK) {
+ if (mRule.getTargetMixType() == MIX_TYPE_PLAYERS) {
+ mDeviceSystemType = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+ } else if (mRule.getTargetMixType() == MIX_TYPE_RECORDERS) {
+ mDeviceSystemType = AudioSystem.DEVICE_IN_REMOTE_SUBMIX;
+ } else {
+ throw new IllegalArgumentException("Unknown mixing rule type");
+ }
+ }
}
- return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceId,
+ return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType,
mDeviceAddress);
}
}
// write callback flags
dest.writeInt(mix.mCallbackFlags);
// write device information
- dest.writeInt(mix.mDeviceId);
+ dest.writeInt(mix.mDeviceSystemType);
dest.writeString(mix.mDeviceAddress);
// write mix format
dest.writeInt(mix.getFormat().getSampleRate());
* Interface used to receive the created session.
* @hide
*/
- @SystemApi
public abstract static class SessionCallback {
/**
* This is called after {@link TvInputManager#createSession} has been processed.
* @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) {
}
* @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) {
}
* @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);
* @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);
* 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;
* @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");
*
* @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) {
* 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");
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) {
priority,
effectCallback,
&lpJniStorage->mCallbackData,
- sessionId,
+ (audio_session_t) sessionId,
0);
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
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) {
0,
android_media_visualizer_effect_callback,
lpJniStorage,
- sessionId);
+ (audio_session_t) sessionId);
if (lpVisualizer == 0) {
ALOGE("Error creating Visualizer");
goto setup_failure;
/*****************************************************************************/
+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(
<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"
--- /dev/null
+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)
+
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+ }
+}
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;
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;
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;
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);
}
}
+ /**
+ * 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;
*/
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 {
/**
* 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);
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.documentsui.services.FileOperations;
-
import com.google.common.collect.Lists;
import java.lang.annotation.Retention;
private String mQuery = null;
private Selection mSelection = null;
private boolean mSearchMode = false;
+ private @Nullable ActionMode mActionMode;
@Override
public View onCreateView(
int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
- assert(mRecView.getWidth() > 0);
-
- int columnCount = Math.max(1,
+ // RecyclerView sometimes gets a width of 0 (see b/27150284). Clamp so that we always lay
+ // out the grid with at least 2 columns.
+ int columnCount = Math.max(2,
(mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
return columnCount;
implements MultiSelectManager.Callback, ActionMode.Callback {
private Selection mSelected = new Selection();
- private ActionMode mActionMode;
private int mNoCopyCount = 0;
private int mNoDeleteCount = 0;
private int mNoRenameCount = -1;
return true;
case R.id.menu_delete:
- // Pass mode along to the delete function so it can
- // end action mode when documents are deleted.
+ // deleteDocuments will end action mode if the documents are deleted.
// It won't end action mode if user cancels the delete.
- deleteDocuments(selection, mode);
+ deleteDocuments(selection);
return true;
case R.id.menu_copy_to:
}.execute(selected);
}
- private void deleteDocuments(final Selection selected, final ActionMode mode) {
+ private void deleteDocuments(final Selection selected) {
assert(!selected.isEmpty());
final DocumentInfo srcParent = getDisplayState().stack.peek();
// This is done here, rather in the onActionItemClicked
// so we can avoid de-selecting items in the case where
// the user cancels the delete.
- mode.finish();
+ if (mActionMode != null) {
+ mActionMode.finish();
+ }
// Hide the files in the UI...since the operation
// might be queued up on FileOperationService.
// We're walking a line here.
}
// Handle enter key events
- if (keyCode == KeyEvent.KEYCODE_ENTER) {
- if (event.isShiftPressed()) {
- return onSelect(doc);
- } else {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_ENTER:
+ if (event.isShiftPressed()) {
+ return onSelect(doc);
+ }
+ // For non-shifted enter keypresses, fall through.
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_BUTTON_A:
return onActivate(doc);
- }
+ case KeyEvent.KEYCODE_FORWARD_DEL:
+ // This has to be handled here instead of in a keyboard shortcut, because
+ // keyboard shortcuts all have to be modified with the 'Ctrl' key.
+ if (mSelectionManager.hasSelection()) {
+ deleteDocuments(mSelectionManager.getSelection());
+ }
+ // Always handle the key, even if there was nothing to delete. This is a
+ // precaution to prevent other handlers from potentially picking up the event
+ // and triggering extra behaviours.
+ return true;
}
return false;
/**
* Makes the associated item view appear selected. Note that this merely affects the appearance
* of the view, it doesn't actually select the item.
+ * TODO: Use the DirectoryItemAnimator instead of manually controlling animation using a boolean
+ * flag.
*
* @param selected
+ * @param animate Whether or not to animate the change. Only selection changes initiated by the
+ * selection manager should be animated. See
+ * {@link ModelBackedDocumentsAdapter#onBindViewHolder(DocumentHolder, int, java.util.List)}
*/
- public void setSelected(boolean selected) {
+ public void setSelected(boolean selected, boolean animate) {
+ // Note: the animate param doesn't apply for this base implementation, because the
+ // DirectoryItemAnimator takes care of it. It's required by subclasses, which perform their
+ // own animation.
itemView.setActivated(selected);
itemView.setBackgroundColor(selected ? mSelectedBgColor : mDefaultBgColor);
}
return false;
}
- if (mState.action == ACTION_OPEN_TREE) {
+ if (mState.action == ACTION_OPEN_TREE
+ || mState.action == ACTION_PICK_COPY_DESTINATION) {
// In this case nothing *ever* is selectable...the expected user behavior is
// they navigate *into* a folder, then click a confirmation button indicating
// that the current directory is the directory they are picking.
}
@Override
- public void setSelected(boolean selected) {
- super.setSelected(selected);
+ public void setSelected(boolean selected, boolean animate) {
+ super.setSelected(selected, animate);
float checkAlpha = selected ? 1f : 0f;
- mIconCheck.animate().alpha(checkAlpha).start();
- mIconMime.animate().alpha(1f - checkAlpha).start();
+ if (animate) {
+ mIconCheck.animate().alpha(checkAlpha).start();
+ mIconMime.animate().alpha(1f - checkAlpha).start();
+ } else {
+ mIconCheck.setAlpha(checkAlpha);
+ mIconMime.setAlpha(1f - checkAlpha);
+ }
}
/**
}
@Override
- public void setSelected(boolean selected) {
+ public void setSelected(boolean selected, boolean animate) {
// We always want to make sure our check box disappears if we're not selected,
// even if the item is disabled. This is because this object can be reused
// and this method will be called to setup initial state.
float checkAlpha = selected ? 1f : 0f;
- mIconCheck.animate().alpha(checkAlpha).start();
+ if (animate) {
+ mIconCheck.animate().alpha(checkAlpha).start();
+ } else {
+ mIconCheck.setAlpha(checkAlpha);
+ }
// But it should be an error to be set to selected && be disabled.
if (!itemView.isEnabled()) {
return;
}
- super.setSelected(selected);
+ super.setSelected(selected, animate);
- mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+ if (animate) {
+ mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+ } else {
+ mIconMimeSm.setAlpha(1f - checkAlpha);
+ }
}
public void setEnabled(boolean enabled) {
}
@Override
- public void setSelected(boolean selected) {
+ public void setSelected(boolean selected, boolean animate) {
// We always want to make sure our check box disappears if we're not selected,
// even if the item is disabled. But it should be an error (see assert below)
// to be set to selected && be disabled.
float checkAlpha = selected ? 1f : 0f;
- mIconCheck.animate().alpha(checkAlpha).start();
+ if (animate) {
+ mIconCheck.animate().alpha(checkAlpha).start();
+ } else {
+ mIconCheck.setAlpha(checkAlpha);
+ }
if (!itemView.isEnabled()) {
assert(!selected);
return;
}
- super.setSelected(selected);
+ super.setSelected(selected, animate);
- mIconMime.animate().alpha(1f - checkAlpha).start();
- mIconThumb.animate().alpha(1f - checkAlpha).start();
+ if (animate) {
+ mIconMime.animate().alpha(1f - checkAlpha).start();
+ mIconThumb.animate().alpha(1f - checkAlpha).start();
+ } else {
+ mIconMime.setAlpha(1f - checkAlpha);
+ mIconThumb.setAlpha(1f - checkAlpha);
+ }
}
@Override
import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME;
import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
import static com.android.documentsui.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.model.DocumentInfo.getCursorLong;
+import static com.android.documentsui.model.DocumentInfo.getCursorString;
import android.database.Cursor;
-import android.database.MergeCursor;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
private String mIds[] = new String[0];
private int mSortOrder = SORT_ORDER_DISPLAY_NAME;
- private int mAuthorityIndex = -1;
- private int mDocIdIndex = -1;
- private int mMimeTypeIndex = -1;
- private int mDisplayNameIndex = -1;
- private int mColumnSizeIndex = -1;
- private int mLastModifiedIndex = -1;
-
@Nullable String info;
@Nullable String error;
@Nullable DocumentInfo doc;
+ /**
+ * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
+ * string that can be used to identify the document referred to by the cursor.
+ *
+ * @param c A cursor that refers to a document.
+ */
+ private static String createModelId(Cursor c) {
+ // TODO: Maybe more efficient to use just the document ID, in cases where there is only one
+ // authority (which should be the majority of cases).
+ return createModelId(
+ getCursorString(c, RootCursorWrapper.COLUMN_AUTHORITY),
+ getCursorString(c, Document.COLUMN_DOCUMENT_ID));
+ }
+
+ /**
+ * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
+ * string that can be used to identify the document referred to by the cursor.
+ *
+ * @param c A cursor that refers to a document.
+ */
+ static String createModelId(String authority, String docId) {
+ return authority + "|" + docId;
+ }
+
private void notifyUpdateListeners() {
for (UpdateListener listener: mUpdateListeners) {
listener.onModelUpdate(this);
mCursor = result.cursor;
mCursorCount = mCursor.getCount();
mSortOrder = result.sortOrder;
- mAuthorityIndex = mCursor.getColumnIndex(RootCursorWrapper.COLUMN_AUTHORITY);
- assert(mAuthorityIndex != -1);
- mDocIdIndex = mCursor.getColumnIndex(Document.COLUMN_DOCUMENT_ID);
- mMimeTypeIndex = mCursor.getColumnIndex(Document.COLUMN_MIME_TYPE);
- mDisplayNameIndex = mCursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME);
- mColumnSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE);
-
doc = result.doc;
updateModelData();
for (int pos = 0; pos < mCursorCount; ++pos) {
mCursor.moveToNext();
positions[pos] = pos;
+ mIds[pos] = createModelId(mCursor);
- // Generates a Model ID for a cursor entry that refers to a document. The Model ID is a
- // unique string that can be used to identify the document referred to by the cursor.
- // If the cursor is a merged cursor over multiple authorities, then prefix the ids
- // with the authority to avoid collisions.
- if (mCursor instanceof MergeCursor) {
- mIds[pos] = getString(mAuthorityIndex) + "|" + mCursor.getString(mDocIdIndex);
- } else {
- mIds[pos] = mCursor.getString(mDocIdIndex);
- }
-
- mimeType = getString(mMimeTypeIndex);
+ mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
- switch (mSortOrder) {
+ switch(mSortOrder) {
case SORT_ORDER_DISPLAY_NAME:
- displayNames[pos] = getString(mDisplayNameIndex);
+ final String displayName = getCursorString(
+ mCursor, Document.COLUMN_DISPLAY_NAME);
+ displayNames[pos] = displayName;
break;
case SORT_ORDER_LAST_MODIFIED:
- longValues[pos] = getLastModified();
+ longValues[pos] = getLastModified(mCursor);
break;
case SORT_ORDER_SIZE:
- longValues[pos] = mColumnSizeIndex != -1
- ? mCursor.getLong(mColumnSizeIndex) : 0;
+ longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE);
break;
}
}
}
}
- private String getString(int columnIndex) {
- return columnIndex != -1 ? mCursor.getString(columnIndex) : null;
- }
-
/**
* @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
* timestamp - these will be replaced with MAX_LONG so that such files get sorted to the top
* when sorting by date.
*/
- private long getLastModified() {
- long l = mCursor.getLong(mLastModifiedIndex);
+ long getLastModified(Cursor cursor) {
+ long l = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED);
return (l == -1) ? Long.MAX_VALUE : l;
}
import android.view.ViewGroup;
import com.android.documentsui.State;
-
import com.google.common.collect.Sets;
import java.util.ArrayList;
public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
if (payload.contains(SELECTION_CHANGED_MARKER)) {
final boolean selected = mEnv.isSelected(mModelIds.get(position));
- holder.setSelected(selected);
+ holder.setSelected(selected, true);
} else {
onBindViewHolder(holder, position);
}
assert(!selected);
}
holder.setEnabled(enabled);
- holder.setSelected(mEnv.isSelected(modelId));
+ holder.setSelected(mEnv.isSelected(modelId), false);
mEnv.onBindDocumentHolder(holder, cursor);
}
public Selection createFromParcel(Parcel in, ClassLoader loader) {
return new Selection(
in.readString(),
- (ArrayList<String>) in.readArrayList(loader));
+ in.readArrayList(loader));
}
@Override
Rect getAbsoluteRectForChildViewAt(int index);
int getAdapterPositionAt(int index);
int getColumnCount();
- int getRowCount();
int getChildCount();
int getVisibleChildCount();
/**
}
@Override
- public int getRowCount() {
- int numFullColumns = getChildCount() / getColumnCount();
- boolean hasPartiallyFullColumn = getChildCount() % getColumnCount() != 0;
- return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
- }
-
- @Override
public int getHeight() {
return mView.getHeight();
}
}
mCurrentPosition = input.getOrigin();
+ mModel.resizeSelection(input.getOrigin());
scrollViewIfNecessary();
resizeBandSelectRectangle();
}
mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right));
}
- if (mRowBounds.size() != mHelper.getRowCount()) {
- // If not all y-limits have been recorded, record this one.
- recordLimits(
- mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
- }
+ recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
if (columnList == null) {
return ((Limits) other).lowerLimit == lowerLimit &&
((Limits) other).upperLimit == upperLimit;
}
+
+ @Override
+ public String toString() {
+ return "(" + lowerLimit + ", " + upperLimit + ")";
+ }
}
/**
String id = Integer.toString(i);
row.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY);
row.add(Document.COLUMN_DOCUMENT_ID, id);
- currentDownloads.add(id);
+ currentDownloads.add(Model.createModelId(AUTHORITY, id));
}
DirectoryResult r = new DirectoryResult();
import com.android.documentsui.dirlist.MultiSelectManager.GridModel;
import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
@SmallTest
private Set<String> lastSelection;
private int viewWidth;
+ // TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and
+ // #resizeSelection methods instead.
+ //
+ // The reason for this is that selection is stateful and involves operations that take the
+ // current UI state (e.g scrolling) into account. This test maintains its own copy of the
+ // selection bounds as control data for verifying selections. Keep this data in sync by calling
+ // #startSelection and
+ // #resizeSelection.
+ private Point mSelectionOrigin;
+ private Point mSelectionPoint;
+
private void initData(final int numChildren, int numColumns) {
env = new TestEnvironment(numChildren, numColumns);
adapter = new TestDocumentsAdapter(new ArrayList<String>()) {
public void testSelectionLeftOfItems() {
initData(20, 5);
- model.startSelection(new Point(0, 10));
- model.resizeSelection(new Point(1, 11));
- assertSelected();
+ startSelection(new Point(0, 10));
+ resizeSelection(new Point(1, 11));
+ assertNoSelection();
assertEquals(NOT_SET, model.getPositionNearestOrigin());
}
public void testSelectionRightOfItems() {
initData(20, 4);
- model.startSelection(new Point(viewWidth - 1, 10));
- model.resizeSelection(new Point(viewWidth - 2, 11));
- assertSelected();
+ startSelection(new Point(viewWidth - 1, 10));
+ resizeSelection(new Point(viewWidth - 2, 11));
+ assertNoSelection();
assertEquals(NOT_SET, model.getPositionNearestOrigin());
}
public void testSelectionAboveItems() {
initData(20, 4);
- model.startSelection(new Point(10, 0));
- model.resizeSelection(new Point(11, 1));
- assertSelected();
+ startSelection(new Point(10, 0));
+ resizeSelection(new Point(11, 1));
+ assertNoSelection();
assertEquals(NOT_SET, model.getPositionNearestOrigin());
}
public void testSelectionBelowItems() {
initData(5, 4);
- model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
- model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
- assertSelected();
+ startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
+ resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
+ assertNoSelection();
assertEquals(NOT_SET, model.getPositionNearestOrigin());
}
public void testVerticalSelectionBetweenItems() {
initData(20, 4);
- model.startSelection(new Point(106, 0));
- model.resizeSelection(new Point(107, 200));
- assertSelected();
+ startSelection(new Point(106, 0));
+ resizeSelection(new Point(107, 200));
+ assertNoSelection();
assertEquals(NOT_SET, model.getPositionNearestOrigin());
}
public void testHorizontalSelectionBetweenItems() {
initData(20, 4);
- model.startSelection(new Point(0, 105));
- model.resizeSelection(new Point(200, 106));
- assertSelected();
+ startSelection(new Point(0, 105));
+ resizeSelection(new Point(200, 106));
+ assertNoSelection();
assertEquals(NOT_SET, model.getPositionNearestOrigin());
}
public void testGrowingAndShrinkingSelection() {
initData(20, 4);
- model.startSelection(new Point(0, 0));
- model.resizeSelection(new Point(5, 5));
- assertSelected(0);
- model.resizeSelection(new Point(109, 109));
- assertSelected(0);
- model.resizeSelection(new Point(110, 109));
- assertSelected(0, 1);
- model.resizeSelection(new Point(110, 110));
- assertSelected(0, 1, 4, 5);
- model.resizeSelection(new Point(214, 214));
- assertSelected(0, 1, 4, 5);
- model.resizeSelection(new Point(215, 214));
- assertSelected(0, 1, 2, 4, 5, 6);
- model.resizeSelection(new Point(214, 214));
- assertSelected(0, 1, 4, 5);
- model.resizeSelection(new Point(110, 110));
- assertSelected(0, 1, 4, 5);
- model.resizeSelection(new Point(110, 109));
- assertSelected(0, 1);
- model.resizeSelection(new Point(109, 109));
- assertSelected(0);
- model.resizeSelection(new Point(5, 5));
- assertSelected(0);
- model.resizeSelection(new Point(0, 0));
- assertSelected();
+ startSelection(new Point(0, 0));
+
+ resizeSelection(new Point(5, 5));
+ verifySelection();
+
+ resizeSelection(new Point(109, 109));
+ verifySelection();
+
+ resizeSelection(new Point(110, 109));
+ verifySelection();
+
+ resizeSelection(new Point(110, 110));
+ verifySelection();
+
+ resizeSelection(new Point(214, 214));
+ verifySelection();
+
+ resizeSelection(new Point(215, 214));
+ verifySelection();
+
+ resizeSelection(new Point(214, 214));
+ verifySelection();
+
+ resizeSelection(new Point(110, 110));
+ verifySelection();
+
+ resizeSelection(new Point(110, 109));
+ verifySelection();
+
+ resizeSelection(new Point(109, 109));
+ verifySelection();
+
+ resizeSelection(new Point(5, 5));
+ verifySelection();
+
+ resizeSelection(new Point(0, 0));
+ verifySelection();
+
assertEquals(NOT_SET, model.getPositionNearestOrigin());
}
public void testSelectionMovingAroundOrigin() {
initData(16, 4);
- model.startSelection(new Point(210, 210));
- model.resizeSelection(new Point(viewWidth - 1, 0));
- assertSelected(2, 3, 6, 7);
- model.resizeSelection(new Point(0, 0));
- assertSelected(0, 1, 4, 5);
- model.resizeSelection(new Point(0, 420));
- assertSelected(8, 9, 12, 13);
- model.resizeSelection(new Point(viewWidth - 1, 420));
- assertSelected(10, 11, 14, 15);
- assertEquals(10, model.getPositionNearestOrigin());
+
+ startSelection(new Point(210, 210));
+ resizeSelection(new Point(viewWidth - 1, 0));
+ verifySelection();
+
+ resizeSelection(new Point(0, 0));
+ verifySelection();
+
+ resizeSelection(new Point(0, 420));
+ verifySelection();
+
+ resizeSelection(new Point(viewWidth - 1, 420));
+ verifySelection();
+
+ // This is manually figured and will need to be adjusted if the separator position is
+ // changed.
+ assertEquals(7, model.getPositionNearestOrigin());
}
public void testScrollingBandSelect() {
initData(40, 4);
- model.startSelection(new Point(0, 0));
- model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
- assertSelected(0, 4, 8, 12, 16);
+
+ startSelection(new Point(0, 0));
+ resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+ verifySelection();
+
scroll(CHILD_VIEW_EDGE_PX);
- assertSelected(0, 4, 8, 12, 16, 20);
- model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
- assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21);
+ verifySelection();
+
+ resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
+ verifySelection();
+
scroll(CHILD_VIEW_EDGE_PX);
- assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25);
+ verifySelection();
+
scroll(-2 * CHILD_VIEW_EDGE_PX);
- assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17);
- model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
- assertSelected(0, 4, 8, 12, 16);
+ verifySelection();
+
+ resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+ verifySelection();
+
assertEquals(0, model.getPositionNearestOrigin());
}
- private void assertSelected(int... selectedPositions) {
- assertEquals(selectedPositions.length, lastSelection.size());
- for (int position : selectedPositions) {
- assertTrue(lastSelection.contains(Integer.toString(position)));
+ /** Returns the current selection area as a Rect. */
+ private Rect getSelectionArea() {
+ // Construct a rect from the two selection points.
+ Rect selectionArea = new Rect(
+ mSelectionOrigin.x, mSelectionOrigin.y, mSelectionOrigin.x, mSelectionOrigin.y);
+ selectionArea.union(mSelectionPoint.x, mSelectionPoint.y);
+ // Rect intersection tests are exclusive of bounds, while the MSM's selection code is
+ // inclusive. Expand the rect by 1 pixel in all directions to account for this.
+ selectionArea.inset(-1, -1);
+
+ return selectionArea;
+ }
+
+ /** Asserts that the selection is currently empty. */
+ private void assertNoSelection() {
+ assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(),
+ 0, lastSelection.size());
+ }
+
+ /** Verifies the selection using actual bbox checks. */
+ private void verifySelection() {
+ Rect selectionArea = getSelectionArea();
+ for (TestEnvironment.Item item: env.items) {
+ if (Rect.intersects(selectionArea, item.rect)) {
+ assertTrue("Expected item " + item + " was not in selection " + selectionArea,
+ lastSelection.contains(item.name));
+ } else {
+ assertFalse("Unexpected item " + item + " in selection" + selectionArea,
+ lastSelection.contains(item.name));
+ }
}
}
+ private void startSelection(Point p) {
+ model.startSelection(p);
+ mSelectionOrigin = env.createAbsolutePoint(p);
+ }
+
+ private void resizeSelection(Point p) {
+ model.resizeSelection(p);
+ mSelectionPoint = env.createAbsolutePoint(p);
+ }
+
private void scroll(int dy) {
assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight());
env.verticalOffset += dy;
+ // Correct the cached selection point as well.
+ mSelectionPoint.y += dy;
model.onScrolled(null, 0, dy);
}
private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment {
- public int horizontalOffset = 0;
- public int verticalOffset = 0;
private final int mNumColumns;
private final int mNumRows;
private final int mNumChildren;
+ private final int mSeparatorPosition;
+
+ public int horizontalOffset = 0;
+ public int verticalOffset = 0;
+ private List<Item> items = new ArrayList<>();
public TestEnvironment(int numChildren, int numColumns) {
mNumChildren = numChildren;
mNumColumns = numColumns;
- mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
+ mSeparatorPosition = mNumColumns + 1;
+ mNumRows = setupGrid();
+ }
+
+ private int setupGrid() {
+ // Split the input set into folders and documents. Do this such that there is a
+ // partially-populated row in the middle of the grid, to test corner cases in layout
+ // code.
+ int y = VIEW_PADDING_PX;
+ int i = 0;
+ int numRows = 0;
+ while (i < mNumChildren) {
+ int top = y;
+ int height = CHILD_VIEW_EDGE_PX;
+ int width = CHILD_VIEW_EDGE_PX;
+ for (int j = 0; j < mNumColumns && i < mNumChildren; j++) {
+ int left = VIEW_PADDING_PX + (j * (width + VIEW_PADDING_PX));
+ items.add(new Item(
+ Integer.toString(i),
+ new Rect(
+ left,
+ top,
+ left + width - 1,
+ top + height - 1)));
+
+ // Create a partially populated row at the separator position.
+ if (++i == mSeparatorPosition) {
+ break;
+ }
+ }
+ y += height + VIEW_PADDING_PX;
+ numRows++;
+ }
+
+ return numRows;
}
private int getTotalHeight() {
private int getNumItemsInRow(int index) {
assertTrue(index >= 0 && index < mNumRows);
- if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) {
- return mNumChildren % mNumColumns;
+ int mod = mSeparatorPosition % mNumColumns;
+ if (index == (mSeparatorPosition / mNumColumns)) {
+ // The row containing the separator may be incomplete
+ return mod > 0 ? mod : mNumColumns;
+ }
+ // Account for the partial separator row in the final row tally.
+ if (index == mNumRows - 1) {
+ // The last row may be incomplete
+ int finalRowCount = (mNumChildren - mod) % mNumColumns;
+ return finalRowCount > 0 ? finalRowCount : mNumColumns;
}
return mNumColumns;
@Override
public int getAdapterPositionAt(int index) {
- return index + mNumColumns * (getFirstVisibleRowIndex());
+ // Account for partial rows by actually tallying up the items in hidden rows.
+ int hiddenCount = 0;
+ for (int i = 0; i < getFirstVisibleRowIndex(); i++) {
+ hiddenCount += getNumItemsInRow(i);
+ }
+ return index + hiddenCount;
}
@Override
public Rect getAbsoluteRectForChildViewAt(int index) {
- int adapterPosition = (getFirstVisibleRowIndex() * mNumColumns) + index;
- int rowIndex = adapterPosition / mNumColumns;
- int columnIndex = adapterPosition % mNumColumns;
-
- Rect rect = new Rect();
- rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
- rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1;
- rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
- rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1;
- return rect;
+ int adapterPosition = getAdapterPositionAt(index);
+ return items.get(adapterPosition).rect;
}
@Override
}
@Override
- public int getRowCount() {
- return mNumRows;
- }
-
- @Override
public void showBand(Rect rect) {
throw new UnsupportedOperationException();
}
public boolean isLayoutItem(int adapterPosition) {
return false;
}
+
+ public static final class Item {
+ public String name;
+ public Rect rect;
+
+ public Item(String n, Rect r) {
+ name = n;
+ rect = r;
+ }
+
+ public String toString() {
+ return name + ": " + rect;
+ }
+ }
}
}
update(r);
}
+ // Note that model id includes authority qualifier and is distinct
+ // WRT documentId because of this.
String idForPosition(int p) {
- return Integer.toString(p);
+ return createModelId(mAuthority, Integer.toString(p));
}
}
}
@Override
- public int getRowCount() {
- return 0;
- }
-
- @Override
public int getChildCount() {
return 0;
}
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"/>
<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"/>
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" />
<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" />
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">
android:process="com.android.systemui"
android:persistent="true"
android:supportsRtl="true"
- android:forceDeviceEncrypted="true"
- android:encryptionAware="true">
+ android:defaultToDeviceProtectedStorage="true"
+ android:directBootAware="true">
</application>
</manifest>
* limitations under the License.
*/
-package com.android.mtp.exceptions;
+package com.android.mtp;
import java.io.IOException;
/**
* Exception thrown when the device is busy and the requested operation cannon be completed.
*/
-public class BusyDeviceException extends IOException {
+class BusyDeviceException extends IOException {
+ BusyDeviceException() {
+ super("The MTP device is busy.");
+ }
}
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;
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;
if (DEBUG) {
Log.d(TAG, "createDocument: " + displayName);
}
+ final Identifier parentId;
+ final MtpDeviceRecord record;
+ final ParcelFileDescriptor[] pipe;
try {
- final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
+ parentId = mDatabase.createIdentifier(parentDocumentId);
openDevice(parentId.mDeviceId);
- final MtpDeviceRecord record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
+ record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Writing operation is not supported by the device.");
+ }
+ pipe = ParcelFileDescriptor.createReliablePipe();
+ int objectHandle = -1;
+ MtpObjectInfo info = null;
+ try {
+ pipe[0].close(); // 0 bytes for a new document.
+
+ final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
+ MtpConstants.FORMAT_ASSOCIATION :
+ MediaFile.getFormatCode(displayName, mimeType);
+ info = new MtpObjectInfo.Builder()
+ .setStorageId(parentId.mStorageId)
+ .setParent(parentId.mObjectHandle)
+ .setFormat(formatCode)
+ .setName(displayName)
+ .build();
+
+ final String[] parts = FileUtils.splitFileName(mimeType, displayName);
+ final String baseName = parts[0];
+ final String extension = parts[1];
+ for (int i = 0; i <= 32; i++) {
+ final MtpObjectInfo infoUniqueName;
+ if (i == 0) {
+ infoUniqueName = info;
+ } else {
+ infoUniqueName = new MtpObjectInfo.Builder(info).setName(
+ baseName + " (" + i + ")." + extension).build();
+ }
+ try {
+ objectHandle = mMtpManager.createDocument(
+ parentId.mDeviceId, infoUniqueName, pipe[1]);
+ break;
+ } catch (SendObjectInfoFailure exp) {
+ // This can be caused when we have an existing file with the same name.
+ continue;
+ }
+ }
+ } finally {
+ pipe[1].close();
+ }
+ if (objectHandle == -1) {
+ throw new IllegalArgumentException(
+ "The file name \"" + displayName + "\" is conflicted with existing files " +
+ "and the provider failed to find unique name.");
}
- final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
- pipe[0].close(); // 0 bytes for a new document.
- final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
- MtpConstants.FORMAT_ASSOCIATION :
- MediaFile.getFormatCode(displayName, mimeType);
- final MtpObjectInfo info = new MtpObjectInfo.Builder()
- .setStorageId(parentId.mStorageId)
- .setParent(parentId.mObjectHandle)
- .setFormat(formatCode)
- .setName(displayName)
- .build();
- final int objectHandle = mMtpManager.createDocument(parentId.mDeviceId, info, pipe[1]);
final MtpObjectInfo infoWithHandle =
new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
final String documentId = mDatabase.putNewDocument(
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);
}
}
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.mtp.exceptions.BusyDeviceException;
import java.io.FileNotFoundException;
import java.io.IOException;
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(),
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mtp;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when sendObjectInfo failed.
+ */
+class SendObjectInfoFailure extends IOException {
+ SendObjectInfoFailure() {
+ super("Failed to MtpDevice#sendObjectInfo.");
+ }
+}
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;
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;
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();
+ }
+ });
}
}
<!-- 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>
if (sSystemSignature == null) {
sSystemSignature = new Signature[]{ getSystemSignature(pm) };
}
- return sSystemSignature[0] != null && sSystemSignature[0].equals(getFirstSignature(pkg));
+ if (sPermissionControllerPackageName == null) {
+ sPermissionControllerPackageName = pm.getPermissionControllerPackageName();
+ }
+ return (sSystemSignature[0] != null
+ && sSystemSignature[0].equals(getFirstSignature(pkg)))
+ || (sPermissionControllerPackageName != null
+ && sPermissionControllerPackageName.equals(pkg.packageName));
}
private static Signature[] sSystemSignature;
+ private static String sPermissionControllerPackageName;
private static Signature getFirstSignature(PackageInfo pkg) {
if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
}
@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) {
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"
@Override
public Bundle call(String method, String name, Bundle args) {
+ // If the remote side sent us bad parcelables, they won't get the
+ // results they want, which is their loss.
+ if (args != null) args.setDefusable(true);
+
final int requestingUserId = getRequestingUserId(args);
switch (method) {
case Settings.CALL_METHOD_GET_GLOBAL: {
<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"
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. -->
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="100dp"
+ android:height="132dp"
+ android:viewportWidth="100"
+ android:viewportHeight="132">
+
+ <path
+ android:fillColor="#5AFFFFFF"
+ android:pathData="M86.91,68.67H13.09c-4.96,0-9,4.04-9,9V119c0,4.96,4.04,9,9,9h73.82c4.96,0,9-4.04,9-9V77.67
+C95.91,72.7,91.87,68.67,86.91,68.67z M27.59,77.27h26.72v3.94H27.59V77.27z
+M18.73,74.74c2.49,0,4.5,2.01,4.5,4.5
+c0,2.49-2.01,4.5-4.5,4.5s-4.5-2.01-4.5-4.5C14.23,76.75,16.24,74.74,18.73,74.74z
+M89.91,119c0,1.65-1.35,3-3,3H13.09 c-1.65,0-3-1.35-3-3V88.67h79.82V119z" />
+ <path
+ android:fillColor="#5AFFFFFF"
+ android:pathData="M86.91,36.3H13.09c-4.96,0-9,4.04-9,9v23c1.65-1.58,3.71-2.73,6-3.28v-9.08h79.82v9.08
+c2.29,0.55,4.35,1.69,6,3.28v-23C95.91,40.34,91.87,36.3,86.91,36.3z
+M18.73,51.38c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,51.38,18.73,51.38z M54.31,48.84H27.59v-3.94h26.72V48.84z" />
+ <path
+ android:fillColor="#5AFFFFFF"
+ android:pathData="M86.91,4H13.09c-4.96,0-9,4.04-9,9v22.94c1.65-1.58,3.71-2.73,6-3.28V24h79.82v8.67
+c2.29,0.55,4.35,1.69,6,3.28V13C95.91,8.04,91.87,4,86.91,4z
+M18.73,18.5c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,18.5,18.73,18.5z M54.31,15.97H27.59v-3.94h26.72V15.97z" />
+ <path
+ android:pathData="M 0 0 H 100 V 132 H 0 V 0 Z" />
+</vector>
\ No newline at end of file
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
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">
<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"
android:singleLine="true"
android:ellipsize="start"
android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+ android:textIsSelectable="true"
android:imeOptions="actionSend|flagNoExtractUi" />
<FrameLayout
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" />
<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>
<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>
<!-- 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>
<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">
-->
<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>
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);
}
public void hide(int x, int y) {
if (isShown) {
isShown = false;
+ mToolbar.dismissPopupMenus();
setCustomizing(false);
save();
mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
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;
@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);
super.onSelectedChanged(viewHolder, actionState);
if (mCurrentDrag != null) {
mCurrentDrag.stopDrag();
+ mCurrentDrag = null;
}
if (viewHolder != null) {
mCurrentDrag = (Holder) viewHolder;
mCurrentDrag.startDrag();
}
+ notifyItemChanged(mDividerIndex);
}
@Override
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;
boolean mCanReuseTaskStackViews = true;
boolean mDraggingInRecents;
boolean mLaunchedWhileDocking;
+ private boolean mIsRunningOnTv;
// Task launching
Rect mSearchBarBounds = new Rect();
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;
}
}
}
}
+ /**
+ * 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;
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.
}
/**
+ * 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,
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;
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);
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;
};
}
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);
}
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;
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);
}
}
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;
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;
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";
"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;
private UserManager mUserManager;
private int mDensity;
+ private KeyguardManager mKeyguardManager;
+ private LockPatternUtils mLockPatternUtils;
+
// UI-specific methods
/**
);
}
+ } 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 */
+ }
}
}
};
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);
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);
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);
});
a.start();
guts.setExposed(true);
+ row.closeRemoteInput();
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
mNotificationGutsExposed = guts;
}
ActivityManagerNative.getDefault().resumeAppSwitches();
} catch (RemoteException e) {
}
-
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
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) {
}, 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) {
/**
* 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;
}
}
+ public void closeRemoteInput() {
+ mPrivateLayout.closeRemoteInput();
+ mPublicLayout.closeRemoteInput();
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
private View mHeadsUpChild;
private HybridNotificationView mSingleLineView;
+ private RemoteInputView mExpandedRemoteInput;
+ private RemoteInputView mHeadsUpRemoteInput;
+
private NotificationViewWrapper mContractedWrapper;
private NotificationViewWrapper mExpandedWrapper;
private NotificationViewWrapper mHeadsUpWrapper;
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) {
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();
}
}
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;
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;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
public class NavigationBarView extends LinearLayout {
final static boolean DEBUG = false;
private boolean mDockedStackExists;
private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
+ private int mDensity;
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
mShowMenu = false;
mGestureHelper = new NavigationBarGestureHelper(context);
+ mDensity = context.getResources().getConfiguration().densityDpi;
getIcons(context);
mBarTransitions = new NavigationBarTransitions(this);
// we are switching to.
setNavigationIconHints(mNavigationIconHints, true);
}
+ if (mDensity != newConfig.densityDpi) {
+ mDensity = newConfig.densityDpi;
+ getIcons(getContext());
+ }
}
/**
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;
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);
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() {
+ }
+ };
+
}
@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
}
private void fireCallback(boolean isEnabled) {
- for (Callback callback : mCallbacks) {
- callback.onHotspotChanged(isEnabled);
+ synchronized (mCallbacks) {
+ for (Callback callback : mCallbacks) {
+ callback.onHotspotChanged(isEnabled);
+ }
}
}
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;
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.
private RemoteInputController mController;
private NotificationData.Entry mEntry;
+ private LongPressCancelable mLongPressCancelable;
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
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.
--- /dev/null
+/*
+ * 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();
+}
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";
}
}
+ @Override
+ public void requestDisallowLongPress() {
+ removeLongPressCallback();
+ }
+
public void removeLongPressCallback() {
mSwipeHelper.removeLongPressCallback();
}
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();
<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">
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;
private final PackageManager mPackageManager;
+ private final PowerManager mPowerManager;
+
private final WindowManagerInternal mWindowManagerService;
private final SecurityPolicy mSecurityPolicy;
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();
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++) {
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;
}
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) {
}
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);
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;
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
* 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());
mKeyEventTimeoutHandler =
new Handler(mHandlerToSendKeyEventsToInputFilter.getLooper(), new Callback());
mLock = lock;
+ mPowerManager = powerManager;
}
/**
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);
}
}
int policyFlags = pendingEvent.policyFlags | WindowManagerPolicy.FLAG_PASS_TO_USER;
mHandlerToSendKeyEventsToInputFilter
.obtainMessage(mMessageTypeForSendKeyEvent, policyFlags, 0, pendingEvent.event)
- .sendToTarget();
+ .sendToTarget();
} else {
pendingEvent.event.recycle();
}
// 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
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
* - SparseArray w/ mapping:
* AppOp code --> Set of packages that are not restricted for this code
*
+ * For efficiency, a core assumption here is that the number of per-package exemptions stored
+ * here will be relatively small. If this changes, this data structure should be revisited.
*/
private final ArrayMap<IBinder, SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>>>
mOpUserRestrictions = new ArrayMap<>();
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;
}
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) {
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);
return uidMode;
}
}
- Op op = getOpLocked(code, uid, packageName, false);
+ Op op = getOpLocked(code, uid, resolvedPackageName, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@Override
public int checkPackage(int uid, String packageName) {
+ Preconditions.checkNotNull(packageName);
synchronized (this) {
if (getOpsRawLocked(uid, packageName, true) != null) {
return AppOpsManager.MODE_ALLOWED;
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);
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);
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;
}
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;
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;
}
@Override
public int permissionToOpCode(String permission) {
+ if (permission == null) {
+ return AppOpsManager.OP_NONE;
+ }
return AppOpsManager.permissionToOpCode(permission);
}
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) {
}
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;
}
}
if (opRestrictions[code]) {
- if (opExceptions != null && opExceptions.get(code) != null &&
- opExceptions.get(code).contains(packageName)) {
- continue; // AppOps code is restricted, but this package is exempt
+
+ if (opExceptions != null) {
+ ArraySet<String> ex = opExceptions.get(code);
+ if (ex != null && ex.contains(packageName)) {
+ continue; // AppOps code is restricted, but this package is exempt
+ }
}
if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
// If we are the system, bypass user restrictions for certain codes
synchronized (this) {
- Ops ops = getOpsLocked(uid, packageName, true);
+ Ops ops = getOpsRawLocked(uid, packageName, true);
if ((ops != null) && ops.isPrivileged) {
return false;
}
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) {
@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) {
final SparseArray<ArraySet<String>> opExceptions =
getUserPackageExemptionsForToken(token, userHandle);
- // If exceptionPackages is not null, update the exception packages for this AppOps code
ArraySet<String> exceptions = opExceptions.get(code);
- if (exceptionPackages != null) {
+ if (exceptionPackages != null && exceptionPackages.length > 0) {
if (exceptions == null) {
exceptions = new ArraySet<>(exceptionPackages.length);
opExceptions.put(code, exceptions);
exceptions.clear();
}
- exceptions.addAll(Arrays.asList(exceptionPackages));
+ for (String p : exceptionPackages) {
+ exceptions.add(p);
+ }
+ } else {
+ opExceptions.remove(code);
}
}
if (restrictions != null) {
final boolean[] opRestrictions = restrictions.first;
+ final SparseArray<ArraySet<String>> opExceptions = restrictions.second;
+ boolean stillHasRestrictions = false;
if (opRestrictions != null) {
- for (boolean restriction : opRestrictions) {
+ for (int i = 0; i < opRestrictions.length; i++) {
+ boolean restriction = opRestrictions[i];
if (restriction) {
- return;
+ stillHasRestrictions = true;
+ } else {
+ opExceptions.remove(i);
}
}
}
+ if (stillHasRestrictions) {
+ return;
+ }
+
// No restrictions set for this client
perTokenRestrictions.remove(userHandle);
if (perTokenRestrictions.size() <= 0) {
}
}
+ 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 {
class SettingsObserver extends ContentObserver {
int mUserId;
boolean mRegistered = false;
+ @NonNull
String mLastEnabled = "";
/**
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 {
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;
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;
private final Handler mFgHandler;
private final Handler mDaemonHandler;
+ private INetd mNetdService;
+
private IBatteryStats mBatteryStats;
private final Thread mThread;
}
public static NetworkManagementService create(Context context) throws InterruptedException {
- return create(context, NETD_SOCKET_NAME);
+ return create(context, NETD_SERVICE_NAME);
}
public void systemReady() {
* 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
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;
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) {
}
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) {
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;
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());
}
}
- 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) {
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() {
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");
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));
}
* 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)) {
}
private boolean canHaveProfile(final int parentUserId) {
- final UserInfo userInfo = mUserManager.getUserInfo(parentUserId);
+ final UserInfo userInfo = getUserManager().getUserInfo(parentUserId);
return userInfo != null && userInfo.canHaveProfile();
}
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);
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;
|| 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,
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;
mRecentTasks.loadUserRecentsLocked(userId);
}
if (userId == UserHandle.USER_SYSTEM) {
- startPersistentApps(PackageManager.MATCH_ENCRYPTION_UNAWARE);
+ startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
installEncryptionUnawareProviders(userId);
break;
}
}
+ // We're going to be splicing together extras before sending, so we're
+ // okay poking into any contained extras.
+ if (intents != null) {
+ for (int i = 0; i < intents.length; i++) {
+ intents[i].setDefusable(true);
+ }
+ }
+
final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
// 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();
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;
&& 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);
}
}
}
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;
private static final int MSG_SET_FORCE_USE = 8;
private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
private static final int MSG_SET_ALL_VOLUMES = 10;
- private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
private static final int MSG_REPORT_NEW_ROUTES = 12;
private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
private static final int MSG_SYSTEM_READY = 21;
private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
- private static final int MSG_PERSIST_MICROPHONE_MUTE = 23;
private static final int MSG_UNMUTE_STREAM = 24;
private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
private static final int MSG_INDICATE_SYSTEM_READY = 26;
// array initialized by updateStreamVolumeAlias()
updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
readPersistedSettings();
+ readUserRestrictions();
mSettingsObserver = new SettingsObserver();
createStreamStates();
System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
UserHandle.USER_CURRENT);
+ updateMasterMono(cr);
+
+ // Each stream will read its own persisted settings
+
+ // Broadcast the sticky intents
+ broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
+ broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
+
+ // Broadcast vibrate settings
+ broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
+ broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
+
+ // Load settings for the volume controller
+ mVolumeController.loadSettings(cr);
+ }
+
+ private void readUserRestrictions() {
final int currentUser = getCurrentUserId();
- // In addition to checking the system setting, also check the current user restriction.
- // Because of the delay before persisting VOLUME_MASTER_MUTE, there's a window where
- // DISALLOW_ADJUST_VOLUME will be ignored when it's set right before switching users.
- boolean masterMute = (System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
- 0, UserHandle.USER_CURRENT) == 1)
- || mUserManagerInternal.getUserRestriction(
+ // Check the current user restriction.
+ boolean masterMute = mUserManagerInternal.getUserRestriction(
currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
if (mUseFixedVolume) {
masterMute = false;
AudioSystem.setMasterMute(masterMute);
broadcastMasterMuteStatus(masterMute);
- boolean microphoneMute =
- (System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1)
- || mUserManagerInternal.getUserRestriction(
- currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+ boolean microphoneMute = mUserManagerInternal.getUserRestriction(
+ currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
if (DEBUG_VOL) {
Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
}
AudioSystem.muteMicrophone(microphoneMute);
-
- updateMasterMono(cr);
-
- // Each stream will read its own persisted settings
-
- // Broadcast the sticky intents
- broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
- broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
-
- // Broadcast vibrate settings
- broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
- broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
-
- // Load settings for the volume controller
- mVolumeController.loadSettings(cr);
}
private int rescaleIndex(int index, int srcStream, int dstStream) {
// 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) {
if (mute != AudioSystem.getMasterMute()) {
setSystemAudioMute(mute);
AudioSystem.setMasterMute(mute);
- // Post a persist master volume msg
- sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
- : 0, userId, null, PERSIST_DELAY);
sendMasterMuteUpdate(mute, flags);
Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
sendBroadcastToAll(intent);
}
- } else {
- // If not the current user just persist the setting which will be loaded
- // on user switch.
- sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
- : 0, userId, null, PERSIST_DELAY);
}
}
AudioSystem.muteMicrophone(on);
}
// Post a persist microphone msg.
- sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
- : 0, userId, null, PERSIST_DELAY);
}
@Override
private void readAudioSettings(boolean userSwitch) {
// restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
readPersistedSettings();
+ readUserRestrictions();
// restore volume settings
int numStreamTypes = AudioSystem.getNumStreamTypes();
* 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();
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;
persistVolume((VolumeStreamState) msg.obj, msg.arg1);
break;
- case MSG_PERSIST_MASTER_VOLUME_MUTE:
- if (mUseFixedVolume) {
- return;
- }
- Settings.System.putIntForUser(mContentResolver,
- Settings.System.VOLUME_MASTER_MUTE,
- msg.arg1,
- msg.arg2);
- break;
-
case MSG_PERSIST_RINGER_MODE:
// note that the value persisted is the current ringer mode, not the
// value of ringer mode as of the time the request was made to persist
Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
UserHandle.USER_CURRENT);
break;
- case MSG_PERSIST_MICROPHONE_MUTE:
- Settings.System.putIntForUser(mContentResolver,
- Settings.System.MICROPHONE_MUTE,
- msg.arg1,
- msg.arg2);
- break;
+
case MSG_UNMUTE_STREAM:
onUnmuteStream(msg.arg1, msg.arg2);
break;
+
case MSG_DYN_POLICY_MIX_STATE_UPDATE:
onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
break;
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);
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) {
}
}
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;
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);
// 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();
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;
// 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";
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);
}
private void loadPolicyFile() {
if (DBG) Slog.d(TAG, "loadPolicyFile");
synchronized(mPolicyFile) {
- mBlockedPackages.clear();
FileInputStream infile = null;
try {
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();
}
/**
- * 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
checkCallerIsSystem();
setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
+ mRankingHelper.setEnabled(pkg, uid, enabled);
+ savePolicyFile();
}
/**
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();
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;
}
/**
// Sanitize inputs
notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
Notification.PRIORITY_MAX);
+ if (notification.extras != null) {
+ // If the remote side sent us bad parcelables, they won't get the
+ // results they want, which is their loss.
+ notification.extras.setDefusable(true);
+ }
// setup local book-keeping
final StatusBarNotification n = new StatusBarNotification(
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) {
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();
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;
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";
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;
}
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()) {
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";
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) {
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);
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);
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);
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);
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);
// 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;
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;
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 {
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 {
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++) {
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) {
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) {
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!");
}
}
* 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;
| 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;
}
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;
}
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))
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 ?
return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
}
- ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
- int userId) {
+ private Intent getHomeIntent() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
+ return intent;
+ }
+
+ private IntentFilter getHomeFilter() {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
+ filter.addCategory(Intent.CATEGORY_HOME);
+ filter.addCategory(Intent.CATEGORY_DEFAULT);
+ return filter;
+ }
+
+ ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+ int userId) {
+ Intent intent = getHomeIntent();
List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
PackageManager.GET_META_DATA, userId);
ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
}
@Override
+ public void setHomeActivity(ComponentName comp, int userId) {
+ ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
+ getHomeActivitiesAsUser(homeActivities, userId);
+
+ boolean found = false;
+
+ final int size = homeActivities.size();
+ final ComponentName[] set = new ComponentName[size];
+ for (int i = 0; i < size; i++) {
+ final ResolveInfo candidate = homeActivities.get(i);
+ final ActivityInfo info = candidate.activityInfo;
+ final ComponentName activityName = new ComponentName(info.packageName, info.name);
+ set[i] = activityName;
+ if (!found && activityName.equals(comp)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ throw new IllegalArgumentException("Component " + comp + " cannot be home on user "
+ + userId);
+ }
+ replacePreferredActivity(getHomeFilter(), IntentFilter.MATCH_CATEGORY_EMPTY,
+ set, comp, userId);
+ }
+
+ @Override
public void setApplicationEnabledSetting(String appPackageName,
int newState, int flags, int userId, String callingPackage) {
if (!sUserManager.exists(userId)) return;
}
}
+ @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)
/**
* 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 {
return runSuspend(true);
case "unsuspend":
return runSuspend(false);
+ case "set-home-activity":
+ return runSetHomeActivity();
default:
return handleDefaultCommands(cmd);
}
return params;
}
+ private int runSetHomeActivity() {
+ final PrintWriter pw = getOutPrintWriter();
+ int userId = UserHandle.USER_SYSTEM;
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "--user":
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ String component = getNextArg();
+ ComponentName componentName =
+ component != null ? ComponentName.unflattenFromString(component) : null;
+
+ if (componentName == null) {
+ pw.println("Error: component name not specified or invalid");
+ return 1;
+ }
+
+ try {
+ mInterface.setHomeActivity(componentName, userId);
+ return 0;
+ } catch (RemoteException e) {
+ pw.println(e.toString());
+ return 1;
+ }
+ }
+
private static String checkAbiArgument(String abi) {
if (TextUtils.isEmpty(abi)) {
throw new IllegalArgumentException("Missing ABI argument");
pw.println(" Suspends the specified package (as user).");
pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
pw.println(" Unsuspends the specified package (as user).");
+ pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
+ pw.println(" set the default home activity (aka launcher).");
pw.println();
Intent.printIntentArgsHelp(pw , "");
}
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);
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",
static final String TAG_EXTRAS = "extras";
static final String TAG_SHORTCUT = "shortcut";
static final String TAG_LAUNCHER = "launcher";
+ static final String TAG_PIN = "pin";
+ static final String TAG_LAUNCHER_PINS = "launcher-pins";
static final String ATTR_VALUE = "value";
static final String ATTR_NAME = "name";
static final String ATTR_FLAGS = "flags";
static final String ATTR_ICON_RES = "icon-res";
static final String ATTR_BITMAP_PATH = "bitmap-path";
+ static final String ATTR_PACKAGE_NAME = "package-name";
@VisibleForTesting
interface ConfigConstants {
/** 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);
/** 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 ===
// 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;
}
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
// 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);
fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
// Add it.
- newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
- ps.updateShortcutWithCapping(this, newShortcut);
+ ps.addDynamicShortcut(this, newShortcut);
}
userPackageChanged(packageName, userId);
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);
}
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;
}
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
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;
}
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);
}
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();
}
private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>();
+ private final ArrayMap<String, LauncherShortcuts> mLaunchers = new ArrayMap<>();
+
private ComponentName mLauncherComponent;
public UserShortcuts(int userId) {
return mPackages;
}
+ public ArrayMap<String, LauncherShortcuts> getLaunchers() {
+ return mLaunchers;
+ }
+
+ public PackageShortcuts getPackageShortcuts(@NonNull String packageName) {
+ PackageShortcuts ret = mPackages.get(packageName);
+ if (ret == null) {
+ ret = new PackageShortcuts(mUserId, packageName);
+ mPackages.put(packageName, ret);
+ }
+ return ret;
+ }
+
+ public LauncherShortcuts getLauncherShortcuts(@NonNull String packageName) {
+ LauncherShortcuts ret = mLaunchers.get(packageName);
+ if (ret == null) {
+ ret = new LauncherShortcuts(mUserId, packageName);
+ mLaunchers.put(packageName, ret);
+ }
+ return ret;
+ }
+
public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
out.startTag(null, ShortcutService.TAG_USER);
ShortcutService.writeTagValue(out, ShortcutService.TAG_LAUNCHER,
mLauncherComponent);
- for (int i = 0; i < mPackages.size(); i++) {
+ final int lsize = mLaunchers.size();
+ for (int i = 0; i < lsize; i++) {
+ mLaunchers.valueAt(i).saveToXml(out);
+ }
+
+ final int psize = mPackages.size();
+ for (int i = 0; i < psize; i++) {
mPackages.valueAt(i).saveToXml(out);
}
final int depth = parser.getDepth();
final String tag = parser.getName();
switch (tag) {
- case ShortcutService.TAG_LAUNCHER:
+ case ShortcutService.TAG_LAUNCHER: {
ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
parser, ShortcutService.ATTR_VALUE);
continue;
- case ShortcutService.TAG_PACKAGE:
+ }
+ case ShortcutService.TAG_PACKAGE: {
final PackageShortcuts shortcuts = PackageShortcuts.loadFromXml(parser, userId);
// Don't use addShortcut(), we don't need to save the icon.
ret.getPackages().put(shortcuts.mPackageName, shortcuts);
continue;
+ }
+
+ case ShortcutService.TAG_LAUNCHER_PINS: {
+ final LauncherShortcuts shortcuts =
+ LauncherShortcuts.loadFromXml(parser, userId);
+
+ ret.getLaunchers().put(shortcuts.mPackageName, shortcuts);
+ continue;
+ }
}
throw ShortcutService.throwForInvalidTag(depth, tag);
}
pw.print(mLauncherComponent);
pw.println();
+ for (int i = 0; i < mLaunchers.size(); i++) {
+ mLaunchers.valueAt(i).dump(s, pw, prefix + " ");
+ }
+
for (int i = 0; i < mPackages.size(); i++) {
mPackages.valueAt(i).dump(s, pw, prefix + " ");
}
}
}
+class LauncherShortcuts {
+ private static final String TAG = ShortcutService.TAG;
+
+ @UserIdInt
+ final int mUserId;
+
+ @NonNull
+ final String mPackageName;
+
+ /**
+ * Package name -> IDs.
+ */
+ final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
+
+ LauncherShortcuts(@UserIdInt int userId, @NonNull String packageName) {
+ mUserId = userId;
+ mPackageName = packageName;
+ }
+
+ public void pinShortcuts(@NonNull ShortcutService s, @NonNull String packageName,
+ @NonNull List<String> ids) {
+ final int idSize = ids.size();
+ if (idSize == 0) {
+ mPinnedShortcuts.remove(packageName);
+ } else {
+ final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName);
+
+ // Pin shortcuts. Make sure only pin the ones that were visible to the caller.
+ // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
+
+ final PackageShortcuts packageShortcuts =
+ s.getPackageShortcutsLocked(packageName, mUserId);
+ final ArraySet<String> newSet = new ArraySet<>();
+
+ for (int i = 0; i < idSize; i++) {
+ final String id = ids.get(i);
+ final ShortcutInfo si = packageShortcuts.findShortcutById(id);
+ if (si == null) {
+ continue;
+ }
+ if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) {
+ newSet.add(id);
+ }
+ }
+ mPinnedShortcuts.put(packageName, newSet);
+ }
+ s.getPackageShortcutsLocked(packageName, mUserId).refreshPinnedFlags(s);
+ }
+
+ /**
+ * Return the pinned shortcut IDs for the publisher package.
+ */
+ public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) {
+ return mPinnedShortcuts.get(packageName);
+ }
+
+ /**
+ * Persist.
+ */
+ public void saveToXml(XmlSerializer out) throws IOException {
+ out.startTag(null, ShortcutService.TAG_LAUNCHER_PINS);
+ ShortcutService.writeAttr(out, ShortcutService.ATTR_PACKAGE_NAME,
+ mPackageName);
+
+ final int size = mPinnedShortcuts.size();
+ for (int i = 0; i < size; i++) {
+ out.startTag(null, ShortcutService.TAG_PACKAGE);
+ ShortcutService.writeAttr(out, ShortcutService.ATTR_PACKAGE_NAME,
+ mPinnedShortcuts.keyAt(i));
+
+ final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+ final int idSize = ids.size();
+ for (int j = 0; j < idSize; j++) {
+ ShortcutService.writeTagValue(out, ShortcutService.TAG_PIN, ids.valueAt(j));
+ }
+ out.endTag(null, ShortcutService.TAG_PACKAGE);
+ }
+
+ out.endTag(null, ShortcutService.TAG_LAUNCHER_PINS);
+ }
+
+ /**
+ * Load.
+ */
+ public static LauncherShortcuts loadFromXml(XmlPullParser parser, int userId)
+ throws IOException, XmlPullParserException {
+ final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
+ ShortcutService.ATTR_PACKAGE_NAME);
+
+ final LauncherShortcuts ret = new LauncherShortcuts(userId, launcherPackageName);
+
+ ArraySet<String> ids = null;
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ final int depth = parser.getDepth();
+ final String tag = parser.getName();
+ switch (tag) {
+ case ShortcutService.TAG_PACKAGE: {
+ final String packageName = ShortcutService.parseStringAttribute(parser,
+ ShortcutService.ATTR_PACKAGE_NAME);
+ ids = new ArraySet<>();
+ ret.mPinnedShortcuts.put(packageName, ids);
+ continue;
+ }
+ case ShortcutService.TAG_PIN: {
+ ids.add(ShortcutService.parseStringAttribute(parser,
+ ShortcutService.ATTR_VALUE));
+ continue;
+ }
+ }
+ throw ShortcutService.throwForInvalidTag(depth, tag);
+ }
+ return ret;
+ }
+
+ public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.println();
+
+ pw.print(prefix);
+ pw.print("Launcher: ");
+ pw.print(mPackageName);
+ pw.println();
+
+ final int size = mPinnedShortcuts.size();
+ for (int i = 0; i < size; i++) {
+ pw.println();
+
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("Package: ");
+ pw.println(mPinnedShortcuts.keyAt(i));
+
+ final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+ final int idSize = ids.size();
+
+ for (int j = 0; j < idSize; j++) {
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print(ids.valueAt(j));
+ pw.println();
+ }
+ }
+ }
+}
+
/**
* All the information relevant to shortcuts from a single package (per-user).
*/
*
* 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;
}
}
+ /**
+ * 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);
mDynamicShortcutCount = 0;
}
+ /**
+ * Remove a dynamic shortcut by ID.
+ */
public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
}
}
- 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);
}
/**
* 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);
}
}
}
}
public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.println();
+
pw.print(prefix);
pw.print("Package: ");
pw.print(mPackageName);
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);
final boolean fullscreenTask = !inMultiWindowMode();
final boolean windowsAreFloating = task != null && task.isFloating();
- if (fullscreenTask || (isChildWindow()
- && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) {
+ // If the task has temp inset bounds set, we have to make sure all its windows uses
+ // the temp inset frame. Otherwise different display frames get applied to the main
+ // window and the child window, making them misaligned.
+ if (fullscreenTask) {
+ mInsetFrame.setEmpty();
+ } else {
+ task.getTempInsetBounds(mInsetFrame);
+ }
+
+ if (mInsetFrame.isEmpty() && (fullscreenTask
+ || (isChildWindow() && (mAttrs.privateFlags
+ & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0))) {
// We use the parent frame as the containing frame for fullscreen and child windows
mContainingFrame.set(pf);
mDisplayFrame.set(df);
- mInsetFrame.setEmpty();
} else {
task.getBounds(mContainingFrame);
- task.getTempInsetBounds(mInsetFrame);
if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
// If the bounds are frozen, we still want to translate the window freely and only
// Start a new transaction and apply position & offset.
final int layerStack = w.getDisplayContent().getDisplay().getLayerStack();
- if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
- "POS " + mTmpSize.left + ", " + mTmpSize.top, false);
mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
mLastHidden = true;
mSurfaceY = top;
try {
+ if (SHOW_TRANSACTIONS) logSurface(
+ "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
mSurfaceControl.setPosition(left, top);
mSurfaceControl.setLayerStack(layerStack);
mSurfaceY = top;
try {
+ if (SHOW_TRANSACTIONS) logSurface(
+ "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null);
+
mSurfaceControl.setPosition(left, top);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + this
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;
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;
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;
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) {
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());
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();
}
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.
}
mOwners.clearDeviceOwner();
mOwners.writeDeviceOwner();
updateDeviceOwnerLocked();
- disableDeviceLoggingIfNotCompliant();
+ disableSecurityLoggingIfNotCompliant();
// Reactivate backup service.
long ident = mInjector.binderClearCallingIdentity();
try {
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);
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);
}
@Override
- public boolean getDeviceLoggingEnabled(ComponentName admin) {
+ public boolean isSecurityLoggingEnabled(ComponentName admin) {
Preconditions.checkNotNull(admin);
synchronized (this) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@Override
- public ParceledListSlice<SecurityEvent> retrievePreviousDeviceLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
Preconditions.checkNotNull(admin);
ensureDeviceOwnerManagingSingleUser(admin);
}
@Override
- public ParceledListSlice<SecurityEvent> retrieveDeviceLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
Preconditions.checkNotNull(admin);
ensureDeviceOwnerManagingSingleUser(admin);
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;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
+import android.os.BaseBundle;
import android.os.Build;
import android.os.Environment;
import android.os.FactoryTest;
import android.os.IPowerManager;
import android.os.Looper;
import android.os.PowerManager;
-import android.os.RecoverySystem;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.os.ZygoteInit;
+import com.android.internal.widget.ILockSettings;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accounts.AccountManagerService;
import com.android.server.am.ActivityManagerService;
import com.android.server.input.InputManagerService;
import com.android.server.job.JobSchedulerService;
import com.android.server.lights.LightsService;
-import com.android.internal.widget.ILockSettings;
+import com.android.server.media.MediaResourceMonitorService;
import com.android.server.media.MediaRouterService;
import com.android.server.media.MediaSessionService;
-import com.android.server.media.MediaResourceMonitorService;
import com.android.server.media.projection.MediaProjectionManagerService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
// explicitly specifying a user.
Environment.setUserRequired(true);
+ // Within the system server, any incoming Bundles should be defused
+ // to avoid throwing BadParcelableException.
+ BaseBundle.setShouldDefuse(true);
+
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
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);
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;
r.run();
mContext.injectRestoreCallingIdentity(token);
}
+
+ @Override
+ void wtf(String message, Exception e) {
+ // During tests, WTF is fatal.
+ fail(message + " exception: " + e);
+ }
}
/** ShortcutManager with injection override methods. */
public void testPinShortcutAndGetPinnedShortcuts() {
// Create some shortcuts.
- setCaller(CALLING_PACKAGE_1);
- final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
- final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
+ final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
- assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+ });
- setCaller(CALLING_PACKAGE_2);
- final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
- final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
- final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
- assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
+ final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
+ final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+ });
- setCaller(CALLING_PACKAGE_3);
- final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
- assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2)));
+ runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+ final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s3_2)));
+ });
// Pin some.
- setCaller(LAUNCHER_1);
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ Arrays.asList("s2", "s3"), getCallingUser());
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
- Arrays.asList("s2", "s3"), getCallingUser());
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+ Arrays.asList("s3", "s4", "s5"), getCallingUser());
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
- Arrays.asList("s3", "s4", "s5"), getCallingUser());
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
+ Arrays.asList("s3"), getCallingUser()); // Note ID doesn't exist
+ });
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
- Arrays.asList("s3"), getCallingUser()); // Note ID doesn't exist
+ // Delete some.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+ mManager.deleteDynamicShortcut("s2");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+ });
+
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ mManager.deleteDynamicShortcut("s3");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ });
+
+ runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ mManager.deleteDynamicShortcut("s2");
+ assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ });
+
+ // Get pinned shortcuts from launcher
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s2");
+
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s3", "s4");
+
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+ /* none */);
+ });
+ }
+
+ public void testPinShortcutAndGetPinnedShortcuts_multi() {
+ // Create some shortcuts.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+
+ dumpsysOnLogcat();
+
+ // Pin some.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ Arrays.asList("s3", "s4"), getCallingUser());
+
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+ Arrays.asList("s1", "s2", "s4"), getCallingUser());
+ });
+
+ dumpsysOnLogcat();
// Delete some.
- setCaller(CALLING_PACKAGE_1);
- assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
- mManager.deleteDynamicShortcut("s2");
- assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+ mManager.deleteDynamicShortcut("s3");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+ });
- setCaller(CALLING_PACKAGE_2);
- assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
- mManager.deleteDynamicShortcut("s3");
- assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ dumpsysOnLogcat();
- setCaller(CALLING_PACKAGE_3);
- assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
- mManager.deleteDynamicShortcut("s2");
- assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
+ mManager.deleteDynamicShortcut("s1");
+ mManager.deleteDynamicShortcut("s3");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
+ });
+
+ dumpsysOnLogcat();
// Get pinned shortcuts from launcher
- setCaller(LAUNCHER_1);
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s3");
+
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s1", "s2");
+
+ assertShortcutIds(assertAllDynamicOrPinned(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s1", "s2", "s3");
+
+ assertShortcutIds(assertAllDynamicOrPinned(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s1", "s2");
+ });
- // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
- assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
- mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
- /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
- "s2");
+ dumpsysOnLogcat();
- assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
- mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
- /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
- "s3", "s4");
+ runWithCaller(LAUNCHER_2, USER_0, () -> {
+ // Launcher2 still has no pinned ones.
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+ /* none */);
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+ /* none */);
- assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
- mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
- /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
- /* none */);
+ assertShortcutIds(assertAllDynamic(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s1", "s2");
+ assertShortcutIds(assertAllDynamic(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s2");
+
+ // Now pin some.
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ Arrays.asList("s1", "s2"), getCallingUser());
+
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+ Arrays.asList("s1", "s2"), getCallingUser());
+
+ assertShortcutIds(assertAllDynamic(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s1", "s2");
+
+ // S1 was not visible to it, so shouldn't be pinned.
+ assertShortcutIds(assertAllDynamic(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s2");
+ });
+
+ // Re-initialize and load from the files.
+ initService();
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s3");
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s1", "s2");
+ });
+ runWithCaller(LAUNCHER_2, USER_0, () -> {
+ assertShortcutIds(assertAllDynamic(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s1", "s2");
+ assertShortcutIds(assertAllDynamic(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+ | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+ "s2");
+ });
+
+ // Delete all dynamic.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.deleteAllDynamicShortcuts();
+
+ assertEquals(0, mManager.getDynamicShortcuts().size());
+ assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ mManager.deleteAllDynamicShortcuts();
+
+ assertEquals(0, mManager.getDynamicShortcuts().size());
+ assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2", "s1");
+ });
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s3");
+
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s1", "s2");
+
+ // from all packages.
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, null,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s1", "s2", "s3");
+
+ // Update pined. Note s2 and s3 are actually available, but not visible to this
+ // launcher, so still can't be pinned.
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+ getCallingUser());
+
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s3");
+ });
+ // Re-publish s1.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+
+ assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+ assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
+ });
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s3");
+
+ // Now "s1" is visible, so can be pinned.
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+ getCallingUser());
+
+ assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+ "s1", "s3");
+ });
+
+ // Now clear pinned shortcuts. First, from launcher 1.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+
+ assertEquals(0,
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+ assertEquals(0,
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+ });
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+ assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2");
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertEquals(0, mManager.getDynamicShortcuts().size());
+ assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2");
+ });
+
+ // Clear all pins from launcher 2.
+ runWithCaller(LAUNCHER_2, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+
+ assertEquals(0,
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+ assertEquals(0,
+ mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+ });
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+ assertEquals(0, mManager.getPinnedShortcuts().size());
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertEquals(0, mManager.getDynamicShortcuts().size());
+ assertEquals(0, mManager.getPinnedShortcuts().size());
+ });
}
public void testCreateShortcutIntent() {
}
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
public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
/**
+ * Flag specifying whether ICCID is showed in SIM Status screen, default to false.
+ */
+ public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
+
+ /**
* Flag specifying whether an additional (client initiated) intent needs to be sent on System
* update
*/
sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false);
sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true);
sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
+ sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false);
sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
}
@Override
- public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+ public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
throw new UnsupportedOperationException();
}
}
@Override
- public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+ public boolean moveDatabaseFrom(Context sourceContext, String name) {
throw new UnsupportedOperationException();
}
}
@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();
}
}
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) {
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+ android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillType="evenOdd"
+ android:fillColor="#f00"
+ android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+ android:strokeColor="#000" android:strokeWidth="3"/>
+ <path android:fillType="evenOdd"
+ android:fillColor="#f00"
+ android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+ android:strokeColor="#000" android:strokeWidth="3"/>
+ <path android:fillType="evenOdd"
+ android:fillColor="#f00"
+ android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+ android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+ android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillType="nonZero"
+ android:fillColor="#f00"
+ android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+ android:strokeColor="#000" android:strokeWidth="3"/>
+ <path android:fillType="nonZero"
+ android:fillColor="#f00"
+ android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+ android:strokeColor="#000" android:strokeWidth="3"/>
+ <path android:fillType="nonZero"
+ android:fillColor="#f00"
+ android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+ android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
public class VectorDrawablePerformance extends Activity {
private static final String LOGCAT = "VectorDrawable1";
protected int[] icon = {
+ R.drawable.vector_icon_filltype_nonzero,
+ R.drawable.vector_icon_filltype_evenodd,
R.drawable.vector_icon_gradient_1,
R.drawable.vector_icon_gradient_2,
R.drawable.vector_icon_gradient_3,
sys.exit('None of characters in %s were found in %s' % (chars, font))
+def assert_font_supports_all_of_chars(font, chars):
+ best_cmap = get_best_cmap(font)
+ for char in chars:
+ assert char in best_cmap, (
+ 'U+%04X was not found in %s' % (char, font))
+
+
+def assert_font_supports_none_of_chars(font, chars):
+ best_cmap = get_best_cmap(font)
+ for char in chars:
+ assert char not in best_cmap, (
+ 'U+%04X was found in %s' % (char, font))
+
+
def check_hyphens(hyphens_dir):
# Find all the scripts that need automatic hyphenation
scripts = set()
_script_to_font_map[script].add((font_file, index))
+def check_emoji_availability():
+ emoji_fonts = [font[5] for font in _fallback_chain if 'Zsye' in font[1]]
+ emoji_chars = _emoji_properties['Emoji']
+ for emoji_font in emoji_fonts:
+ assert_font_supports_all_of_chars(emoji_font, emoji_chars)
+
+
+def check_emoji_defaults():
+ default_emoji_chars = _emoji_properties['Emoji_Presentation']
+ missing_text_chars = _emoji_properties['Emoji'] - default_emoji_chars
+ emoji_font_seen = False
+ for name, scripts, variant, weight, style, font in _fallback_chain:
+ if 'Zsye' in scripts:
+ emoji_font_seen = True
+ # No need to check the emoji font
+ continue
+ # For later fonts, we only check them if they have a script
+ # defined, since the defined script may get them to a higher
+ # score even if they appear after the emoji font.
+ if emoji_font_seen and not scripts:
+ continue
+
+ # Check default emoji-style characters
+ assert_font_supports_none_of_chars(font, sorted(default_emoji_chars))
+
+ # Mark default text-style characters appearing in fonts above the emoji
+ # font as seen
+ if not emoji_font_seen:
+ missing_text_chars -= set(get_best_cmap(font))
+
+ # Noto does not have monochrome symbols for Unicode 7.0 wingdings and
+ # webdings
+ missing_text_chars -= _chars_by_age['7.0']
+ # TODO: Remove these after b/26113320 is fixed
+ missing_text_chars -= {
+ 0x263A, # WHITE SMILING FACE
+ 0x270C, # VICTORY HAND
+ 0x2744, # SNOWFLAKE
+ 0x2764, # HEAVY BLACK HEART
+ }
+ assert missing_text_chars == set(), (
+ 'Text style version of some emoji characters are missing.')
+
+
+# Setting reverse to true returns a dictionary that maps the values to sets of
+# characters, useful for some binary properties. Otherwise, we get a
+# dictionary that maps characters to the property values, assuming there's only
+# one property in the file.
+def parse_unicode_datafile(file_path, reverse=False):
+ if reverse:
+ output_dict = collections.defaultdict(set)
+ else:
+ output_dict = {}
+ with open(file_path) as datafile:
+ for line in datafile:
+ if '#' in line:
+ line = line[:line.index('#')]
+ line = line.strip()
+ if not line:
+ continue
+ char_range, prop = line.split(';')
+ char_range = char_range.strip()
+ prop = prop.strip()
+ if '..' in char_range:
+ char_start, char_end = char_range.split('..')
+ else:
+ char_start = char_end = char_range
+ char_start = int(char_start, 16)
+ char_end = int(char_end, 16)
+ char_range = xrange(char_start, char_end+1)
+ if reverse:
+ output_dict[prop].update(char_range)
+ else:
+ for char in char_range:
+ assert char not in output_dict
+ output_dict[char] = prop
+ return output_dict
+
+
+def parse_ucd(ucd_path):
+ global _emoji_properties, _chars_by_age
+ _emoji_properties = parse_unicode_datafile(
+ path.join(ucd_path, 'emoji-data.txt'), reverse=True)
+ _chars_by_age = parse_unicode_datafile(
+ path.join(ucd_path, 'DerivedAge.txt'), reverse=True)
+
+
def main():
target_out = sys.argv[1]
global _fonts_dir
hyphens_dir = path.join(target_out, 'usr', 'hyphen-data')
check_hyphens(hyphens_dir)
+ ucd_path = sys.argv[2]
+ parse_ucd(ucd_path)
+ check_emoji_availability()
+ check_emoji_defaults()
+
if __name__ == '__main__':
main()
}
@Override
- public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+ public boolean moveDatabaseFrom(Context sourceContext, String name) {
// pass
return false;
}
}
@Override
- public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+ public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
// pass
return false;
}
}
@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;
}
}
}
@Override
+ public void flushPackageRestrictionsAsUser(int userId) {
+ }
+
+ @Override
public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
UserHandle userHandle) {
return false;