diff options
453 files changed, 8155 insertions, 3257 deletions
diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk index 3a7f945f55fd..200f92fb590c 100644 --- a/apct-tests/perftests/core/Android.mk +++ b/apct-tests/perftests/core/Android.mk @@ -8,7 +8,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_JAVA_LIBRARIES := \ android-support-test \ - apct-perftests-utils + apct-perftests-utils \ + legacy-android-test LOCAL_PACKAGE_NAME := CorePerfTests diff --git a/api/current.txt b/api/current.txt index ddaf8c1f8f7f..9f1ab1bfc796 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1054,6 +1054,7 @@ package android { field public static final int resizeable = 16843405; // 0x101028d field public static final int resizeableActivity = 16844022; // 0x10104f6 field public static final int resource = 16842789; // 0x1010025 + field public static final int restartOnConfigChanges = 16844105; // 0x1010549 field public static final int restoreAnyVersion = 16843450; // 0x10102ba field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d field public static final int restrictedAccountType = 16843733; // 0x10103d5 @@ -1378,7 +1379,7 @@ package android { field public static final int toYDelta = 16843209; // 0x10101c9 field public static final int toYScale = 16843205; // 0x10101c5 field public static final int toolbarStyle = 16843946; // 0x10104aa - field public static final int tooltip = 16844084; // 0x1010534 + field public static final int tooltipText = 16844084; // 0x1010534 field public static final int top = 16843182; // 0x10101ae field public static final int topBright = 16842955; // 0x10100cb field public static final int topDark = 16842951; // 0x10100c7 @@ -2880,15 +2881,18 @@ package android.accounts { public class AccountManager { method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle); - method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, int[]); + method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>); method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean); + method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]); method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException; method public void clearPassword(android.accounts.Account); method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public static android.accounts.AccountManager get(android.content.Context); + method public int getAccountVisibility(android.accounts.Account, int); method public android.accounts.Account[] getAccounts(); + method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String); method public android.accounts.Account[] getAccountsByType(java.lang.String); method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler); method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String); @@ -2899,13 +2903,11 @@ package android.accounts { method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes(); method public java.lang.String getPassword(android.accounts.Account); method public java.lang.String getPreviousName(android.accounts.Account); - method public int[] getRequestingUidsForType(java.lang.String); + method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account); method public java.lang.String getUserData(android.accounts.Account, java.lang.String); method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public void invalidateAuthToken(java.lang.String, java.lang.String); - method public boolean isAccountVisible(android.accounts.Account, int); method public android.accounts.AccountManagerFuture<java.lang.Boolean> isCredentialsUpdateSuggested(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); - method public boolean makeAccountVisible(android.accounts.Account, int); method public static deprecated android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.List<android.accounts.Account>, java.lang.String[], java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); method public boolean notifyAccountAuthenticated(android.accounts.Account); @@ -2913,9 +2915,9 @@ package android.accounts { method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean removeAccountExplicitly(android.accounts.Account); - method public boolean removeAccountVisibility(android.accounts.Account, int); method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener); method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler); + method public boolean setAccountVisibility(android.accounts.Account, int, int); method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String); method public void setPassword(android.accounts.Account, java.lang.String); method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String); @@ -2954,7 +2956,14 @@ package android.accounts { field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime"; field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; - field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; + field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; + field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd + field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe + field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3 + field public static final int VISIBILITY_UNDEFINED = 0; // 0x0 + field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4 + field public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2; // 0x2 + field public static final int VISIBILITY_VISIBLE = 1; // 0x1 } public abstract interface AccountManagerCallback<V> { @@ -3492,8 +3501,7 @@ package android.app { method public boolean dispatchTrackballEvent(android.view.MotionEvent); method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public void enterPictureInPictureMode(); - method public void enterPictureInPictureMode(float); - method public void enterPictureInPictureModeOnMoveToBackground(boolean); + method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs); method public android.view.View findViewById(int); method public void finish(); method public void finishActivity(int); @@ -3666,8 +3674,7 @@ package android.app { method public void setIntent(android.content.Intent); method public final void setMediaController(android.media.session.MediaController); method public void setOverlayWithDecorCaptionEnabled(boolean); - method public void setPictureInPictureActions(java.util.List<android.app.RemoteAction>); - method public void setPictureInPictureAspectRatio(float); + method public void setPictureInPictureArgs(android.app.PictureInPictureArgs); method public final deprecated void setProgress(int); method public final deprecated void setProgressBarIndeterminate(boolean); method public final deprecated void setProgressBarIndeterminateVisibility(boolean); @@ -4829,11 +4836,13 @@ package android.app { public static class Instrumentation.ActivityMonitor { ctor public Instrumentation.ActivityMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean); ctor public Instrumentation.ActivityMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean); + ctor public Instrumentation.ActivityMonitor(); method public final android.content.IntentFilter getFilter(); method public final int getHits(); method public final android.app.Activity getLastActivity(); method public final android.app.Instrumentation.ActivityResult getResult(); method public final boolean isBlocking(); + method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent); method public final android.app.Activity waitForActivity(); method public final android.app.Activity waitForActivityWithTimeout(long); } @@ -5402,7 +5411,6 @@ package android.app { method public java.lang.CharSequence getName(); method public android.net.Uri getSound(); method public long[] getVibrationPattern(); - method public boolean isAllowed(); method public void setBypassDnd(boolean); method public void setImportance(int); method public void setLights(boolean); @@ -5440,6 +5448,7 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); + method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; @@ -5525,6 +5534,17 @@ package android.app { method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle); } + public final class PictureInPictureArgs implements android.os.Parcelable { + ctor public PictureInPictureArgs(); + ctor public PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>); + method public android.app.PictureInPictureArgs clone(); + method public int describeContents(); + method public void setActions(java.util.List<android.app.RemoteAction>); + method public void setAspectRatio(float); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR; + } + public class Presentation extends android.app.Dialog { ctor public Presentation(android.content.Context, android.view.Display); ctor public Presentation(android.content.Context, android.view.Display, int); @@ -6139,6 +6159,7 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String); + method public boolean isBackupServiceEnabled(android.content.ComponentName); method public boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isDeviceOwnerApp(java.lang.String); method public boolean isLockTaskPermitted(java.lang.String); @@ -6169,6 +6190,7 @@ package android.app.admin { method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public void setAutoTimeRequired(android.content.ComponentName, boolean); + method public void setBackupServiceEnabled(android.content.ComponentName, boolean); method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean); method public void setCameraDisabled(android.content.ComponentName, boolean); method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; @@ -9533,6 +9555,7 @@ package android.content.pm { method public int describeContents(); method public void dump(android.util.Printer, java.lang.String); method public final int getThemeResource(); + field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000 field public static final int CONFIG_DENSITY = 4096; // 0x1000 field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000 field public static final int CONFIG_KEYBOARD = 16; // 0x10 @@ -9804,6 +9827,7 @@ package android.content.pm { method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle); method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle); method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent); + method public java.util.List<android.os.UserHandle> getProfiles(); method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int); method public android.content.IntentSender getShortcutConfigActivityIntent(android.content.pm.LauncherActivityInfo); method public java.util.List<android.content.pm.LauncherActivityInfo> getShortcutConfigActivityList(java.lang.String, android.os.UserHandle); @@ -9841,7 +9865,7 @@ package android.content.pm { method public boolean accept(android.os.Bundle); method public boolean accept(); method public int describeContents(); - method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(); + method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context); method public int getRequestType(); method public android.content.pm.ShortcutInfo getShortcutInfo(); method public boolean isValid(); @@ -10527,7 +10551,9 @@ package android.content.res { method public int getLayoutDirection(); method public android.os.LocaleList getLocales(); method public boolean isLayoutSizeAtLeast(int); + method public boolean isScreenHdr(); method public boolean isScreenRound(); + method public boolean isScreenWideColorGamut(); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); method public void setLayoutDirection(java.util.Locale); @@ -10537,6 +10563,16 @@ package android.content.res { method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); method public void writeToParcel(android.os.Parcel, int); + field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc + field public static final int COLORIMETRY_HDR_NO = 4; // 0x4 + field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2 + field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_HDR_YES = 8; // 0x8 + field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2 field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR; field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0 field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1 @@ -10602,6 +10638,7 @@ package android.content.res { field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0 field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7 field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6 + field public int colorimetry; field public int densityDpi; field public float fontScale; field public int hardKeyboardHidden; @@ -12587,7 +12624,6 @@ package android.graphics { method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt); method public android.graphics.Paint.FontMetricsInt getFontMetricsInt(); method public float getFontSpacing(); - method public java.lang.String getFontVariationSettings(); method public int getHinting(); method public float getLetterSpacing(); method public android.graphics.MaskFilter getMaskFilter(); @@ -12645,7 +12681,6 @@ package android.graphics { method public void setFilterBitmap(boolean); method public void setFlags(int); method public void setFontFeatureSettings(java.lang.String); - method public void setFontVariationSettings(java.lang.String); method public void setHinting(int); method public void setLetterSpacing(float); method public void setLinearText(boolean); @@ -24473,6 +24508,7 @@ package android.net { public class TrafficStats { ctor public TrafficStats(); method public static void clearThreadStatsTag(); + method public static int getAndSetThreadStatsTag(int); method public static long getMobileRxBytes(); method public static long getMobileRxPackets(); method public static long getMobileTxBytes(); @@ -30054,6 +30090,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); + method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeath(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure(); @@ -35246,6 +35283,7 @@ package android.security.keystore { field public static final int PURPOSE_ENCRYPT = 1; // 0x1 field public static final int PURPOSE_SIGN = 4; // 0x4 field public static final int PURPOSE_VERIFY = 8; // 0x8 + field public static final int PURPOSE_WRAP_KEY = 16; // 0x10 field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1"; field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS"; } @@ -39035,6 +39073,7 @@ package android.test.mock { method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public android.content.ComponentName startService(android.content.Intent); + method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean stopService(android.content.Intent); method public void unbindService(android.content.ServiceConnection); method public void unregisterReceiver(android.content.BroadcastReceiver); @@ -42897,7 +42936,7 @@ package android.view { method public abstract android.view.SubMenu getSubMenu(); method public abstract java.lang.CharSequence getTitle(); method public abstract java.lang.CharSequence getTitleCondensed(); - method public default java.lang.CharSequence getTooltip(); + method public default java.lang.CharSequence getTooltipText(); method public abstract boolean hasSubMenu(); method public abstract boolean isActionViewExpanded(); method public abstract boolean isCheckable(); @@ -42924,7 +42963,7 @@ package android.view { method public abstract android.view.MenuItem setTitle(java.lang.CharSequence); method public abstract android.view.MenuItem setTitle(int); method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence); - method public default android.view.MenuItem setTooltip(java.lang.CharSequence); + method public default android.view.MenuItem setTooltipText(java.lang.CharSequence); method public abstract android.view.MenuItem setVisible(boolean); field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2 field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8 @@ -43618,7 +43657,8 @@ package android.view { method public java.lang.Object getTag(int); method public int getTextAlignment(); method public int getTextDirection(); - method public final java.lang.CharSequence getTooltip(); + method public final deprecated java.lang.CharSequence getTooltip(); + method public final java.lang.CharSequence getTooltipText(); method public final int getTop(); method protected float getTopFadingEdgeStrength(); method protected int getTopPaddingOffset(); @@ -43919,7 +43959,8 @@ package android.view { method public void setTag(int, java.lang.Object); method public void setTextAlignment(int); method public void setTextDirection(int); - method public final void setTooltip(java.lang.CharSequence); + method public final deprecated void setTooltip(java.lang.CharSequence); + method public final void setTooltipText(java.lang.CharSequence); method public final void setTop(int); method public void setTouchDelegate(android.view.TouchDelegate); method public final void setTransitionName(java.lang.String); @@ -49335,7 +49376,6 @@ package android.widget { method public int getExtendedPaddingTop(); method public android.text.InputFilter[] getFilters(); method public java.lang.String getFontFeatureSettings(); - method public java.lang.String getFontVariationSettings(); method public boolean getFreezesText(); method public int getGravity(); method public int getHighlightColor(); @@ -49441,7 +49481,6 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFilters(android.text.InputFilter[]); method public void setFontFeatureSettings(java.lang.String); - method public void setFontVariationSettings(java.lang.String); method protected boolean setFrame(int, int, int, int); method public void setFreezesText(boolean); method public void setGravity(int); diff --git a/api/system-current.txt b/api/system-current.txt index f3a0a346ebd9..5c107aec939c 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1163,6 +1163,7 @@ package android { field public static final int resizeable = 16843405; // 0x101028d field public static final int resizeableActivity = 16844022; // 0x10104f6 field public static final int resource = 16842789; // 0x1010025 + field public static final int restartOnConfigChanges = 16844105; // 0x1010549 field public static final int restoreAnyVersion = 16843450; // 0x10102ba field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d field public static final int restrictedAccountType = 16843733; // 0x10103d5 @@ -1491,7 +1492,7 @@ package android { field public static final int toYDelta = 16843209; // 0x10101c9 field public static final int toYScale = 16843205; // 0x10101c5 field public static final int toolbarStyle = 16843946; // 0x10104aa - field public static final int tooltip = 16844084; // 0x1010534 + field public static final int tooltipText = 16844084; // 0x1010534 field public static final int top = 16843182; // 0x10101ae field public static final int topBright = 16842955; // 0x10100cb field public static final int topDark = 16842951; // 0x10100c7 @@ -2996,8 +2997,9 @@ package android.accounts { public class AccountManager { method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle); - method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, int[]); + method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>); method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean); + method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]); method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException; method public void clearPassword(android.accounts.Account); method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); @@ -3005,7 +3007,9 @@ package android.accounts { method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSessionAsUser(android.os.Bundle, android.app.Activity, android.os.UserHandle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public static android.accounts.AccountManager get(android.content.Context); + method public int getAccountVisibility(android.accounts.Account, int); method public android.accounts.Account[] getAccounts(); + method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String); method public android.accounts.Account[] getAccountsByType(java.lang.String); method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler); method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String); @@ -3016,13 +3020,11 @@ package android.accounts { method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes(); method public java.lang.String getPassword(android.accounts.Account); method public java.lang.String getPreviousName(android.accounts.Account); - method public int[] getRequestingUidsForType(java.lang.String); + method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account); method public java.lang.String getUserData(android.accounts.Account, java.lang.String); method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public void invalidateAuthToken(java.lang.String, java.lang.String); - method public boolean isAccountVisible(android.accounts.Account, int); method public android.accounts.AccountManagerFuture<java.lang.Boolean> isCredentialsUpdateSuggested(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); - method public boolean makeAccountVisible(android.accounts.Account, int); method public static deprecated android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.List<android.accounts.Account>, java.lang.String[], java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); method public boolean notifyAccountAuthenticated(android.accounts.Account); @@ -3030,9 +3032,9 @@ package android.accounts { method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean removeAccountExplicitly(android.accounts.Account); - method public boolean removeAccountVisibility(android.accounts.Account, int); method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener); method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler); + method public boolean setAccountVisibility(android.accounts.Account, int, int); method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String); method public void setPassword(android.accounts.Account, java.lang.String); method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String); @@ -3071,7 +3073,14 @@ package android.accounts { field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime"; field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; - field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; + field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; + field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd + field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe + field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3 + field public static final int VISIBILITY_UNDEFINED = 0; // 0x0 + field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4 + field public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2; // 0x2 + field public static final int VISIBILITY_VISIBLE = 1; // 0x1 } public abstract interface AccountManagerCallback<V> { @@ -3611,8 +3620,7 @@ package android.app { method public boolean dispatchTrackballEvent(android.view.MotionEvent); method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public void enterPictureInPictureMode(); - method public void enterPictureInPictureMode(float); - method public void enterPictureInPictureModeOnMoveToBackground(boolean); + method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs); method public android.view.View findViewById(int); method public void finish(); method public void finishActivity(int); @@ -3787,8 +3795,7 @@ package android.app { method public void setIntent(android.content.Intent); method public final void setMediaController(android.media.session.MediaController); method public void setOverlayWithDecorCaptionEnabled(boolean); - method public void setPictureInPictureActions(java.util.List<android.app.RemoteAction>); - method public void setPictureInPictureAspectRatio(float); + method public void setPictureInPictureArgs(android.app.PictureInPictureArgs); method public final deprecated void setProgress(int); method public final deprecated void setProgressBarIndeterminate(boolean); method public final deprecated void setProgressBarIndeterminateVisibility(boolean); @@ -4986,11 +4993,13 @@ package android.app { public static class Instrumentation.ActivityMonitor { ctor public Instrumentation.ActivityMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean); ctor public Instrumentation.ActivityMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean); + ctor public Instrumentation.ActivityMonitor(); method public final android.content.IntentFilter getFilter(); method public final int getHits(); method public final android.app.Activity getLastActivity(); method public final android.app.Instrumentation.ActivityResult getResult(); method public final boolean isBlocking(); + method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent); method public final android.app.Activity waitForActivity(); method public final android.app.Activity waitForActivityWithTimeout(long); } @@ -5574,10 +5583,11 @@ package android.app { method public android.net.Uri getSound(); method public int getUserLockedFields(); method public long[] getVibrationPattern(); - method public boolean isAllowed(); + method public boolean isDeleted(); method public void lockFields(int); method public void populateFromXml(org.xmlpull.v1.XmlPullParser); method public void setBypassDnd(boolean); + method public void setDeleted(boolean); method public void setImportance(int); method public void setLights(boolean); method public void setLockscreenVisibility(int); @@ -5625,6 +5635,7 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); + method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; @@ -5710,6 +5721,17 @@ package android.app { method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle); } + public final class PictureInPictureArgs implements android.os.Parcelable { + ctor public PictureInPictureArgs(); + ctor public PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>); + method public android.app.PictureInPictureArgs clone(); + method public int describeContents(); + method public void setActions(java.util.List<android.app.RemoteAction>); + method public void setAspectRatio(float); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR; + } + public class Presentation extends android.app.Dialog { ctor public Presentation(android.content.Context, android.view.Display); ctor public Presentation(android.content.Context, android.view.Display, int); @@ -6340,6 +6362,7 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String); + method public boolean isBackupServiceEnabled(android.content.ComponentName); method public boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isDeviceManaged(); method public boolean isDeviceOwnerApp(java.lang.String); @@ -6357,6 +6380,7 @@ package android.app.admin { method public void lockNow(); method public void lockNow(int); method public void notifyPendingSystemUpdate(long); + method public boolean packageHasActiveAdmins(java.lang.String); method public void reboot(android.content.ComponentName); method public void removeActiveAdmin(android.content.ComponentName); method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); @@ -6375,6 +6399,7 @@ package android.app.admin { method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public void setAutoTimeRequired(android.content.ComponentName, boolean); + method public void setBackupServiceEnabled(android.content.ComponentName, boolean); method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean); method public void setCameraDisabled(android.content.ComponentName, boolean); method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; @@ -6739,6 +6764,7 @@ package android.app.backup { method public boolean isBackupEnabled(); method public java.lang.String[] listAllTransports(); method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver); + method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver, int); method public int requestRestore(android.app.backup.RestoreObserver); method public java.lang.String selectBackupTransport(java.lang.String); method public void setAutoRestore(boolean); @@ -6749,6 +6775,8 @@ package android.app.backup { field public static final int ERROR_TRANSPORT_ABORTED = -1000; // 0xfffffc18 field public static final int ERROR_TRANSPORT_PACKAGE_REJECTED = -1002; // 0xfffffc16 field public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED = -1005; // 0xfffffc13 + field public static final int FLAG_NON_INCREMENTAL_BACKUP = 1; // 0x1 + field public static final java.lang.String PACKAGE_MANAGER_SENTINEL = "@pm@"; field public static final int SUCCESS = 0; // 0x0 } @@ -9927,6 +9955,7 @@ package android.content.pm { method public int describeContents(); method public void dump(android.util.Printer, java.lang.String); method public final int getThemeResource(); + field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000 field public static final int CONFIG_DENSITY = 4096; // 0x1000 field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000 field public static final int CONFIG_KEYBOARD = 16; // 0x10 @@ -10232,6 +10261,7 @@ package android.content.pm { method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle); method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle); method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent); + method public java.util.List<android.os.UserHandle> getProfiles(); method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int); method public android.content.IntentSender getShortcutConfigActivityIntent(android.content.pm.LauncherActivityInfo); method public java.util.List<android.content.pm.LauncherActivityInfo> getShortcutConfigActivityList(java.lang.String, android.os.UserHandle); @@ -10269,7 +10299,7 @@ package android.content.pm { method public boolean accept(android.os.Bundle); method public boolean accept(); method public int describeContents(); - method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(); + method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context); method public int getRequestType(); method public android.content.pm.ShortcutInfo getShortcutInfo(); method public boolean isValid(); @@ -10616,6 +10646,7 @@ package android.content.pm { field public static final java.lang.String FEATURE_SIP = "android.software.sip"; field public static final java.lang.String FEATURE_SIP_VOIP = "android.software.sip.voip"; field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony"; + field public static final java.lang.String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock"; field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma"; field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm"; field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television"; @@ -11042,7 +11073,9 @@ package android.content.res { method public int getLayoutDirection(); method public android.os.LocaleList getLocales(); method public boolean isLayoutSizeAtLeast(int); + method public boolean isScreenHdr(); method public boolean isScreenRound(); + method public boolean isScreenWideColorGamut(); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); method public void setLayoutDirection(java.util.Locale); @@ -11052,6 +11085,16 @@ package android.content.res { method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); method public void writeToParcel(android.os.Parcel, int); + field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc + field public static final int COLORIMETRY_HDR_NO = 4; // 0x4 + field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2 + field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_HDR_YES = 8; // 0x8 + field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2 field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR; field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0 field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1 @@ -11117,6 +11160,7 @@ package android.content.res { field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0 field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7 field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6 + field public int colorimetry; field public int densityDpi; field public float fontScale; field public int hardKeyboardHidden; @@ -13102,7 +13146,6 @@ package android.graphics { method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt); method public android.graphics.Paint.FontMetricsInt getFontMetricsInt(); method public float getFontSpacing(); - method public java.lang.String getFontVariationSettings(); method public int getHinting(); method public float getLetterSpacing(); method public android.graphics.MaskFilter getMaskFilter(); @@ -13160,7 +13203,6 @@ package android.graphics { method public void setFilterBitmap(boolean); method public void setFlags(int); method public void setFontFeatureSettings(java.lang.String); - method public void setFontVariationSettings(java.lang.String); method public void setHinting(int); method public void setLetterSpacing(float); method public void setLinearText(boolean); @@ -26348,6 +26390,8 @@ package android.net { method public android.net.wifi.WifiConfiguration[] getConnectableConfigs(); method public android.net.wifi.WifiConfiguration getConnectedConfig(); method public android.net.wifi.WifiConfiguration getDefaultWifiConfig(); + method public int getLastSelectedNetworkId(); + method public long getLastSelectedNetworkTimestamp(); method public android.net.wifi.ScanResult[] getScanResults(); method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]); method public void setConnectedConfig(android.net.wifi.WifiConfiguration); @@ -26361,6 +26405,7 @@ package android.net { method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]); method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration); method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration); + method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long); method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]); } @@ -26452,6 +26497,7 @@ package android.net { ctor public TrafficStats(); method public static void clearThreadStatsTag(); method public static void clearThreadStatsUid(); + method public static int getAndSetThreadStatsTag(int); method public static long getMobileRxBytes(); method public static long getMobileRxPackets(); method public static long getMobileTxBytes(); @@ -27458,6 +27504,7 @@ package android.net.wifi { method public int describeContents(); method public android.net.ProxyInfo getHttpProxy(); method public boolean hasNoInternetAccess(); + method public boolean isEphemeral(); method public boolean isNoInternetAccessExpected(); method public boolean isPasspoint(); method public void setHttpProxy(android.net.ProxyInfo); @@ -32698,6 +32745,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); + method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeath(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure(); @@ -38149,6 +38197,7 @@ package android.security.keystore { field public static final int PURPOSE_ENCRYPT = 1; // 0x1 field public static final int PURPOSE_SIGN = 4; // 0x4 field public static final int PURPOSE_VERIFY = 8; // 0x8 + field public static final int PURPOSE_WRAP_KEY = 16; // 0x10 field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1"; field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS"; } @@ -41521,6 +41570,7 @@ package android.telephony { method public void enableVideoCalling(boolean); method public boolean endCall(); method public java.util.List<android.telephony.CellInfo> getAllCellInfo(); + method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); method public int getCallState(); method public android.os.PersistableBundle getCarrierConfig(); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); @@ -41596,6 +41646,7 @@ package android.telephony { method public java.lang.String sendEnvelopeWithStatus(java.lang.String); method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler); method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler); + method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method public void setDataEnabled(boolean); method public void setDataEnabled(int, boolean); method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String); @@ -42287,6 +42338,7 @@ package android.test.mock { method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public android.content.ComponentName startService(android.content.Intent); + method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean stopService(android.content.Intent); method public void unbindService(android.content.ServiceConnection); method public void unregisterReceiver(android.content.BroadcastReceiver); @@ -46157,7 +46209,7 @@ package android.view { method public abstract android.view.SubMenu getSubMenu(); method public abstract java.lang.CharSequence getTitle(); method public abstract java.lang.CharSequence getTitleCondensed(); - method public default java.lang.CharSequence getTooltip(); + method public default java.lang.CharSequence getTooltipText(); method public abstract boolean hasSubMenu(); method public abstract boolean isActionViewExpanded(); method public abstract boolean isCheckable(); @@ -46184,7 +46236,7 @@ package android.view { method public abstract android.view.MenuItem setTitle(java.lang.CharSequence); method public abstract android.view.MenuItem setTitle(int); method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence); - method public default android.view.MenuItem setTooltip(java.lang.CharSequence); + method public default android.view.MenuItem setTooltipText(java.lang.CharSequence); method public abstract android.view.MenuItem setVisible(boolean); field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2 field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8 @@ -46878,7 +46930,8 @@ package android.view { method public java.lang.Object getTag(int); method public int getTextAlignment(); method public int getTextDirection(); - method public final java.lang.CharSequence getTooltip(); + method public final deprecated java.lang.CharSequence getTooltip(); + method public final java.lang.CharSequence getTooltipText(); method public final int getTop(); method protected float getTopFadingEdgeStrength(); method protected int getTopPaddingOffset(); @@ -47179,7 +47232,8 @@ package android.view { method public void setTag(int, java.lang.Object); method public void setTextAlignment(int); method public void setTextDirection(int); - method public final void setTooltip(java.lang.CharSequence); + method public final deprecated void setTooltip(java.lang.CharSequence); + method public final void setTooltipText(java.lang.CharSequence); method public final void setTop(int); method public void setTouchDelegate(android.view.TouchDelegate); method public final void setTransitionName(java.lang.String); @@ -52955,7 +53009,6 @@ package android.widget { method public int getExtendedPaddingTop(); method public android.text.InputFilter[] getFilters(); method public java.lang.String getFontFeatureSettings(); - method public java.lang.String getFontVariationSettings(); method public boolean getFreezesText(); method public int getGravity(); method public int getHighlightColor(); @@ -53061,7 +53114,6 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFilters(android.text.InputFilter[]); method public void setFontFeatureSettings(java.lang.String); - method public void setFontVariationSettings(java.lang.String); method protected boolean setFrame(int, int, int, int); method public void setFreezesText(boolean); method public void setGravity(int); diff --git a/api/test-current.txt b/api/test-current.txt index f29820fad065..84aa96c89b03 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1054,6 +1054,7 @@ package android { field public static final int resizeable = 16843405; // 0x101028d field public static final int resizeableActivity = 16844022; // 0x10104f6 field public static final int resource = 16842789; // 0x1010025 + field public static final int restartOnConfigChanges = 16844105; // 0x1010549 field public static final int restoreAnyVersion = 16843450; // 0x10102ba field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d field public static final int restrictedAccountType = 16843733; // 0x10103d5 @@ -1378,7 +1379,7 @@ package android { field public static final int toYDelta = 16843209; // 0x10101c9 field public static final int toYScale = 16843205; // 0x10101c5 field public static final int toolbarStyle = 16843946; // 0x10104aa - field public static final int tooltip = 16844084; // 0x1010534 + field public static final int tooltipText = 16844084; // 0x1010534 field public static final int top = 16843182; // 0x10101ae field public static final int topBright = 16842955; // 0x10100cb field public static final int topDark = 16842951; // 0x10100c7 @@ -2880,15 +2881,18 @@ package android.accounts { public class AccountManager { method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle); - method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, int[]); + method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>); method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean); + method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]); method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException; method public void clearPassword(android.accounts.Account); method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public static android.accounts.AccountManager get(android.content.Context); + method public int getAccountVisibility(android.accounts.Account, int); method public android.accounts.Account[] getAccounts(); + method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String); method public android.accounts.Account[] getAccountsByType(java.lang.String); method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler); method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String); @@ -2899,13 +2903,11 @@ package android.accounts { method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes(); method public java.lang.String getPassword(android.accounts.Account); method public java.lang.String getPreviousName(android.accounts.Account); - method public int[] getRequestingUidsForType(java.lang.String); + method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account); method public java.lang.String getUserData(android.accounts.Account, java.lang.String); method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public void invalidateAuthToken(java.lang.String, java.lang.String); - method public boolean isAccountVisible(android.accounts.Account, int); method public android.accounts.AccountManagerFuture<java.lang.Boolean> isCredentialsUpdateSuggested(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); - method public boolean makeAccountVisible(android.accounts.Account, int); method public static deprecated android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.List<android.accounts.Account>, java.lang.String[], java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); method public boolean notifyAccountAuthenticated(android.accounts.Account); @@ -2913,9 +2915,9 @@ package android.accounts { method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean removeAccountExplicitly(android.accounts.Account); - method public boolean removeAccountVisibility(android.accounts.Account, int); method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener); method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler); + method public boolean setAccountVisibility(android.accounts.Account, int, int); method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String); method public void setPassword(android.accounts.Account, java.lang.String); method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String); @@ -2954,7 +2956,14 @@ package android.accounts { field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime"; field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; - field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; + field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; + field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd + field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe + field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3 + field public static final int VISIBILITY_UNDEFINED = 0; // 0x0 + field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4 + field public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2; // 0x2 + field public static final int VISIBILITY_VISIBLE = 1; // 0x1 } public abstract interface AccountManagerCallback<V> { @@ -3494,8 +3503,7 @@ package android.app { method public boolean dispatchTrackballEvent(android.view.MotionEvent); method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public void enterPictureInPictureMode(); - method public void enterPictureInPictureMode(float); - method public void enterPictureInPictureModeOnMoveToBackground(boolean); + method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs); method public android.view.View findViewById(int); method public void finish(); method public void finishActivity(int); @@ -3668,8 +3676,7 @@ package android.app { method public void setIntent(android.content.Intent); method public final void setMediaController(android.media.session.MediaController); method public void setOverlayWithDecorCaptionEnabled(boolean); - method public void setPictureInPictureActions(java.util.List<android.app.RemoteAction>); - method public void setPictureInPictureAspectRatio(float); + method public void setPictureInPictureArgs(android.app.PictureInPictureArgs); method public final deprecated void setProgress(int); method public final deprecated void setProgressBarIndeterminate(boolean); method public final deprecated void setProgressBarIndeterminateVisibility(boolean); @@ -4839,11 +4846,13 @@ package android.app { public static class Instrumentation.ActivityMonitor { ctor public Instrumentation.ActivityMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean); ctor public Instrumentation.ActivityMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean); + ctor public Instrumentation.ActivityMonitor(); method public final android.content.IntentFilter getFilter(); method public final int getHits(); method public final android.app.Activity getLastActivity(); method public final android.app.Instrumentation.ActivityResult getResult(); method public final boolean isBlocking(); + method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent); method public final android.app.Activity waitForActivity(); method public final android.app.Activity waitForActivityWithTimeout(long); } @@ -5412,7 +5421,6 @@ package android.app { method public java.lang.CharSequence getName(); method public android.net.Uri getSound(); method public long[] getVibrationPattern(); - method public boolean isAllowed(); method public void setBypassDnd(boolean); method public void setImportance(int); method public void setLights(boolean); @@ -5451,6 +5459,7 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); + method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; @@ -5536,6 +5545,17 @@ package android.app { method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle); } + public final class PictureInPictureArgs implements android.os.Parcelable { + ctor public PictureInPictureArgs(); + ctor public PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>); + method public android.app.PictureInPictureArgs clone(); + method public int describeContents(); + method public void setActions(java.util.List<android.app.RemoteAction>); + method public void setAspectRatio(float); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR; + } + public class Presentation extends android.app.Dialog { ctor public Presentation(android.content.Context, android.view.Display); ctor public Presentation(android.content.Context, android.view.Display, int); @@ -6160,6 +6180,7 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String); + method public boolean isBackupServiceEnabled(android.content.ComponentName); method public boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isDeviceManaged(); method public boolean isDeviceOwnerApp(java.lang.String); @@ -6191,6 +6212,7 @@ package android.app.admin { method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public void setAutoTimeRequired(android.content.ComponentName, boolean); + method public void setBackupServiceEnabled(android.content.ComponentName, boolean); method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean); method public void setCameraDisabled(android.content.ComponentName, boolean); method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; @@ -9558,6 +9580,7 @@ package android.content.pm { method public int describeContents(); method public void dump(android.util.Printer, java.lang.String); method public final int getThemeResource(); + field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000 field public static final int CONFIG_DENSITY = 4096; // 0x1000 field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000 field public static final int CONFIG_KEYBOARD = 16; // 0x10 @@ -9832,6 +9855,7 @@ package android.content.pm { method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle); method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle); method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent); + method public java.util.List<android.os.UserHandle> getProfiles(); method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int); method public android.content.IntentSender getShortcutConfigActivityIntent(android.content.pm.LauncherActivityInfo); method public java.util.List<android.content.pm.LauncherActivityInfo> getShortcutConfigActivityList(java.lang.String, android.os.UserHandle); @@ -9869,7 +9893,7 @@ package android.content.pm { method public boolean accept(android.os.Bundle); method public boolean accept(); method public int describeContents(); - method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(); + method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context); method public int getRequestType(); method public android.content.pm.ShortcutInfo getShortcutInfo(); method public boolean isValid(); @@ -10559,7 +10583,9 @@ package android.content.res { method public int getLayoutDirection(); method public android.os.LocaleList getLocales(); method public boolean isLayoutSizeAtLeast(int); + method public boolean isScreenHdr(); method public boolean isScreenRound(); + method public boolean isScreenWideColorGamut(); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); method public void setLayoutDirection(java.util.Locale); @@ -10569,6 +10595,16 @@ package android.content.res { method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); method public void writeToParcel(android.os.Parcel, int); + field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc + field public static final int COLORIMETRY_HDR_NO = 4; // 0x4 + field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2 + field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_HDR_YES = 8; // 0x8 + field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0 + field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2 field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR; field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0 field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1 @@ -10634,6 +10670,7 @@ package android.content.res { field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0 field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7 field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6 + field public int colorimetry; field public int densityDpi; field public float fontScale; field public int hardKeyboardHidden; @@ -12619,7 +12656,6 @@ package android.graphics { method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt); method public android.graphics.Paint.FontMetricsInt getFontMetricsInt(); method public float getFontSpacing(); - method public java.lang.String getFontVariationSettings(); method public int getHinting(); method public float getLetterSpacing(); method public android.graphics.MaskFilter getMaskFilter(); @@ -12677,7 +12713,6 @@ package android.graphics { method public void setFilterBitmap(boolean); method public void setFlags(int); method public void setFontFeatureSettings(java.lang.String); - method public void setFontVariationSettings(java.lang.String); method public void setHinting(int); method public void setLetterSpacing(float); method public void setLinearText(boolean); @@ -24563,6 +24598,7 @@ package android.net { public class TrafficStats { ctor public TrafficStats(); method public static void clearThreadStatsTag(); + method public static int getAndSetThreadStatsTag(int); method public static long getMobileRxBytes(); method public static long getMobileRxPackets(); method public static long getMobileTxBytes(); @@ -30166,6 +30202,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); + method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeath(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure(); @@ -35367,6 +35404,7 @@ package android.security.keystore { field public static final int PURPOSE_ENCRYPT = 1; // 0x1 field public static final int PURPOSE_SIGN = 4; // 0x4 field public static final int PURPOSE_VERIFY = 8; // 0x8 + field public static final int PURPOSE_WRAP_KEY = 16; // 0x10 field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1"; field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS"; } @@ -39157,6 +39195,7 @@ package android.test.mock { method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public android.content.ComponentName startService(android.content.Intent); + method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean stopService(android.content.Intent); method public void unbindService(android.content.ServiceConnection); method public void unregisterReceiver(android.content.BroadcastReceiver); @@ -43186,7 +43225,7 @@ package android.view { method public abstract android.view.SubMenu getSubMenu(); method public abstract java.lang.CharSequence getTitle(); method public abstract java.lang.CharSequence getTitleCondensed(); - method public default java.lang.CharSequence getTooltip(); + method public default java.lang.CharSequence getTooltipText(); method public abstract boolean hasSubMenu(); method public abstract boolean isActionViewExpanded(); method public abstract boolean isCheckable(); @@ -43213,7 +43252,7 @@ package android.view { method public abstract android.view.MenuItem setTitle(java.lang.CharSequence); method public abstract android.view.MenuItem setTitle(int); method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence); - method public default android.view.MenuItem setTooltip(java.lang.CharSequence); + method public default android.view.MenuItem setTooltipText(java.lang.CharSequence); method public abstract android.view.MenuItem setVisible(boolean); field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2 field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8 @@ -43909,7 +43948,8 @@ package android.view { method public java.lang.Object getTag(int); method public int getTextAlignment(); method public int getTextDirection(); - method public final java.lang.CharSequence getTooltip(); + method public final deprecated java.lang.CharSequence getTooltip(); + method public final java.lang.CharSequence getTooltipText(); method public android.view.View getTooltipView(); method public final int getTop(); method protected float getTopFadingEdgeStrength(); @@ -44211,7 +44251,8 @@ package android.view { method public void setTag(int, java.lang.Object); method public void setTextAlignment(int); method public void setTextDirection(int); - method public final void setTooltip(java.lang.CharSequence); + method public final deprecated void setTooltip(java.lang.CharSequence); + method public final void setTooltipText(java.lang.CharSequence); method public final void setTop(int); method public void setTouchDelegate(android.view.TouchDelegate); method public final void setTransitionName(java.lang.String); @@ -49639,7 +49680,6 @@ package android.widget { method public int getExtendedPaddingTop(); method public android.text.InputFilter[] getFilters(); method public java.lang.String getFontFeatureSettings(); - method public java.lang.String getFontVariationSettings(); method public boolean getFreezesText(); method public int getGravity(); method public int getHighlightColor(); @@ -49745,7 +49785,6 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFilters(android.text.InputFilter[]); method public void setFontFeatureSettings(java.lang.String); - method public void setFontVariationSettings(java.lang.String); method protected boolean setFrame(int, int, int, int); method public void setFreezesText(boolean); method public void setGravity(int); diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index 5bf80765a7de..780db5e26c35 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -270,7 +270,7 @@ public final class Bmgr { } } - private void backupNowAllPackages() { + private void backupNowAllPackages(boolean nonIncrementalBackup) { int userId = UserHandle.USER_SYSTEM; IPackageManager mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); @@ -297,14 +297,19 @@ public final class Bmgr { System.err.println(BMGR_NOT_RUNNING_ERR); } } - backupNowPackages(packages); + backupNowPackages(packages, nonIncrementalBackup); } } - private void backupNowPackages(List<String> packages) { + private void backupNowPackages(List<String> packages, boolean nonIncrementalBackup) { + int flags = 0; + if (nonIncrementalBackup) { + flags |= BackupManager.FLAG_NON_INCREMENTAL_BACKUP; + } try { BackupObserver observer = new BackupObserver(); - int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer); + int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer, + flags); if (err == 0) { // Off and running -- wait for the backup to complete observer.waitForCompletion(); @@ -320,24 +325,31 @@ public final class Bmgr { private void doBackupNow() { String pkg; boolean backupAll = false; + boolean nonIncrementalBackup = false; ArrayList<String> allPkgs = new ArrayList<String>(); while ((pkg = nextArg()) != null) { if (pkg.equals("--all")) { backupAll = true; + } else if (pkg.equals("--non-incremental")) { + nonIncrementalBackup = true; + } else if (pkg.equals("--incremental")) { + nonIncrementalBackup = false; } else { allPkgs.add(pkg); } } if (backupAll) { if (allPkgs.size() == 0) { - System.out.println("Running backup for all packages."); - backupNowAllPackages(); + System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") + + "incremental backup for all packages."); + backupNowAllPackages(nonIncrementalBackup); } else { System.err.println("Provide only '--all' flag or list of packages."); } } else if (allPkgs.size() > 0) { - System.out.println("Running backup for " + allPkgs.size() +" requested packages."); - backupNowPackages(allPkgs); + System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") + + "incremental backup for " + allPkgs.size() +" requested packages."); + backupNowPackages(allPkgs, nonIncrementalBackup); } else { System.err.println("Provide '--all' flag or list of packages."); } diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk index de46b8c21259..f932388b0617 100644 --- a/cmds/uiautomator/library/Android.mk +++ b/cmds/uiautomator/library/Android.mk @@ -36,8 +36,7 @@ include $(BUILD_STATIC_JAVA_LIBRARY) # Generate the stub source files include $(CLEAR_VARS) LOCAL_SRC_FILES := $(uiautomator.core_src_files) -LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries) -LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test +LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries) legacy-android-test LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/core-src \ $(LOCAL_PATH)/testrunner-src diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 8185818ccd29..b27fa242e935 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -286,46 +286,31 @@ public class AccountManager { /** * Account visibility was not set. - * @hide */ public static final int VISIBILITY_UNDEFINED = 0; /** * Account is always visible to given application and only authenticator can revoke visibility. - * @hide */ public static final int VISIBILITY_VISIBLE = 1; /** * Account is visible to given application, but user can revoke visibility. - * @hide */ public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2; /** * Account is not visible to given application and only authenticator can grant visibility. - * @hide */ public static final int VISIBILITY_NOT_VISIBLE = 3; /** * Account is not visible to given application, but user can reveal it, for example, using * {@link #newChooseAccountIntent(Account, List, String[], String, String, String[], Bundle)} - * @hide */ public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; /** - * Key to manifest entry with a list of account types in which application is interested. - * Example value: "com.google;com.customtype". If it is specified then the application - * will only get notifications related to the types in the list (see - * {@link #ACTION_VISIBLE_ACCOUNTS_CHANGED}). Authenticators managing whitelisted types will be - * able to know about the application using {@link #ACTION_ACCOUNTS_LISTENER_PACKAGE_INSTALLED} - * @hide - */ - public static final String SUPPORTED_ACCOUNT_TYPES = "android.accounts.SupportedAccountTypes"; - - /** * Token type for the special case where a UID has access only to an account * but no authenticator specific auth token types. * @@ -344,48 +329,27 @@ public class AccountManager { * * @see #addOnAccountsUpdatedListener * - * Deprecated - use ACTION_VISIBLE_ACCOUNTS_CHANGED instead. + * @deprecated use #addOnAccountsUpdatedListener to get account updates in runtime. */ public static final String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; /** - * Action sent as a broadcast Intent by the AccountsService when accounts potentially visible to - * the applications are added, accounts are removed, or an account's credentials (saved - * password, etc) are changed. List of supported account types shoud be specified in the - * Manifest file using {@link #SUPPORTED_ACCOUNT_TYPES} - * - * @see #addOnAccountsUpdatedListener - * @hide - */ - public static final String ACTION_VISIBLE_ACCOUNTS_CHANGED = - "android.accounts.action.VISIBLE_ACCOUNTS_CHANGED"; - - /** - * Authenticators may subscribe to get notifications about apps interested in their managed account - * types using {@link #SUPPORTED_ACCOUNT_TYPES}. - * @hide - */ - public static final String ACTION_ACCOUNTS_LISTENER_PACKAGE_INSTALLED = - "android.accounts.action.ACCOUNTS_LISTENER_PACKAGE_INSTALLED"; - - /** * Uid key to set default visibility for applications targeting API level - * {@link android.os.Build.VERSION_CODES#O} or above. See {@link #getAccountVisibility}. If the - * value was not set by authenticator USER_MANAGED_NOT_VISIBLE is used. - * @hide + * {@link android.os.Build.VERSION_CODES#O} or above and don't have the same signature as + * authenticator See {@link #getAccountVisibility}. If the value was not set by authenticator + * USER_MANAGED_NOT_VISIBLE is used. */ - public static final int DEFAULT_VISIBILITY = -2; + public static final int UID_KEY_DEFAULT_VISIBILITY = -2; /** * Uid key to set visibility for applications targeting API level below - * {@link android.os.Build.VERSION_CODES#O}, which were able to see the account before. It - * includes applications with GET_ACCOUNTS permission or with the same signature as - * authenticator. See {@link #getAccountVisibility}. If the value was not set by authenticator - * USER_MANAGED_VISIBLE is used. - * @hide + * {@link android.os.Build.VERSION_CODES#O} with GET_ACCOUNS permission, or applications with + * any targeting API level with the same signature as authenticator. See + * {@link #getAccountVisibility}. If the value was not set by authenticator USER_MANAGED_VISIBLE + * is used. */ - public static final int DEFAULT_LEGACY_VISIBILITY = -3; + public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; /** * @hide @@ -874,43 +838,11 @@ public class AccountManager { * @param account The {@link Account} to add * @param password The password to associate with the account, null for none * @param extras String values to use for the account's userdata, null for none - * @param selectedUids Array of uids whose associated applications can access this account - * without any additional user approval. - * - * @return True if the account was successfully added, false if the account already exists, the - * account is null, or another error occurs. - */ - public boolean addAccountExplicitly(Account account, String password, Bundle extras, - int[] selectedUids) { - return false; // TODO remove this method. - } - - /** - * Adds an account directly to the AccountManager. Additionally this makes the Account visible - * to desired UIDs of applications on the device, and sends directed broadcasts to these - * individual applications. - * <p> - * Normally used by sign-up wizards associated with authenticators, not directly by - * applications. - * <p> - * Calling this method does not update the last authenticated timestamp, referred by - * {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call - * {@link #notifyAccountAuthenticated(Account)} after getting success. - * <p> - * It is safe to call this method from the main thread. - * <p> - * This method requires the caller to have a signature match with the authenticator that owns - * the specified account. - * - * @param account The {@link Account} to add - * @param password The password to associate with the account, null for none - * @param extras String values to use for the account's userdata, null for none * @param visibility Map from uid to visibility values which will be set before account is * added. See getAccountVisibility for possilbe values. * * @return True if the account was successfully added, false if the account already exists, the * account is null, or another error occurs. - * @hide */ public boolean addAccountExplicitly(Account account, String password, Bundle extras, Map<Integer, Integer> visibility) { @@ -925,22 +857,18 @@ public class AccountManager { } /** - * Returns all UIDs for applications that requested the account type. - * <p>This method requires the caller to have a signature match with the authenticator - * that owns the specified account. + * Returns UIDs of applications for which visibility of given account was explicitly set. + * <p> + * This method requires the caller to have a signature match with the authenticator that owns + * the specified account. * - * @param accountType The account type to be authenticated. + * @param account The account for which visibility data should be returned. * - * @return array of all UIDs that support accounts of this - * account type that seek approval (to be used to know which accounts for - * the authenticator to include in addAccountExplicitly). Null if none. + * @return Map from uid to visibility for given account */ - public int[] getRequestingUidsForType(String accountType) { - try { - return mService.getRequestingUidsForType(accountType); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } + public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) { + // TODO implement. + return null; } /** @@ -954,9 +882,8 @@ public class AccountManager { * @param packageName Package name. * @param accountType Account type. * - * @return Map with visibility for all accounts of given type. See {@link #getAccountVisibility} - * for possilbe values. - * @hide + * @return Map with visibility for all accounts of given type. + * See {@link #getAccountVisibility} for possilbe values. */ public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName, String accountType) { @@ -971,67 +898,6 @@ public class AccountManager { } /** - * Gives a certain UID, represented a application, access to an account - * <p> - * This method requires the caller to have a signature match with the authenticator that owns - * the specified account. - * - * @param account Account to make visible. - * @param uid The UID of the application to add account access. - * - * @return True if account made visible to application and was not previously visible. - */ - public boolean makeAccountVisible(Account account, int uid) { - try { - return mService.setAccountVisibility(account, uid, VISIBILITY_USER_MANAGED_VISIBLE); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - - /** - * Removes visibility of certain account of a process identified by a given UID to an - * application. This is called by the Authenticator. - * <p> - * This method requires the caller to have a signature match with the authenticator that owns - * the specified account. - * - * @param account Remove visibility of this account.. - * @param uid The UID of the application to remove account access. - * - * @return True if application access to account removed and was previously visible. - */ - public boolean removeAccountVisibility(Account account, int uid) { - try { - return mService.setAccountVisibility(account, uid, VISIBILITY_USER_MANAGED_NOT_VISIBLE); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - - /** - * Checks visibility of certain account of a process identified by a given UID. This is called - * by the Authenticator. - * <p> - * This method requires the caller to have a signature match with the authenticator that owns - * the specified account. - * - * @param account Account to check visibility. - * @param uid The UID of the application to check account access. - * - * @return True if application has access to the account - */ - public boolean isAccountVisible(Account account, int uid) { - try { - Integer visibility = mService.getAccountVisibility(account, uid); - return visibility == VISIBILITY_USER_MANAGED_NOT_VISIBLE - || visibility == VISIBILITY_VISIBLE; - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - - /** * Set visibility value of given account to certain UID. * <p> * See {@link #getAccountVisibility} for possible values. @@ -1044,7 +910,6 @@ public class AccountManager { * @param visibility - new visibility value. * * @return True if visibility value was succesfully updated. - * @hide */ public boolean setAccountVisibility(Account account, int uid, @AccountVisibility int visibility) { @@ -1058,6 +923,7 @@ public class AccountManager { /** * Gets visibility of certain account for given UID. Possible returned values are: * <ul> + * <li>{@link #VISIBILITY_UNDEFINED}</li> * <li>{@link #VISIBILITY_VISIBLE}</li> * <li>{@link #VISIBILITY_USER_MANAGED_VISIBLE}</li> * <li>{@link #VISIBILITY_NOT_VISIBLE} @@ -1072,7 +938,6 @@ public class AccountManager { * @param uid The UID of the application to get account visibility. * * @return int Visibility for given account and uid. - * @hide */ public @AccountVisibility int getAccountVisibility(Account account, int uid) { try { @@ -2916,20 +2781,29 @@ public class AccountManager { /** * Adds an {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}. This * listener will be notified whenever user or AbstractAcccountAuthenticator made changes to - * accounts related to the caller - either list of accounts returned by {@link #getAccounts()} - * was changed, or new account was added for which user can grant access to the caller. + * accounts of any type related to the caller. This method is equivalent to + * addOnAccountsUpdatedListener(listener, handler, updateImmediately, null) * + * @see #addOnAccountsUpdatedListener(OnAccountsUpdateListener, Handler, boolean, Handler, + * String[]) + */ + public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener, + Handler handler, boolean updateImmediately) { + addOnAccountsUpdatedListener(listener, handler,updateImmediately, null); + } + + /** + * Adds an {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}. This + * listener will be notified whenever user or AbstractAcccountAuthenticator made changes to + * accounts of given types related to the caller - + * either list of accounts returned by {@link #getAccounts()} + * was changed, or new account was added for which user can grant access to the caller. * <p> * As long as this listener is present, the AccountManager instance will not be * garbage-collected, and neither will the {@link Context} used to retrieve it, which may be a * large Activity instance. To avoid memory leaks, you must remove this listener before then. * Normally listeners are added in an Activity or Service's {@link Activity#onCreate} and * removed in {@link Activity#onDestroy}. - * - * - * If SUPPORTED_ACCOUNT_TYPES is specified in the manifest file, listener will only be - * notified about whitelisted types. - * * <p> * It is safe to call this method from the main thread. * @@ -2938,11 +2812,12 @@ public class AccountManager { * main thread * @param updateImmediately If true, the listener will be invoked (on the handler thread) right * away with the current account list + * @param accountTypes If set, only changes to accounts of given types will be reported. * @throws IllegalArgumentException if listener is null * @throws IllegalStateException if listener was already added */ public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener, - Handler handler, boolean updateImmediately) { + Handler handler, boolean updateImmediately, String[] accountTypes) { if (listener == null) { throw new IllegalArgumentException("the listener is null"); } @@ -2958,11 +2833,11 @@ public class AccountManager { if (wasEmpty) { // Register a broadcast receiver to monitor account changes IntentFilter intentFilter = new IntentFilter(); - if (isVisibleAccountsChangedBroadcastSupported()) { - intentFilter.addAction(ACTION_VISIBLE_ACCOUNTS_CHANGED); - } else { - intentFilter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION); - } + // TODO get rid of the broadcast receiver + // create android.os.ResultReceiver + // send it to the service via aidl + // handle onReceiveResult + intentFilter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION); // To recover from disk-full. intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); // Register a broadcast receiver to monitor account changes @@ -2975,26 +2850,6 @@ public class AccountManager { } /** - * @hide - */ - private boolean isVisibleAccountsChangedBroadcastSupported() { - String interestedTypes = null; - try { - String packageName = mContext.getOpPackageName(); - ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(packageName, - PackageManager.GET_META_DATA); - Bundle b = ai.metaData; - if (b == null) { - return false; - } - interestedTypes = b.getString(SUPPORTED_ACCOUNT_TYPES); - } catch (PackageManager.NameNotFoundException e) { - return false; - } - return !TextUtils.isEmpty(interestedTypes); - } - - /** * Removes an {@link OnAccountsUpdateListener} previously registered with * {@link #addOnAccountsUpdatedListener}. The listener will no longer * receive notifications of account changes. diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f6771857f26b..556d7add513f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2029,78 +2029,53 @@ public class Activity extends ContextThemeWrapper } /** - * Puts the activity in picture-in-picture mode. + * Puts the activity in picture-in-picture mode if possible in the current system state. Any + * prior calls to {@link #setPictureInPictureArgs(PictureInPictureArgs)} will still apply when + * entering picture-in-picture through this call. + * + * @see #enterPictureInPictureMode(PictureInPictureArgs) * @see android.R.attr#supportsPictureInPicture */ public void enterPictureInPictureMode() { - try { - ActivityManager.getService().enterPictureInPictureMode(mToken); - } catch (RemoteException e) { - } + enterPictureInPictureMode(new PictureInPictureArgs()); } /** - * Puts the activity in picture-in-picture mode with a given aspect ratio. - * @see android.R.attr#supportsPictureInPicture + * Puts the activity in picture-in-picture mode if possible in the current system state with + * explicit given arguments. Only the set parameters in {@param args} will override prior calls + * {@link #setPictureInPictureArgs(PictureInPictureArgs)}. * - * @param aspectRatio the new aspect ratio of the picture-in-picture. - */ - public void enterPictureInPictureMode(float aspectRatio) { - try { - ActivityManagerNative.getDefault().enterPictureInPictureModeWithAspectRatio(mToken, - aspectRatio); - } catch (RemoteException e) { - } - } - - /** - * Requests to the system that the activity can be automatically put into picture-in-picture - * mode when the user leaves the activity causing it normally to be hidden. Generally, this - * happens when another task is brought to the forground or the task containing this activity - * is moved to the background. This is a *not* a guarantee that the activity will actually be - * put in picture-in-picture mode, and depends on a number of factors, including whether there - * is already something in picture-in-picture. + * The system may disallow entering picture-in-picture in various cases, including when the + * activity is not visible. * - * @param enterPictureInPictureOnMoveToBg whether or not this activity can automatically enter - * picture-in-picture - */ - public void enterPictureInPictureModeOnMoveToBackground( - boolean enterPictureInPictureOnMoveToBg) { - try { - ActivityManagerNative.getDefault().enterPictureInPictureModeOnMoveToBackground(mToken, - enterPictureInPictureOnMoveToBg); - } catch (RemoteException e) { - } - } - - /** - * Updates the aspect ratio of the current picture-in-picture activity if this activity is - * already in picture-in-picture mode, or sets it to be used later if - * {@link #enterPictureInPictureModeOnMoveToBackground(boolean)} is requested. + * @see android.R.attr#supportsPictureInPicture * - * @param aspectRatio the new aspect ratio of the picture-in-picture. + * @param args the explicit non-null arguments to use when entering picture-in-picture. + * @return whether the system successfully entered picture-in-picture. */ - public void setPictureInPictureAspectRatio(float aspectRatio) { + public boolean enterPictureInPictureMode(@NonNull PictureInPictureArgs args) { try { - ActivityManagerNative.getDefault().setPictureInPictureAspectRatio(mToken, aspectRatio); + if (args == null) { + throw new IllegalArgumentException("Expected non-null picture-in-picture args"); + } + return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, args); } catch (RemoteException e) { + return false; } } /** - * Updates the set of user actions associated with the picture-in-picture activity. + * Updates the properties of the picture-in-picture activity, or sets it to be used later when + * {@link #enterPictureInPictureMode()} is called. * - * @param actions the new actions for picture-in-picture (can be null to reset the set of - * actions). The maximum number of actions that will be displayed on this device - * is defined by {@link ActivityManager#getMaxNumPictureInPictureActions()}. + * @param args the new properties of the picture-in-picture. */ - public void setPictureInPictureActions(List<RemoteAction> actions) { + public void setPictureInPictureArgs(@NonNull PictureInPictureArgs args) { try { - if (actions == null) { - actions = new ArrayList<>(); + if (args == null) { + throw new IllegalArgumentException("Expected non-null picture-in-picture args"); } - ActivityManagerNative.getDefault().setPictureInPictureActions(mToken, - new ParceledListSlice<RemoteAction>(actions)); + ActivityManagerNative.getDefault().setPictureInPictureArgs(mToken, args); } catch (RemoteException e) { } } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 2e3c100c3005..1d4b038f2d82 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -526,9 +526,13 @@ public class ActivityManager { /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later. */ public static final int APP_START_MODE_DELAYED = 1; + /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later, with + * rigid errors (throwing exception). */ + public static final int APP_START_MODE_DELAYED_RIGID = 2; + /** @hide Mode for {@link IActivityManager#getAppStartMode}: disable/cancel pending - * launches. */ - public static final int APP_START_MODE_DISABLED = 2; + * launches; this is the mode for ephemeral apps. */ + public static final int APP_START_MODE_DISABLED = 3; /** * Lock task mode is not active. diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 87700dc7aa35..89510d9f2d15 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -64,36 +64,6 @@ public abstract class ActivityManagerInternal { public static final int APP_TRANSITION_TIMEOUT = 3; /** - * Class to hold deferred properties to apply for picture-in-picture for a given activity. - */ - public static class PictureInPictureArguments { - /** - * The expected aspect ratio of the picture-in-picture. - */ - public float aspectRatio; - - /** - * The set of actions that are associated with this activity when in picture in picture. - */ - public List<RemoteAction> userActions = new ArrayList<>(); - - public void dump(PrintWriter pw, String prefix) { - pw.println(prefix + "aspectRatio=" + aspectRatio); - if (userActions.isEmpty()) { - pw.println(prefix + " userActions=[]"); - } else { - pw.println(prefix + " userActions=["); - for (int i = 0; i < userActions.size(); i++) { - RemoteAction action = userActions.get(i); - pw.print(prefix + " Action[" + i + "]: "); - action.dump("", pw); - } - pw.println(prefix + " ]"); - } - } - } - - /** * Grant Uri permissions from one app to another. This method only extends * permission grants if {@code callingUid} has permission to them. */ @@ -201,6 +171,17 @@ public abstract class ActivityManagerInternal { public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration); /** + * Allow DeviceIdleController to tell us about what apps are whitelisted. + */ + public abstract void setDeviceIdleWhitelist(int[] appids); + + /** + * Update information about which app IDs are on the temp whitelist. + */ + public abstract void updateDeviceIdleTempWhitelist(int[] appids, int changingAppId, + boolean adding); + + /** * Updates and persists the {@link Configuration} for a given user. * * @param values the configuration to update diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 74614cc8a703..d814ddcc7f27 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4919,18 +4919,27 @@ public final class ActivityThread { } void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) { + // Updates triggered by package installation go through a package update + // receiver. Here we try to capture ApplicationInfo changes that are + // caused by other sources, such as overlays. That means we want to be as conservative + // about code changes as possible. Take the diff of the old ApplicationInfo and the new + // to see if anything needs to change. synchronized (mResourcesManager) { // Update all affected loaded packages with new package information WeakReference<LoadedApk> ref = mPackages.get(ai.packageName); LoadedApk apk = ref != null ? ref.get() : null; if (apk != null) { - apk.updateApplicationInfo(ai, null); + final ArrayList<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths, null /*outLibPaths*/); + apk.updateApplicationInfo(ai, oldPaths); } ref = mResourcePackages.get(ai.packageName); apk = ref != null ? ref.get() : null; if (apk != null) { - apk.updateApplicationInfo(ai, null); + final ArrayList<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths, null /*outLibPaths*/); + apk.updateApplicationInfo(ai, oldPaths); } // Update all affected Resources objects to use new ResourcesImpl diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 67fbc5a46832..9cc13abcbabc 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -243,8 +243,10 @@ public class AppOpsManager { public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64; /** @hide Read the phone number. */ public static final int OP_READ_PHONE_NUMBER = 65; + /** @hide Request package installs through package installer */ + public static final int OP_REQUEST_INSTALL_PACKAGES = 66; /** @hide */ - public static final int _NUM_OP = 66; + public static final int _NUM_OP = 67; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -461,6 +463,7 @@ public class AppOpsManager { OP_RUN_IN_BACKGROUND, OP_AUDIO_ACCESSIBILITY_VOLUME, OP_READ_PHONE_NUMBER, + OP_REQUEST_INSTALL_PACKAGES, }; /** @@ -534,6 +537,7 @@ public class AppOpsManager { null, null, // OP_AUDIO_ACCESSIBILITY_VOLUME OPSTR_READ_PHONE_NUMBER, + null, // OP_REQUEST_INSTALL_PACKAGES }; /** @@ -607,6 +611,7 @@ public class AppOpsManager { "RUN_IN_BACKGROUND", "AUDIO_ACCESSIBILITY_VOLUME", "READ_PHONE_NUMBER", + "REQUEST_INSTALL_PACKAGES", }; /** @@ -680,6 +685,7 @@ public class AppOpsManager { null, // no permission for running in background null, // no permission for changing accessibility volume Manifest.permission.READ_PHONE_NUMBER, + Manifest.permission.REQUEST_INSTALL_PACKAGES, }; /** @@ -754,6 +760,7 @@ public class AppOpsManager { null, // RUN_IN_BACKGROUND UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ACCESSIBILITY_VOLUME null, // READ_PHONE_NUMBER + null, // REQUEST_INSTALL_PACKAGES }; /** @@ -827,6 +834,7 @@ public class AppOpsManager { false, // RUN_IN_BACKGROUND false, // AUDIO_ACCESSIBILITY_VOLUME false, // READ_PHONE_NUMBER + false, // REQUEST_INSTALL_PACKAGES }; /** @@ -899,6 +907,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, // OP_RUN_IN_BACKGROUND AppOpsManager.MODE_ALLOWED, // OP_AUDIO_ACCESSIBILITY_VOLUME AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES }; /** @@ -975,6 +984,7 @@ public class AppOpsManager { false, false, // OP_AUDIO_ACCESSIBILITY_VOLUME false, + false, // OP_REQUEST_INSTALL_PACKAGES }; /** diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index f3185a8d3a6b..20f7e63e4d77 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -24,6 +24,7 @@ import android.annotation.XmlRes; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.ContentResolver; +import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; @@ -1386,7 +1387,7 @@ public class ApplicationPackageManager extends PackageManager { } } - ApplicationPackageManager(ContextImpl context, + protected ApplicationPackageManager(ContextImpl context, IPackageManager pm) { mContext = context; mPM = pm; @@ -1820,6 +1821,12 @@ public class ApplicationPackageManager extends PackageManager { @Override public @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app) { final StorageManager storage = mContext.getSystemService(StorageManager.class); + return getPackageCurrentVolume(app, storage); + } + + @VisibleForTesting + protected @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app, + StorageManager storage) { if (app.isInternal()) { return storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL); } else if (app.isExternalAsec()) { @@ -1831,25 +1838,43 @@ public class ApplicationPackageManager extends PackageManager { @Override public @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) { - final StorageManager storage = mContext.getSystemService(StorageManager.class); - final VolumeInfo currentVol = getPackageCurrentVolume(app); - final List<VolumeInfo> vols = storage.getVolumes(); + final StorageManager storageManager = mContext.getSystemService(StorageManager.class); + return getPackageCandidateVolumes(app, storageManager, mPM); + } + + @VisibleForTesting + protected @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app, + StorageManager storageManager, IPackageManager pm) { + final VolumeInfo currentVol = getPackageCurrentVolume(app, storageManager); + final List<VolumeInfo> vols = storageManager.getVolumes(); final List<VolumeInfo> candidates = new ArrayList<>(); for (VolumeInfo vol : vols) { - if (Objects.equals(vol, currentVol) || isPackageCandidateVolume(mContext, app, vol)) { + if (Objects.equals(vol, currentVol) + || isPackageCandidateVolume(mContext, app, vol, pm)) { candidates.add(vol); } } return candidates; } - private boolean isPackageCandidateVolume( - ContextImpl context, ApplicationInfo app, VolumeInfo vol) { - final boolean forceAllowOnExternal = Settings.Global.getInt( + @VisibleForTesting + protected boolean isForceAllowOnExternal(Context context) { + return Settings.Global.getInt( context.getContentResolver(), Settings.Global.FORCE_ALLOW_ON_EXTERNAL, 0) != 0; - // Private internal is always an option + } + + @VisibleForTesting + protected boolean isAllow3rdPartyOnInternal(Context context) { + return context.getResources().getBoolean( + com.android.internal.R.bool.config_allow3rdPartyAppOnInternal); + } + + private boolean isPackageCandidateVolume( + ContextImpl context, ApplicationInfo app, VolumeInfo vol, IPackageManager pm) { + final boolean forceAllowOnExternal = isForceAllowOnExternal(context); + if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) { - return true; + return app.isSystemApp() || isAllow3rdPartyOnInternal(context); } // System apps and apps demanding internal storage can't be moved @@ -1875,7 +1900,7 @@ public class ApplicationPackageManager extends PackageManager { // Some apps can't be moved. (e.g. device admins) try { - if (mPM.isPackageDeviceAdminOnAnyUser(app.packageName)) { + if (pm.isPackageDeviceAdminOnAnyUser(app.packageName)) { return false; } } catch (RemoteException e) { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index d08bee507b77..5e7d46fe05aa 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1385,7 +1385,14 @@ class ContextImpl extends Context { @Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); - return startServiceCommon(service, mUser); + return startServiceCommon(service, -1, null, mUser); + } + + @Override + public ComponentName startServiceInForeground(Intent service, + int id, Notification notification) { + warnIfCallingFromSystemProcess(); + return startServiceCommon(service, id, notification, mUser); } @Override @@ -1396,16 +1403,24 @@ class ContextImpl extends Context { @Override public ComponentName startServiceAsUser(Intent service, UserHandle user) { - return startServiceCommon(service, user); + return startServiceCommon(service, -1, null, user); } - private ComponentName startServiceCommon(Intent service, UserHandle user) { + @Override + public ComponentName startServiceInForegroundAsUser(Intent service, + int id, Notification notification, UserHandle user) { + return startServiceCommon(service, id, notification, user); + } + + private ComponentName startServiceCommon(Intent service, int id, Notification notification, + UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( - getContentResolver()), getOpPackageName(), user.getIdentifier()); + getContentResolver()), id, notification, getOpPackageName(), + user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( @@ -1415,6 +1430,9 @@ class ContextImpl extends Context { throw new SecurityException( "Unable to start service " + service + ": " + cn.getClassName()); + } else if (cn.getPackageName().equals("?")) { + throw new IllegalStateException( + "Not allowed to start service " + service + ": " + cn.getClassName()); } } return cn; diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index e143255bbd43..135c2a4eef91 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -34,6 +34,7 @@ import android.app.IUidObserver; import android.app.IUserSwitchObserver; import android.app.Notification; import android.app.PendingIntent; +import android.app.PictureInPictureArgs; import android.app.ProfilerInfo; import android.app.WaitResult; import android.app.assist.AssistContent; @@ -128,7 +129,8 @@ interface IActivityManager { void finishSubActivity(in IBinder token, in String resultWho, int requestCode); PendingIntent getRunningServiceControlPanel(in ComponentName service); ComponentName startService(in IApplicationThread caller, in Intent service, - in String resolvedType, in String callingPackage, int userId); + in String resolvedType, int id, in Notification notification, + in String callingPackage, int userId); int stopService(in IApplicationThread caller, in Intent service, in String resolvedType, int userId); int bindService(in IApplicationThread caller, in IBinder token, in Intent service, @@ -479,12 +481,8 @@ interface IActivityManager { boolean isInMultiWindowMode(in IBinder token); boolean isInPictureInPictureMode(in IBinder token); void killPackageDependents(in String packageName, int userId); - void enterPictureInPictureMode(in IBinder token); - void enterPictureInPictureModeWithAspectRatio(in IBinder token, float aspectRatio); - void enterPictureInPictureModeOnMoveToBackground(in IBinder token, - boolean enterPictureInPictureOnMoveToBg); - void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio); - void setPictureInPictureActions(in IBinder token, in ParceledListSlice actions); + boolean enterPictureInPictureMode(in IBinder token, in PictureInPictureArgs args); + void setPictureInPictureArgs(in IBinder token, in PictureInPictureArgs args); void activityRelaunched(in IBinder token); IBinder getUriPermissionOwnerForActivity(in IBinder activityToken); /** diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 07c21a57f796..f909af069224 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -40,6 +40,7 @@ interface INotificationManager { void cancelAllNotifications(String pkg, int userId); + void clearData(String pkg, int uid); void enqueueToast(String pkg, ITransientNotification callback, int duration); void cancelToast(String pkg, ITransientNotification callback); void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id, @@ -54,10 +55,10 @@ interface INotificationManager void createNotificationChannels(String pkg, in ParceledListSlice channelsList); void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel); NotificationChannel getNotificationChannel(String pkg, String channelId); - NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId); + NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, boolean includeDeleted); void deleteNotificationChannel(String pkg, String channelId); ParceledListSlice getNotificationChannels(String pkg); - ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid); + ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted); // TODO: Remove this when callers have been migrated to the equivalent // INotificationListener method. diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl index 6deedb6f5278..5e420c085b53 100644 --- a/core/java/android/app/ITaskStackListener.aidl +++ b/core/java/android/app/ITaskStackListener.aidl @@ -31,8 +31,10 @@ oneway interface ITaskStackListener { * Called whenever IActivityManager.startActivity is called on an activity that is already * running in the pinned stack and the activity is not actually started, but the task is either * brought to the front or a new Intent is delivered to it. + * + * @param sourceComponent the component name of the activity that initiated the restart attempt */ - void onPinnedActivityRestartAttempt(); + void onPinnedActivityRestartAttempt(in ComponentName sourceComponent); /** * Called whenever the pinned stack is done animating a resize. diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index cc7981c24027..b1bdea1cb502 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -443,6 +443,7 @@ public class Instrumentation { private final String mClass; private final ActivityResult mResult; private final boolean mBlock; + private final boolean mIgnoreMatchingSpecificIntents; // This is protected by 'Instrumentation.this.mSync'. @@ -454,7 +455,7 @@ public class Instrumentation { /** * Create a new ActivityMonitor that looks for a particular kind of * intent to be started. - * + * * @param which The set of intents this monitor is responsible for. * @param result A canned result to return if the monitor is hit; can * be null. @@ -470,6 +471,7 @@ public class Instrumentation { mClass = null; mResult = result; mBlock = block; + mIgnoreMatchingSpecificIntents = false; } /** @@ -491,6 +493,34 @@ public class Instrumentation { mClass = cls; mResult = result; mBlock = block; + mIgnoreMatchingSpecificIntents = false; + } + + /** + * Create a new ActivityMonitor that can be used for intercepting any activity to be + * started. + * + * <p> When an activity is started, {@link #onMatchIntent(Intent)} will be called on + * instances created using this constructor to see if it is a hit. + * + * @see #onMatchIntent(Intent) + */ + public ActivityMonitor() { + mWhich = null; + mClass = null; + mResult = null; + mBlock = false; + mIgnoreMatchingSpecificIntents = true; + } + + /** + * @return true if this monitor is used for intercepting any started activity by calling + * into {@link #onMatchIntent(Intent)}, false if this monitor is only used + * for specific intents corresponding to the intent filter or activity class + * passed in the constructor. + */ + final boolean ignoreMatchingSpecificIntents() { + return mIgnoreMatchingSpecificIntents; } /** @@ -577,10 +607,31 @@ public class Instrumentation { } } } - + + /** + * Used for intercepting any started activity. + * + * <p> A non-null return value here will be considered a hit for this monitor. + * By default this will return {@code null} and subclasses can override this to return + * a non-null value if the intent needs to be intercepted. + * + * <p> Whenever a new activity is started, this method will be called on instances created + * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case + * of a match, the activity start will be blocked and the returned result will be used. + * + * @param intent The intent used for starting the activity. + * @return The {@link ActivityResult} that needs to be used in case of a match. + */ + public ActivityResult onMatchIntent(Intent intent) { + return null; + } + final boolean match(Context who, Activity activity, Intent intent) { + if (mIgnoreMatchingSpecificIntents) { + return false; + } synchronized (this) { if (mWhich != null && mWhich.match(who.getContentResolver(), intent, @@ -1492,7 +1543,14 @@ public class Instrumentation { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); - if (am.match(who, null, intent)) { + ActivityResult result = null; + if (am.ignoreMatchingSpecificIntents()) { + result = am.onMatchIntent(intent); + } + if (result != null) { + am.mHits++; + return result; + } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; @@ -1548,7 +1606,14 @@ public class Instrumentation { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); - if (am.match(who, null, intents[0])) { + ActivityResult result = null; + if (am.ignoreMatchingSpecificIntents()) { + result = am.onMatchIntent(intents[0]); + } + if (result != null) { + am.mHits++; + return; + } else if (am.match(who, null, intents[0])) { am.mHits++; if (am.isBlocking()) { return; @@ -1611,7 +1676,14 @@ public class Instrumentation { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); - if (am.match(who, null, intent)) { + ActivityResult result = null; + if (am.ignoreMatchingSpecificIntents()) { + result = am.onMatchIntent(intent); + } + if (result != null) { + am.mHits++; + return result; + } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; @@ -1671,7 +1743,14 @@ public class Instrumentation { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); - if (am.match(who, null, intent)) { + ActivityResult result = null; + if (am.ignoreMatchingSpecificIntents()) { + result = am.onMatchIntent(intent); + } + if (result != null) { + am.mHits++; + return result; + } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; @@ -1710,7 +1789,14 @@ public class Instrumentation { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); - if (am.match(who, null, intent)) { + ActivityResult result = null; + if (am.ignoreMatchingSpecificIntents()) { + result = am.onMatchIntent(intent); + } + if (result != null) { + am.mHits++; + return result; + } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; @@ -1748,7 +1834,14 @@ public class Instrumentation { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); - if (am.match(who, null, intent)) { + ActivityResult result = null; + if (am.ignoreMatchingSpecificIntents()) { + result = am.onMatchIntent(intent); + } + if (result != null) { + am.mHits++; + return; + } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return; diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index db1162a3cbb3..4ab07432ad1f 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -16,6 +16,8 @@ package android.app; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -262,7 +264,15 @@ public final class LoadedApk { return ai.sharedLibraryFiles; } - public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) { + /** + * Update the ApplicationInfo for an app. If oldPaths is null, all the paths are considered + * new. + * @param aInfo The new ApplicationInfo to use for this LoadedApk + * @param oldPaths The code paths for the old ApplicationInfo object. null means no paths can + * be reused. + */ + public void updateApplicationInfo(@NonNull ApplicationInfo aInfo, + @Nullable List<String> oldPaths) { setApplicationInfo(aInfo); final List<String> newPaths = new ArrayList<>(); diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java index 09e95dfa3044..d2d7b6d9fa62 100644 --- a/core/java/android/app/MediaRouteButton.java +++ b/core/java/android/app/MediaRouteButton.java @@ -174,7 +174,7 @@ public class MediaRouteButton extends View { @Override public void setContentDescription(CharSequence contentDescription) { super.setContentDescription(contentDescription); - setTooltip(contentDescription); + setTooltipText(contentDescription); } @Override diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index bdccb8a9620c..56ef791d365a 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -44,6 +44,7 @@ public final class NotificationChannel implements Parcelable { private static final String TAG_CHANNEL = "channel"; private static final String ATT_NAME = "name"; private static final String ATT_ID = "id"; + private static final String ATT_DELETED = "deleted"; private static final String ATT_PRIORITY = "priority"; private static final String ATT_VISIBILITY = "visibility"; private static final String ATT_IMPORTANCE = "importance"; @@ -120,7 +121,7 @@ public final class NotificationChannel implements Parcelable { NotificationManager.VISIBILITY_NO_OVERRIDE; private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED; - private static final boolean DEFAULT_ALLOWED = true; + private static final boolean DEFAULT_DELETED = false; private final String mId; private CharSequence mName; @@ -133,7 +134,7 @@ public final class NotificationChannel implements Parcelable { private int mUserLockedFields; private boolean mVibrationEnabled; private boolean mShowBadge; - private boolean mAllowed = DEFAULT_ALLOWED; + private boolean mDeleted = DEFAULT_DELETED; /** * Creates a notification channel. @@ -170,7 +171,7 @@ public final class NotificationChannel implements Parcelable { mUserLockedFields = in.readInt(); mVibrationEnabled = in.readByte() != 0; mShowBadge = in.readByte() != 0; - mAllowed = in.readByte() != 0; + mDeleted = in.readByte() != 0; } @Override @@ -196,7 +197,7 @@ public final class NotificationChannel implements Parcelable { dest.writeInt(mUserLockedFields); dest.writeByte(mVibrationEnabled ? (byte) 1 : (byte) 0); dest.writeByte(mShowBadge ? (byte) 1 : (byte) 0); - dest.writeByte(mAllowed ? (byte) 1 : (byte) 0); + dest.writeByte(mDeleted ? (byte) 1 : (byte) 0); } /** @@ -207,6 +208,14 @@ public final class NotificationChannel implements Parcelable { mUserLockedFields |= field; } + /** + * @hide + */ + @SystemApi + public void setDeleted(boolean deleted) { + mDeleted = deleted; + } + // Modifiable by a notification ranker. /** @@ -365,10 +374,11 @@ public final class NotificationChannel implements Parcelable { } /** - * Returns whether notifications are allowed to post to this channel. + * @hide */ - public boolean isAllowed() { - return mAllowed; + @SystemApi + public boolean isDeleted() { + return mDeleted; } /** @@ -393,6 +403,7 @@ public final class NotificationChannel implements Parcelable { enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false)); setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null)); setShowBadge(safeBool(parser, ATT_SHOW_BADGE, false)); + setDeleted(safeBool(parser, ATT_DELETED, false)); lockFields(safeInt(parser, ATT_USER_LOCKED, 0)); } @@ -434,6 +445,9 @@ public final class NotificationChannel implements Parcelable { if (canShowBadge()) { out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(canShowBadge())); } + if (isDeleted()) { + out.attribute(null, ATT_DELETED, Boolean.toString(isDeleted())); + } out.endTag(null, TAG_CHANNEL); } @@ -464,6 +478,7 @@ public final class NotificationChannel implements Parcelable { record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields())); record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern())); record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge())); + record.put(ATT_DELETED, Boolean.toString(isDeleted())); return record; } @@ -547,7 +562,7 @@ public final class NotificationChannel implements Parcelable { if (mUserLockedFields != that.mUserLockedFields) return false; if (mVibrationEnabled != that.mVibrationEnabled) return false; if (mShowBadge != that.mShowBadge) return false; - if (mAllowed != that.mAllowed) return false; + if (mDeleted != that.mDeleted) return false; if (mId != null ? !mId.equals(that.mId) : that.mId != null) return false; if (mName != null ? !mName.equals(that.mName) : that.mName != null) return false; if (mSound != null ? !mSound.equals(that.mSound) : that.mSound != null) return false; @@ -568,7 +583,7 @@ public final class NotificationChannel implements Parcelable { result = 31 * result + mUserLockedFields; result = 31 * result + (mVibrationEnabled ? 1 : 0); result = 31 * result + (mShowBadge ? 1 : 0); - result = 31 * result + (mAllowed ? 1 : 0); + result = 31 * result + (mDeleted ? 1 : 0); return result; } @@ -586,7 +601,7 @@ public final class NotificationChannel implements Parcelable { ", mUserLockedFields=" + mUserLockedFields + ", mVibrationEnabled=" + mVibrationEnabled + ", mShowBadge=" + mShowBadge + - ", mAllowed=" + mAllowed + + ", mDeleted=" + mDeleted + '}'; } } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 3551691b18be..c0aae6df34fe 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -24,6 +24,7 @@ import android.annotation.TestApi; import android.app.Notification.Builder; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.pm.ParceledListSlice; import android.graphics.drawable.Icon; import android.net.Uri; @@ -1085,4 +1086,38 @@ public class NotificationManager default: return defValue; } } + + /** + * Start a service directly into the "foreground service" state. Unlike + * {@link android.content.Context#startService(Intent)}, this method + * can be used from within background operations like broadcast receivers + * or scheduled jobs. + * + * @param service Description of the service to be stopped. The Intent must be either + * fully explicit (supplying a component name) or specify a specific package + * name it is targeted to. + * @param id The identifier for this notification as per + * {@link #notify(int, Notification) NotificationManager.notify(int, Notification)}; + * must not be 0. + * @param notification The Notification to be displayed. + * @return If the service is being started or is already running, the + * {@link ComponentName} of the actual service that was started is + * returned; else if the service does not exist null is returned. + */ + @Nullable + public ComponentName startServiceInForeground(Intent service, + int id, Notification notification) { + return mContext.startServiceInForeground(service, id, notification); + } + + /** + * @hide like {@link #startServiceInForeground(Intent, int, Notification)} + * but for a specific user. + */ + @Nullable + public ComponentName startServiceInForegroundAsUser(Intent service, + int id, Notification notification, UserHandle user) { + return mContext.startServiceInForegroundAsUser(service, id, notification, user); + } + } diff --git a/core/java/android/app/PictureInPictureArgs.aidl b/core/java/android/app/PictureInPictureArgs.aidl new file mode 100644 index 000000000000..49df39a73a7d --- /dev/null +++ b/core/java/android/app/PictureInPictureArgs.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +parcelable PictureInPictureArgs; diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java new file mode 100644 index 000000000000..fbdcbf4e6b11 --- /dev/null +++ b/core/java/android/app/PictureInPictureArgs.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a set of arguments used to initialize the picture-in-picture mode. + */ +public final class PictureInPictureArgs implements Parcelable { + + /** + * The expected aspect ratio of the picture-in-picture. + */ + @Nullable + private Float mAspectRatio; + + /** + * The set of actions that are associated with this activity when in picture in picture. + */ + @Nullable + private List<RemoteAction> mUserActions; + + PictureInPictureArgs(Parcel in) { + if (in.readInt() != 0) { + mAspectRatio = in.readFloat(); + } + if (in.readInt() != 0) { + mUserActions = new ArrayList<>(); + in.readParcelableList(mUserActions, RemoteAction.class.getClassLoader()); + } + } + + /** + * Creates a new set of picture-in-picture arguments. + */ + public PictureInPictureArgs() { + // Empty constructor + } + + /** + * Creates a new set of picture-in-picture arguments from the given {@param aspectRatio} and + * {@param actions}. + */ + public PictureInPictureArgs(float aspectRatio, List<RemoteAction> actions) { + mAspectRatio = aspectRatio; + if (actions != null) { + mUserActions = new ArrayList<>(actions); + } + } + + /** + * Copies the set parameters from the other picture-in-picture args. + * @hide + */ + public void copyOnlySet(PictureInPictureArgs otherArgs) { + if (otherArgs.hasSetAspectRatio()) { + mAspectRatio = otherArgs.mAspectRatio; + } + if (otherArgs.hasSetActions()) { + mUserActions = otherArgs.mUserActions; + } + } + + /** + * Sets the aspect ratio. + * @param aspectRatio the new aspect ratio for picture-in-picture. + */ + public void setAspectRatio(float aspectRatio) { + mAspectRatio = aspectRatio; + } + + /** + * @return the aspect ratio. If none is set, return 0. + * @hide + */ + public float getAspectRatio() { + if (mAspectRatio != null) { + return mAspectRatio; + } + return 0f; + } + + /** + * @return whether the aspect ratio is set. + * @hide + */ + public boolean hasSetAspectRatio() { + return mAspectRatio != null; + } + + /** + * Sets the user actions. + * @param actions the new actions to show in the picture-in-picture menu. + */ + public void setActions(List<RemoteAction> actions) { + if (mUserActions != null) { + mUserActions = null; + } + if (actions != null) { + mUserActions = new ArrayList<>(actions); + } + } + + /** + * @return the set of user actions. + * @hide + */ + public List<RemoteAction> getActions() { + return mUserActions; + } + + /** + * @return whether the user actions are set. + * @hide + */ + public boolean hasSetActions() { + return mUserActions != null; + } + + @Override + public PictureInPictureArgs clone() { + return new PictureInPictureArgs(mAspectRatio, mUserActions); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + if (mAspectRatio != null) { + out.writeInt(1); + out.writeFloat(mAspectRatio); + } else { + out.writeInt(0); + } + if (mUserActions != null) { + out.writeInt(1); + out.writeParcelableList(mUserActions, 0); + } else { + out.writeInt(0); + } + } + + public static final Creator<PictureInPictureArgs> CREATOR = + new Creator<PictureInPictureArgs>() { + public PictureInPictureArgs createFromParcel(Parcel in) { + return new PictureInPictureArgs(in); + } + public PictureInPictureArgs[] newArray(int size) { + return new PictureInPictureArgs[size]; + } + }; +}
\ No newline at end of file diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java index fd766bfbff21..35c67d30cc5a 100644 --- a/core/java/android/app/TaskStackListener.java +++ b/core/java/android/app/TaskStackListener.java @@ -35,7 +35,7 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub { } @Override - public void onPinnedActivityRestartAttempt() throws RemoteException { + public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) throws RemoteException { } @Override diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 2701698e531b..b8bc7f155176 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1485,6 +1485,7 @@ public class DevicePolicyManager { * or uninstalled. * @hide */ + @SystemApi public boolean packageHasActiveAdmins(String packageName) { return packageHasActiveAdmins(packageName, myUserId()); } @@ -7137,15 +7138,14 @@ public class DevicePolicyManager { } /** - * @hide - * Enable backup service. - * <p>This includes all backup and restore mechanisms. - * Setting this to {@code false} will make backup service no-op or return empty results. + * Allows the device owner to enable or disable the backup service. * - * <p>There must be only one user on the device, managed by the device owner. - * Otherwise a {@link SecurityException} will be thrown. + * <p> Backup service manages all backup and restore mechanisms on the device. Setting this to + * false will prevent data from being backed up or restored. * - * <p>Backup service is off by default when device owner is present. + * <p> Backup service is off by default when device owner is present. + * + * @throws SecurityException if {@code admin} is not a device owner. */ public void setBackupServiceEnabled(@NonNull ComponentName admin, boolean enabled) { try { @@ -7156,8 +7156,12 @@ public class DevicePolicyManager { } /** - * @hide + * Return whether the backup service is enabled by the device owner. + * + * <p> Backup service manages all backup and restore mechanisms on the device. + * * @return {@code true} if backup service is enabled, {@code false} otherwise. + * @see #setBackupServiceEnabled */ public boolean isBackupServiceEnabled(@NonNull ComponentName admin) { try { diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 80bc1364fa58..540683deeecb 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -136,6 +136,27 @@ public class BackupManager { */ public static final String EXTRA_BACKUP_SERVICES_AVAILABLE = "backup_services_available"; + /** + * If this flag is passed to {@link #requestBackup(String[], BackupObserver, int)}, + * BackupManager will pass a blank old state to BackupAgents of requested packages. + * + * @hide + */ + @SystemApi + public static final int FLAG_NON_INCREMENTAL_BACKUP = 1; + + /** + * Use with {@link #requestBackup} to force backup of + * package meta data. Typically you do not need to explicitly request this be backed up as it is + * handled internally by the BackupManager. If you are requesting backups with + * FLAG_NON_INCREMENTAL, this package won't automatically be backed up and you have to + * explicitly request for its backup. + * + * @hide + */ + @SystemApi + public static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; + private Context mContext; private static IBackupManager sService; @@ -484,13 +505,34 @@ public class BackupManager { */ @SystemApi public int requestBackup(String[] packages, BackupObserver observer) { + return requestBackup(packages, observer, 0); + } + + /** + * Request an immediate backup, providing an observer to which results of the backup operation + * will be published. The Android backup system will decide for each package whether it will + * be full app data backup or key/value-pair-based backup. + * + * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all + * provided packages using the remote transport. + * + * @param packages List of package names to backup. + * @param observer The {@link BackupObserver} to receive callbacks during the backup + * operation. Could be {@code null}. + * @param flags {@link #FLAG_NON_INCREMENTAL_BACKUP}. + * @return {@link BackupManager#SUCCESS} on success; nonzero on error. + * @throws IllegalArgumentException on null or empty {@code packages} param. + * @hide + */ + @SystemApi + public int requestBackup(String[] packages, BackupObserver observer, int flags) { checkServiceBinder(); if (sService != null) { try { BackupObserverWrapper observerWrapper = observer == null ? null : new BackupObserverWrapper(mContext, observer); - return sService.requestBackup(packages, observerWrapper); + return sService.requestBackup(packages, observerWrapper, flags); } catch (RemoteException e) { Log.e(TAG, "requestBackup() couldn't connect"); } diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl index a320bbf9d178..fe23c288c7ce 100644 --- a/core/java/android/app/backup/IBackupManager.aidl +++ b/core/java/android/app/backup/IBackupManager.aidl @@ -357,7 +357,9 @@ interface IBackupManager { * @param observer The {@link BackupObserver} to receive callbacks during the backup * operation. * + * @param flags {@link BackupManager#FLAG_NON_INCREMENTAL_BACKUP}. + * * @return Zero on success; nonzero on error. */ - int requestBackup(in String[] packages, IBackupObserver observer); + int requestBackup(in String[] packages, IBackupObserver observer, int flags); } diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index cd144695a989..6ba52b70d1ab 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -36,7 +36,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.DisplayMetrics; import android.util.SparseArray; -import android.util.TypedValue; import android.widget.RemoteViews; import android.widget.RemoteViews.OnClickHandler; @@ -381,15 +380,7 @@ public class AppWidgetHost { // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the // AppWidgetService, which doesn't have our context, hence we need to do the // conversion here. - appWidget.minWidth = - TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics); - appWidget.minHeight = - TypedValue.complexToDimensionPixelSize(appWidget.minHeight, mDisplayMetrics); - appWidget.minResizeWidth = - TypedValue.complexToDimensionPixelSize(appWidget.minResizeWidth, mDisplayMetrics); - appWidget.minResizeHeight = - TypedValue.complexToDimensionPixelSize(appWidget.minResizeHeight, mDisplayMetrics); - + appWidget.updateDimensions(mDisplayMetrics); synchronized (mViews) { v = mViews.get(appWidgetId); } diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 31e779f0dc4b..9980e9661dd3 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -31,7 +31,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.util.DisplayMetrics; -import android.util.TypedValue; import android.widget.RemoteViews; import com.android.internal.appwidget.IAppWidgetService; @@ -760,7 +759,7 @@ public class AppWidgetManager { } for (AppWidgetProviderInfo info : providers.getList()) { // Converting complex to dp. - convertSizesToPixels(info); + info.updateDimensions(mDisplayMetrics); } return providers.getList(); } catch (RemoteException e) { @@ -782,7 +781,7 @@ public class AppWidgetManager { AppWidgetProviderInfo info = mService.getAppWidgetInfo(mPackageName, appWidgetId); if (info != null) { // Converting complex to dp. - convertSizesToPixels(info); + info.updateDimensions(mDisplayMetrics); } return info; } catch (RemoteException e) { @@ -1072,18 +1071,6 @@ public class AppWidgetManager { } } - private void convertSizesToPixels(AppWidgetProviderInfo info) { - // Converting complex to dp. - info.minWidth = TypedValue.complexToDimensionPixelSize(info.minWidth, - mDisplayMetrics); - info.minHeight = TypedValue.complexToDimensionPixelSize(info.minHeight, - mDisplayMetrics); - info.minResizeWidth = TypedValue.complexToDimensionPixelSize(info.minResizeWidth, - mDisplayMetrics); - info.minResizeHeight = TypedValue.complexToDimensionPixelSize(info.minResizeHeight, - mDisplayMetrics); - } - /** * Request to pin an app widget on the current launcher. It's up to the launcher to accept this * request (optionally showing a user confirmation). If the request is accepted, the caller will diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index b4d79b484c89..06fdb32fe495 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -26,6 +26,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.content.ComponentName; import android.os.UserHandle; +import android.util.DisplayMetrics; +import android.util.TypedValue; /** * Describes the meta data for an installed AppWidget provider. The fields in this class @@ -379,6 +381,17 @@ public class AppWidgetProviderInfo implements Parcelable { } /** + * @hide + */ + public void updateDimensions(DisplayMetrics displayMetrics) { + // Converting complex to dp. + minWidth = TypedValue.complexToDimensionPixelSize(minWidth, displayMetrics); + minHeight = TypedValue.complexToDimensionPixelSize(minHeight, displayMetrics); + minResizeWidth = TypedValue.complexToDimensionPixelSize(minResizeWidth, displayMetrics); + minResizeHeight = TypedValue.complexToDimensionPixelSize(minResizeHeight, displayMetrics); + } + + /** * Parcelable.Creator that instantiates AppWidgetProviderInfo objects */ public static final Parcelable.Creator<AppWidgetProviderInfo> CREATOR diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index af5e64381bf1..596a9fd0610a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -35,6 +35,7 @@ import android.annotation.UserIdInt; import android.app.IApplicationThread; import android.app.IServiceConnection; import android.app.LoadedApk; +import android.app.Notification; import android.app.admin.DevicePolicyManager; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -2508,7 +2509,10 @@ public abstract class Context { * {@link ComponentName} of the actual service that was started is * returned; else if the service does not exist null is returned. * - * @throws SecurityException + * @throws SecurityException If the caller does not permission to access the service + * or the service can not be found. + * @throws IllegalStateException If the application is in a state where the service + * can not be started (such as not in the foreground in a state when services are allowed). * * @see #stopService * @see #bindService @@ -2517,6 +2521,17 @@ public abstract class Context { public abstract ComponentName startService(Intent service); /** + * Start a service directly into the "foreground service" state. Unlike {@link #startService}, + * this method can be used from within background operations like broadcast receivers + * or scheduled jobs. The API entry point for this is in NotificationManager in order to + * preserve appropriate public package layering. + * @hide + */ + @Nullable + public abstract ComponentName startServiceInForeground(Intent service, + int id, Notification notification); + + /** * Request that a given application service be stopped. If the service is * not running, nothing happens. Otherwise it is stopped. Note that calls * to startService() are not counted -- this stops the service no matter @@ -2538,7 +2553,10 @@ public abstract class Context { * @return If there is a service matching the given Intent that is already * running, then it is stopped and {@code true} is returned; else {@code false} is returned. * - * @throws SecurityException + * @throws SecurityException If the caller does not permission to access the service + * or the service can not be found. + * @throws IllegalStateException If the application is in a state where the service + * can not be started (such as not in the foreground in a state when services are allowed). * * @see #startService */ @@ -2547,9 +2565,18 @@ public abstract class Context { /** * @hide like {@link #startService(Intent)} but for a specific user. */ + @Nullable public abstract ComponentName startServiceAsUser(Intent service, UserHandle user); /** + * @hide like {@link #startServiceInForeground(Intent, int, Notification)} + * but for a specific user. + */ + @Nullable + public abstract ComponentName startServiceInForegroundAsUser(Intent service, + int id, Notification notification, UserHandle user); + + /** * @hide like {@link #stopService(Intent)} but for a specific user. */ public abstract boolean stopServiceAsUser(Intent service, UserHandle user); @@ -2591,7 +2618,8 @@ public abstract class Context { * {@code false} is returned if the connection is not made so you will not * receive the service object. * - * @throws SecurityException + * @throws SecurityException If the caller does not permission to access the service + * or the service can not be found. * * @see #unbindService * @see #startService diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index e437de0fb9ba..b131eccbe48a 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.IApplicationThread; import android.app.IServiceConnection; +import android.app.Notification; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; @@ -623,6 +624,13 @@ public class ContextWrapper extends Context { return mBase.startService(service); } + /** @hide */ + @Override + public ComponentName startServiceInForeground(Intent service, + int id, Notification notification) { + return mBase.startServiceInForeground(service, id, notification); + } + @Override public boolean stopService(Intent name) { return mBase.stopService(name); @@ -636,6 +644,13 @@ public class ContextWrapper extends Context { /** @hide */ @Override + public ComponentName startServiceInForegroundAsUser(Intent service, + int id, Notification notification, UserHandle user) { + return mBase.startServiceInForegroundAsUser(service, id, notification, user); + } + + /** @hide */ + @Override public boolean stopServiceAsUser(Intent name, UserHandle user) { return mBase.stopServiceAsUser(name, user); } diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 298dc4eafa15..4bd091dae77e 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -566,6 +566,7 @@ public class ActivityInfo extends ComponentInfo CONFIG_SMALLEST_SCREEN_SIZE, CONFIG_DENSITY, CONFIG_LAYOUT_DIRECTION, + CONFIG_COLORIMETRY, CONFIG_FONT_SCALE, }) @Retention(RetentionPolicy.SOURCE) @@ -671,6 +672,12 @@ public class ActivityInfo extends ComponentInfo public static final int CONFIG_LAYOUT_DIRECTION = 0x2000; /** * Bit in {@link #configChanges} that indicates that the activity + * can itself handle the change to the display color gamut or dynamic + * range. Set from the {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_COLORIMETRY = 0x4000; + /** + * Bit in {@link #configChanges} that indicates that the activity * can itself handle asset path changes. Set from the {@link android.R.attr#configChanges} * attribute. This is not a core resource configuration, but a higher-level value, so its * constant starts at the high bits. @@ -706,6 +713,7 @@ public class ActivityInfo extends ComponentInfo Configuration.NATIVE_CONFIG_SMALLEST_SCREEN_SIZE, // SMALLEST SCREEN SIZE Configuration.NATIVE_CONFIG_DENSITY, // DENSITY Configuration.NATIVE_CONFIG_LAYOUTDIR, // LAYOUT DIRECTION + Configuration.NATIVE_CONFIG_COLORIMETRY, // COLORIMETRY }; /** @@ -761,7 +769,8 @@ public class ActivityInfo extends ComponentInfo * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN}, * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, * {@link #CONFIG_ORIENTATION}, {@link #CONFIG_SCREEN_LAYOUT}, - * {@link #CONFIG_DENSITY}, and {@link #CONFIG_LAYOUT_DIRECTION}. + * {@link #CONFIG_DENSITY}, {@link #CONFIG_LAYOUT_DIRECTION} and + * {@link #CONFIG_COLORIMETRY}. * Set from the {@link android.R.attr#configChanges} attribute. */ public int configChanges; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 19cca8ed1f66..01f4e00210bd 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -138,6 +138,8 @@ interface IPackageManager { ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId); + ResolveInfo findPersistentPreferredActivity(in Intent intent, int userId); + boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId); ParceledListSlice queryIntentActivities(in Intent intent, diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index cf873b0278d9..c6a86748bfe8 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -61,15 +61,18 @@ import java.util.List; /** * Class for retrieving a list of launchable activities for the current user and any associated - * managed profiles. This is mainly for use by launchers. Apps can be queried for each user profile. + * managed profiles that are visible to the current user, which can be retrieved with + * {@link #getProfiles}. This is mainly for use by launchers. + * + * Apps can be queried for each user profile. * Since the PackageManager will not deliver package broadcasts for other profiles, you can register * for package changes here. * <p> * To watch for managed profiles being added or removed, register for the following broadcasts: * {@link Intent#ACTION_MANAGED_PROFILE_ADDED} and {@link Intent#ACTION_MANAGED_PROFILE_REMOVED}. * <p> - * You can retrieve the list of profiles associated with this user with - * {@link UserManager#getUserProfiles()}. + * Note as of Android O, apps on a managed profile are no longer allowed to access apps on the + * main profile. Apps can only access profiles returned by {@link #getProfiles()}. */ public class LauncherApps { @@ -376,6 +379,24 @@ public class LauncherApps { } /** + * Return a list of profiles that the caller can access via the {@link LauncherApps} APIs. + * + * <p>If the caller is running on a managed profile, it'll return only the current profile. + * Otherwise it'll return the same list as {@link UserManager#getUserProfiles()} would. + */ + public List<UserHandle> getProfiles() { + final UserManager um = mContext.getSystemService(UserManager.class); + if (um.isManagedProfile()) { + // If it's a managed profile, only return the current profile. + final List result = new ArrayList(1); + result.add(android.os.Process.myUserHandle()); + return result; + } else { + return um.getUserProfiles(); + } + } + + /** * Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and * {@link Intent#CATEGORY_LAUNCHER}, for a specified user. * @@ -1185,6 +1206,13 @@ public class LauncherApps { * Represents a "pin shortcut" request made by an app, which is sent with * an {@link #ACTION_CONFIRM_PIN_ITEM} intent to the default launcher app. * + * <p>Note the launcher may receive a request to pin a shortcut that is already pinned, because + * the user may actually want to have multiple icons of the same shortcut on the launcher. + * The launcher can tell this case by calling {@link ShortcutInfo#isPinned()} on the shortcut + * returned by {@link #getShortcutInfo()}. In this case, calling {@link #accept()} is optional; + * even if the launcher does not call it, the shortcut is already pinned. Also in this case, + * the {@code options} argument to {@link #accept(Bundle)} will be ignored. + * * @see #EXTRA_PIN_ITEM_REQUEST * @see #getPinItemRequest(Intent) */ @@ -1249,8 +1277,13 @@ public class LauncherApps { * {@link #REQUEST_TYPE_APPWIDGET} request. */ @Nullable - public AppWidgetProviderInfo getAppWidgetProviderInfo() { - return mAppWidgetInfo; + public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) { + if (mAppWidgetInfo != null) { + AppWidgetProviderInfo info = mAppWidgetInfo.clone(); + info.updateDimensions(context.getResources().getDisplayMetrics()); + return info; + } + return null; } /** diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 04e649cba092..507608a5dced 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1360,6 +1360,14 @@ public abstract class PackageManager { public static final int MOVE_FAILED_DEVICE_ADMIN = -8; /** + * Error code that is passed to the {@link IPackageMoveObserver} if system does not allow + * non-system apps to be moved to internal storage. + * + * @hide + */ + public static final int MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL = -9; + + /** * Flag parameter for {@link #movePackage} to indicate that * the package should be moved to internal storage if its * been installed on external media. @@ -1854,6 +1862,20 @@ public abstract class PackageManager { public static final String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm"; /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: + * The device supports telephony carrier restriction mechanism. + * + * <p>Devices declaring this feature must have an implementation of the + * {@link android.telephony.TelephonyManager#getAllowedCarriers} and + * {@link android.telephony.TelephonyManager#setAllowedCarriers}. + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_TELEPHONY_CARRIERLOCK = + "android.hardware.telephony.carrierlock"; + + /** * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device supports connecting to USB devices * as the USB host. diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 2590a6beda39..a1747c7d22b9 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -138,9 +138,8 @@ public abstract class PackageManagerInternal { * @param userId The user under which to check. * * @return An {@link ApplicationInfo} containing information about the - * package. - * @throws NameNotFoundException if a package with the given name cannot be - * found on the system. + * package, or {@code null} if no application exists with that + * package name. */ public abstract ApplicationInfo getApplicationInfo(String packageName, int userId); @@ -223,6 +222,27 @@ public abstract class PackageManagerInternal { int userId); /** + * Grants access to the package metadata for an ephemeral application. + * <p> + * When an ephemeral application explicitly tries to interact with a full + * install application [via an activity, service or provider that has been + * exposed using the {@code visibleToInstantApp} attribute], the normal + * application must be able to see metadata about the connecting ephemeral + * app. If the ephemeral application uses an implicit intent [ie action VIEW, + * category BROWSABLE], it remains hidden from the launched activity. + * <p> + * If the {@code sourceUid} is not for an ephemeral app or {@code targetUid} + * is not for a fully installed app, this method will be a no-op. + * + * @param userId the user + * @param intent the intent that triggered the grant + * @param targetAppId The app ID of the fully installed application + * @param ephemeralAppId The app ID of the ephemeral application + */ + public abstract void grantEphemeralAccess(int userId, Intent intent, + int targetAppId, int ephemeralAppId); + + /** * @return The SetupWizard package name. */ public abstract String getSetupWizardPackageName(); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 083e4cc6676b..2fdc527208c0 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -179,6 +179,13 @@ public class PackageParser { private static final String TAG_PACKAGE = "package"; private static final String TAG_RESTRICT_UPDATE = "restrict-update"; + /** + * Bit mask of all the valid bits that can be set in restartOnConfigChanges. + * @hide + */ + private static final int RESTART_ON_CONFIG_CHANGES_MASK = + ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC; + // These are the tags supported by child packages private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>(); static { @@ -3855,7 +3862,9 @@ public class PackageParser { a.info.maxRecents = sa.getInt( R.styleable.AndroidManifestActivity_maxRecents, ActivityManager.getDefaultAppRecentsLimitStatic()); - a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0); + a.info.configChanges = getActivityConfigChanges( + sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0), + sa.getInt(R.styleable.AndroidManifestActivity_restartOnConfigChanges, 0)); a.info.softInputMode = sa.getInt( R.styleable.AndroidManifestActivity_windowSoftInputMode, 0); @@ -4083,6 +4092,17 @@ public class PackageParser { } } + /** + * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml. + * @param restartOnConfigChanges The bit mask restartOnConfigChanges fetched from + * AndroidManifest.xml. + * @hide Exposed for unit testing only. + */ + @TestApi + public static int getActivityConfigChanges(int configChanges, int restartOnConfigChanges) { + return configChanges | ((~restartOnConfigChanges) & RESTART_ON_CONFIG_CHANGES_MASK); + } + private void parseLayout(Resources res, AttributeSet attrs, Activity a) { TypedArray sw = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestLayout); diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 65f49578071f..a81329d9ee67 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -101,6 +101,68 @@ public final class Configuration implements Parcelable, Comparable<Configuration */ public boolean userSetLocale; + + /** Constant for {@link #colorimetry}: bits that encode whether the screen is wide gamut. */ + public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 0x3; + /** + * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value + * indicating that it is unknown whether or not the screen is wide gamut. + */ + public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0x0; + /** + * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value + * indicating that the screen is not wide gamut. + * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p> + */ + public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 0x1; + /** + * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value + * indicating that the screen is wide gamut. + * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p> + */ + public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 0x2; + + /** Constant for {@link #colorimetry}: bits that encode whether the dynamic range of the screen. */ + public static final int COLORIMETRY_HDR_MASK = 0xc; + /** Constant for {@link #colorimetry}: bits shift to get the screen dynamic range. */ + public static final int COLORIMETRY_HDR_SHIFT = 2; + /** + * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value + * indicating that it is unknown whether or not the screen is HDR. + */ + public static final int COLORIMETRY_HDR_UNDEFINED = 0x0; + /** + * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value + * indicating that the screen is not HDR (low/standard dynamic range). + * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p> + */ + public static final int COLORIMETRY_HDR_NO = 0x1 << COLORIMETRY_HDR_SHIFT; + /** + * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value + * indicating that the screen is HDR (dynamic range). + * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p> + */ + public static final int COLORIMETRY_HDR_YES = 0x2 << COLORIMETRY_HDR_SHIFT; + + /** Constant for {@link #colorimetry}: a value indicating that colorimetry is undefined */ + @SuppressWarnings("PointlessBitwiseExpression") + public static final int COLORIMETRY_UNDEFINED = COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED | + COLORIMETRY_HDR_UNDEFINED; + + /** + * Bit mask of for color capabilities of the screen. Currently there are two fields: + * <p>The {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of + * the screen. They may be one of + * {@link #COLORIMETRY_WIDE_COLOR_GAMUT_NO} or {@link #COLORIMETRY_WIDE_COLOR_GAMUT_YES}.</p> + * + * <p>The {@link #COLORIMETRY_HDR_MASK} defines the dynamic range of the screen. They may be + * one of {@link #COLORIMETRY_HDR_NO} or {@link #COLORIMETRY_HDR_YES}.</p> + * + * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting + * Multiple Screens</a> for more information.</p> + */ + public int colorimetry; + /** Constant for {@link #screenLayout}: bits that encode the size. */ public static final int SCREENLAYOUT_SIZE_MASK = 0x0f; /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} @@ -331,6 +393,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) { list.add("CONFIG_SCREEN_LAYOUT"); } + if ((diff & ActivityInfo.CONFIG_COLORIMETRY) != 0) { + list.add("CONFIG_COLORIMETRY"); + } if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) { list.add("CONFIG_UI_MODE"); } @@ -711,6 +776,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration NATIVE_CONFIG_UI_MODE, NATIVE_CONFIG_SMALLEST_SCREEN_SIZE, NATIVE_CONFIG_LAYOUTDIR, + NATIVE_CONFIG_COLORIMETRY, }) @Retention(RetentionPolicy.SOURCE) public @interface NativeConfig {} @@ -747,6 +813,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000; /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/ public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000; + /** @hide Native-specific bit mask for COLORIMETRY config ; DO NOT USE UNLESS YOU ARE SURE.*/ + public static final int NATIVE_CONFIG_COLORIMETRY = 0x10000; /** * <p>Construct an invalid Configuration. This state is only suitable for constructing a @@ -805,6 +873,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration navigationHidden = o.navigationHidden; orientation = o.orientation; screenLayout = o.screenLayout; + colorimetry = o.colorimetry; uiMode = o.uiMode; screenWidthDp = o.screenWidthDp; screenHeightDp = o.screenHeightDp; @@ -885,6 +954,20 @@ public final class Configuration implements Parcelable, Comparable<Configuration default: sb.append(" layoutLong="); sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break; } + switch ((colorimetry&COLORIMETRY_HDR_MASK)) { + case COLORIMETRY_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR + case COLORIMETRY_HDR_NO: /* ldr is not interesting to print */ break; + case COLORIMETRY_HDR_YES: sb.append(" hdr"); break; + default: sb.append(" dynamicRange="); + sb.append(colorimetry&COLORIMETRY_HDR_MASK); break; + } + switch ((colorimetry&COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) { + case COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break; + case COLORIMETRY_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break; + case COLORIMETRY_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break; + default: sb.append(" wideColorGamut="); + sb.append(colorimetry&COLORIMETRY_WIDE_COLOR_GAMUT_MASK); break; + } switch (orientation) { case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break; case ORIENTATION_LANDSCAPE: sb.append(" land"); break; @@ -976,6 +1059,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration navigationHidden = NAVIGATIONHIDDEN_UNDEFINED; orientation = ORIENTATION_UNDEFINED; screenLayout = SCREENLAYOUT_UNDEFINED; + colorimetry = COLORIMETRY_UNDEFINED; uiMode = UI_MODE_TYPE_UNDEFINED; screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; @@ -1111,6 +1195,23 @@ public final class Configuration implements Parcelable, Comparable<Configuration | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED); } + if (((delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) != + COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED) + && (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) + != (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) { + changed |= ActivityInfo.CONFIG_COLORIMETRY; + colorimetry = (colorimetry & ~COLORIMETRY_WIDE_COLOR_GAMUT_MASK) + | (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK); + } + + if (((delta.colorimetry & COLORIMETRY_HDR_MASK) != COLORIMETRY_HDR_UNDEFINED) + && (delta.colorimetry & COLORIMETRY_HDR_MASK) + != (colorimetry & COLORIMETRY_HDR_MASK)) { + changed |= ActivityInfo.CONFIG_COLORIMETRY; + colorimetry = (colorimetry & ~COLORIMETRY_HDR_MASK) + | (delta.colorimetry & COLORIMETRY_HDR_MASK); + } + if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED) && uiMode != delta.uiMode) { changed |= ActivityInfo.CONFIG_UI_MODE; @@ -1260,6 +1361,19 @@ public final class Configuration implements Parcelable, Comparable<Configuration getScreenLayoutNoDirection(delta.screenLayout)) { changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; } + if ((compareUndefined || + (delta.colorimetry & COLORIMETRY_HDR_MASK) != COLORIMETRY_HDR_UNDEFINED) + && (colorimetry & COLORIMETRY_HDR_MASK) != + (delta.colorimetry & COLORIMETRY_HDR_MASK)) { + changed |= ActivityInfo.CONFIG_COLORIMETRY; + } + if ((compareUndefined || + (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) != + COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED) + && (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) != + (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) { + changed |= ActivityInfo.CONFIG_COLORIMETRY; + } if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)) && uiMode != delta.uiMode) { changed |= ActivityInfo.CONFIG_UI_MODE; @@ -1371,6 +1485,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeInt(navigationHidden); dest.writeInt(orientation); dest.writeInt(screenLayout); + dest.writeInt(colorimetry); dest.writeInt(uiMode); dest.writeInt(screenWidthDp); dest.writeInt(screenHeightDp); @@ -1405,6 +1520,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration navigationHidden = source.readInt(); orientation = source.readInt(); screenLayout = source.readInt(); + colorimetry = source.readInt(); uiMode = source.readInt(); screenWidthDp = source.readInt(); screenHeightDp = source.readInt(); @@ -1486,6 +1602,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (n != 0) return n; n = this.orientation - that.orientation; if (n != 0) return n; + n = this.colorimetry - that.colorimetry; + if (n != 0) return n; n = this.screenLayout - that.screenLayout; if (n != 0) return n; n = this.uiMode - that.uiMode; @@ -1531,6 +1649,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration result = 31 * result + navigationHidden; result = 31 * result + orientation; result = 31 * result + screenLayout; + result = 31 * result + colorimetry; result = 31 * result + uiMode; result = 31 * result + screenWidthDp; result = 31 * result + screenHeightDp; @@ -1639,6 +1758,24 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** + * Return whether the screen has a wide color gamut. + * + * @return true if the screen has a wide color gamut, false otherwise + */ + public boolean isScreenWideColorGamut() { + return (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) == COLORIMETRY_WIDE_COLOR_GAMUT_YES; + } + + /** + * Return whether the screen has a high dynamic range. + * + * @return true if the screen has a high dynamic range, false otherwise + */ + public boolean isScreenHdr() { + return (colorimetry & COLORIMETRY_HDR_MASK) == COLORIMETRY_HDR_YES; + } + + /** * * @hide */ @@ -1770,6 +1907,28 @@ public final class Configuration implements Parcelable, Comparable<Configuration break; } + switch (config.colorimetry & Configuration.COLORIMETRY_HDR_MASK) { + case Configuration.COLORIMETRY_HDR_YES: + parts.add("highdr"); + break; + case Configuration.COLORIMETRY_HDR_NO: + parts.add("lowdr"); + break; + default: + break; + } + + switch (config.colorimetry & Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_MASK) { + case Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_YES: + parts.add("widecg"); + break; + case Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_NO: + parts.add("nowidecg"); + break; + default: + break; + } + switch (config.orientation) { case Configuration.ORIENTATION_LANDSCAPE: parts.add("land"); @@ -1995,6 +2154,16 @@ public final class Configuration implements Parcelable, Comparable<Configuration delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK; } + if ((base.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) != + (change.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) { + delta.colorimetry |= change.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK; + } + + if ((base.colorimetry & COLORIMETRY_HDR_MASK) != + (change.colorimetry & COLORIMETRY_HDR_MASK)) { + delta.colorimetry |= change.colorimetry & COLORIMETRY_HDR_MASK; + } + if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) { delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK; } @@ -2037,6 +2206,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid"; private static final String XML_ATTR_ORIENTATION = "ori"; private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay"; + private static final String XML_ATTR_COLORIMETRY = "clrMtry"; private static final String XML_ATTR_UI_MODE = "ui"; private static final String XML_ATTR_SCREEN_WIDTH = "width"; private static final String XML_ATTR_SCREEN_HEIGHT = "height"; @@ -2079,6 +2249,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration ORIENTATION_UNDEFINED); configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT, SCREENLAYOUT_UNDEFINED); + configOut.colorimetry = XmlUtils.readIntAttribute(parser, XML_ATTR_COLORIMETRY, + COLORIMETRY_UNDEFINED); configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0); configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH, SCREEN_WIDTH_DP_UNDEFINED); @@ -2141,6 +2313,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (config.screenLayout != SCREENLAYOUT_UNDEFINED) { XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout); } + if (config.colorimetry != COLORIMETRY_UNDEFINED) { + XmlUtils.writeIntAttribute(xml, XML_ATTR_COLORIMETRY, config.colorimetry); + } if (config.uiMode != 0) { XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode); } diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java index ffbc4011f5d6..1a128e05ce6e 100644 --- a/core/java/android/net/NetworkKey.java +++ b/core/java/android/net/NetworkKey.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.SystemApi; +import android.net.wifi.ScanResult; import android.os.Parcel; import android.os.Parcelable; @@ -52,6 +53,18 @@ public class NetworkKey implements Parcelable { public final WifiKey wifiKey; /** + * Constructs a new NetworkKey for the given wifi {@link ScanResult}. + * + * @throws IllegalArgumentException if the given ScanResult is malformed + * @hide + */ + public static NetworkKey createFromScanResult(ScanResult result) { + return new NetworkKey( + new WifiKey( + '"' + result.wifiSsid.toString() + '"', result.BSSID)); + } + + /** * Construct a new {@link NetworkKey} for a Wi-Fi network. * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network. */ diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java index a227f18fe2bf..b89a245623ee 100644 --- a/core/java/android/net/RecommendationRequest.java +++ b/core/java/android/net/RecommendationRequest.java @@ -37,6 +37,8 @@ public final class RecommendationRequest implements Parcelable { private final WifiConfiguration mDefaultConfig; private WifiConfiguration mConnectedConfig; private WifiConfiguration[] mConnectableConfigs; + private final int mLastSelectedNetworkId; + private final long mLastSelectedNetworkTimestamp; /** * Builder class for constructing {@link RecommendationRequest} instances. @@ -48,17 +50,9 @@ public final class RecommendationRequest implements Parcelable { private WifiConfiguration mDefaultConfig; private WifiConfiguration mConnectedConfig; private WifiConfiguration[] mConnectableConfigs; + private int mLastSelectedNetworkId; + private long mLastSelectedTimestamp; - /** - * @param scanResults the array of {@link ScanResult}s the recommendation must be - * constrained to i.e. if a non-null wifi config recommendation is - * returned then it must be able to connect to one of the networks in - * the results list. - * - * If the array is {@code null} or empty then there is no constraint. - * - * @return this - */ public Builder setScanResults(ScanResult[] scanResults) { mScanResults = scanResults; return this; @@ -89,7 +83,20 @@ public final class RecommendationRequest implements Parcelable { * @return this */ public Builder setConnectableConfigs(WifiConfiguration[] connectableConfigs) { - mConnectableConfigs = connectableConfigs; + this.mConnectableConfigs = connectableConfigs; + return this; + } + + /** + * @param networkId The {@link WifiConfiguration#networkId} of the last user selected + * network. + * @param timestamp The {@link android.os.SystemClock#elapsedRealtime()} when the user + * selected {@code networkId}. + * @return this + */ + public Builder setLastSelectedNetwork(int networkId, long timestamp) { + this.mLastSelectedNetworkId = networkId; + this.mLastSelectedTimestamp = timestamp; return this; } @@ -97,10 +104,8 @@ public final class RecommendationRequest implements Parcelable { * @return a new {@link RecommendationRequest} instance */ public RecommendationRequest build() { - return new RecommendationRequest(mScanResults, - mDefaultConfig, - mConnectedConfig, - mConnectableConfigs); + return new RecommendationRequest(mScanResults, mDefaultConfig, mConnectedConfig, + mConnectableConfigs, mLastSelectedNetworkId, mLastSelectedTimestamp); } } @@ -154,15 +159,35 @@ public final class RecommendationRequest implements Parcelable { mConnectableConfigs = connectableConfigs; } + /** + * @return The {@link WifiConfiguration#networkId} of the last user selected network. + * {@code 0} if not set. + */ + public int getLastSelectedNetworkId() { + return mLastSelectedNetworkId; + } + + /** + * @return The {@link android.os.SystemClock#elapsedRealtime()} when the user selected + * {@link #getLastSelectedNetworkId()}. {@code 0} if not set. + */ + public long getLastSelectedNetworkTimestamp() { + return mLastSelectedNetworkTimestamp; + } + @VisibleForTesting RecommendationRequest(ScanResult[] scanResults, WifiConfiguration defaultWifiConfig, WifiConfiguration connectedWifiConfig, - WifiConfiguration[] connectableConfigs) { + WifiConfiguration[] connectableConfigs, + int lastSelectedNetworkId, + long lastSelectedNetworkTimestamp) { mScanResults = scanResults; mDefaultConfig = defaultWifiConfig; mConnectedConfig = connectedWifiConfig; mConnectableConfigs = connectableConfigs; + mLastSelectedNetworkId = lastSelectedNetworkId; + mLastSelectedNetworkTimestamp = lastSelectedNetworkTimestamp; } protected RecommendationRequest(Parcel in) { @@ -190,6 +215,9 @@ public final class RecommendationRequest implements Parcelable { } else { mConnectableConfigs = null; } + + mLastSelectedNetworkId = in.readInt(); + mLastSelectedNetworkTimestamp = in.readLong(); } @Override @@ -220,7 +248,8 @@ public final class RecommendationRequest implements Parcelable { dest.writeInt(0); } - + dest.writeInt(mLastSelectedNetworkId); + dest.writeLong(mLastSelectedNetworkTimestamp); } public static final Creator<RecommendationRequest> CREATOR = diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java index cea56b53d763..ffc735c93aef 100644 --- a/core/java/android/net/SntpClient.java +++ b/core/java/android/net/SntpClient.java @@ -96,6 +96,7 @@ public class SntpClient { public boolean requestTime(InetAddress address, int port, int timeout) { DatagramSocket socket = null; + final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP); try { socket = new DatagramSocket(); socket.setSoTimeout(timeout); @@ -161,6 +162,7 @@ public class SntpClient { if (socket != null) { socket.close(); } + TrafficStats.setThreadStatsTag(oldTag); } return true; diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e7436be273a3..fc66395bcd00 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -168,6 +168,24 @@ public class TrafficStats { /** * Set active tag to use when accounting {@link Socket} traffic originating + * from the current thread. Only one active tag per thread is supported. + * <p> + * Changes only take effect during subsequent calls to + * {@link #tagSocket(Socket)}. + * <p> + * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and + * used internally by system services like {@link DownloadManager} when + * performing traffic on behalf of an application. + * + * @return the current tag for the calling thread, which can be used to + * restore any existing values after a nested operation is finished + */ + public static int getAndSetThreadStatsTag(int tag) { + return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); + } + + /** + * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. The tag used internally is well-defined to * distinguish all backup-related traffic. * diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 73c9462403f2..7c015deae8f5 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -38,7 +38,6 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; @@ -334,12 +333,7 @@ public class FileUtils { * @throws IOException */ public static void stringToFile(String filename, String string) throws IOException { - FileWriter out = new FileWriter(filename); - try { - out.write(string); - } finally { - out.close(); - } + bytesToFile(filename, string.getBytes(StandardCharsets.UTF_8)); } /** diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index e15f086a8874..d6d5cb6493e0 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -27,6 +27,8 @@ import android.util.SizeF; import android.util.SparseArray; import android.util.SparseBooleanArray; +import libcore.util.SneakyThrow; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; @@ -250,6 +252,7 @@ public final class Parcel { private static final int EX_NETWORK_MAIN_THREAD = -6; private static final int EX_UNSUPPORTED_OPERATION = -7; private static final int EX_SERVICE_SPECIFIC = -8; + private static final int EX_PARCELABLE = -9; private static final int EX_HAS_REPLY_HEADER = -128; // special; see below // EX_TRANSACTION_FAILED is used exclusively in native code. // see libbinder's binder/Status.h @@ -1597,7 +1600,12 @@ public final class Parcel { */ public final void writeException(Exception e) { int code = 0; - if (e instanceof SecurityException) { + if (e instanceof Parcelable + && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) { + // We only send Parcelable exceptions that are in the + // BootClassLoader to ensure that the receiver can unpack them + code = EX_PARCELABLE; + } else if (e instanceof SecurityException) { code = EX_SECURITY; } else if (e instanceof BadParcelableException) { code = EX_BAD_PARCELABLE; @@ -1623,8 +1631,20 @@ public final class Parcel { throw new RuntimeException(e); } writeString(e.getMessage()); - if (e instanceof ServiceSpecificException) { - writeInt(((ServiceSpecificException)e).errorCode); + switch (code) { + case EX_SERVICE_SPECIFIC: + writeInt(((ServiceSpecificException) e).errorCode); + break; + case EX_PARCELABLE: + // Write parceled exception prefixed by length + final int sizePosition = dataPosition(); + writeInt(0); + writeParcelable((Parcelable) e, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + final int payloadPosition = dataPosition(); + setDataPosition(sizePosition); + writeInt(payloadPosition - sizePosition); + setDataPosition(payloadPosition); + break; } } @@ -1722,6 +1742,13 @@ public final class Parcel { */ public final void readException(int code, String msg) { switch (code) { + case EX_PARCELABLE: + if (readInt() > 0) { + SneakyThrow.sneakyThrow( + (Exception) readParcelable(Parcelable.class.getClassLoader())); + } else { + throw new RuntimeException(msg + " [missing Parcelable]"); + } case EX_SECURITY: throw new SecurityException(msg); case EX_BAD_PARCELABLE: diff --git a/core/java/android/os/ParcelableException.java b/core/java/android/os/ParcelableException.java new file mode 100644 index 000000000000..d84d62997d93 --- /dev/null +++ b/core/java/android/os/ParcelableException.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import java.io.IOException; + +/** + * Wrapper class that offers to transport typical {@link Throwable} across a + * {@link Binder} call. This class is typically used to transport exceptions + * that cannot be modified to add {@link Parcelable} behavior, such as + * {@link IOException}. + * <ul> + * <li>The wrapped throwable must be defined as system class (that is, it must + * be in the same {@link ClassLoader} as {@link Parcelable}). + * <li>The wrapped throwable must support the + * {@link Throwable#Throwable(String)} constructor. + * <li>The receiver side must catch any thrown {@link ParcelableException} and + * call {@link #maybeRethrow(Class)} for all expected exception types. + * </ul> + * + * @hide + */ +public final class ParcelableException extends RuntimeException implements Parcelable { + public ParcelableException(Throwable t) { + super(t); + } + + @SuppressWarnings("unchecked") + public <T extends Throwable> void maybeRethrow(Class<T> clazz) throws T { + if (clazz.isAssignableFrom(getCause().getClass())) { + throw (T) getCause(); + } + } + + /** {@hide} */ + public static Throwable readFromParcel(Parcel in) { + final String name = in.readString(); + final String msg = in.readString(); + try { + final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader()); + return (Throwable) clazz.getConstructor(String.class).newInstance(msg); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(name + ": " + msg); + } + } + + /** {@hide} */ + public static void writeToParcel(Parcel out, Throwable t) { + out.writeString(t.getClass().getName()); + out.writeString(t.getMessage()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + writeToParcel(dest, getCause()); + } + + public static final Creator<ParcelableException> CREATOR = new Creator<ParcelableException>() { + @Override + public ParcelableException createFromParcel(Parcel source) { + return new ParcelableException(readFromParcel(source)); + } + + @Override + public ParcelableException[] newArray(int size) { + return new ParcelableException[size]; + } + }; +} diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 0da4bd16c697..ae981b77ca84 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -24,6 +24,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.net.TrafficStats; import android.net.Uri; import android.util.ArrayMap; import android.util.Log; @@ -245,11 +246,17 @@ public final class StrictMode { */ private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy + /** + * @hide + */ + private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy + private static final int ALL_VM_DETECT_BITS = DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS | DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE | - DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION; + DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION | + DETECT_VM_UNTAGGED_SOCKET; // Byte 3: Penalty @@ -300,6 +307,8 @@ public final class StrictMode { */ public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24; + // CAUTION: we started stealing the top bits of Byte 4 for VM above + /** * Mask of all the penalty bits valid for thread policies. */ @@ -715,7 +724,8 @@ public final class StrictMode { public Builder detectAll() { int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS - | DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION; + | DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION + | DETECT_VM_UNTAGGED_SOCKET; // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility // for apps to mark sockets that should be ignored @@ -820,6 +830,22 @@ public final class StrictMode { } /** + * Detect any sockets in the calling app which have not been tagged + * using {@link TrafficStats}. Tagging sockets can help you + * investigate network usage inside your app, such as a narrowing + * down heavy usage to a specific library or component. + * <p> + * This currently does not detect sockets created in native code. + * + * @see TrafficStats#setThreadStatsTag(int) + * @see TrafficStats#tagSocket(java.net.Socket) + * @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket) + */ + public Builder detectUntaggedSockets() { + return enable(DETECT_VM_UNTAGGED_SOCKET); + } + + /** * Crashes the whole process on violation. This penalty runs at the * end of all enabled penalties so you'll still get your logging or * other violations before the process dies. @@ -1152,6 +1178,11 @@ public final class StrictMode { if (IS_ENG_BUILD) { policyBuilder.penaltyLog(); } + // All core system components need to tag their sockets to aid + // system health investigations + if (android.os.Process.myUid() < android.os.Process.FIRST_APPLICATION_UID) { + policyBuilder.detectUntaggedSockets(); + } setVmPolicy(policyBuilder.build()); setCloseGuardEnabled(vmClosableObjectLeaksEnabled()); } @@ -1832,6 +1863,13 @@ public final class StrictMode { /** * @hide */ + public static boolean vmUntaggedSocketEnabled() { + return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0; + } + + /** + * @hide + */ public static void onSqliteObjectLeaked(String message, Throwable originStack) { onVmPolicyViolation(message, originStack); } @@ -1911,6 +1949,14 @@ public final class StrictMode { forceDeath); } + /** + * @hide + */ + public static void onUntaggedSocket() { + onVmPolicyViolation(null, new Throwable("Untagged socket detected; use" + + " TrafficStats.setThreadSocketTag() to track all network usage")); + } + // Map from VM violation fingerprint to uptime millis. private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>(); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 371c0f3b90ca..d136ec591030 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -50,6 +50,7 @@ import android.net.ConnectivityManager; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; +import android.os.Binder; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.DropBoxManager; @@ -286,6 +287,21 @@ public final class Settings { "android.settings.SECURITY_SETTINGS"; /** + * Activity Action: Show settings to allow configuration of trusted external sources + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_EXTERNAL_SOURCES = + "android.settings.action.MANAGE_EXTERNAL_SOURCES"; + + /** * Activity Action: Show trusted credentials settings, opening to the user tab, * to allow management of installed credentials. * <p> @@ -1581,6 +1597,24 @@ public final class Settings { // with a partial enable/disable state in multi-threaded situations. private static final Object mLocationSettingsLock = new Object(); + // Used in system server calling uid workaround in call() + private static boolean sInSystemServer = false; + private static final Object sInSystemServerLock = new Object(); + + /** @hide */ + public static void setInSystemServer() { + synchronized (sInSystemServerLock) { + sInSystemServer = true; + } + } + + /** @hide */ + public static boolean isInSystemServer() { + synchronized (sInSystemServerLock) { + return sInSystemServer; + } + } + public static class SettingNotFoundException extends AndroidException { public SettingNotFoundException(String msg) { super(msg); @@ -1789,7 +1823,23 @@ public final class Settings { } } } - Bundle b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); + Bundle b; + // If we're in system server and in a binder transaction we need to clear the + // calling uid. This works around code in system server that did not call + // clearCallingIdentity, previously this wasn't needed because reading settings + // did not do permission checking but thats no longer the case. + // Long term this should be removed and callers should properly call + // clearCallingIdentity or use a ContentResolver from the caller as needed. + if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { + final long token = Binder.clearCallingIdentity(); + try { + b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); + } finally { + Binder.restoreCallingIdentity(token); + } + } else { + b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); + } if (b != null) { String value = b.getString(Settings.NameValueTable.VALUE); // Don't update our cache for reads of other users' data @@ -1849,7 +1899,19 @@ public final class Settings { try { Bundle queryArgs = ContentResolver.createSqlQueryBundle( NAME_EQ_PLACEHOLDER, new String[]{name}, null); - c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null); + // Same workaround as above. + if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { + final long token = Binder.clearCallingIdentity(); + try { + c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, + null); + } finally { + Binder.restoreCallingIdentity(token); + } + } else { + c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, + null); + } if (c == null) { Log.w(TAG, "Can't get key " + name + " from " + mUri); return null; @@ -4006,6 +4068,22 @@ public final class Settings { } /** + * System settings which can be accessed by ephemeral apps. + * @hide + */ + public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); + static { + EPHEMERAL_SETTINGS.add(TEXT_AUTO_REPLACE); + EPHEMERAL_SETTINGS.add(TEXT_AUTO_CAPS); + EPHEMERAL_SETTINGS.add(TEXT_AUTO_PUNCTUATE); + EPHEMERAL_SETTINGS.add(TEXT_SHOW_PASSWORD); + EPHEMERAL_SETTINGS.add(DATE_FORMAT); + EPHEMERAL_SETTINGS.add(FONT_SCALE); + EPHEMERAL_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED); + EPHEMERAL_SETTINGS.add(TIME_12_24); + } + + /** * When to use Wi-Fi calling * * @see android.telephony.TelephonyManager.WifiCallingChoices @@ -6884,6 +6962,20 @@ public final class Settings { } /** + * Secure settings which can be accessed by ephemeral apps. + * @hide + */ + public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); + static { + EPHEMERAL_SETTINGS.add(ENABLED_ACCESSIBILITY_SERVICES); + EPHEMERAL_SETTINGS.add(ACCESSIBILITY_SPEAK_PASSWORD); + EPHEMERAL_SETTINGS.add(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); + + EPHEMERAL_SETTINGS.add(DEFAULT_INPUT_METHOD); + EPHEMERAL_SETTINGS.add(ENABLED_INPUT_METHODS); + } + + /** * Helper method for determining if a location provider is enabled. * * @param cr the content resolver to use @@ -9891,6 +9983,20 @@ public final class Settings { * @hide */ public static final String CELL_ON = "cell_on"; + + /** + * Global settings which can be accessed by ephemeral apps. + * @hide + */ + public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); + static { + EPHEMERAL_SETTINGS.add(WAIT_FOR_DEBUGGER); + EPHEMERAL_SETTINGS.add(DEVICE_PROVISIONED); + EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES); + EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RTL); + EPHEMERAL_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES); + } + } /** diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java index c3cbcdc3932c..a4b6807e216f 100644 --- a/core/java/android/provider/VoicemailContract.java +++ b/core/java/android/provider/VoicemailContract.java @@ -30,6 +30,7 @@ import android.provider.CallLog.Calls; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.Voicemail; + import java.util.List; /** @@ -279,6 +280,48 @@ public class VoicemailContract { public static final String LAST_MODIFIED = "last_modified"; /** + * Flag to indicate the voicemail was backed up. The value will be 1 if backed up, 0 if + * not. + * + * <P>Type: INTEGER (boolean)</P> + * + * @hide + */ + public static final String BACKED_UP = "backed_up"; + + /** + * Flag to indicate the voicemail was restored from a backup. The value will be 1 if + * restored, 0 if not. + * + * <P>Type: INTEGER (boolean)</P> + * + * @hide + */ + public static final String RESTORED = "restored"; + + /** + * Flag to indicate the voicemail was marked as archived. Archived voicemail should not be + * deleted even if it no longer exist on the server. The value will be 1 if archived true, 0 + * if not. + * + * <P>Type: INTEGER (boolean)</P> + * + * @hide + */ + public static final String ARCHIVED = "archived"; + + /** + * Flag to indicate the voicemail is a OMTP voicemail handled by the {@link + * android.telephony.VisualVoicemailService}. The UI should only show OMTP voicemails from + * the current visual voicemail package. + * + * <P>Type: INTEGER (boolean)</P> + * + * @hide + */ + public static final String IS_OMTP_VOICEMAIL = "is_omtp_voicmail"; + + /** * A convenience method to build voicemail URI specific to a source package by appending * {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI. */ diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index eb3d0312b2cf..22f1bedc6072 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -132,6 +132,8 @@ public final class KeymasterDefs { public static final int KM_PURPOSE_DECRYPT = 1; public static final int KM_PURPOSE_SIGN = 2; public static final int KM_PURPOSE_VERIFY = 3; + public static final int KM_PURPOSE_DERIVE_KEY = 4; + public static final int KM_PURPOSE_WRAP_KEY = 5; // Key formats. public static final int KM_KEY_FORMAT_X509 = 0; diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java index f5d515d5e5d5..da0b609dbd9b 100644 --- a/core/java/android/util/ExceptionUtils.java +++ b/core/java/android/util/ExceptionUtils.java @@ -16,6 +16,8 @@ package android.util; +import android.os.ParcelableException; + import java.io.IOException; /** @@ -24,19 +26,13 @@ import java.io.IOException; * @hide */ public class ExceptionUtils { - // TODO: longer term these should be replaced with first-class - // Parcel.read/writeException() and AIDL support, but for now do this using - // a nasty hack. - - private static final String PREFIX_IO = "\u2603"; - public static RuntimeException wrap(IOException e) { - throw new IllegalStateException(PREFIX_IO + e.getMessage()); + throw new ParcelableException(e); } public static void maybeUnwrapIOException(RuntimeException e) throws IOException { - if ((e instanceof IllegalStateException) && e.getMessage().startsWith(PREFIX_IO)) { - throw new IOException(e.getMessage().substring(PREFIX_IO.length())); + if (e instanceof ParcelableException) { + ((ParcelableException) e).maybeRethrow(IOException.class); } } diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java index f3f3d40213ec..7a5c65f6a87e 100644 --- a/core/java/android/view/MenuInflater.java +++ b/core/java/android/view/MenuInflater.java @@ -335,7 +335,7 @@ public class MenuInflater { private ActionProvider itemActionProvider; private CharSequence itemContentDescription; - private CharSequence itemTooltip; + private CharSequence itemTooltipText; private static final int defaultGroupId = NO_ID; private static final int defaultItemId = NO_ID; @@ -429,7 +429,7 @@ public class MenuInflater { itemContentDescription = a.getText(com.android.internal.R.styleable.MenuItem_contentDescription); - itemTooltip = a.getText(com.android.internal.R.styleable.MenuItem_tooltip); + itemTooltipText = a.getText(com.android.internal.R.styleable.MenuItem_tooltipText); a.recycle(); @@ -495,7 +495,7 @@ public class MenuInflater { } item.setContentDescription(itemContentDescription); - item.setTooltip(itemTooltip); + item.setTooltipText(itemTooltipText); } public MenuItem addItem() { diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java index 5ced76592756..3f8d08937a77 100644 --- a/core/java/android/view/MenuItem.java +++ b/core/java/android/view/MenuItem.java @@ -621,9 +621,9 @@ public interface MenuItem { /** * Change the tooltip text associated with this menu item. * - * @param tooltip The new tooltip text. + * @param tooltipText The new tooltip text. */ - default MenuItem setTooltip(CharSequence tooltip) { + default MenuItem setTooltipText(CharSequence tooltipText) { return this; } @@ -632,7 +632,7 @@ public interface MenuItem { * * @return The tooltip text. */ - default CharSequence getTooltip() { + default CharSequence getTooltipText() { return null; } } diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index f3ebcb4b326b..b0826a8e3f70 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -360,6 +360,7 @@ public final class ThreadedRenderer { void destroy() { mInitialized = false; updateEnabledState(null); + mRootNode.discardDisplayList(); nDestroy(mNativeProxy, mRootNode.mNativeRenderNode); } @@ -491,20 +492,12 @@ public final class ThreadedRenderer { */ void destroyHardwareResources(View view) { destroyResources(view); + mRootNode.discardDisplayList(); nDestroyHardwareResources(mNativeProxy); } private static void destroyResources(View view) { view.destroyHardwareResources(); - - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - - int count = group.getChildCount(); - for (int i = 0; i < count; i++) { - destroyResources(group.getChildAt(i)); - } - } } /** diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 37dfdb92996b..26e311c6a921 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3718,7 +3718,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Text to be displayed in a tooltip popup. */ @Nullable - CharSequence mTooltip; + CharSequence mTooltipText; /** * View-relative position of the tooltip anchor point. @@ -4761,8 +4761,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, forceHasOverlappingRendering(a.getBoolean(attr, true)); } break; - case R.styleable.View_tooltip: - setTooltip(a.getText(attr)); + case R.styleable.View_tooltipText: + setTooltipText(a.getText(attr)); break; case R.styleable.View_keyboardNavigationCluster: if (a.peekValue(attr) != null) { @@ -16641,6 +16641,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // safe to free its copy of the display list as it knows that we will // push an updated DisplayList if we try to draw again resetDisplayList(); + if (mOverlay != null) { + mOverlay.getOverlayView().destroyHardwareResources(); + } + if (mGhostView != null) { + mGhostView.destroyHardwareResources(); + } } /** @@ -16811,11 +16817,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void resetDisplayList() { - if (mRenderNode.isValid()) { - mRenderNode.discardDisplayList(); - } + mRenderNode.discardDisplayList(); - if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) { + if (mBackgroundRenderNode != null) { mBackgroundRenderNode.discardDisplayList(); } } @@ -24638,10 +24642,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * menu). </li> * <li>On hover, after a brief delay since the pointer has stopped moving </li> * - * @param tooltip the tooltip text, or null if no tooltip is required + * @param tooltipText the tooltip text, or null if no tooltip is required */ - public final void setTooltip(@Nullable CharSequence tooltip) { - if (TextUtils.isEmpty(tooltip)) { + public final void setTooltipText(@Nullable CharSequence tooltipText) { + if (TextUtils.isEmpty(tooltipText)) { setFlags(0, TOOLTIP); hideTooltip(); mTooltipInfo = null; @@ -24652,21 +24656,42 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip; mTooltipInfo.mHideTooltipRunnable = this::hideTooltip; } - mTooltipInfo.mTooltip = tooltip; + mTooltipInfo.mTooltipText = tooltipText; if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) { - mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltip); + mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText); } } } /** + * To be removed once the support library has stopped using it. + * + * @deprecated use {@link #setTooltipText} instead + */ + @Deprecated + public final void setTooltip(@Nullable CharSequence tooltipText) { + setTooltipText(tooltipText); + } + + /** * Returns the view's tooltip text. * * @return the tooltip text */ @Nullable + public final CharSequence getTooltipText() { + return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null; + } + + /** + * To be removed once the support library has stopped using it. + * + * @deprecated use {@link #getTooltipText} instead + */ + @Deprecated + @Nullable public final CharSequence getTooltip() { - return mTooltipInfo != null ? mTooltipInfo.mTooltip : null; + return getTooltipText(); } private boolean showTooltip(int x, int y, boolean fromLongClick) { @@ -24676,7 +24701,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if ((mViewFlags & ENABLED_MASK) != ENABLED) { return false; } - final CharSequence tooltipText = getTooltip(); + final CharSequence tooltipText = getTooltipText(); if (TextUtils.isEmpty(tooltipText)) { return false; } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index a479bb34302c..d252d75856da 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3450,6 +3450,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager super.dispatchDetachedFromWindow(); } + /** @hide */ + @Override + protected void destroyHardwareResources() { + super.destroyHardwareResources(); + int count = getChildCount(); + for (int i = 0; i < count; i++) { + getChildAt(i).destroyHardwareResources(); + } + } + /** * @hide */ diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index b6693c715da2..08b18a4e5313 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3257,20 +3257,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Returns the font variation settings. - * - * @return the currently set font variation settings. Returns null if no variation is - * specified. - * - * @see #setFontVariationSettings(String) - * @see Paint#setFontVariationSettings(String) Paint.setFontVariationSettings(String) - */ - @Nullable - public String getFontVariationSettings() { - return mTextPaint.getFontVariationSettings(); - } - - /** * Sets the break strategy for breaking paragraphs into lines. The default value for * TextView is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}, and the default value for * EditText is {@link Layout#BREAK_STRATEGY_SIMPLE}, the latter to avoid the @@ -3377,41 +3363,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** - * Sets TrueType or OpenType font variation settings. The settings string is constructed from - * multiple pairs of axis tag and style values. The axis tag must contain four ASCII characters - * and must be wrapped with single quotes (U+0027) or double quotes (U+0022). Axis strings that - * are longer or shorter than four characters, or contain characters outside of U+0020..U+007E - * are invalid. If a specified axis name is not defined in the font, the settings will be - * ignored. - * - * <pre> - * textView.setFontVariationSettings("'wdth' 1.0"); - * textView.setFontVariationSettings("'AX ' 1.8, 'FB ' 2.0"); - * </pre> - * - * @param fontVariationSettings font variation settings. You can pass null or empty string as - * no variation settings. - * - * @see #getFontVariationSettings() - * @see Paint#getFontVariationSettings() Paint.getFontVariationSettings() - */ - public void setFontVariationSettings(@Nullable String fontVariationSettings) { - final String existingSettings = mTextPaint.getFontVariationSettings(); - if (fontVariationSettings == existingSettings - || (fontVariationSettings != null - && fontVariationSettings.equals(existingSettings))) { - return; - } - mTextPaint.setFontVariationSettings(fontVariationSettings); - - if (mLayout != null) { - nullLayouts(); - requestLayout(); - invalidate(); - } - } - - /** * Sets the text color for all the states (normal, selected, * focused) to be this color. * diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index c828d11fd3d2..e8919ede82b5 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -120,7 +120,7 @@ public class KernelUidCpuTimeReader { sb.append(" s="); TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb); sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms"); - Slog.wtf(TAG, sb.toString()); + Slog.e(TAG, sb.toString()); userTimeDeltaUs = 0; systemTimeDeltaUs = 0; diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java index c8697ddba029..1fce0b78db50 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItem.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java @@ -48,7 +48,7 @@ public class ActionMenuItem implements MenuItem { private MenuItem.OnMenuItemClickListener mClickListener; private CharSequence mContentDescription; - private CharSequence mTooltip; + private CharSequence mTooltipText; private static final int NO_ICON = 0; @@ -290,13 +290,13 @@ public class ActionMenuItem implements MenuItem { } @Override - public MenuItem setTooltip(CharSequence tooltip) { - mTooltip = tooltip; + public MenuItem setTooltipText(CharSequence tooltipText) { + mTooltipText = tooltipText; return this; } @Override - public CharSequence getTooltip() { - return mTooltip; + public CharSequence getTooltipText() { + return mTooltipText; } } diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java index 4ee59931d831..92e1d80ebdbe 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java @@ -193,12 +193,12 @@ public class ActionMenuItemView extends TextView setContentDescription(contentDescription); } - final CharSequence tooltip = mItemData.getTooltip(); - if (TextUtils.isEmpty(tooltip)) { + final CharSequence tooltipText = mItemData.getTooltipText(); + if (TextUtils.isEmpty(tooltipText)) { // Use the uncondensed title for tooltip, but only if the title is not shown already. - setTooltip(visible ? null : mItemData.getTitle()); + setTooltipText(visible ? null : mItemData.getTitle()); } else { - setTooltip(tooltip); + setTooltipText(tooltipText); } } diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java index f9ebdbc4f0bb..6c8f330fbcc8 100644 --- a/core/java/com/android/internal/view/menu/IconMenuItemView.java +++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java @@ -113,7 +113,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie } else { setContentDescription(contentDescription); } - setTooltip(mItemData.getTooltip()); + setTooltipText(mItemData.getTooltipText()); } } diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java index 7c9f70902d05..43005e6cac54 100644 --- a/core/java/com/android/internal/view/menu/ListMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java @@ -115,7 +115,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView setEnabled(itemData.isEnabled()); setSubMenuArrowVisible(itemData.hasSubMenu()); setContentDescription(itemData.getContentDescription()); - setTooltip(itemData.getTooltip()); + setTooltipText(itemData.getTooltipText()); } public void setForceShowIcon(boolean forceShow) { diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index cad027616582..342943f814ba 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -94,7 +94,7 @@ public final class MenuItemImpl implements MenuItem { private ContextMenuInfo mMenuInfo; private CharSequence mContentDescription; - private CharSequence mTooltip; + private CharSequence mTooltipText; private static String sLanguage; private static String sPrependShortcutLabel; @@ -689,8 +689,8 @@ public final class MenuItemImpl implements MenuItem { } @Override - public MenuItem setTooltip(CharSequence tooltip) { - mTooltip = tooltip; + public MenuItem setTooltipText(CharSequence tooltipText) { + mTooltipText = tooltipText; mMenu.onItemsChanged(false); @@ -698,7 +698,7 @@ public final class MenuItemImpl implements MenuItem { } @Override - public CharSequence getTooltip() { - return mTooltip; + public CharSequence getTooltipText() { + return mTooltipText; } } diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 04e09a85d1bf..58e694a15a1d 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -1591,7 +1591,7 @@ public final class FloatingToolbar { } else { menuButton.setContentDescription(contentDescription); } - menuButton.setTooltip(menuItem.getTooltip()); + menuButton.setTooltipText(menuItem.getTooltipText()); menuButton.setMinimumWidth(minimumWidth); } return menuButton; @@ -1642,17 +1642,17 @@ public final class FloatingToolbar { ((ImageButton) menuItemButton .findViewById(R.id.floating_toolbar_menu_item_image_button)) .setImageDrawable(menuItem.getIcon()); - final CharSequence tooltip = menuItem.getTooltip(); - if (TextUtils.isEmpty(tooltip)) { - menuItemButton.setTooltip(menuItem.getTitle()); + final CharSequence tooltipText = menuItem.getTooltipText(); + if (TextUtils.isEmpty(tooltipText)) { + menuItemButton.setTooltipText(menuItem.getTitle()); } else { - menuItemButton.setTooltip(tooltip); + menuItemButton.setTooltipText(tooltipText); } } else { menuItemButton = LayoutInflater.from(context) .inflate(R.layout.floating_popup_menu_button, null); ((Button) menuItemButton).setText(menuItem.getTitle()); - menuItemButton.setTooltip(menuItem.getTooltip()); + menuItemButton.setTooltipText(menuItem.getTooltipText()); } final CharSequence contentDescription = menuItem.getContentDescription(); if (TextUtils.isEmpty(contentDescription)) { diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java index 44665759660e..311bfac6e883 100644 --- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java +++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java @@ -471,7 +471,7 @@ public class ScrollingTabContainerView extends HorizontalScrollView if (mIconView != null) { mIconView.setContentDescription(tab.getContentDescription()); } - setTooltip(hasText? null : tab.getContentDescription()); + setTooltipText(hasText? null : tab.getContentDescription()); } } diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java index 06ef4c9d6443..03f2bc10b551 100644 --- a/core/java/com/android/server/NetworkManagementSocketTagger.java +++ b/core/java/com/android/server/NetworkManagementSocketTagger.java @@ -16,6 +16,7 @@ package com.android.server; +import android.os.StrictMode; import android.os.SystemProperties; import android.util.Log; import android.util.Slog; @@ -50,16 +51,20 @@ public final class NetworkManagementSocketTagger extends SocketTagger { SocketTagger.set(new NetworkManagementSocketTagger()); } - public static void setThreadSocketStatsTag(int tag) { + public static int setThreadSocketStatsTag(int tag) { + final int old = threadSocketTags.get().statsTag; threadSocketTags.get().statsTag = tag; + return old; } public static int getThreadSocketStatsTag() { return threadSocketTags.get().statsTag; } - public static void setThreadSocketStatsUid(int uid) { + public static int setThreadSocketStatsUid(int uid) { + final int old = threadSocketTags.get().statsUid; threadSocketTags.get().statsUid = uid; + return old; } @Override @@ -69,6 +74,9 @@ public final class NetworkManagementSocketTagger extends SocketTagger { Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x" + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid); } + if (options.statsTag == -1 && StrictMode.vmUntaggedSocketEnabled()) { + StrictMode.onUntaggedSocket(); + } // TODO: skip tagging when options would be no-op tagSocketFd(fd, options.statsTag, options.statsUid); } diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index 168da5fa691d..fcb4c7b48125 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -109,6 +109,10 @@ public class SystemConfig { // background while in data-usage save mode, as read from the configuration files. final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>(); + // These are the action strings of broadcasts which are whitelisted to + // be delivered anonymously even to apps which target O+. + final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>(); + // These are the package names of apps which should be in the 'always' // URL-handling state upon factory reset. final ArraySet<String> mLinkedApps = new ArraySet<>(); @@ -162,6 +166,10 @@ public class SystemConfig { return mPermissions; } + public ArraySet<String> getAllowImplicitBroadcasts() { + return mAllowImplicitBroadcasts; + } + public ArraySet<String> getAllowInPowerSaveExceptIdle() { return mAllowInPowerSaveExceptIdle; } @@ -438,6 +446,17 @@ public class SystemConfig { XmlUtils.skipCurrentTag(parser); continue; + } else if ("allow-implicit-broadcast".equals(name) && allowAll) { + String action = parser.getAttributeValue(null, "action"); + if (action == null) { + Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile + + " at " + parser.getPositionDescription()); + } else { + mAllowImplicitBroadcasts.add(action); + } + XmlUtils.skipCurrentTag(parser); + continue; + } else if ("app-link".equals(name) && allowAppConfigs) { String pkgname = parser.getAttributeValue(null, "package"); if (pkgname == null) { diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 6a9ed8e4f308..0d3ccdc87aa2 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -118,7 +118,6 @@ LOCAL_SRC_FILES:= \ android/graphics/ColorFilter.cpp \ android/graphics/DrawFilter.cpp \ android/graphics/FontFamily.cpp \ - android/graphics/FontUtils.cpp \ android/graphics/CreateJavaOutputStreamAdaptor.cpp \ android/graphics/GIFMovie.cpp \ android/graphics/GraphicBuffer.cpp \ diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index 685c93d55924..15e7165210ae 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -30,7 +30,6 @@ #include <android_runtime/android_util_AssetManager.h> #include <androidfw/AssetManager.h> #include "Utils.h" -#include "FontUtils.h" #include <hwui/MinikinSkia.h> #include <hwui/Typeface.h> @@ -40,54 +39,27 @@ namespace android { -struct NativeFamilyBuilder { - uint32_t langId; - int variant; - std::vector<minikin::Font> fonts; -}; - -static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring lang, jint variant) { - NativeFamilyBuilder* builder = new NativeFamilyBuilder(); - if (lang != nullptr) { - ScopedUtfChars str(env, lang); - builder->langId = minikin::FontStyle::registerLanguageList(str.c_str()); - } else { - builder->langId = minikin::FontStyle::registerLanguageList(""); - } - builder->variant = variant; - return reinterpret_cast<jlong>(builder); -} - -static jlong FontFamily_create(jlong builderPtr) { - if (builderPtr == 0) { - return 0; +static jlong FontFamily_create(JNIEnv* env, jobject clazz, jstring lang, jint variant) { + if (lang == NULL) { + return (jlong)new minikin::FontFamily(variant); } - NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr); - minikin::FontFamily* family = new minikin::FontFamily( - builder->langId, builder->variant, std::move(builder->fonts)); - delete builder; - return reinterpret_cast<jlong>(family); + ScopedUtfChars str(env, lang); + uint32_t langId = minikin::FontStyle::registerLanguageList(str.c_str()); + return (jlong)new minikin::FontFamily(langId, variant); } -static void FontFamily_unref(jlong familyPtr) { +static void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) { minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); fontFamily->Unref(); } -static void addSkTypeface(jlong builderPtr, sk_sp<SkTypeface> face, const void* fontData, - size_t fontSize, int ttcIndex) { +static jboolean addSkTypeface(minikin::FontFamily* family, sk_sp<SkTypeface> face, + const void* fontData, size_t fontSize, int ttcIndex) { minikin::MinikinFont* minikinFont = new MinikinFontSkia(std::move(face), fontData, fontSize, ttcIndex); - NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr); - int weight; - bool italic; - if (!minikin::FontFamily::analyzeStyle(minikinFont, &weight, &italic)) { - ALOGE("analyzeStyle failed. Using default style"); - weight = 400; - italic = false; - } - builder->fonts.push_back(minikin::Font(minikinFont, minikin::FontStyle(weight / 100, italic))); + bool result = family->addFont(minikinFont); minikinFont->Unref(); + return result; } static void release_global_ref(const void* /*data*/, void* context) { @@ -113,7 +85,7 @@ static void release_global_ref(const void* /*data*/, void* context) { } } -static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong builderPtr, jobject bytebuf, +static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jobject bytebuf, jint ttcIndex) { NPE_CHECK_RETURN_ZERO(env, bytebuf); const void* fontPtr = env->GetDirectBufferAddress(bytebuf); @@ -140,11 +112,21 @@ static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong builderPtr, ALOGE("addFont failed to create font"); return false; } - addSkTypeface(builderPtr, std::move(face), fontPtr, (size_t)fontSize, ttcIndex); - return true; + minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); + return addSkTypeface(fontFamily, std::move(face), fontPtr, (size_t)fontSize, ttcIndex); } -static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong builderPtr, +static struct { + jmethodID mGet; + jmethodID mSize; +} gListClassInfo; + +static struct { + jfieldID mTag; + jfieldID mStyleValue; +} gAxisClassInfo; + +static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr, jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) { NPE_CHECK_RETURN_ZERO(env, font); @@ -152,22 +134,20 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong std::unique_ptr<SkFontMgr::FontParameters::Axis[]> skiaAxes; int skiaAxesLength = 0; if (listOfAxis) { - ListHelper list(env, listOfAxis); - jint listSize = list.size(); + jint listSize = env->CallIntMethod(listOfAxis, gListClassInfo.mSize); skiaAxes.reset(new SkFontMgr::FontParameters::Axis[listSize]); skiaAxesLength = listSize; for (jint i = 0; i < listSize; ++i) { - jobject axisObject = list.get(i); + jobject axisObject = env->CallObjectMethod(listOfAxis, gListClassInfo.mGet, i); if (!axisObject) { skiaAxes[i].fTag = 0; skiaAxes[i].fStyleValue = 0; continue; } - AxisHelper axis(env, axisObject); - jint tag = axis.getTag(); - jfloat stylevalue = axis.getStyleValue(); + jint tag = env->GetIntField(axisObject, gAxisClassInfo.mTag); + jfloat stylevalue = env->GetFloatField(axisObject, gAxisClassInfo.mStyleValue); skiaAxes[i].fTag = tag; skiaAxes[i].fStyleValue = SkFloatToScalar(stylevalue); } @@ -198,11 +178,10 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong ALOGE("addFont failed to create font, invalid request"); return false; } + minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); minikin::MinikinFont* minikinFont = - new MinikinFontSkia(std::move(face), fontPtr, fontSize, ttcIndex); - NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr); - builder->fonts.push_back(minikin::Font(minikinFont, - minikin::FontStyle(weight / 100, isItalic))); + new MinikinFontSkia(std::move(face), fontPtr, (size_t)fontSize, ttcIndex); + fontFamily->addFont(minikinFont, minikin::FontStyle(weight / 100, isItalic)); minikinFont->Unref(); return true; } @@ -211,7 +190,7 @@ static void releaseAsset(const void* ptr, void* context) { delete static_cast<Asset*>(context); } -static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong builderPtr, +static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr, jobject jassetMgr, jstring jpath) { NPE_CHECK_RETURN_ZERO(env, jassetMgr); NPE_CHECK_RETURN_ZERO(env, jpath); @@ -243,16 +222,14 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong builderP ALOGE("addFontFromAsset failed to create font %s", str.c_str()); return false; } - - addSkTypeface(builderPtr, std::move(face), buf, bufSize, 0 /* ttc index */); - return true; + minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); + return addSkTypeface(fontFamily, std::move(face), buf, bufSize, /* ttcIndex */ 0); } /////////////////////////////////////////////////////////////////////////////// static const JNINativeMethod gFontFamilyMethods[] = { - { "nInitBuilder", "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder }, - { "nCreateFamily", "(J)J", (void*)FontFamily_create }, + { "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create }, { "nUnrefFamily", "(J)V", (void*)FontFamily_unref }, { "nAddFont", "(JLjava/nio/ByteBuffer;I)Z", (void*)FontFamily_addFont }, { "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;ILjava/util/List;IZ)Z", @@ -266,7 +243,14 @@ int register_android_graphics_FontFamily(JNIEnv* env) int err = RegisterMethodsOrDie(env, "android/graphics/FontFamily", gFontFamilyMethods, NELEM(gFontFamilyMethods)); - init_FontUtils(env); + jclass listClass = FindClassOrDie(env, "java/util/List"); + gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;"); + gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I"); + + jclass axisClass = FindClassOrDie(env, "android/graphics/FontListParser$Axis"); + gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "tag", "I"); + gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "styleValue", "F"); + return err; } diff --git a/core/jni/android/graphics/FontUtils.cpp b/core/jni/android/graphics/FontUtils.cpp deleted file mode 100644 index 11c2d29ec03c..000000000000 --- a/core/jni/android/graphics/FontUtils.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 "FontUtils.h" - -#include "JNIHelp.h" -#include <core_jni_helpers.h> - -namespace android { -namespace { - -static struct { - jmethodID mGet; - jmethodID mSize; -} gListClassInfo; - -static struct { - jfieldID mTag; - jfieldID mStyleValue; -} gAxisClassInfo; - -} // namespace - -jint ListHelper::size() const { - return mEnv->CallIntMethod(mList, gListClassInfo.mSize); -} - -jobject ListHelper::get(jint index) const { - return mEnv->CallObjectMethod(mList, gListClassInfo.mGet, index); -} - -jint AxisHelper::getTag() const { - return mEnv->GetIntField(mAxis, gAxisClassInfo.mTag); -} - -jfloat AxisHelper::getStyleValue() const { - return mEnv->GetFloatField(mAxis, gAxisClassInfo.mStyleValue); -} - -void init_FontUtils(JNIEnv* env) { - jclass listClass = FindClassOrDie(env, "java/util/List"); - gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;"); - gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I"); - - jclass axisClass = FindClassOrDie(env, "android/graphics/FontListParser$Axis"); - gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "tag", "I"); - gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "styleValue", "F"); -} - -} // namespace android diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h deleted file mode 100644 index 6fbd5e32afde..000000000000 --- a/core/jni/android/graphics/FontUtils.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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. - */ - -#ifndef _ANDROID_GRAPHICS_FONT_UTILS_H_ -#define _ANDROID_GRAPHICS_FONT_UTILS_H_ - -#include <jni.h> - -namespace android { - -// Utility wrapper for java.util.List -class ListHelper { -public: - ListHelper(JNIEnv* env, jobject list) : mEnv(env), mList(list) {} - - jint size() const; - jobject get(jint index) const; - -private: - JNIEnv* mEnv; - jobject mList; -}; - -// Utility wrapper for android.graphics.FontListParser$Axis -class AxisHelper { -public: - AxisHelper(JNIEnv* env, jobject axis) : mEnv(env), mAxis(axis) {} - - jint getTag() const; - jfloat getStyleValue() const; - -private: - JNIEnv* mEnv; - jobject mAxis; -}; - -void init_FontUtils(JNIEnv* env); - -}; // namespace android - -#endif // _ANDROID_GRAPHICS_FONT_UTILS_H_ diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp index 0a0fce3ecfab..c920b8d653ab 100644 --- a/core/jni/android/graphics/Typeface.cpp +++ b/core/jni/android/graphics/Typeface.cpp @@ -17,14 +17,12 @@ #include "jni.h" #include "core_jni_helpers.h" -#include "FontUtils.h" #include "GraphicsJNI.h" #include "ScopedPrimitiveArray.h" #include "SkTypeface.h" #include <android_runtime/android_util_AssetManager.h> #include <androidfw/AssetManager.h> #include <hwui/Typeface.h> -#include <minikin/FontFamily.h> using namespace android; @@ -42,23 +40,6 @@ static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandl return reinterpret_cast<jlong>(face); } -static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle, - jobject listOfAxis) { - std::vector<minikin::FontVariation> variations; - ListHelper list(env, listOfAxis); - for (jint i = 0; i < list.size(); i++) { - jobject axisObject = list.get(i); - if (axisObject == nullptr) { - continue; - } - AxisHelper axis(env, axisObject); - variations.push_back(minikin::FontVariation(axis.getTag(), axis.getStyleValue())); - } - Typeface* baseTypeface = reinterpret_cast<Typeface*>(familyHandle); - Typeface* result = Typeface::createFromTypefaceWithVariation(baseTypeface, variations); - return reinterpret_cast<jlong>(result); -} - static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) { Typeface* family = reinterpret_cast<Typeface*>(familyHandle); Typeface* face = Typeface::createWeightAlias(family, weight); @@ -96,8 +77,6 @@ static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) { static const JNINativeMethod gTypefaceMethods[] = { { "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface }, - { "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J", - (void*)Typeface_createFromTypefaceWithVariation }, { "nativeCreateWeightAlias", "(JI)J", (void*)Typeface_createWeightAlias }, { "nativeUnref", "(J)V", (void*)Typeface_unref }, { "nativeGetStyle", "(J)I", (void*)Typeface_getStyle }, diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index d75d5c179d3c..3eccc42df1f5 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -88,6 +88,7 @@ void onRenderNodeRemoved(JNIEnv* env, RenderNode* node) { return; } + node->setStagingDisplayList(nullptr, nullptr); // Update the valid field, since native has already removed // the staging DisplayList env->SetBooleanField(jnode, gRenderNode_validFieldID, false); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7f25cf354639..db846c8dcdb9 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1269,7 +1269,7 @@ recommendations and scores from the NetworkScoreService. <p>Not for use by third-party applications. @hide --> <permission android:name="android.permission.REQUEST_NETWORK_SCORES" - android:protectionLevel="signature" /> + android:protectionLevel="signature|setup" /> <!-- ======================================= --> <!-- Permissions for short range, peripheral networks --> @@ -2480,14 +2480,14 @@ android:protectionLevel="signature" /> <!-- Allows an application to request installing packages. Apps - targeting APIs greater than 22 must hold this permission in + targeting APIs greater than 25 must hold this permission in order to use {@link android.content.Intent#ACTION_INSTALL_PACKAGE}. <p>Protection level: normal --> <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" android:label="@string/permlab_requestInstallPackages" android:description="@string/permdesc_requestInstallPackages" - android:protectionLevel="normal" /> + android:protectionLevel="signature|appop" /> <!-- @SystemApi Allows an application to install packages. <p>Not for use by third-party applications. --> diff --git a/core/res/res/layout/preference_widget_seekbar.xml b/core/res/res/layout/preference_widget_seekbar.xml index 05daa1a42011..0c6dbf1f2400 100644 --- a/core/res/res/layout/preference_widget_seekbar.xml +++ b/core/res/res/layout/preference_widget_seekbar.xml @@ -50,7 +50,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceMedium" + android:textAppearance="?android:attr/textAppearanceLarge" android:ellipsize="marquee" android:fadingEdge="horizontal" /> diff --git a/core/res/res/layout/preference_widget_seekbar_material.xml b/core/res/res/layout/preference_widget_seekbar_material.xml index f70a4726aa9b..6c72c9ed007d 100644 --- a/core/res/res/layout/preference_widget_seekbar_material.xml +++ b/core/res/res/layout/preference_widget_seekbar_material.xml @@ -51,7 +51,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceMedium" + android:textAppearance="?android:attr/textAppearanceListItem" android:ellipsize="marquee" android:fadingEdge="horizontal" /> @@ -60,7 +60,7 @@ android:layout_height="wrap_content" android:layout_below="@android:id/title" android:layout_alignStart="@android:id/title" - android:textAppearance="?android:attr/textAppearanceSmall" + android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textColor="?android:attr/textColorSecondary" android:maxLines="4" /> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index a5c1a94da47e..a40131469076 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2890,7 +2890,7 @@ <attr name="forceHasOverlappingRendering" format="boolean" /> <!-- Defines text displayed in a small popup window on hover or long press. --> - <attr name="tooltip" format="string" localization="suggested" /> + <attr name="tooltipText" format="string" localization="suggested" /> <!-- Whether this view is a root of a keyboard navigation cluster. See {@link android.view.View#setKeyboardNavigationCluster(boolean)}. --> @@ -7029,7 +7029,7 @@ <attr name="contentDescription" format="string" /> <!-- The tooltip text associated with the item. --> - <attr name="tooltip" format="string" /> + <attr name="tooltipText" format="string" /> </declare-styleable> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index b9613949627c..6a4711a81fb2 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -776,6 +776,21 @@ <enum name="locked" value="14" /> </attr> + <!-- Specify the configuration changes that trigger the system to restart the + current activity if any of these configuration changes happen in the system. + The valid configuration changes include mcc and mnc which are the same with + those in configChanges. By default from Android O, we don't restart the activity + even the app doesn't specify mcc or mnc in configChanges. If the app wants to + restart, specify them in restartOnConfigChanges. --> + <attr name="restartOnConfigChanges"> + <!-- The IMSI MCC has changed, that is a SIM has been detected and + updated the Mobile Country Code. --> + <flag name="mcc" value="0x0001" /> + <!-- The IMSI MNC has changed, that is a SIM has been detected and + updated the Mobile Network Code. --> + <flag name="mnc" value="0x0002" /> + </attr> + <!-- Specify one or more configuration changes that the activity will handle itself. If not specified, the activity will be restarted if any of these configuration changes happen in the system. Otherwise, @@ -793,10 +808,16 @@ include/utils/ResourceTypes.h. --> <attr name="configChanges"> <!-- The IMSI MCC has changed, that is a SIM has been detected and - updated the Mobile Country Code. --> + updated the Mobile Country Code. By default from Android O, we + don't restart the activity even the app doesn't specify mcc in + configChanges. If the app wants to restart, specify mcc in + restartOnConfigChanges. --> <flag name="mcc" value="0x0001" /> <!-- The IMSI MNC has changed, that is a SIM has been detected and - updated the Mobile Network Code. --> + updated the Mobile Network Code. By default from Android O, we + don't restart the activity even the app doesn't specify mnc in + configChanges. If the app wants to restart, specify mnc in + restartOnConfigChanges. --> <flag name="mnc" value="0x0002" /> <!-- The locale has changed, that is the user has selected a new language that text should be displayed in. --> @@ -843,6 +864,9 @@ <flag name="density" value="0x1000" /> <!-- The layout direction has changed. For example going from LTR to RTL. --> <flag name="layoutDirection" value="0x2000" /> + <!-- The colorimetry capabilities of the screen have changed (color gamut + or dynamic range). --> + <flag name="colorimetry" value="0x4000" /> <!-- The font scaling factor has changed, that is the user has selected a new global font size. --> <flag name="fontScale" value="0x40000000" /> @@ -1917,6 +1941,7 @@ <attr name="launchMode" /> <attr name="screenOrientation" /> <attr name="configChanges" /> + <attr name="restartOnConfigChanges" /> <attr name="permission" /> <attr name="multiprocess" /> <attr name="process" /> diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml index 8f0350a887b9..e2498df71e45 100644 --- a/core/res/res/values/colors_device_defaults.xml +++ b/core/res/res/values/colors_device_defaults.xml @@ -20,11 +20,14 @@ <color name="primary_device_default_dark">@color/primary_material_dark</color> <color name="primary_device_default_light">@color/primary_material_light</color> <color name="primary_device_default_settings">@color/primary_material_settings</color> + <color name="primary_device_default_settings_light">@color/primary_material_settings_light</color> <color name="primary_dark_device_default_dark">@color/primary_dark_material_dark</color> <color name="primary_dark_device_default_light">@color/primary_dark_material_light</color> <color name="primary_dark_device_default_settings">@color/primary_dark_material_settings</color> + <color name="primary_dark_device_default_settings_light">@color/primary_dark_material_settings_light</color> <color name="secondary_device_default_settings">@color/secondary_material_settings</color> + <color name="secondary_device_default_settings_light">@color/secondary_material_settings_light</color> <color name="tertiary_device_default_settings">@color/tertiary_material_settings</color> <color name="quaternary_device_default_settings">@color/quaternary_material_settings</color> diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml index 835b8b60d253..db89c22a6496 100644 --- a/core/res/res/values/colors_material.xml +++ b/core/res/res/values/colors_material.xml @@ -27,12 +27,15 @@ <color name="primary_material_dark">@color/material_grey_900</color> <color name="primary_material_light">@color/material_grey_100</color> <color name="primary_material_settings">@color/material_blue_grey_900</color> + <color name="primary_material_settings_light">@color/material_grey_100</color> <color name="primary_dark_material_dark">@color/black</color> <color name="primary_dark_material_light">@color/material_grey_600</color> <color name="primary_dark_material_light_light_status_bar">@color/material_grey_300</color> <color name="primary_dark_material_settings">@color/material_blue_grey_950</color> + <color name="primary_dark_material_settings_light">@color/material_grey_300</color> <color name="secondary_material_settings">@color/material_blue_grey_800</color> + <color name="secondary_material_settings_light">@color/material_grey_200</color> <color name="tertiary_material_settings">@color/material_blue_grey_700</color> <color name="quaternary_material_settings">@color/material_blue_grey_200</color> @@ -88,6 +91,7 @@ <color name="material_grey_800">#ff424242</color> <color name="material_grey_600">#ff757575</color> <color name="material_grey_300">#ffe0e0e0</color> + <color name="material_grey_200">#ffeeeeee</color> <color name="material_grey_100">#fff5f5f5</color> <color name="material_grey_50">#fffafafa</color> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 099fe083e72f..ad9e4d984cc8 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2764,7 +2764,7 @@ <public name="fontStyle" /> <public name="font" /> <public name="fontWeight" /> - <public name="tooltip" /> + <public name="tooltipText" /> <public name="autoSizeText" /> <public name="autoSizeStepGranularity" /> <public name="autoSizeStepSizeSet" /> @@ -2785,6 +2785,7 @@ <public name="appCategory" /> <public name="autoSizeMaxTextSize" /> <public name="supportsDismissingWindow" /> + <public name="restartOnConfigChanges" /> </public-group> <public-group type="style" first-id="0x010302e0"> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index d252f23950a6..3d497ccef7c5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -397,7 +397,7 @@ <string name="network_logging_notification_title">Network traffic is being monitored</string> <!-- Content text for a notification. Tapping opens a dialog with more information on network logging. [CHAR LIMIT=NONE]--> - <string name="network_logging_notification_text">Tap for more details</string> + <string name="network_logging_notification_text">Tap to learn more</string> <!-- Factory reset warning dialog strings--> <skip /> <!-- Shows up in the dialog's title to warn about an impeding factory reset. [CHAR LIMIT=NONE] --> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 842b5759a5ea..faf451bcec97 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1290,7 +1290,7 @@ please see styles_device_defaults.xml. <style name="Widget.ActionButton.Overflow"> <item name="src">@drawable/ic_menu_more</item> <item name="contentDescription">@string/action_menu_overflow_description</item> - <item name="tooltip">@string/action_menu_overflow_description</item> + <item name="tooltipText">@string/action_menu_overflow_description</item> </style> <style name="Widget.ActionButton.CloseMode"> diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml index 12b8164ad001..dc32b269f73a 100644 --- a/core/res/res/values/styles_holo.xml +++ b/core/res/res/values/styles_holo.xml @@ -660,7 +660,7 @@ please see styles_device_defaults.xml. <item name="src">@drawable/ic_menu_moreoverflow_holo_dark</item> <item name="background">?attr/actionBarItemBackground</item> <item name="contentDescription">@string/action_menu_overflow_description</item> - <item name="tooltip">@string/action_menu_overflow_description</item> + <item name="tooltipText">@string/action_menu_overflow_description</item> </style> <style name="Widget.Holo.ActionButton.TextButton" parent="Widget.Holo.ButtonBar.Button" /> @@ -995,7 +995,7 @@ please see styles_device_defaults.xml. <style name="Widget.Holo.Light.ActionButton.Overflow"> <item name="src">@drawable/ic_menu_moreoverflow_holo_light</item> <item name="contentDescription">@string/action_menu_overflow_description</item> - <item name="tooltip">@string/action_menu_overflow_description</item> + <item name="tooltipText">@string/action_menu_overflow_description</item> </style> <style name="Widget.Holo.Light.ActionBar.TabView" parent="Widget.Holo.ActionBar.TabView" /> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index 709200eabff2..0b326e94382d 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -944,7 +944,7 @@ please see styles_device_defaults.xml. <item name="src">@drawable/ic_menu_moreoverflow_material</item> <item name="background">?attr/actionBarItemBackground</item> <item name="contentDescription">@string/action_menu_overflow_description</item> - <item name="tooltip">@string/action_menu_overflow_description</item> + <item name="tooltipText">@string/action_menu_overflow_description</item> <item name="minWidth">@dimen/action_button_min_width_overflow_material</item> <item name="minHeight">@dimen/action_button_min_height_material</item> <item name="paddingStart">@dimen/action_bar_overflow_padding_start_material</item> diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml index 6bd6e1c1ce4a..5961cb041cd4 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -736,20 +736,12 @@ easier. <!-- DeviceDefault theme for a window that should look like the Settings app. --> <style name="Theme.DeviceDefault.Settings" parent="Theme.Material.Settings"> <!-- Color palette --> - <item name="colorPrimary">@color/primary_device_default_settings</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item> - <item name="colorSecondary">@color/secondary_device_default_settings</item> + <item name="colorPrimary">@color/primary_device_default_settings_light</item> + <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item> + <item name="colorSecondary">@color/secondary_device_default_settings_light</item> <item name="colorAccent">@color/accent_device_default_light</item> </style> - <!-- @hide DeviceDefault theme that should look like the Settings app. The action bar will use a - light background and accent color for text and icon. --> - <style name="Theme.DeviceDefault.Settings.LightActionBar"> - <!-- ActionBar --> - <item name="actionBarTheme">@style/ThemeOverlay.DeviceDefault.ActionBar.Accent</item> - <item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar</item> - </style> - <!-- @hide DeviceDefault theme for a window that should use Settings theme colors but has a full dark palette. ONLY USED FOR QUICK SETTINGS THEME --> <style name="Theme.DeviceDefault.QuickSettings" parent="Theme.Material"> @@ -817,12 +809,6 @@ easier. <style name="ThemeOverlay.DeviceDefault" /> - <!-- @hide Theme overlay that inherits from material actionbar, and use accent color for - primary text --> - <style name="ThemeOverlay.DeviceDefault.ActionBar.Accent" parent="ThemeOverlay.Material.ActionBar"> - <item name="textColorPrimary">@color/btn_colored_borderless_text_material</item> - </style> - <style name="ThemeOverlay.DeviceDefault.Accent"> <item name="colorAccent">@color/accent_device_default_dark</item> </style> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index d0f202ba76d0..3587fecb7b5d 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -1323,10 +1323,10 @@ please see themes_device_defaults.xml. </style> <!-- Default theme for Settings and activities launched from Settings. --> - <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar"> - <item name="colorPrimary">@color/primary_material_settings</item> - <item name="colorPrimaryDark">@color/primary_dark_material_settings</item> - <item name="colorSecondary">@color/secondary_material_settings</item> + <style name="Theme.Material.Settings" parent="Theme.Material.Light.LightStatusBar"> + <item name="colorPrimary">@color/primary_material_settings_light</item> + <item name="colorPrimaryDark">@color/primary_dark_material_settings_light</item> + <item name="colorSecondary">@color/secondary_material_settings_light</item> <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item> <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item> diff --git a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java new file mode 100644 index 000000000000..f60bf94f8c99 --- /dev/null +++ b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; +import android.content.pm.PackageInfo; +import android.os.storage.StorageManager; +import android.os.storage.VolumeInfo; + +import junit.framework.TestCase; + +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static android.os.storage.VolumeInfo.STATE_MOUNTED; +import static android.os.storage.VolumeInfo.STATE_UNMOUNTED; + +public class ApplicationPackageManagerTest extends TestCase { + private static final String sInternalVolPath = "/data"; + private static final String sAdoptedVolPath = "/mnt/expand/123"; + private static final String sPublicVolPath = "/emulated"; + private static final String sPrivateUnmountedVolPath = "/private"; + + private static final String sInternalVolUuid = null; //StorageManager.UUID_PRIVATE_INTERNAL + private static final String sAdoptedVolUuid = "adopted"; + private static final String sPublicVolUuid = "emulated"; + private static final String sPrivateUnmountedVolUuid = "private"; + + private static final VolumeInfo sInternalVol = new VolumeInfo("private", + VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/); + + private static final VolumeInfo sAdoptedVol = new VolumeInfo("adopted", + VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/); + + private static final VolumeInfo sPublicVol = new VolumeInfo("public", + VolumeInfo.TYPE_PUBLIC, null /*DiskInfo*/, null /*partGuid*/); + + private static final VolumeInfo sPrivateUnmountedVol = new VolumeInfo("private2", + VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/); + + private static final List<VolumeInfo> sVolumes = new ArrayList<>(); + + static { + sInternalVol.path = sInternalVolPath; + sInternalVol.state = STATE_MOUNTED; + sInternalVol.fsUuid = sInternalVolUuid; + + sAdoptedVol.path = sAdoptedVolPath; + sAdoptedVol.state = STATE_MOUNTED; + sAdoptedVol.fsUuid = sAdoptedVolUuid; + + sPublicVol.state = STATE_MOUNTED; + sPublicVol.path = sPublicVolPath; + sPublicVol.fsUuid = sPublicVolUuid; + + sPrivateUnmountedVol.state = STATE_UNMOUNTED; + sPrivateUnmountedVol.path = sPrivateUnmountedVolPath; + sPrivateUnmountedVol.fsUuid = sPrivateUnmountedVolUuid; + + sVolumes.add(sInternalVol); + sVolumes.add(sAdoptedVol); + sVolumes.add(sPublicVol); + sVolumes.add(sPrivateUnmountedVol); + } + + private static final class MockedApplicationPackageManager extends ApplicationPackageManager { + private boolean mForceAllowOnExternal = false; + private boolean mAllow3rdPartyOnInternal = true; + + public MockedApplicationPackageManager() { + super(null, null); + } + + public void setForceAllowOnExternal(boolean forceAllowOnExternal) { + mForceAllowOnExternal = forceAllowOnExternal; + } + + public void setAllow3rdPartyOnInternal(boolean allow3rdPartyOnInternal) { + mAllow3rdPartyOnInternal = allow3rdPartyOnInternal; + } + + @Override + public boolean isForceAllowOnExternal(Context context) { + return mForceAllowOnExternal; + } + + @Override + public boolean isAllow3rdPartyOnInternal(Context context) { + return mAllow3rdPartyOnInternal; + } + } + + private StorageManager getMockedStorageManager() { + StorageManager storageManager = Mockito.mock(StorageManager.class); + Mockito.when(storageManager.getVolumes()).thenReturn(sVolumes); + Mockito.when(storageManager.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL)) + .thenReturn(sInternalVol); + Mockito.when(storageManager.findVolumeByUuid(sAdoptedVolUuid)) + .thenReturn(sAdoptedVol); + Mockito.when(storageManager.findVolumeByUuid(sPublicVolUuid)) + .thenReturn(sPublicVol); + Mockito.when(storageManager.findVolumeByUuid(sPrivateUnmountedVolUuid)) + .thenReturn(sPrivateUnmountedVol); + return storageManager; + } + + private void verifyReturnedVolumes(List<VolumeInfo> actualVols, VolumeInfo... exptectedVols) { + boolean failed = false; + if (actualVols.size() != exptectedVols.length) { + failed = true; + } else { + for (VolumeInfo vol : exptectedVols) { + if (!actualVols.contains(vol)) { + failed = true; + break; + } + } + } + + if (failed) { + fail("Wrong volumes returned.\n Expected: " + Arrays.toString(exptectedVols) + + "\n Actual: " + Arrays.toString(actualVols.toArray())); + } + } + + public void testGetCandidateVolumes_systemApp() throws Exception { + ApplicationInfo sysAppInfo = new ApplicationInfo(); + sysAppInfo.flags = ApplicationInfo.FLAG_SYSTEM; + + StorageManager storageManager = getMockedStorageManager(); + IPackageManager pm = Mockito.mock(IPackageManager.class); + + MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager(); + + appPkgMgr.setAllow3rdPartyOnInternal(true); + appPkgMgr.setForceAllowOnExternal(true); + List<VolumeInfo> candidates = + appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol); + + appPkgMgr.setAllow3rdPartyOnInternal(true); + appPkgMgr.setForceAllowOnExternal(false); + candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol); + + appPkgMgr.setAllow3rdPartyOnInternal(false); + appPkgMgr.setForceAllowOnExternal(false); + candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol); + + appPkgMgr.setAllow3rdPartyOnInternal(false); + appPkgMgr.setForceAllowOnExternal(true); + candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol); + } + + public void testGetCandidateVolumes_3rdParty_internalOnly() throws Exception { + ApplicationInfo appInfo = new ApplicationInfo(); + StorageManager storageManager = getMockedStorageManager(); + + IPackageManager pm = Mockito.mock(IPackageManager.class); + Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(false); + + MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager(); + + // must allow 3rd party on internal, otherwise the app wouldn't have been installed before. + appPkgMgr.setAllow3rdPartyOnInternal(true); + + // INSTALL_LOCATION_INTERNAL_ONLY AND INSTALL_LOCATION_UNSPECIFIED are treated the same. + int[] locations = {PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY, + PackageInfo.INSTALL_LOCATION_UNSPECIFIED}; + + for (int location : locations) { + appInfo.installLocation = location; + appPkgMgr.setForceAllowOnExternal(true); + List<VolumeInfo> candidates = appPkgMgr.getPackageCandidateVolumes( + appInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol, sAdoptedVol); + + appPkgMgr.setForceAllowOnExternal(false); + candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol); + } + } + + public void testGetCandidateVolumes_3rdParty_auto() throws Exception { + ApplicationInfo appInfo = new ApplicationInfo(); + StorageManager storageManager = getMockedStorageManager(); + + IPackageManager pm = Mockito.mock(IPackageManager.class); + + MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager(); + appPkgMgr.setForceAllowOnExternal(true); + + // INSTALL_LOCATION_AUTO AND INSTALL_LOCATION_PREFER_EXTERNAL are treated the same. + int[] locations = {PackageInfo.INSTALL_LOCATION_AUTO, + PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL}; + + for (int location : locations) { + appInfo.installLocation = location; + appInfo.flags = 0; + + appInfo.volumeUuid = sInternalVolUuid; + Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(false); + appPkgMgr.setAllow3rdPartyOnInternal(true); + List<VolumeInfo> candidates = appPkgMgr.getPackageCandidateVolumes( + appInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol, sAdoptedVol); + + appInfo.volumeUuid = sInternalVolUuid; + appPkgMgr.setAllow3rdPartyOnInternal(true); + Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(true); + candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sInternalVol); + + appInfo.flags = ApplicationInfo.FLAG_EXTERNAL_STORAGE; + appInfo.volumeUuid = sAdoptedVolUuid; + appPkgMgr.setAllow3rdPartyOnInternal(false); + candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm); + verifyReturnedVolumes(candidates, sAdoptedVol); + } + } +} diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java index 2a3c22c64ec2..ca4141afae2d 100644 --- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java +++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java @@ -215,4 +215,46 @@ public class PackageParserTest { // DEV: Released API 20 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1); } + + /** + * Unit test for PackageParser.getActivityConfigChanges(). + * If the bit is 1 in the original configChanges, it is still 1 in the final configChanges. + * If the bit is 0 in the original configChanges and the bit is not set to 1 in + * restartOnConfigChanges, the bit is changed to 1 in the final configChanges by default. + */ + @Test + public void testGetActivityConfigChanges() { + // Not set in either configChanges or restartOnConfigChanges. + int configChanges = 0x0000; // 00000000. + int restartOnConfigChanges = 0x0000; // 00000000. + int finalConfigChanges = + PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges); + assertEquals(0x0003, finalConfigChanges); // Should be 00000011. + + // Not set in configChanges, but set in restartOnConfigChanges. + configChanges = 0x0000; // 00000000. + restartOnConfigChanges = 0x0003; // 00000011. + finalConfigChanges = + PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges); + assertEquals(0x0000, finalConfigChanges); // Should be 00000000. + + // Set in configChanges. + configChanges = 0x0003; // 00000011. + restartOnConfigChanges = 0X0000; // 00000000. + finalConfigChanges = + PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges); + assertEquals(0x0003, finalConfigChanges); // Should be 00000011. + + restartOnConfigChanges = 0x0003; // 00000011. + finalConfigChanges = + PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges); + assertEquals(0x0003, finalConfigChanges); // Should still be 00000011. + + // Other bit set in configChanges. + configChanges = 0x0080; // 10000000, orientation. + restartOnConfigChanges = 0x0000; // 00000000. + finalConfigChanges = + PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges); + assertEquals(0x0083, finalConfigChanges); // Should be 10000011. + } } diff --git a/core/tests/coretests/src/android/net/RecommendationRequestTest.java b/core/tests/coretests/src/android/net/RecommendationRequestTest.java index 39c1691b09a7..bd2550073dd3 100644 --- a/core/tests/coretests/src/android/net/RecommendationRequestTest.java +++ b/core/tests/coretests/src/android/net/RecommendationRequestTest.java @@ -3,6 +3,7 @@ package android.net; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.os.Parcel; +import android.os.SystemClock; import android.test.AndroidTestCase; public class RecommendationRequestTest extends AndroidTestCase { @@ -10,6 +11,8 @@ public class RecommendationRequestTest extends AndroidTestCase { private WifiConfiguration mDefaultConfig; private WifiConfiguration mConnectedConfig; private WifiConfiguration[] mConnectableConfigs; + private int mLastSelectedNetworkId; + private long mLastSelectedNetworkTimestamp; @Override public void setUp() throws Exception { @@ -35,6 +38,8 @@ public class RecommendationRequestTest extends AndroidTestCase { mConnectedConfig = new WifiConfiguration(); mConnectedConfig.SSID = "connected_config"; mConnectableConfigs = new WifiConfiguration[] {mDefaultConfig, mConnectedConfig}; + mLastSelectedNetworkId = 5; + mLastSelectedNetworkTimestamp = SystemClock.elapsedRealtime(); } public void testParceling() throws Exception { @@ -43,6 +48,7 @@ public class RecommendationRequestTest extends AndroidTestCase { .setScanResults(mScanResults) .setConnectedWifiConfig(mConnectedConfig) .setConnectableConfigs(mConnectableConfigs) + .setLastSelectedNetwork(mLastSelectedNetworkId, mLastSelectedNetworkTimestamp) .build(); RecommendationRequest parceled = passThroughParcel(request); @@ -60,6 +66,8 @@ public class RecommendationRequestTest extends AndroidTestCase { for (int i = 0; i < parceledConfigs.length; i++) { assertEquals(mConnectableConfigs[i].SSID, parceledConfigs[i].SSID); } + assertEquals(mLastSelectedNetworkId, parceled.getLastSelectedNetworkId()); + assertEquals(mLastSelectedNetworkTimestamp, parceled.getLastSelectedNetworkTimestamp()); } public void testParceling_nullScanResults() throws Exception { @@ -82,6 +90,16 @@ public class RecommendationRequestTest extends AndroidTestCase { assertNull(parceledConfigs); } + public void testParceling_unsetLastSelectedNetwork() throws Exception { + RecommendationRequest request = new RecommendationRequest.Builder() + .build(); + + RecommendationRequest parceled = passThroughParcel(request); + + assertEquals(0, parceled.getLastSelectedNetworkId()); + assertEquals(0, parceled.getLastSelectedNetworkTimestamp()); + } + private RecommendationRequest passThroughParcel(RecommendationRequest request) { Parcel p = Parcel.obtain(); RecommendationRequest output = null; diff --git a/data/etc/Android.mk b/data/etc/Android.mk index 6718259e4c2f..b2c68401d7e7 100644 --- a/data/etc/Android.mk +++ b/data/etc/Android.mk @@ -18,6 +18,14 @@ LOCAL_PATH := $(my-dir) ######################## include $(CLEAR_VARS) +LOCAL_MODULE := framework-sysconfig.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/sysconfig +LOCAL_SRC_FILES := $(LOCAL_MODULE) +include $(BUILD_PREBUILT) + +######################## +include $(CLEAR_VARS) LOCAL_MODULE := platform.xml LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions @@ -31,4 +39,3 @@ LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions LOCAL_SRC_FILES := $(LOCAL_MODULE) include $(BUILD_PREBUILT) - diff --git a/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml b/data/etc/framework-sysconfig.xml index 21caab4fae18..2f18de0b1797 100644 --- a/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml +++ b/data/etc/framework-sysconfig.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,13 +13,13 @@ See the License for the specific language governing permissions and limitations under the License. --> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> -</set> + +<!-- These are configurations that must exist on all Android devices. --> +<config> + + <!-- Broadcast actions that are currently exempted from O+ background + delivery restrictions. --> + <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" /> + <allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" /> + +</config> diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd index 77e8d7720c61..021a07ecaa5b 100644 --- a/docs/html/guide/topics/resources/providing-resources.jd +++ b/docs/html/guide/topics/resources/providing-resources.jd @@ -565,6 +565,38 @@ which indicates whether the screen is long.</p> method, which indicates whether the screen is round.</p> </td> </tr> + <tr id="WideColorGamutQualifier"> + <td>Wide Color Gamut</td> + <td> + <code>widecg</code><br/> + <code>nowidecg</code> + </td> + <td> + <ul class="nolist"> + <li>{@code widecg}: Displays with a wide color gamut such as Display P3 or AdobeRGB</li> + <li>{@code nowidecg}: Displays with a narrow color gamut such as sRGB</li> + </ul> + <p><em>Added in API level 26.</em></p> + <p>Also see the {@link android.content.res.Configuration#isScreenWideColorGamut()} configuration + method, which indicates whether the screen has a wide color gamut.</p> + </td> + </tr> + <tr id="HDRQualifier"> + <td>High Dynamic Range (HDR)</td> + <td> + <code>highdr</code><br/> + <code>lowdr</code> + </td> + <td> + <ul class="nolist"> + <li>{@code highdr}: Displays with a high-dynamic range</li> + <li>{@code lowdr}: Displays with a low/standard dynamic range</li> + </ul> + <p><em>Added in API level 26.</em></p> + <p>Also see the {@link android.content.res.Configuration#isScreenHdr()} configuration + method, which indicates whether the screen has a HDR capabilities.</p> + </td> + </tr> <tr id="OrientationQualifier"> <td>Screen orientation</td> <td> diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index 2733c43f8b98..e48bf7956df3 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -18,7 +18,6 @@ package android.graphics; import android.content.res.AssetManager; import android.util.Log; -import dalvik.annotation.optimization.CriticalNative; import java.io.FileInputStream; import java.io.IOException; @@ -40,11 +39,11 @@ public class FontFamily { */ public long mNativePtr; - // Points native font family builder. Must be zero after freezing this family. - private long mBuilderPtr; - public FontFamily() { - mBuilderPtr = nInitBuilder(null, 0); + mNativePtr = nCreateFamily(null, 0); + if (mNativePtr == 0) { + throw new IllegalStateException("error creating native FontFamily"); + } } public FontFamily(String lang, String variant) { @@ -54,15 +53,10 @@ public class FontFamily { } else if ("elegant".equals(variant)) { varEnum = 2; } - mBuilderPtr = nInitBuilder(lang, varEnum); - } - - public void freeze() { - if (mBuilderPtr == 0) { - throw new IllegalStateException("This FontFamily is already frozen"); + mNativePtr = nCreateFamily(lang, varEnum); + if (mNativePtr == 0) { + throw new IllegalStateException("error creating native FontFamily"); } - mNativePtr = nCreateFamily(mBuilderPtr); - mBuilderPtr = 0; } @Override @@ -75,14 +69,11 @@ public class FontFamily { } public boolean addFont(String path, int ttcIndex) { - if (mBuilderPtr == 0) { - throw new IllegalStateException("Unable to call addFont after freezing."); - } try (FileInputStream file = new FileInputStream(path)) { FileChannel fileChannel = file.getChannel(); long fontSize = fileChannel.size(); ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize); - return nAddFont(mBuilderPtr, fontBuffer, ttcIndex); + return nAddFont(mNativePtr, fontBuffer, ttcIndex); } catch (IOException e) { Log.e(TAG, "Error mapping font file " + path); return false; @@ -91,29 +82,19 @@ public class FontFamily { public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontListParser.Axis> axes, int weight, boolean style) { - if (mBuilderPtr == 0) { - throw new IllegalStateException("Unable to call addFontWeightStyle after freezing."); - } - return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, axes, weight, style); + return nAddFontWeightStyle(mNativePtr, font, ttcIndex, axes, weight, style); } public boolean addFontFromAsset(AssetManager mgr, String path) { - if (mBuilderPtr == 0) { - throw new IllegalStateException("Unable to call addFontFromAsset after freezing."); - } - return nAddFontFromAsset(mBuilderPtr, mgr, path); + return nAddFontFromAsset(mNativePtr, mgr, path); } - private static native long nInitBuilder(String lang, int variant); - - @CriticalNative - private static native long nCreateFamily(long mBuilderPtr); - - @CriticalNative + private static native long nCreateFamily(String lang, int variant); private static native void nUnrefFamily(long nativePtr); - private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex); - private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font, + private static native boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex); + private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, int ttcIndex, List<FontListParser.Axis> listOfAxis, int weight, boolean isItalic); - private static native boolean nAddFontFromAsset(long builderPtr, AssetManager mgr, String path); + private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, + String path); } diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index 5b53296d388c..9490436d4f04 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -21,7 +21,6 @@ import android.util.Xml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import android.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import java.io.IOException; @@ -105,12 +104,9 @@ public class FontListParser { // Note that a well-formed variation contains a four-character tag and a float as styleValue, // with spacers in between. The tag is enclosd either by double quotes or single quotes. @VisibleForTesting - public static ArrayList<Axis> parseFontVariationSettings(@Nullable String settings) { - ArrayList<Axis> axisList = new ArrayList<>(); - if (settings == null) { - return axisList; - } + public static Axis[] parseFontVariationSettings(String settings) { String[] settingList = settings.split(","); + ArrayList<Axis> axisList = new ArrayList<>(); settingLoop: for (String setting : settingList) { int pos = 0; @@ -154,7 +150,7 @@ public class FontListParser { tagString.charAt(3)); axisList.add(new Axis(tag, styleValue)); } - return axisList; + return axisList.toArray(new Axis[axisList.size()]); } @VisibleForTesting diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 4ee0c3413968..7815ae16e7e2 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -71,7 +71,6 @@ public class Paint { private LocaleList mLocales; private String mFontFeatureSettings; - private String mFontVariationSettings; private static final Object sCacheLock = new Object(); @@ -1495,37 +1494,6 @@ public class Paint { } /** - * Returns the font variation settings. - * - * @return the paint's currently set font variation settings. Default is null. - * - * @see #setFontVariationSettings(String) - */ - public String getFontVariationSettings() { - return mFontVariationSettings; - } - - /** - * Set font variation settings. - * - * @param settings font variation settings, e.g. "'wdth' 300, 'wght' 1.8" - * - * @see #getFontVariationSettings() - * - * @param settings the font variation settings. You can pass null or empty string as no - * variation settings. - */ - public void setFontVariationSettings(String settings) { - settings = TextUtils.nullIfEmpty(settings); - if (settings == mFontVariationSettings - || (settings != null && settings.equals(mFontVariationSettings))) { - return; - } - mFontVariationSettings = settings; - setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, settings)); - } - - /** * Get the current value of hyphen edit. * * @return the current hyphen edit value diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 166ef1b3113e..2886f0dd4a2e 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -21,7 +21,6 @@ import android.util.Log; import android.util.LongSparseArray; import android.util.LruCache; import android.util.SparseArray; -import android.graphics.FontListParser; import org.xmlpull.v1.XmlPullParserException; @@ -172,15 +171,6 @@ public class Typeface { return typeface; } - /** @hide */ - public static Typeface createFromTypefaceWithVariation(Typeface family, - String fontVariationSettings) { - final long ni = family == null ? 0 : family.native_instance; - ArrayList<FontListParser.Axis> axes = - FontListParser.parseFontVariationSettings(fontVariationSettings); - return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes)); - } - /** * Returns one of the default typeface objects, based on the specified style * @@ -206,7 +196,6 @@ public class Typeface { FontFamily fontFamily = new FontFamily(); if (fontFamily.addFontFromAsset(mgr, path)) { - fontFamily.freeze(); FontFamily[] families = { fontFamily }; typeface = createFromFamiliesWithDefault(families); sDynamicTypefaceCache.put(key, typeface); @@ -256,7 +245,6 @@ public class Typeface { if (sFallbackFonts != null) { FontFamily fontFamily = new FontFamily(); if (fontFamily.addFont(path, 0 /* ttcIndex */)) { - fontFamily.freeze(); FontFamily[] families = { fontFamily }; return createFromFamiliesWithDefault(families); } @@ -327,7 +315,6 @@ public class Typeface { Log.e(TAG, "Error creating font " + font.fontName + "#" + font.ttcIndex); } } - fontFamily.freeze(); return fontFamily; } @@ -453,8 +440,6 @@ public class Typeface { } private static native long nativeCreateFromTypeface(long native_instance, int style); - private static native long nativeCreateFromTypefaceWithVariation( - long native_instance, List<FontListParser.Axis> axes); private static native long nativeCreateWeightAlias(long native_instance, int weight); private static native void nativeUnref(long native_instance); private static native int nativeGetStyle(long native_instance); diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java index 23de416040f0..d046c1103efc 100644 --- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java +++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java @@ -17,7 +17,6 @@ package android.graphics; import android.test.suitebuilder.annotation.SmallTest; -import java.util.List; import junit.framework.TestCase; @@ -26,92 +25,92 @@ public class VariationParserTest extends TestCase { @SmallTest public void testParseFontVariationSetting() { int tag = FontListParser.makeTag('w', 'd', 't', 'h'); - List<FontListParser.Axis> axes = FontListParser.parseFontVariationSettings("'wdth' 1"); - assertEquals(tag, axes.get(0).tag); - assertEquals(1.0f, axes.get(0).styleValue); + FontListParser.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 1"); + assertEquals(tag, axis[0].tag); + assertEquals(1.0f, axis[0].styleValue); - axes = FontListParser.parseFontVariationSettings("\"wdth\" 100"); - assertEquals(tag, axes.get(0).tag); - assertEquals(100.0f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings("\"wdth\" 100"); + assertEquals(tag, axis[0].tag); + assertEquals(100.0f, axis[0].styleValue); - axes = FontListParser.parseFontVariationSettings(" 'wdth' 100"); - assertEquals(tag, axes.get(0).tag); - assertEquals(100.0f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings(" 'wdth' 100"); + assertEquals(tag, axis[0].tag); + assertEquals(100.0f, axis[0].styleValue); - axes = FontListParser.parseFontVariationSettings("\t'wdth' 0.5"); - assertEquals(tag, axes.get(0).tag); - assertEquals(0.5f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings("\t'wdth' 0.5"); + assertEquals(tag, axis[0].tag); + assertEquals(0.5f, axis[0].styleValue); tag = FontListParser.makeTag('A', 'X', ' ', ' '); - axes = FontListParser.parseFontVariationSettings("'AX ' 1"); - assertEquals(tag, axes.get(0).tag); - assertEquals(1.0f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings("'AX ' 1"); + assertEquals(tag, axis[0].tag); + assertEquals(1.0f, axis[0].styleValue); - axes = FontListParser.parseFontVariationSettings("'AX '\t1"); - assertEquals(tag, axes.get(0).tag); - assertEquals(1.0f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings("'AX '\t1"); + assertEquals(tag, axis[0].tag); + assertEquals(1.0f, axis[0].styleValue); - axes = FontListParser.parseFontVariationSettings("'AX '\n1"); - assertEquals(tag, axes.get(0).tag); - assertEquals(1.0f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings("'AX '\n1"); + assertEquals(tag, axis[0].tag); + assertEquals(1.0f, axis[0].styleValue); - axes = FontListParser.parseFontVariationSettings("'AX '\r1"); - assertEquals(tag, axes.get(0).tag); - assertEquals(1.0f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings("'AX '\r1"); + assertEquals(tag, axis[0].tag); + assertEquals(1.0f, axis[0].styleValue); - axes = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1"); - assertEquals(tag, axes.get(0).tag); - assertEquals(1.0f, axes.get(0).styleValue); + axis = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1"); + assertEquals(tag, axis[0].tag); + assertEquals(1.0f, axis[0].styleValue); // Test for invalid input - axes = FontListParser.parseFontVariationSettings(""); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("invalid_form"); - assertEquals(0, axes.size()); + axis = FontListParser.parseFontVariationSettings(""); + assertEquals(0, axis.length); + axis = FontListParser.parseFontVariationSettings("invalid_form"); + assertEquals(0, axis.length); // Test with invalid tag - axes = FontListParser.parseFontVariationSettings("'' 1"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'invalid' 1"); - assertEquals(0, axes.size()); + axis = FontListParser.parseFontVariationSettings("'' 1"); + assertEquals(0, axis.length); + axis = FontListParser.parseFontVariationSettings("'invalid' 1"); + assertEquals(0, axis.length); // Test with invalid styleValue - axes = FontListParser.parseFontVariationSettings("'wdth' "); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'wdth' x"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'wdth' \t"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'wdth' \n\r"); - assertEquals(0, axes.size()); + axis = FontListParser.parseFontVariationSettings("'wdth' "); + assertEquals(0, axis.length); + axis = FontListParser.parseFontVariationSettings("'wdth' x"); + assertEquals(0, axis.length); + axis = FontListParser.parseFontVariationSettings("'wdth' \t"); + assertEquals(0, axis.length); + axis = FontListParser.parseFontVariationSettings("'wdth' \n\r"); + assertEquals(0, axis.length); } @SmallTest public void testParseFontVariationStyleSettings() { - List<FontListParser.Axis> axes = + FontListParser.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 10,'AX '\r1"); int tag1 = FontListParser.makeTag('w', 'd', 't', 'h'); int tag2 = FontListParser.makeTag('A', 'X', ' ', ' '); - assertEquals(tag1, axes.get(0).tag); - assertEquals(10.0f, axes.get(0).styleValue); - assertEquals(tag2, axes.get(1).tag); - assertEquals(1.0f, axes.get(1).styleValue); + assertEquals(tag1, axis[0].tag); + assertEquals(10.0f, axis[0].styleValue); + assertEquals(tag2, axis[1].tag); + assertEquals(1.0f, axis[1].styleValue); // Test only spacers are allowed before tag - axes = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1"); + axis = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1"); tag1 = FontListParser.makeTag('w', 'd', 't', 'h'); - assertEquals(tag1, axes.get(0).tag); - assertEquals(10.0f, axes.get(0).styleValue); - assertEquals(1, axes.size()); + assertEquals(tag1, axis[0].tag); + assertEquals(10.0f, axis[0].styleValue); + assertEquals(1, axis.length); } @SmallTest public void testInvalidTagCharacters() { - List<FontListParser.Axis> axes = + FontListParser.Axis[] axis = FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10"); - assertEquals(0, axes.size()); + assertEquals(0, axis.length); + axis = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10"); + assertEquals(0, axis.length); } @SmallTest diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java index d6b1cf1da8a2..bf7a779ace08 100644 --- a/keystore/java/android/security/keystore/KeyProperties.java +++ b/keystore/java/android/security/keystore/KeyProperties.java @@ -45,6 +45,7 @@ public abstract class KeyProperties { PURPOSE_DECRYPT, PURPOSE_SIGN, PURPOSE_VERIFY, + PURPOSE_WRAP_KEY, }) public @interface PurposeEnum {} @@ -69,6 +70,12 @@ public abstract class KeyProperties { public static final int PURPOSE_VERIFY = 1 << 3; /** + * Purpose of key: wrapping key for secure key import. + */ + public static final int PURPOSE_WRAP_KEY = 1 << 4; + + + /** * @hide */ public static abstract class Purpose { @@ -84,6 +91,8 @@ public abstract class KeyProperties { return KeymasterDefs.KM_PURPOSE_SIGN; case PURPOSE_VERIFY: return KeymasterDefs.KM_PURPOSE_VERIFY; + case PURPOSE_WRAP_KEY: + return KeymasterDefs.KM_PURPOSE_WRAP_KEY; default: throw new IllegalArgumentException("Unknown purpose: " + purpose); } @@ -99,6 +108,8 @@ public abstract class KeyProperties { return PURPOSE_SIGN; case KeymasterDefs.KM_PURPOSE_VERIFY: return PURPOSE_VERIFY; + case KeymasterDefs.KM_PURPOSE_WRAP_KEY: + return PURPOSE_WRAP_KEY; default: throw new IllegalArgumentException("Unknown purpose: " + purpose); } diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index a30c8497b0f8..a4bcc624ef31 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -1907,6 +1907,8 @@ int ResTable_config::compare(const ResTable_config& o) const { if (diff != 0) return diff; diff = (int32_t)(screenLayout2 - o.screenLayout2); if (diff != 0) return diff; + diff = (int32_t)(colorimetry - o.colorimetry); + if (diff != 0) return diff; diff = (int32_t)(uiMode - o.uiMode); if (diff != 0) return diff; diff = (int32_t)(smallestScreenWidthDp - o.smallestScreenWidthDp); @@ -1967,6 +1969,9 @@ int ResTable_config::compareLogical(const ResTable_config& o) const { if (screenLayout2 != o.screenLayout2) { return screenLayout2 < o.screenLayout2 ? -1 : 1; } + if (colorimetry != o.colorimetry) { + return colorimetry < o.colorimetry ? -1 : 1; + } if (uiMode != o.uiMode) { return uiMode < o.uiMode ? -1 : 1; } @@ -1992,6 +1997,8 @@ int ResTable_config::diff(const ResTable_config& o) const { if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) diffs |= CONFIG_LAYOUTDIR; if ((screenLayout & ~MASK_LAYOUTDIR) != (o.screenLayout & ~MASK_LAYOUTDIR)) diffs |= CONFIG_SCREEN_LAYOUT; if ((screenLayout2 & MASK_SCREENROUND) != (o.screenLayout2 & MASK_SCREENROUND)) diffs |= CONFIG_SCREEN_ROUND; + if ((colorimetry & MASK_WIDE_COLOR_GAMUT) != (o.colorimetry & MASK_WIDE_COLOR_GAMUT)) diffs |= CONFIG_COLORIMETRY; + if ((colorimetry & MASK_HDR) != (o.colorimetry & MASK_HDR)) diffs |= CONFIG_COLORIMETRY; if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE; if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE; if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE; @@ -2103,6 +2110,17 @@ bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const { } } + if (colorimetry || o.colorimetry) { + if (((colorimetry^o.colorimetry) & MASK_HDR) != 0) { + if (!(colorimetry & MASK_HDR)) return false; + if (!(o.colorimetry & MASK_HDR)) return true; + } + if (((colorimetry^o.colorimetry) & MASK_WIDE_COLOR_GAMUT) != 0) { + if (!(colorimetry & MASK_WIDE_COLOR_GAMUT)) return false; + if (!(o.colorimetry & MASK_WIDE_COLOR_GAMUT)) return true; + } + } + if (orientation != o.orientation) { if (!orientation) return false; if (!o.orientation) return true; @@ -2390,6 +2408,17 @@ bool ResTable_config::isBetterThan(const ResTable_config& o, } } + if (colorimetry || o.colorimetry) { + if (((colorimetry^o.colorimetry) & MASK_WIDE_COLOR_GAMUT) != 0 && + (requested->colorimetry & MASK_WIDE_COLOR_GAMUT)) { + return colorimetry & MASK_WIDE_COLOR_GAMUT; + } + if (((colorimetry^o.colorimetry) & MASK_HDR) != 0 && + (requested->colorimetry & MASK_HDR)) { + return colorimetry & MASK_HDR; + } + } + if ((orientation != o.orientation) && requested->orientation) { return (orientation); } @@ -2639,6 +2668,18 @@ bool ResTable_config::match(const ResTable_config& settings) const { if (screenRound != 0 && screenRound != setScreenRound) { return false; } + + const int hdr = colorimetry & MASK_HDR; + const int setHdr = settings.colorimetry & MASK_HDR; + if (hdr != 0 && hdr != setHdr) { + return false; + } + + const int wideColorGamut = colorimetry & MASK_WIDE_COLOR_GAMUT; + const int setWideColorGamut = settings.colorimetry & MASK_WIDE_COLOR_GAMUT; + if (wideColorGamut != 0 && wideColorGamut != setWideColorGamut) { + return false; + } } if (screenSizeDp != 0) { @@ -2959,6 +3000,34 @@ String8 ResTable_config::toString() const { break; } } + if ((colorimetry&MASK_HDR) != 0) { + if (res.size() > 0) res.append("-"); + switch (colorimetry&MASK_HDR) { + case ResTable_config::HDR_NO: + res.append("lowdr"); + break; + case ResTable_config::HDR_YES: + res.append("highdr"); + break; + default: + res.appendFormat("hdr=%d", dtohs(colorimetry&MASK_HDR)); + break; + } + } + if ((colorimetry&MASK_WIDE_COLOR_GAMUT) != 0) { + if (res.size() > 0) res.append("-"); + switch (colorimetry&MASK_WIDE_COLOR_GAMUT) { + case ResTable_config::WIDE_COLOR_GAMUT_NO: + res.append("nowidecg"); + break; + case ResTable_config::WIDE_COLOR_GAMUT_YES: + res.append("widecg"); + break; + default: + res.appendFormat("wideColorGamut=%d", dtohs(colorimetry&MASK_WIDE_COLOR_GAMUT)); + break; + } + } if (orientation != ORIENTATION_ANY) { if (res.size() > 0) res.append("-"); switch (orientation) { diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index c118b57510f9..1e4aee9d18e7 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1146,11 +1146,26 @@ struct ResTable_config SCREENROUND_YES = ACONFIGURATION_SCREENROUND_YES, }; + enum { + // colorimetry bits for wide-color gamut/narrow-color gamut. + MASK_WIDE_COLOR_GAMUT = 0x03, + WIDE_COLOR_GAMUT_ANY = ACONFIGURATION_WIDE_COLOR_GAMUT_ANY, + WIDE_COLOR_GAMUT_NO = ACONFIGURATION_WIDE_COLOR_GAMUT_NO, + WIDE_COLOR_GAMUT_YES = ACONFIGURATION_WIDE_COLOR_GAMUT_YES, + + // colorimetry bits for HDR/LDR. + MASK_HDR = 0x0c, + SHIFT_COLORIMETRY_HDR = 2, + HDR_ANY = ACONFIGURATION_HDR_ANY << SHIFT_COLORIMETRY_HDR, + HDR_NO = ACONFIGURATION_HDR_NO << SHIFT_COLORIMETRY_HDR, + HDR_YES = ACONFIGURATION_HDR_YES << SHIFT_COLORIMETRY_HDR, + }; + // An extension of screenConfig. union { struct { uint8_t screenLayout2; // Contains round/notround qualifier. - uint8_t screenConfigPad1; // Reserved padding. + uint8_t colorimetry; // Wide-gamut, HDR, etc. uint16_t screenConfigPad2; // Reserved padding. }; uint32_t screenConfig2; @@ -1193,6 +1208,7 @@ struct ResTable_config CONFIG_UI_MODE = ACONFIGURATION_UI_MODE, CONFIG_LAYOUTDIR = ACONFIGURATION_LAYOUTDIR, CONFIG_SCREEN_ROUND = ACONFIGURATION_SCREEN_ROUND, + CONFIG_COLORIMETRY = ACONFIGURATION_COLORIMETRY, }; // Compare two configuration, returning CONFIG_* flags set for each value diff --git a/tools/aapt2/util/StringPiece.h b/libs/androidfw/include/androidfw/StringPiece.h index 5144b1f1fd6a..c9effd1a5112 100644 --- a/tools/aapt2/util/StringPiece.h +++ b/libs/androidfw/include/androidfw/StringPiece.h @@ -14,26 +14,24 @@ * limitations under the License. */ -#ifndef AAPT_STRING_PIECE_H -#define AAPT_STRING_PIECE_H +#ifndef ANDROIDFW_STRING_PIECE_H +#define ANDROIDFW_STRING_PIECE_H #include <ostream> #include <string> #include "utils/JenkinsHash.h" -#include "utils/String8.h" #include "utils/Unicode.h" -namespace aapt { +namespace android { -/** - * Read only wrapper around basic C strings. - * Prevents excessive copying. - * - * WARNING: When creating from std::basic_string<>, moving the original - * std::basic_string<> will invalidate the data held in a BasicStringPiece<>. - * BasicStringPiece<> should only be used transitively. - */ +// Read only wrapper around basic C strings. Prevents excessive copying. +// StringPiece does not own the data it is wrapping. The lifetime of the underlying +// data must outlive this StringPiece. +// +// WARNING: When creating from std::basic_string<>, moving the original +// std::basic_string<> will invalidate the data held in a BasicStringPiece<>. +// BasicStringPiece<> should only be used transitively. template <typename TChar> class BasicStringPiece { public: @@ -53,15 +51,14 @@ class BasicStringPiece { BasicStringPiece<TChar>& assign(const TChar* str, size_t len); BasicStringPiece<TChar> substr(size_t start, size_t len = npos) const; - BasicStringPiece<TChar> substr( - BasicStringPiece<TChar>::const_iterator begin, - BasicStringPiece<TChar>::const_iterator end) const; + BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin, + BasicStringPiece<TChar>::const_iterator end) const; const TChar* data() const; size_t length() const; size_t size() const; bool empty() const; - std::basic_string<TChar> ToString() const; + std::basic_string<TChar> to_string() const; bool contains(const BasicStringPiece<TChar>& rhs) const; int compare(const BasicStringPiece<TChar>& rhs) const; @@ -89,17 +86,14 @@ template <typename TChar> constexpr const size_t BasicStringPiece<TChar>::npos; template <typename TChar> -inline BasicStringPiece<TChar>::BasicStringPiece() - : data_(nullptr), length_(0) {} +inline BasicStringPiece<TChar>::BasicStringPiece() : data_(nullptr), length_(0) {} template <typename TChar> -inline BasicStringPiece<TChar>::BasicStringPiece( - const BasicStringPiece<TChar>& str) +inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) : data_(str.data_), length_(str.length_) {} template <typename TChar> -inline BasicStringPiece<TChar>::BasicStringPiece( - const std::basic_string<TChar>& str) +inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) : data_(str.data()), length_(str.length()) {} template <> @@ -123,16 +117,14 @@ inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=( } template <typename TChar> -inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign( - const TChar* str, size_t len) { +inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) { data_ = str; length_ = len; return *this; } template <typename TChar> -inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr( - size_t start, size_t len) const { +inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const { if (len == npos) { len = length_ - start; } @@ -171,13 +163,12 @@ inline bool BasicStringPiece<TChar>::empty() const { } template <typename TChar> -inline std::basic_string<TChar> BasicStringPiece<TChar>::ToString() const { +inline std::basic_string<TChar> BasicStringPiece<TChar>::to_string() const { return std::basic_string<TChar>(data_, length_); } template <> -inline bool BasicStringPiece<char>::contains( - const BasicStringPiece<char>& rhs) const { +inline bool BasicStringPiece<char>::contains(const BasicStringPiece<char>& rhs) const { if (!data_ || !rhs.data_) { return false; } @@ -188,8 +179,7 @@ inline bool BasicStringPiece<char>::contains( } template <> -inline int BasicStringPiece<char>::compare( - const BasicStringPiece<char>& rhs) const { +inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const { const char nullStr = '\0'; const char* b1 = data_ != nullptr ? data_ : &nullStr; const char* e1 = b1 + length_; @@ -205,15 +195,21 @@ inline int BasicStringPiece<char>::compare( return static_cast<int>(length_ - rhs.length_); } -inline ::std::ostream& operator<<(::std::ostream& out, - const BasicStringPiece<char16_t>& str) { - android::String8 utf8(str.data(), str.size()); - return out.write(utf8.string(), utf8.size()); +inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) { + const ssize_t result_len = utf16_to_utf8_length(str.data(), str.size()); + if (result_len < 0) { + // Empty string. + return out; + } + + std::string result; + result.resize(static_cast<size_t>(result_len)); + utf16_to_utf8(str.data(), str.length(), &*result.begin(), static_cast<size_t>(result_len) + 1); + return out << result; } template <> -inline bool BasicStringPiece<char16_t>::contains( - const BasicStringPiece<char16_t>& rhs) const { +inline bool BasicStringPiece<char16_t>::contains(const BasicStringPiece<char16_t>& rhs) const { if (!data_ || !rhs.data_) { return false; } @@ -224,8 +220,7 @@ inline bool BasicStringPiece<char16_t>::contains( } template <> -inline int BasicStringPiece<char16_t>::compare( - const BasicStringPiece<char16_t>& rhs) const { +inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const { const char16_t nullStr = u'\0'; const char16_t* b1 = data_ != nullptr ? data_ : &nullStr; const char16_t* b2 = rhs.data_ != nullptr ? rhs.data_ : &nullStr; @@ -233,66 +228,52 @@ inline int BasicStringPiece<char16_t>::compare( } template <typename TChar> -inline bool BasicStringPiece<TChar>::operator<( - const BasicStringPiece<TChar>& rhs) const { +inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const { return compare(rhs) < 0; } template <typename TChar> -inline bool BasicStringPiece<TChar>::operator>( - const BasicStringPiece<TChar>& rhs) const { +inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const { return compare(rhs) > 0; } template <typename TChar> -inline bool BasicStringPiece<TChar>::operator==( - const BasicStringPiece<TChar>& rhs) const { +inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const { return compare(rhs) == 0; } template <typename TChar> -inline bool BasicStringPiece<TChar>::operator!=( - const BasicStringPiece<TChar>& rhs) const { +inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const { return compare(rhs) != 0; } template <typename TChar> -inline typename BasicStringPiece<TChar>::const_iterator -BasicStringPiece<TChar>::begin() const { +inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const { return data_; } template <typename TChar> -inline typename BasicStringPiece<TChar>::const_iterator -BasicStringPiece<TChar>::end() const { +inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const { return data_ + length_; } -inline ::std::ostream& operator<<(::std::ostream& out, - const BasicStringPiece<char>& str) { +inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) { return out.write(str.data(), str.size()); } -} // namespace aapt - -inline ::std::ostream& operator<<(::std::ostream& out, - const std::u16string& str) { - android::String8 utf8(str.data(), str.size()); - return out.write(utf8.string(), utf8.size()); -} +} // namespace android namespace std { template <typename TChar> -struct hash<aapt::BasicStringPiece<TChar>> { - size_t operator()(const aapt::BasicStringPiece<TChar>& str) const { +struct hash<android::BasicStringPiece<TChar>> { + size_t operator()(const android::BasicStringPiece<TChar>& str) const { uint32_t hashCode = android::JenkinsHashMixBytes( - 0, reinterpret_cast<const uint8_t*>(str.data()), - sizeof(TChar) * str.size()); + 0, reinterpret_cast<const uint8_t*>(str.data()), sizeof(TChar) * str.size()); return static_cast<size_t>(hashCode); } }; } // namespace std -#endif // AAPT_STRING_PIECE_H +#endif // ANDROIDFW_STRING_PIECE_H diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk index 6754cd89944a..650f8138366b 100644 --- a/libs/androidfw/tests/Android.mk +++ b/libs/androidfw/tests/Android.mk @@ -34,6 +34,7 @@ testFiles := \ LoadedArsc_test.cpp \ ResTable_test.cpp \ Split_test.cpp \ + StringPiece_test.cpp \ TestHelpers.cpp \ TestMain.cpp \ Theme_test.cpp \ diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp index 778c7bfb2053..3e5aca7ab655 100644 --- a/libs/androidfw/tests/Config_test.cpp +++ b/libs/androidfw/tests/Config_test.cpp @@ -182,4 +182,24 @@ TEST(ConfigTest, RoundIsMoreSpecific) { EXPECT_TRUE(targetConfigC.isBetterThan(targetConfigB, &deviceConfig)); } +TEST(ConfigTest, ScreenIsWideGamut) { + ResTable_config defaultConfig; + memset(&defaultConfig, 0, sizeof(defaultConfig)); + + ResTable_config wideGamutConfig = defaultConfig; + wideGamutConfig.colorimetry = ResTable_config::WIDE_COLOR_GAMUT_YES; + + EXPECT_EQ(defaultConfig.diff(wideGamutConfig), ResTable_config::CONFIG_COLORIMETRY); +} + +TEST(ConfigTest, ScreenIsHdr) { + ResTable_config defaultConfig; + memset(&defaultConfig, 0, sizeof(defaultConfig)); + + ResTable_config hdrConfig = defaultConfig; + hdrConfig.colorimetry = ResTable_config::HDR_YES; + + EXPECT_EQ(defaultConfig.diff(hdrConfig), ResTable_config::CONFIG_COLORIMETRY); +} + } // namespace android. diff --git a/tools/aapt2/util/StringPiece_test.cpp b/libs/androidfw/tests/StringPiece_test.cpp index 048961d49584..316a5c1bf40e 100644 --- a/tools/aapt2/util/StringPiece_test.cpp +++ b/libs/androidfw/tests/StringPiece_test.cpp @@ -14,15 +14,15 @@ * limitations under the License. */ -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" #include <algorithm> #include <string> #include <vector> -#include "test/Test.h" +#include "TestHelpers.h" -namespace aapt { +namespace android { TEST(StringPieceTest, CompareNonNullTerminatedPiece) { StringPiece a("hello world", 5); @@ -92,4 +92,4 @@ TEST(StringPieceTest, ContainsOtherStringPiece) { EXPECT_FALSE(text16.contains(long_needle16)); } -} // namespace aapt +} // namespace android diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp index 6a003794fb28..956f66ed22cb 100644 --- a/libs/hwui/hwui/MinikinSkia.cpp +++ b/libs/hwui/hwui/MinikinSkia.cpp @@ -17,8 +17,7 @@ #include "MinikinSkia.h" #include <log/log.h> -#include <SkFontDescriptor.h> -#include <SkFontMgr.h> + #include <SkPaint.h> #include <SkTypeface.h> @@ -87,28 +86,6 @@ int MinikinFontSkia::GetFontIndex() const { return mTtcIndex; } -minikin::MinikinFont* MinikinFontSkia::createFontWithVariation( - const std::vector<minikin::FontVariation>& variations) const { - SkFontMgr::FontParameters params; - - int ttcIndex; - SkStreamAsset* stream = mTypeface->openStream(&ttcIndex); - LOG_ALWAYS_FATAL_IF(stream == nullptr, "openStream failed"); - - params.setCollectionIndex(ttcIndex); - std::vector<SkFontMgr::FontParameters::Axis> skAxes; - skAxes.resize(variations.size()); - for (size_t i = 0; i < variations.size(); i++) { - skAxes[i].fTag = variations[i].axisTag; - skAxes[i].fStyleValue = SkFloatToScalar(variations[i].value); - } - params.setAxes(skAxes.data(), skAxes.size()); - sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault()); - sk_sp<SkTypeface> face(fm->createFromStream(stream, params)); - - return new MinikinFontSkia(std::move(face), mFontData, mFontSize, ttcIndex); -} - uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) { uint32_t flags = paint->getFlags(); SkPaint::Hinting hinting = paint->getHinting(); diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h index 249b0cbe44de..3ee916c6e8b1 100644 --- a/libs/hwui/hwui/MinikinSkia.h +++ b/libs/hwui/hwui/MinikinSkia.h @@ -44,8 +44,6 @@ public: const void* GetFontData() const; size_t GetFontSize() const; int GetFontIndex() const; - minikin::MinikinFont* createFontWithVariation( - const std::vector<minikin::FontVariation>&) const; static uint32_t packPaintFlags(const SkPaint* paint); static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags); diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index b69b0cb29efe..ca43156e88a1 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -62,7 +62,7 @@ Typeface* Typeface::resolveDefault(Typeface* src) { Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) { Typeface* resolvedFace = Typeface::resolveDefault(src); Typeface* result = new Typeface; - if (result != nullptr) { + if (result != 0) { result->fFontCollection = resolvedFace->fFontCollection; result->fFontCollection->Ref(); result->fSkiaStyle = style; @@ -72,30 +72,10 @@ Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) { return result; } -Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src, - const std::vector<minikin::FontVariation>& variations) { - Typeface* resolvedFace = Typeface::resolveDefault(src); - Typeface* result = new Typeface(); - if (result != nullptr) { - result->fFontCollection = - resolvedFace->fFontCollection->createCollectionWithVariation(variations); - if (result->fFontCollection == nullptr) { - // None of passed axes are supported by this collection. - // So we will reuse the same collection with incrementing reference count. - result->fFontCollection = resolvedFace->fFontCollection; - result->fFontCollection->Ref(); - } - result->fSkiaStyle = resolvedFace->fSkiaStyle; - result->fBaseWeight = resolvedFace->fBaseWeight; - resolveStyle(result); - } - return result; -} - Typeface* Typeface::createWeightAlias(Typeface* src, int weight) { Typeface* resolvedFace = Typeface::resolveDefault(src); Typeface* result = new Typeface; - if (result != nullptr) { + if (result != 0) { result->fFontCollection = resolvedFace->fFontCollection; result->fFontCollection->Ref(); result->fSkiaStyle = resolvedFace->fSkiaStyle; @@ -150,9 +130,9 @@ void Typeface::setRobotoTypefaceForTest() { sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release()); LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont); + minikin::FontFamily* family = new minikin::FontFamily(); minikin::MinikinFont* font = new MinikinFontSkia(std::move(typeface), data, st.st_size, 0); - minikin::FontFamily* family = new minikin::FontFamily( - std::vector<minikin::Font>({ minikin::Font(font, minikin::FontStyle()) })); + family->addFont(font); font->Unref(); std::vector<minikin::FontFamily*> typefaces = { family }; diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h index 4392ebc36bad..1be630c1e978 100644 --- a/libs/hwui/hwui/Typeface.h +++ b/libs/hwui/hwui/Typeface.h @@ -43,9 +43,6 @@ struct ANDROID_API Typeface { static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style); - static Typeface* createFromTypefaceWithVariation(Typeface* src, - const std::vector<minikin::FontVariation>& variations); - static Typeface* createWeightAlias(Typeface* src, int baseweight); static Typeface* createFromFamilies(const std::vector<minikin::FontFamily*>& families); diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp index 419c8a99fe74..6ca8d8bbff8a 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp @@ -19,7 +19,6 @@ #include "RenderNode.h" #include "SkClipStack.h" #include <private/hwui/DrawGlInfo.h> -#include <SkPath.h> #include <GrContext.h> namespace android { @@ -76,9 +75,7 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) { //apply a simple clip with a scissor or a complex clip with a stencil SkRegion clipRegion; - SkPath path; - canvas->getClipStack()->asPath(&path); - clipRegion.setPath(path, SkRegion(ibounds)); + canvas->temporary_internal_getRgnClip(&clipRegion); if (CC_UNLIKELY(clipRegion.isComplex())) { //It is only a temporary solution to use a scissor to draw the stencil. //There is a bug 31489986 to implement efficiently non-rectangular clips. diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk index ad07283eb4f7..67ef40a23e4e 100644 --- a/packages/SettingsLib/Android.mk +++ b/packages/SettingsLib/Android.mk @@ -12,6 +12,8 @@ LOCAL_SHARED_ANDROID_LIBRARIES := \ android-support-v7-appcompat \ android-support-v14-preference +LOCAL_STATIC_JAVA_LIBRARY := legacy-android-test + LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_JAR_EXCLUDE_FILES := none @@ -21,4 +23,4 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) include $(BUILD_STATIC_JAVA_LIBRARY) # For the test package. -include $(call all-makefiles-under, $(LOCAL_PATH))
\ No newline at end of file +include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/packages/SystemUI/res/anim/ic_hotspot_disable_animation_root.xml b/packages/SettingsLib/res/layout/access_point_friction_widget.xml index 770c40149dcf..7409686779e4 100644 --- a/packages/SystemUI/res/anim/ic_hotspot_disable_animation_root.xml +++ b/packages/SettingsLib/res/layout/access_point_friction_widget.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2014 The Android Open Source Project +<!-- Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,11 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. --> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> + +<ImageView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/friction_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:contentDescription="@null" /> diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml index 24a542223b20..b659cee03780 100644 --- a/packages/SettingsLib/res/layout/settings_with_drawer.xml +++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml @@ -26,12 +26,12 @@ android:orientation="vertical" android:fitsSystemWindows="true"> <FrameLayout + style="?android:attr/actionBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="?android:attr/actionBarTheme"> <Toolbar android:id="@+id/action_bar" - style="?android:attr/actionBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:navigationContentDescription="@*android:string/action_bar_up_description"/> diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml index f064e4e16c69..1f35d3e286e9 100644 --- a/packages/SettingsLib/res/values/attrs.xml +++ b/packages/SettingsLib/res/values/attrs.xml @@ -36,7 +36,12 @@ <declare-styleable name="WifiEncryptionState"> <attr name="state_encrypted" format="boolean" /> </declare-styleable> + <declare-styleable name="WifiSavedState"> + <attr name="state_saved" format="boolean" /> + </declare-styleable> + <attr name="wifi_signal" format="reference" /> + <attr name="wifi_friction" format="reference" /> <declare-styleable name="UsageView"> <attr name="android:colorAccent" /> diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index 6179244a27f6..fbc6aa382876 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -13,8 +13,11 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Color; import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.net.ConnectivityManager; +import android.net.ScoredNetwork; import android.os.BatteryManager; import android.os.UserManager; import android.print.PrintManager; @@ -29,6 +32,14 @@ public class Utils { private static String sServicesSystemSharedLibPackageName; private static String sSharedSystemSharedLibPackageName; + static final int[] WIFI_PIE_FOR_BADGING = { + com.android.internal.R.drawable.ic_signal_wifi_badged_0_bars, + com.android.internal.R.drawable.ic_signal_wifi_badged_1_bar, + com.android.internal.R.drawable.ic_signal_wifi_badged_2_bars, + com.android.internal.R.drawable.ic_signal_wifi_badged_3_bars, + com.android.internal.R.drawable.ic_signal_wifi_badged_4_bars + }; + /** * Return string resource that best describes combination of tethering * options available on this device. @@ -160,10 +171,7 @@ public class Utils { @ColorInt public static int getColorAccent(Context context) { - TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent}); - @ColorInt int colorAccent = ta.getColor(0, 0); - ta.recycle(); - return colorAccent; + return getColorAttr(context, android.R.attr.colorAccent); } @ColorInt @@ -182,6 +190,29 @@ public class Utils { return list.getDefaultColor(); } + @ColorInt + public static int getDisabled(Context context, int inputColor) { + return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor); + } + + @ColorInt + public static int applyAlphaAttr(Context context, int attr, int inputColor) { + TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); + float alpha = ta.getFloat(0, 0); + ta.recycle(); + alpha *= Color.alpha(inputColor); + return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor), + Color.blue(inputColor)); + } + + @ColorInt + public static int getColorAttr(Context context, int attr) { + TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); + @ColorInt int colorAccent = ta.getColor(0, 0); + ta.recycle(); + return colorAccent; + } + /** * Determine whether a package is a "system package", in which case certain things (like * disabling notifications or disabling the package altogether) should be disallowed. @@ -233,4 +264,41 @@ public class Utils { com.android.internal.R.string.config_deviceProvisioningPackage); return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName); } + + /** + * Returns a badged Wifi icon drawable. + * + * <p>The first layer contains the Wifi pie and the second layer contains the badge. Callers + * should set the drawable to the appropriate size and tint color. + * + * @param context The caller's context (must have access to internal resources) + * @param level The number of bars to show (0-4) + * @param badge The badge enum {@see android.net.ScoredNetwork} + * + * @throws IllegalArgumentException if an invalid badge enum is given + * + * @deprecated TODO(sghuman): Finalize the form of this method and then move it to a new + * location. + */ + public static LayerDrawable getBadgedWifiIcon(Context context, int level, int badge) { + return new LayerDrawable( + new Drawable[] { + context.getDrawable(WIFI_PIE_FOR_BADGING[level]), + context.getDrawable(getWifiBadgeResource(badge)) + }); + } + + private static int getWifiBadgeResource(int badge) { + switch (badge) { + case ScoredNetwork.BADGING_SD: + return com.android.internal.R.drawable.ic_signal_wifi_badged_sd; + case ScoredNetwork.BADGING_HD: + return com.android.internal.R.drawable.ic_signal_wifi_badged_hd; + case ScoredNetwork.BADGING_4K: + return com.android.internal.R.drawable.ic_signal_wifi_badged_4k; + default: + throw new IllegalArgumentException( + "No badge resource found for badge value: " + badge); + } + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index b327be0e3225..6e10aab829e9 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -21,6 +21,7 @@ import android.content.IContentProvider; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; @@ -105,6 +106,12 @@ public class TileUtils { private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category"; /** + * The key used to get the package name of the icon resource for the preference. + */ + private static final String EXTRA_PREFERENCE_ICON_PACKAGE = + "com.android.settings.icon_package"; + + /** * Name of the meta-data item that should be set in the AndroidManifest.xml * to specify the key that should be used for the preference. */ @@ -342,6 +349,7 @@ public class TileUtils { ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) { if (applicationInfo.isSystemApp()) { int icon = 0; + Pair<String, Integer> iconFromUri = null; CharSequence title = null; String summary = null; String keyHint = null; @@ -358,10 +366,10 @@ public class TileUtils { if (res != null && metaData != null) { if (metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) { - icon = getIconFromUri(context, + iconFromUri = getIconFromUri(context, activityInfo.packageName, metaData.getString(META_DATA_PREFERENCE_ICON_URI), providerMap); } - if ((icon == 0) && metaData.containsKey(META_DATA_PREFERENCE_ICON)) { + if (iconFromUri == null && metaData.containsKey(META_DATA_PREFERENCE_ICON)) { icon = metaData.getInt(META_DATA_PREFERENCE_ICON); } if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) { @@ -401,12 +409,18 @@ public class TileUtils { if (TextUtils.isEmpty(title)) { title = activityInfo.loadLabel(pm).toString(); } - if (icon == 0) { - icon = activityInfo.icon; + + // Set the icon + if (iconFromUri != null) { + tile.icon = Icon.createWithResource(iconFromUri.first, iconFromUri.second); + } else { + if (icon == 0) { + icon = activityInfo.icon; + } + tile.icon = Icon.createWithResource(activityInfo.packageName, icon); } - // Set icon, title and summary for the preference - tile.icon = Icon.createWithResource(activityInfo.packageName, icon); + // Set title and summary for the preference tile.title = title; tile.summary = summary; // Replace the intent with this specific activity @@ -422,16 +436,33 @@ public class TileUtils { } /** - * Gets the icon resource id from content provider. + * Gets the icon package name and resource id from content provider. * @param Context context + * @param packageName package name of the target activity * @param uriString URI for the content provider * @param providerMap Maps URI authorities to providers - * @return Resource id if returned by the content provider, otherwise 0 + * @return package name and resource id of the icon specified */ - public static int getIconFromUri(Context context, String uriString, - Map<String, IContentProvider> providerMap) { + public static Pair<String, Integer> getIconFromUri(Context context, String packageName, + String uriString, Map<String, IContentProvider> providerMap) { Bundle bundle = getBundleFromUri(context, uriString, providerMap); - return (bundle != null) ? bundle.getInt(META_DATA_PREFERENCE_ICON, 0) : 0; + if (bundle == null) { + return null; + } + String iconPackageName = bundle.getString(EXTRA_PREFERENCE_ICON_PACKAGE); + if (TextUtils.isEmpty(iconPackageName)) { + return null; + } + int resId = bundle.getInt(META_DATA_PREFERENCE_ICON, 0); + if (resId == 0) { + return null; + } + // Icon can either come from the target package or from the Settings app. + if (iconPackageName.equals(packageName) + || iconPackageName.equals(context.getPackageName())) { + return Pair.create(iconPackageName, bundle.getInt(META_DATA_PREFERENCE_ICON, 0)); + } + return null; } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index e7450fafda25..06ea4459b3ff 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -27,12 +27,15 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.State; +import android.net.NetworkKey; +import android.net.ScoredNetwork; import android.net.wifi.IWifiManager; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; @@ -48,6 +51,7 @@ import android.util.Log; import com.android.settingslib.R; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -132,6 +136,9 @@ public class AccessPoint implements Comparable<AccessPoint> { private Object mTag; + private int mRankingScore = Integer.MIN_VALUE; + private int mBadge = ScoredNetwork.BADGING_NONE; + // used to co-relate internal vs returned accesspoint. int mId; @@ -205,6 +212,8 @@ public class AccessPoint implements Comparable<AccessPoint> { this.mScanResultCache.clear(); this.mScanResultCache.putAll(that.mScanResultCache); this.mId = that.mId; + this.mBadge = that.mBadge; + this.mRankingScore = that.mRankingScore; } @Override @@ -213,6 +222,11 @@ public class AccessPoint implements Comparable<AccessPoint> { if (isActive() && !other.isActive()) return -1; if (!isActive() && other.isActive()) return 1; + // Higher scores go before lower scores + if (mRankingScore != other.mRankingScore) { + return (mRankingScore > other.mRankingScore) ? -1 : 1; + } + // Reachable one goes before unreachable one. if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1; if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1; @@ -268,9 +282,38 @@ public class AccessPoint implements Comparable<AccessPoint> { if (security != SECURITY_NONE) { builder.append(',').append(securityToString(security, pskType)); } + builder.append(",rankingScore=").append(mRankingScore); + builder.append(",badge=").append(mBadge); + return builder.append(')').toString(); } + /** + * Updates the AccessPoint rankingScore and badge, returning true if the data has changed. + * + * @param scoreCache The score cache to use to retrieve scores. + */ + boolean updateScores(WifiNetworkScoreCache scoreCache) { + int oldBadge = mBadge; + int oldRankingScore = mRankingScore; + mBadge = ScoredNetwork.BADGING_NONE; + mRankingScore = Integer.MIN_VALUE; + + for (ScanResult result : mScanResultCache.values()) { + ScoredNetwork score = scoreCache.getScoredNetwork(result); + if (score == null) { + continue; + } + + if (score.hasRankingScore()) { + mRankingScore = Math.max(mRankingScore, score.calculateRankingScore(result.level)); + } + mBadge = Math.max(mBadge, score.calculateBadge(result.level)); + } + + return (oldBadge != mBadge || oldRankingScore != mRankingScore); + } + private void evictOldScanResults() { long nowMs = SystemClock.elapsedRealtime(); for (Iterator<ScanResult> iter = mScanResultCache.values().iterator(); iter.hasNext(); ) { @@ -555,6 +598,8 @@ public class AccessPoint implements Comparable<AccessPoint> { visibility.append(" rssi=").append(mInfo.getRssi()); visibility.append(" "); visibility.append(" score=").append(mInfo.score); + visibility.append(" rankingScore=").append(getRankingScore()); + visibility.append(" badge=").append(getBadge()); visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate)); visibility.append(String.format("%.1f,", mInfo.txRetriesRate)); visibility.append(String.format("%.1f ", mInfo.txBadRate)); @@ -820,6 +865,14 @@ public class AccessPoint implements Comparable<AccessPoint> { mRssi = rssi; } + int getRankingScore() { + return mRankingScore; + } + + int getBadge() { + return mBadge; + } + public static String getSummary(Context context, String ssid, DetailedState state, boolean isEphemeral, String passpointProvider) { if (state == DetailedState.CONNECTED && ssid == null) { diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index aae9cf6de797..8ebea619e4ef 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -18,8 +18,12 @@ package com.android.settingslib.wifi; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.StateListDrawable; +import android.net.ScoredNetwork; import android.net.wifi.WifiConfiguration; import android.os.Looper; import android.os.UserHandle; @@ -28,19 +32,27 @@ import android.support.v7.preference.PreferenceViewHolder; import android.text.TextUtils; import android.util.AttributeSet; import android.util.SparseArray; +import android.widget.ImageView; import android.widget.TextView; import com.android.settingslib.R; +import com.android.settingslib.Utils; public class AccessPointPreference extends Preference { private static final int[] STATE_SECURED = { R.attr.state_encrypted }; + private static final int[] STATE_SAVED = { + R.attr.state_encrypted, + R.attr.state_saved + }; private static final int[] STATE_NONE = {}; - private static int[] wifi_signal_attributes = { R.attr.wifi_signal }; + private static final int[] wifi_signal_attributes = { R.attr.wifi_signal }; + private static final int[] wifi_friction_attributes = { R.attr.wifi_friction }; private final StateListDrawable mWifiSld; + private final StateListDrawable mFrictionSld; private final int mBadgePadding; private final UserBadgeCache mBadgeCache; private TextView mTitleView; @@ -51,6 +63,9 @@ public class AccessPointPreference extends Preference { private int mLevel; private CharSequence mContentDescription; private int mDefaultIconResId; + private int mIconWidth; + private int mIconHeight; + private int mWifiBadge = ScoredNetwork.BADGING_NONE; static final int[] WIFI_CONNECTION_STRENGTH = { R.string.accessibility_wifi_one_bar, @@ -63,6 +78,7 @@ public class AccessPointPreference extends Preference { public AccessPointPreference(Context context, AttributeSet attrs) { super(context, attrs); mWifiSld = null; + mFrictionSld = null; mBadgePadding = 0; mBadgeCache = null; } @@ -70,6 +86,7 @@ public class AccessPointPreference extends Preference { public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache, boolean forSavedNetworks) { super(context); + setWidgetLayoutResource(R.layout.access_point_friction_widget); mBadgeCache = cache; mAccessPoint = accessPoint; mForSavedNetworks = forSavedNetworks; @@ -78,6 +95,17 @@ public class AccessPointPreference extends Preference { mWifiSld = (StateListDrawable) context.getTheme() .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0); + // Save icon width and height to use for creating a badged icon + setIconWidthAndHeight(); + + TypedArray frictionSld; + try { + frictionSld = context.getTheme().obtainStyledAttributes(wifi_friction_attributes); + } catch (Resources.NotFoundException e) { + // Fallback for platforms that do not need friction icon resources. + frictionSld = null; + } + mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null; // Distance from the end of the title at which this AP's user badge should sit. mBadgePadding = context.getResources() @@ -88,6 +116,7 @@ public class AccessPointPreference extends Preference { public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache, int iconResId, boolean forSavedNetworks) { super(context); + setWidgetLayoutResource(R.layout.access_point_friction_widget); mBadgeCache = cache; mAccessPoint = accessPoint; mForSavedNetworks = forSavedNetworks; @@ -97,12 +126,30 @@ public class AccessPointPreference extends Preference { mWifiSld = (StateListDrawable) context.getTheme() .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0); + // Save icon width and height to use for creating a badged icon + setIconWidthAndHeight(); + + TypedArray frictionSld; + try { + frictionSld = context.getTheme().obtainStyledAttributes(wifi_friction_attributes); + } catch (Resources.NotFoundException e) { + // Fallback for platforms that do not need friction icon resources. + frictionSld = null; + } + mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null; // Distance from the end of the title at which this AP's user badge should sit. mBadgePadding = context.getResources() .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding); } + private void setIconWidthAndHeight() { + // TODO(sghuman): Refactor this defined widths and heights into a dimension resource and + // reference directly. + mIconWidth = mWifiSld.getIntrinsicWidth(); + mIconHeight = mWifiSld.getIntrinsicHeight(); + } + public AccessPoint getAccessPoint() { return mAccessPoint; } @@ -126,12 +173,27 @@ public class AccessPointPreference extends Preference { mTitleView.setCompoundDrawablePadding(mBadgePadding); } view.itemView.setContentDescription(mContentDescription); + + if (!mForSavedNetworks) { + ImageView frictionImageView = (ImageView) view.findViewById(R.id.friction_icon); + bindFrictionImage(frictionImageView); + } } protected void updateIcon(int level, Context context) { if (level == -1) { safeSetDefaultIcon(); } else { + if (mWifiBadge != ScoredNetwork.BADGING_NONE) { + // TODO(sghuman): Refactor this to reuse drawable to save memory and add to a + // special subclass of AccessPointPreference + LayerDrawable drawable = Utils.getBadgedWifiIcon(context, level, mWifiBadge); + drawable.setLayerSize(0, mIconWidth, mIconHeight); + drawable.setLayerSize(1, mIconWidth, mIconHeight); + drawable.setTint(Utils.getColorAccent(getContext())); + setIcon(drawable); + return; + } if (getIcon() == null) { // To avoid a drawing race condition, we first set the state (SECURE/NONE) and then // set the icon (drawable) to that state's drawable. @@ -152,6 +214,27 @@ public class AccessPointPreference extends Preference { } } + /** + * Binds the friction icon drawable using a StateListDrawable. + * + * <p>Friction icons will be rebound when notifyChange() is called, and therefore + * do not need to be managed in refresh()</p>. + */ + private void bindFrictionImage(ImageView frictionImageView) { + if (frictionImageView == null || mFrictionSld == null) { + return; + } + if (mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) { + if (mAccessPoint.isSaved()) { + mFrictionSld.setState(STATE_SAVED); + } else { + mFrictionSld.setState(STATE_SECURED); + } + } + Drawable drawable = mFrictionSld.getCurrent(); + frictionImageView.setImageDrawable(drawable); + } + private void safeSetDefaultIcon() { if (mDefaultIconResId != 0) { setIcon(mDefaultIconResId); @@ -182,11 +265,14 @@ public class AccessPointPreference extends Preference { final Context context = getContext(); int level = mAccessPoint.getLevel(); - if (level != mLevel) { + int wifiBadge = mAccessPoint.getBadge(); + if (level != mLevel || wifiBadge != mWifiBadge) { mLevel = level; + mWifiBadge = wifiBadge; updateIcon(mLevel, context); notifyChanged(); } + updateBadge(context); setSummary(mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary() diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index 77a45b31fd1c..799f388057c1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -24,15 +24,22 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; +import android.net.NetworkKey; import android.net.NetworkRequest; +import android.net.NetworkScoreManager; +import android.net.ScoredNetwork; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; +import android.net.wifi.WifiNetworkScoreCache.CacheListener; import android.os.ConditionVariable; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.support.annotation.WorkerThread; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; @@ -49,14 +56,18 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** * Tracks saved or available wifi networks and their state. */ public class WifiTracker { + // TODO(sghuman): Document remaining methods with @UiThread and @WorkerThread where possible. + // TODO(sghuman): Refactor to avoid calling certain methods on the UiThread. + private static final String TAG = "WifiTracker"; - private static final boolean DBG = false; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); /** verbose logging flag. this flag is set thru developer debugging options * and used so as to assist with in-the-field WiFi connectivity debugging */ @@ -122,6 +133,10 @@ public class WifiTracker { private NetworkInfo mLastNetworkInfo; private WifiInfo mLastInfo; + private final NetworkScoreManager mNetworkScoreManager; + private final WifiNetworkScoreCache mScoreCache; + private final Set<NetworkKey> mRequestedScores = new ArraySet<>(); + @VisibleForTesting Scanner mScanner; @@ -144,14 +159,16 @@ public class WifiTracker { boolean includeSaved, boolean includeScans, boolean includePasspoints) { this(context, wifiListener, workerLooper, includeSaved, includeScans, includePasspoints, context.getSystemService(WifiManager.class), - context.getSystemService(ConnectivityManager.class), Looper.myLooper()); + context.getSystemService(ConnectivityManager.class), + context.getSystemService(NetworkScoreManager.class), Looper.myLooper() + ); } @VisibleForTesting WifiTracker(Context context, WifiListener wifiListener, Looper workerLooper, boolean includeSaved, boolean includeScans, boolean includePasspoints, WifiManager wifiManager, ConnectivityManager connectivityManager, - Looper currentLooper) { + NetworkScoreManager networkScoreManager, Looper currentLooper) { if (!includeSaved && !includeScans) { throw new IllegalArgumentException("Must include either saved or scans"); } @@ -186,6 +203,18 @@ public class WifiTracker { .clearCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); + + mNetworkScoreManager = networkScoreManager; + + mScoreCache = new WifiNetworkScoreCache(context, new CacheListener(mWorkHandler) { + @Override + public void networkCacheUpdated(List<ScoredNetwork> networks) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "Score cache was updated with networks: " + networks); + } + Message.obtain(mWorkHandler, WorkHandler.MSG_UPDATE_NETWORK_SCORES).sendToTarget(); + } + }); } /** @@ -216,6 +245,8 @@ public class WifiTracker { /** * Resume scanning for wifi networks after it has been paused. + * + * <p>The score cache should be registered before this method is invoked. */ public void resumeScanning() { if (mScanner == null) { @@ -230,11 +261,20 @@ public class WifiTracker { } /** - * Start tracking wifi networks. - * Registers listeners and starts scanning for wifi networks. If this is not called + * Start tracking wifi networks and scores. + * + * <p>Registers listeners and starts scanning for wifi networks. If this is not called * then forceUpdate() must be called to populate getAccessPoints(). */ public void startTracking() { + mWorkHandler.post(new Runnable() { + @Override + public void run() { + registerScoreCache(); + } + }); + + resumeScanning(); if (!mRegistered) { mContext.registerReceiver(mReceiver, mFilter); @@ -245,9 +285,28 @@ public class WifiTracker { } } + @WorkerThread + private void registerScoreCache() { + mNetworkScoreManager.registerNetworkScoreCache( + NetworkKey.TYPE_WIFI, + mScoreCache, + NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS); + } + + private void requestScoresForNetworkKeys(Collection<NetworkKey> keys) { + if (keys.isEmpty()) return; + + if (DBG) { + Log.d(TAG, "Requesting scores for Network Keys: " + keys); + } + mNetworkScoreManager.requestScores(keys.toArray(new NetworkKey[keys.size()])); + mRequestedScores.addAll(keys); + } + /** - * Stop tracking wifi networks. - * Unregisters all listeners and stops scanning for wifi networks. This should always + * Stop tracking wifi networks and scores. + * + * <p>Unregisters all listeners and stops scanning for wifi networks. This should always * be called when done with a WifiTracker (if startTracking was called) to ensure * proper cleanup. */ @@ -255,11 +314,26 @@ public class WifiTracker { if (mRegistered) { mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS); mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_NETWORK_INFO); + mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_NETWORK_SCORES); mContext.unregisterReceiver(mReceiver); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mRegistered = false; } pauseScanning(); + + mWorkHandler.post(new Runnable() { + @Override + public void run() { + unregisterAndClearScoreCache(); + } + }); + } + + @WorkerThread + private void unregisterAndClearScoreCache() { + mRequestedScores.clear(); + mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache); + mScoreCache.clearScores(); } /** @@ -415,6 +489,7 @@ public class WifiTracker { } } + final List<NetworkKey> scoresToRequest = new ArrayList<>(); if (results != null) { for (ScanResult result : results) { // Ignore hidden and ad-hoc networks. @@ -423,6 +498,11 @@ public class WifiTracker { continue; } + NetworkKey key = NetworkKey.createFromScanResult(result); + if (!mRequestedScores.contains(key)) { + scoresToRequest.add(key); + } + boolean found = false; for (AccessPoint accessPoint : apMap.getAll(result.SSID)) { if (accessPoint.update(result)) { @@ -457,27 +537,35 @@ public class WifiTracker { } } + + requestScoresForNetworkKeys(scoresToRequest); + for (AccessPoint ap : accessPoints) { + ap.updateScores(mScoreCache); + } + // Pre-sort accessPoints to speed preference insertion Collections.sort(accessPoints); // Log accesspoints that were deleted - if (DBG) Log.d(TAG, "------ Dumping SSIDs that were not seen on this scan ------"); - for (AccessPoint prevAccessPoint : mInternalAccessPoints) { - if (prevAccessPoint.getSsid() == null) - continue; - String prevSsid = prevAccessPoint.getSsidStr(); - boolean found = false; - for (AccessPoint newAccessPoint : accessPoints) { - if (newAccessPoint.getSsid() != null && newAccessPoint.getSsid() - .equals(prevSsid)) { - found = true; - break; + if (DBG) { + Log.d(TAG, "------ Dumping SSIDs that were not seen on this scan ------"); + for (AccessPoint prevAccessPoint : mInternalAccessPoints) { + if (prevAccessPoint.getSsid() == null) + continue; + String prevSsid = prevAccessPoint.getSsidStr(); + boolean found = false; + for (AccessPoint newAccessPoint : accessPoints) { + if (newAccessPoint.getSsid() != null && newAccessPoint.getSsid() + .equals(prevSsid)) { + found = true; + break; + } } + if (!found) + Log.d(TAG, "Did not find " + prevSsid + " in this scan"); } - if (!found) - if (DBG) Log.d(TAG, "Did not find " + prevSsid + " in this scan"); + Log.d(TAG, "---- Done dumping SSIDs that were not seen on this scan ----"); } - if (DBG) Log.d(TAG, "---- Done dumping SSIDs that were not seen on this scan ----"); mInternalAccessPoints.clear(); mInternalAccessPoints.addAll(accessPoints); @@ -549,7 +637,38 @@ public class WifiTracker { boolean reorder = false; for (int i = mInternalAccessPoints.size() - 1; i >= 0; --i) { - if (mInternalAccessPoints.get(i).update(connectionConfig, mLastInfo, mLastNetworkInfo)) { + AccessPoint ap = mInternalAccessPoints.get(i); + if (ap.update(connectionConfig, mLastInfo, mLastNetworkInfo)) { + reorder = true; + } + if (ap.updateScores(mScoreCache)) { + reorder = true; + } + } + if (reorder) { + Collections.sort(mInternalAccessPoints); + mMainHandler.scheduleAPCopyingAndCloseWriteLock(); + } + } + + /** + * Update all the internal access points rankingScores and badge. + * + * <p>Will trigger a resort and notify listeners of changes if applicable. + */ + private void updateNetworkScores() { + // Lock required to prevent accidental copying of AccessPoint states while the modification + // is in progress. see #copyAndNotifyListeners + long before = System.currentTimeMillis(); + mInternalAccessPointsWriteLock.block(); + if (DBG) { + Log.d(TAG, "Acquired AP lock on WorkerHandler for inserting NetworkScores. Wait time = " + + (System.currentTimeMillis() - before) + "ms."); + } + + boolean reorder = false; + for (int i = 0; i < mInternalAccessPoints.size(); i++) { + if (mInternalAccessPoints.get(i).updateScores(mScoreCache)) { reorder = true; } } @@ -661,6 +780,7 @@ public class WifiTracker { private static final int MSG_UPDATE_NETWORK_INFO = 1; private static final int MSG_RESUME = 2; private static final int MSG_UPDATE_WIFI_STATE = 3; + private static final int MSG_UPDATE_NETWORK_SCORES = 4; public WorkHandler(Looper looper) { super(looper); @@ -695,6 +815,9 @@ public class WifiTracker { mMainHandler.obtainMessage(MainHandler.MSG_WIFI_STATE_CHANGED, msg.arg1, 0) .sendToTarget(); break; + case MSG_UPDATE_NETWORK_SCORES: + updateNetworkScores(); + break; } } } diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk index 42085225dd91..98bce0ca42b2 100644 --- a/packages/SettingsLib/tests/integ/Android.mk +++ b/packages/SettingsLib/tests/integ/Android.mk @@ -27,7 +27,8 @@ LOCAL_PACKAGE_NAME := SettingsLibTests LOCAL_STATIC_JAVA_LIBRARIES := \ android-support-test \ espresso-core \ - mockito-target-minus-junit4 + mockito-target-minus-junit4 \ + legacy-android-test include frameworks/base/packages/SettingsLib/common.mk diff --git a/packages/SettingsLib/tests/integ/AndroidManifest.xml b/packages/SettingsLib/tests/integ/AndroidManifest.xml index 00b21649959b..0d5ff2ca05a5 100644 --- a/packages/SettingsLib/tests/integ/AndroidManifest.xml +++ b/packages/SettingsLib/tests/integ/AndroidManifest.xml @@ -22,6 +22,7 @@ <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY"/> <uses-permission android:name="android.permission.SET_TIME_ZONE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <application> diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java index c650190b591f..eaf0367822c8 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java @@ -15,29 +15,278 @@ */ package com.android.settingslib.wifi; - +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkKey; +import android.net.NetworkScoreManager; +import android.net.ScoredNetwork; +import android.net.RssiCurve; +import android.net.WifiKey; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; +import android.net.wifi.WifiSsid; +import android.os.Bundle; import android.os.SystemClock; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.provider.Settings; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Matchers; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.List; - +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; @SmallTest @RunWith(AndroidJUnit4.class) public class WifiTrackerTest { + private static final String TAG = "WifiTrackerTest"; + private static final int LATCH_TIMEOUT = 2000; + + private static final String SSID_1 = "ssid1"; + private static final String BSSID_1 = "00:00:00:00:00:00"; + private static final NetworkKey NETWORK_KEY_1 = + new NetworkKey(new WifiKey('"' + SSID_1 + '"', BSSID_1)); + private static final int RSSI_1 = -30; + private static final byte SCORE_1 = 10; + private static final int BADGE_1 = ScoredNetwork.BADGING_SD; + + private static final String SSID_2 = "ssid2"; + private static final String BSSID_2 = "AA:AA:AA:AA:AA:AA"; + private static final NetworkKey NETWORK_KEY_2 = + new NetworkKey(new WifiKey('"' + SSID_2 + '"', BSSID_2)); + private static final int RSSI_2 = -30; + private static final byte SCORE_2 = 15; + private static final int BADGE_2 = ScoredNetwork.BADGING_HD; + + @Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor; + @Mock private ConnectivityManager mockConnectivityManager; + @Mock private NetworkScoreManager mockNetworkScoreManager; + @Mock private RssiCurve mockCurve1; + @Mock private RssiCurve mockCurve2; + @Mock private RssiCurve mockBadgeCurve1; + @Mock private RssiCurve mockBadgeCurve2; + @Mock private WifiManager mockWifiManager; + @Mock private WifiTracker.WifiListener mockWifiListener; + + private final List<NetworkKey> mRequestedKeys = new ArrayList<>(); + + private Context mContext; + private CountDownLatch mAccessPointsChangedLatch; + private CountDownLatch mRequestScoresLatch; + private Handler mScannerHandler; + private HandlerThread mMainThread; + private HandlerThread mWorkerThread; + private Looper mLooper; + private Looper mMainLooper; + private int mOriginalSettingValue; + + @Before + public void setUp() { + mContext = InstrumentationRegistry.getTargetContext(); + MockitoAnnotations.initMocks(this); + + mWorkerThread = new HandlerThread("TestHandlerWorkerThread"); + mWorkerThread.start(); + mLooper = mWorkerThread.getLooper(); + mMainThread = new HandlerThread("TestHandlerThread"); + mMainThread.start(); + mMainLooper = mMainThread.getLooper(); + + // Make sure the scanner doesn't try to run on the testing thread. + HandlerThread scannerThread = new HandlerThread("ScannerWorkerThread"); + scannerThread.start(); + mScannerHandler = new Handler(scannerThread.getLooper()); + + when(mockWifiManager.isWifiEnabled()).thenReturn(true); + when(mockWifiManager.getScanResults()) + .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2())); + + + when(mockCurve1.lookupScore(RSSI_1)).thenReturn(SCORE_1); + when(mockCurve2.lookupScore(RSSI_2)).thenReturn(SCORE_2); + + when(mockBadgeCurve1.lookupScore(RSSI_1)).thenReturn((byte) BADGE_1); + when(mockBadgeCurve2.lookupScore(RSSI_2)).thenReturn((byte) BADGE_2); + + doNothing() + .when(mockNetworkScoreManager) + .registerNetworkScoreCache( + anyInt(), + mScoreCacheCaptor.capture(), + Matchers.anyInt()); + + // Capture requested keys and count down latch if present + doAnswer( + new Answer<Boolean>() { + @Override + public Boolean answer(InvocationOnMock input) { + if (mRequestScoresLatch != null) { + mRequestScoresLatch.countDown(); + } + NetworkKey[] keys = (NetworkKey[]) input.getArguments()[0]; + for (NetworkKey key : keys) { + mRequestedKeys.add(key); + } + return true; + } + }).when(mockNetworkScoreManager).requestScores(Matchers.<NetworkKey[]>any()); + + doAnswer( + new Answer<Void>() { + @Override + public Void answer (InvocationOnMock invocation) throws Throwable { + if (mAccessPointsChangedLatch != null) { + mAccessPointsChangedLatch.countDown(); + } + + return null; + } + }).when(mockWifiListener).onAccessPointsChanged(); + + mOriginalSettingValue = Settings.Global.getInt( + InstrumentationRegistry.getTargetContext().getContentResolver(), + Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, + 0 /* disabled */); + + } + + @After + public void cleanUp() { + Settings.Global.putInt( + InstrumentationRegistry.getTargetContext().getContentResolver(), + Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, + mOriginalSettingValue); + } + + private static ScanResult buildScanResult1() { + return new ScanResult( + WifiSsid.createFromAsciiEncoded(SSID_1), + BSSID_1, + 0, // hessid + 0, //anqpDomainId + null, // osuProviders + "", // capabilities + RSSI_1, + 0, // frequency + SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */); + } + + private static ScanResult buildScanResult2() { + return new ScanResult( + WifiSsid.createFromAsciiEncoded(SSID_2), + BSSID_2, + 0, // hessid + 0, //anqpDomainId + null, // osuProviders + "", // capabilities + RSSI_2, + 0, // frequency + SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */); + } + + private WifiTracker createTrackerAndInjectInitialScanResults() throws InterruptedException { + WifiTracker tracker = createMockedWifiTracker(); + startTracking(tracker); + + mAccessPointsChangedLatch = new CountDownLatch(1); + sendScanResultsAndProcess(tracker); + mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); + + return tracker; + } + + private WifiTracker createMockedWifiTracker() { + WifiTracker tracker = + new WifiTracker( + mContext, + mockWifiListener, + mLooper, + true, + true, + true, + mockWifiManager, + mockConnectivityManager, + mockNetworkScoreManager, mMainLooper + ); + + return tracker; + } + + private void startTracking(WifiTracker tracker) throws InterruptedException { + CountDownLatch latch = new CountDownLatch(1); + mScannerHandler.post(new Runnable() { + @Override + public void run() { + tracker.startTracking(); + latch.countDown(); + } + }); + latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); + } + + private void sendScanResultsAndProcess(WifiTracker tracker) throws InterruptedException { + mAccessPointsChangedLatch = new CountDownLatch(1); + Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + tracker.mReceiver.onReceive(mContext, i); + + mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); + } + + private void updateScores() { + Bundle attr1 = new Bundle(); + attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve1); + ScoredNetwork sc1 = + new ScoredNetwork( + NETWORK_KEY_1, + mockCurve1, + false /* meteredHint */, + attr1); + + Bundle attr2 = new Bundle(); + attr2.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve2); + ScoredNetwork sc2 = + new ScoredNetwork( + NETWORK_KEY_2, + mockCurve2, + false /* meteredHint */, + attr2); + + WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue(); + scoreCache.updateScores(Arrays.asList(sc1, sc2)); + } + @Test public void testAccessPointListenerSetWhenLookingUpUsingScanResults() { ScanResult scanResult = new ScanResult(); @@ -47,7 +296,7 @@ public class WifiTrackerTest { scanResult.capabilities = ""; WifiTracker tracker = new WifiTracker( - InstrumentationRegistry.getTargetContext(), null, true, true); + InstrumentationRegistry.getTargetContext(), null, mLooper, true, true); AccessPoint result = tracker.getCachedOrCreate(scanResult, new ArrayList<AccessPoint>()); assertTrue(result.mAccessPointListener != null); @@ -63,9 +312,125 @@ public class WifiTrackerTest { configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); WifiTracker tracker = new WifiTracker( - InstrumentationRegistry.getTargetContext(), null, true, true); + InstrumentationRegistry.getTargetContext(), null, mLooper, true, true); AccessPoint result = tracker.getCachedOrCreate(configuration, new ArrayList<AccessPoint>()); assertTrue(result.mAccessPointListener != null); } + + @Test + public void startAndStopTrackingShouldRegisterAndUnregisterScoreCache() + throws InterruptedException { + WifiTracker tracker = createMockedWifiTracker(); + + // Test register + startTracking(tracker); + verify(mockNetworkScoreManager) + .registerNetworkScoreCache( + Matchers.anyInt(), + mScoreCacheCaptor.capture(), + Matchers.anyInt()); + + WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue(); + + // Test unregister + tracker.stopTracking(); + + verify(mockNetworkScoreManager) + .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache); + } + + @Test + public void startTrackingShouldRequestScoresForCurrentAccessPoints() throws InterruptedException { + // Start the tracker and inject the initial scan results and then stop tracking + WifiTracker tracker = createTrackerAndInjectInitialScanResults(); + + tracker.stopTracking(); + mRequestedKeys.clear(); + + mRequestScoresLatch = new CountDownLatch(2); + startTracking(tracker); + mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); + + assertTrue(mRequestedKeys.contains(NETWORK_KEY_1)); + assertTrue(mRequestedKeys.contains(NETWORK_KEY_2)); + } + + @Test + public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged() throws InterruptedException { + WifiTracker tracker = createMockedWifiTracker(); + startTracking(tracker); + sendScanResultsAndProcess(tracker); + + updateScoresAndWaitForAccessPointsChangedCallback(); + } + + private void updateScoresAndWaitForAccessPointsChangedCallback() throws InterruptedException { + mAccessPointsChangedLatch = new CountDownLatch(2); + updateScores(); + mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); + } + + @Test + public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException { + WifiTracker tracker = createTrackerAndInjectInitialScanResults(); + List<AccessPoint> aps = tracker.getAccessPoints(); + assertTrue(aps.size() == 2); + assertEquals(aps.get(0).getSsidStr(), SSID_1); + assertEquals(aps.get(1).getSsidStr(), SSID_2); + + updateScoresAndWaitForAccessPointsChangedCallback(); + + aps = tracker.getAccessPoints(); + assertTrue(aps.size() == 2); + assertEquals(aps.get(0).getSsidStr(), SSID_2); + assertEquals(aps.get(1).getSsidStr(), SSID_1); + + } + + @Test + public void scoreCacheUpdateScoresShouldInsertBadgeIntoAccessPoint() throws InterruptedException { + WifiTracker tracker = createTrackerAndInjectInitialScanResults(); + updateScoresAndWaitForAccessPointsChangedCallback(); + + List<AccessPoint> aps = tracker.getAccessPoints(); + + for (AccessPoint ap : aps) { + if (ap.getSsidStr().equals(SSID_1)) { + assertEquals(BADGE_1, ap.getBadge()); + } else if (ap.getSsidStr().equals(SSID_2)) { + assertEquals(BADGE_2, ap.getBadge()); + } + } + } + + @Test + public void scoresShouldBeRequestedForNewScanResultOnly() throws InterruptedException { + mRequestScoresLatch = new CountDownLatch(2); + WifiTracker tracker = createTrackerAndInjectInitialScanResults(); + mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); + mRequestedKeys.clear(); + + String ssid = "ssid3"; + String bssid = "00:00:00:00:00:00"; + ScanResult newResult = new ScanResult( + WifiSsid.createFromAsciiEncoded(ssid), + bssid, + 0, // hessid + 0, //anqpDomainId + null, // osuProviders + "", // capabilities + RSSI_1, + 0, // frequency + SystemClock.elapsedRealtime() * 1000); + when(mockWifiManager.getScanResults()) + .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2(), newResult)); + + mRequestScoresLatch = new CountDownLatch(1); + sendScanResultsAndProcess(tracker); + mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); + + assertEquals(1, mRequestedKeys.size()); + assertTrue(mRequestedKeys.contains(new NetworkKey(new WifiKey('"' + ssid + '"', bssid)))); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index d8082c41b5ff..c95cac5c8c67 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -255,6 +255,7 @@ public class TileUtilsTest { Bundle bundle = new Bundle(); bundle.putInt("com.android.settings.icon", 161803); + bundle.putString("com.android.settings.icon_package", "abc"); bundle.putString("com.android.settings.summary", "dynamic-summary"); when(mIContentProvider.call(anyString(), eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_ICON))), eq(URI_GET_ICON), any())) diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 058e38a5ede1..527631e0fb7c 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -271,6 +271,7 @@ public class SettingsProvider extends ContentProvider { @Override public boolean onCreate() { + Settings.setInSystemServer(); synchronized (mLock) { mUserManager = UserManager.get(getContext()); mPackageManager = AppGlobals.getPackageManager(); @@ -829,7 +830,8 @@ public class SettingsProvider extends ContentProvider { SettingsState settingsState = mSettingsRegistry.getSettingsLocked( SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); - List<String> names = settingsState.getSettingNamesLocked(); + List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_GLOBAL, + UserHandle.USER_SYSTEM); final int nameCount = names.size(); @@ -852,6 +854,9 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")"); } + // Ensure the caller can access the setting. + enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId()); + // Get the value. synchronized (mLock) { return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL, @@ -954,8 +959,7 @@ public class SettingsProvider extends ContentProvider { final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); synchronized (mLock) { - List<String> names = mSettingsRegistry.getSettingsNamesLocked( - SETTINGS_TYPE_SECURE, callingUserId); + List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SECURE, callingUserId); final int nameCount = names.size(); @@ -997,6 +1001,9 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); + // Ensure the caller can access the setting. + enforceSettingReadable(name, SETTINGS_TYPE_SECURE, callingUserId); + // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); @@ -1039,7 +1046,7 @@ public class SettingsProvider extends ContentProvider { name); // Lazy initialize ssaid if not yet present in ssaid table. - if (ssaid.isNull() || ssaid.getValue() == null) { + if (ssaid == null || ssaid.isNull() || ssaid.getValue() == null) { return mSettingsRegistry.generateSsaidLocked(getCallingPackage(), owningUserId); } @@ -1159,8 +1166,7 @@ public class SettingsProvider extends ContentProvider { final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); synchronized (mLock) { - List<String> names = mSettingsRegistry.getSettingsNamesLocked( - SETTINGS_TYPE_SYSTEM, callingUserId); + List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SYSTEM, callingUserId); final int nameCount = names.size(); @@ -1191,6 +1197,9 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); + // Ensure the caller can access the setting. + enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, callingUserId); + // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); @@ -1409,9 +1418,15 @@ public class SettingsProvider extends ContentProvider { && (parentId = getGroupParentLocked(userId)) != userId) { // The setting has a dependency and the profile has a parent String dependency = sSystemCloneFromParentOnDependency.get(setting); - Setting settingObj = getSecureSetting(dependency, userId); - if (settingObj != null && settingObj.getValue().equals("1")) { - return parentId; + // Lookup the dependency setting as ourselves, some callers may not have access to it. + final long token = Binder.clearCallingIdentity(); + try { + Setting settingObj = getSecureSetting(dependency, userId); + if (settingObj != null && settingObj.getValue().equals("1")) { + return parentId; + } + } finally { + Binder.restoreCallingIdentity(token); } } return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting); @@ -1479,6 +1494,55 @@ public class SettingsProvider extends ContentProvider { } } + private Set<String> getEphemeralAccessibleSettings(int settingsType) { + switch (settingsType) { + case SETTINGS_TYPE_GLOBAL: + return Settings.Global.EPHEMERAL_SETTINGS; + case SETTINGS_TYPE_SECURE: + return Settings.Secure.EPHEMERAL_SETTINGS; + case SETTINGS_TYPE_SYSTEM: + return Settings.System.EPHEMERAL_SETTINGS; + default: + throw new IllegalArgumentException("Invalid settings type: " + settingsType); + } + } + + private List<String> getSettingsNamesLocked(int settingsType, int userId) { + ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId); + if (ai.isEphemeralApp()) { + return new ArrayList<String>(getEphemeralAccessibleSettings(settingsType)); + } else { + return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId); + } + } + + private void enforceSettingReadable(String settingName, int settingsType, int userId) { + if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) { + return; + } + ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId); + if (!ai.isEphemeralApp()) { + return; + } + if (!getEphemeralAccessibleSettings(settingsType).contains(settingName)) { + throw new SecurityException("Setting " + settingName + " is not accessible from" + + " ephemeral package " + getCallingPackage()); + } + } + + private ApplicationInfo getCallingApplicationInfoOrThrow(int userId) { + ApplicationInfo ai = null; + try { + ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0 , userId); + } catch (RemoteException ignored) { + } + if (ai == null) { + throw new IllegalStateException("Failed to lookup info for package " + + getCallingPackage()); + } + return ai; + } + private PackageInfo getCallingPackageInfoOrThrow(int userId) { try { PackageInfo packageInfo = mPackageManager.getPackageInfo( @@ -1548,7 +1612,7 @@ public class SettingsProvider extends ContentProvider { value = value.substring(1); Setting settingValue = getSecureSetting( - Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId); + Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId); if (settingValue == null) { return false; } @@ -1923,11 +1987,13 @@ public class SettingsProvider extends ContentProvider { // Read the user's key from the ssaid table. Setting userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY); - if (userKeySetting.isNull() || userKeySetting.getValue() == null) { + if (userKeySetting == null || userKeySetting.isNull() + || userKeySetting.getValue() == null) { // Lazy initialize and store the user key. generateUserKeyLocked(userId); userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY); - if (userKeySetting.isNull() || userKeySetting.getValue() == null) { + if (userKeySetting == null || userKeySetting.isNull() + || userKeySetting.getValue() == null) { throw new IllegalStateException("User key not accessible"); } } @@ -2165,7 +2231,7 @@ public class SettingsProvider extends ContentProvider { SettingsState settingsState = peekSettingsStateLocked(key); if (settingsState == null) { - return settingsState.getNullSetting(); + return null; } // getSettingLocked will return non-null result @@ -2999,8 +3065,13 @@ public class SettingsProvider extends ContentProvider { // user data or first boot on a new device should use new ssaid generation. if (isUpgrade) { // Retrieve the legacy ssaid from the secure settings table. - final String legacySsaid = getSettingLocked(SETTINGS_TYPE_SECURE, userId, - Settings.Secure.ANDROID_ID).getValue(); + final Setting legacySsaidSetting = getSettingLocked(SETTINGS_TYPE_SECURE, + userId, Settings.Secure.ANDROID_ID); + if (legacySsaidSetting == null || legacySsaidSetting.isNull() + || legacySsaidSetting.getValue() == null) { + throw new IllegalStateException("Legacy ssaid not accessible"); + } + final String legacySsaid = legacySsaidSetting.getValue(); // Fill each uid with the legacy ssaid to be backwards compatible. final List<PackageInfo> packages; diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index ff76c56fe94e..fede34d2ced3 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -60,6 +60,7 @@ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> <uses-permission android:name="android.permission.TETHER_PRIVILEGED" /> <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" /> + <uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" /> <uses-permission android:name="android.permission.CONTROL_VPN" /> <uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/> <!-- Physical hardware --> @@ -289,7 +290,7 @@ android:resumeWhilePausing="true" android:screenOrientation="behind" android:resizeableActivity="true" - android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden" android:theme="@style/RecentsTheme.Wallpaper"> <intent-filter> <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" /> diff --git a/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml deleted file mode 100644 index 21caab4fae18..000000000000 --- a/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml deleted file mode 100644 index 770c40149dcf..000000000000 --- a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml deleted file mode 100644 index 387ca290a1ca..000000000000 --- a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="0.3" - android:valueTo="1.0" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml deleted file mode 100644 index 770c40149dcf..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml deleted file mode 100644 index 387ca290a1ca..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="0.3" - android:valueTo="1.0" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml deleted file mode 100644 index 770c40149dcf..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml deleted file mode 100644 index 387ca290a1ca..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="0.3" - android:valueTo="1.0" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml deleted file mode 100644 index 770c40149dcf..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml deleted file mode 100644 index 387ca290a1ca..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="0.3" - android:valueTo="1.0" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_animation_root.xml deleted file mode 100644 index 72834c90f4b9..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.3" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_root.xml deleted file mode 100644 index 85573e05bc81..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_root.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="0.3" - android:valueTo="1.0" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/drawable/ic_access_alarms_small.xml b/packages/SystemUI/res/drawable/ic_access_alarms_small.xml index 994274a580f5..b94cc8e4dc12 100644 --- a/packages/SystemUI/res/drawable/ic_access_alarms_small.xml +++ b/packages/SystemUI/res/drawable/ic_access_alarms_small.xml @@ -18,9 +18,9 @@ Copyright (C) 2014 The Android Open Source Project android:height="16dp" android:viewportWidth="24.0" android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:tint="?android:attr/textColorTertiary"> <path - android:fillColor="#64ffffff" + android:fillColor="#FFFFFFFF" android:pathData="M22.0,5.7l-4.6,-3.9l-1.3,1.5l4.6,3.9L22.0,5.7zM7.9,3.4L6.6,1.9L2.0,5.7l1.3,1.5L7.9,3.4zM12.5,8.0L11.0,8.0l0.0,6.0l4.7,2.9l0.8,-1.2l-4.0,-2.4L12.5,8.0zM12.0,4.0c-5.0,0.0 -9.0,4.0 -9.0,9.0c0.0,5.0 4.0,9.0 9.0,9.0s9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0zM12.0,20.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.9 3.1,-7.0 7.0,-7.0c3.9,0.0 7.0,3.1 7.0,7.0C19.0,16.9 15.9,20.0 12.0,20.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml b/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml index 13ed767d0ca0..d7554811d2ea 100644 --- a/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml @@ -23,7 +23,4 @@ <target android:name="bar01_0" android:animation="@anim/ic_dnd_disable_bar01_0_animation" /> - <target - android:name="ic_dnd_disable" - android:animation="@anim/ic_dnd_disable_alpha_animation" /> </animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml index c0b2d69e2524..f796d62a9442 100644 --- a/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml @@ -23,7 +23,4 @@ <target android:name="outer_ring_merged" android:animation="@anim/ic_dnd_total_silence_disable_outer_ring_merged_animation" /> - <target - android:name="ic_dnd_total_silence_disable" - android:animation="@anim/ic_dnd_total_silence_disable_alpha_animation" /> </animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml b/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml index 694c23f709b2..e446a32494f8 100644 --- a/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_hotspot_disable" > <target - android:name="root" - android:animation="@anim/ic_hotspot_disable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_hotspot_disable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml b/packages/SystemUI/res/drawable/ic_hotspot_enable.xml index 31e7fe1d56ae..7a99630867f1 100644 --- a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml +++ b/packages/SystemUI/res/drawable/ic_hotspot_enable.xml @@ -16,12 +16,10 @@ --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="root" - android:alpha="0.3" android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_hotspot" android:translateX="23.97354" diff --git a/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml b/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml index c5187dd9c464..945e42fa0f14 100644 --- a/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_hotspot_enable" > <target - android:name="root" - android:animation="@anim/ic_hotspot_enable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_hotspot_enable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml index 83f46e590a1d..7641998a8cd9 100644 --- a/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml +++ b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml @@ -19,9 +19,7 @@ android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:alpha="0.25" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_hotspot" android:translateX="23.97354" diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml b/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml index 476c00d028b8..aeda0a5c3f09 100644 --- a/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_invert_colors_disable" > <target - android:name="root" - android:animation="@anim/ic_invert_colors_disable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_invert_colors_disable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml index 879066c35161..85928aca6eea 100644 --- a/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_invert_colors_enable" > <target - android:name="root" - android:animation="@anim/ic_invert_colors_enable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_invert_colors_enable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml b/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml new file mode 100644 index 000000000000..7b29740be338 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml @@ -0,0 +1,28 @@ +<!-- + Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:autoMirrored="true" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:pathData="M5,3 + l3.5,0 l0,-1.5 l7,0 l0,1.5 l3.5,0 l0,19.5 l-14,0z + M10.5,8.5 l0,3 l-3,0 l0,3 l3,0 l0,3 l3,0 l0,-3 l3,0 l0,-3 l-3,0 l0,-3 z" + android:fillColor="#FFFFFF"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml index 36eb418757df..3148a2c9c236 100644 --- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml +++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml @@ -21,6 +21,6 @@ Copyright (C) 2014 The Android Open Source Project android:tint="?android:attr/colorControlNormal"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M26.0,11.8l3.8,3.8l-3.2,3.2l2.8,2.8l6.0,-6.0L24.0,4.2l-2.0,0.0l0.0,10.1l4.0,4.0L26.0,11.8zM10.8,8.2L8.0,11.0l13.2,13.2L10.0,35.3l2.8,2.8L22.0,29.0l0.0,15.2l2.0,0.0l8.6,-8.6l4.6,4.6l2.8,-2.8L10.8,8.2zM26.0,36.5L26.0,29.0l3.8,3.8L26.0,36.5z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml index 0fdbe1f06fc7..06a088678ab4 100644 --- a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml +++ b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml @@ -17,10 +17,9 @@ Copyright (C) 2014 The Android Open Source Project android:width="64dp" android:height="64dp" android:viewportWidth="48.0" - android:viewportHeight="48.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="48.0"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml index d2e9eb2feaaa..794eb9e6bd58 100644 --- a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml +++ b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="64dp" android:height="64dp" android:viewportWidth="48.0" - android:viewportHeight="48.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="48.0"> <path android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_qs_circle.xml b/packages/SystemUI/res/drawable/ic_qs_circle.xml index 57223cff1998..990cec6db8c5 100644 --- a/packages/SystemUI/res/drawable/ic_qs_circle.xml +++ b/packages/SystemUI/res/drawable/ic_qs_circle.xml @@ -14,14 +14,13 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="64dp" - android:height="64dp" + android:width="40dp" + android:height="40dp" android:viewportWidth="2.2" android:viewportHeight="2.2"> <path - android:strokeColor="#4DFFFFFF" - android:strokeWidth=".05" + android:fillColor="#FFFFFFFF" android:pathData="M.1,1.1 c0,.55 .45,1 1,1 c.55,0 1,-.45 1,-1 diff --git a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml index d11b6f461870..439ee3bc60d0 100644 --- a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml +++ b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml @@ -14,11 +14,10 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32.0dp" - android:height="32.0dp" - android:viewportWidth="40.0" - android:viewportHeight="40.0"> + android:width="17dp" + android:height="17.0dp" + android:viewportWidth="20.0" + android:viewportHeight="20.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml index 164a5577fa42..9168dbc417f7 100644 --- a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml +++ b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml @@ -17,9 +17,7 @@ Copyright (C) 2015 The Android Open Source Project android:height="64dp" android:viewportHeight="24.0" android:viewportWidth="24.0" - android:alpha=".3" - android:width="64dp" - android:tint="?android:attr/colorControlNormal" > + android:width="64dp" > <path android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml index 7e2eca86b410..f4c20a9f823a 100644 --- a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml +++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml @@ -17,8 +17,7 @@ android:width="64dp" android:height="64dp" android:viewportWidth="48.0" - android:viewportHeight="48.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="48.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml index 5f4fa11b66ea..fb26c096f9dc 100644 --- a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml +++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml @@ -17,8 +17,7 @@ android:width="64dp" android:height="64dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_qs_minus.xml b/packages/SystemUI/res/drawable/ic_qs_minus.xml index 147a94b8a794..6a3410af2950 100644 --- a/packages/SystemUI/res/drawable/ic_qs_minus.xml +++ b/packages/SystemUI/res/drawable/ic_qs_minus.xml @@ -17,8 +17,7 @@ android:height="24.0dp" android:viewportHeight="48.0" android:viewportWidth="48.0" - android:width="24.0dp" - android:tint="?android:attr/colorControlNormal" > + android:width="24.0dp" > <path android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml index b99dc0316bf9..aaca663e59e9 100644 --- a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml +++ b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml @@ -17,12 +17,10 @@ android:width="64dp" android:height="64dp" android:viewportWidth="24" - android:viewportHeight="24" - android:alpha="0.3" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24"> <path - android:fillColor="#FFFFFF" + android:fillColor="#FFF" android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" /> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml index d875592dfd87..aaca663e59e9 100644 --- a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml +++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml @@ -17,11 +17,10 @@ android:width="64dp" android:height="64dp" android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24"> <path - android:fillColor="#FFFFFF" + android:fillColor="#FFF" android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" /> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml index 2d831b2e3e3f..69869fe9c9be 100644 --- a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml +++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml @@ -17,10 +17,9 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M19.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0l-7.0,0.0L7.7,5.3L19.0,16.7L19.0,5.0zM3.7,3.9L2.4,5.2L5.0,7.8L5.0,19.0c0.0,1.1 0.9,2.0 2.0,2.0l10.0,0.0c0.4,0.0 0.7,-0.1 1.0,-0.3l1.9,1.9l1.3,-1.3L3.7,3.9z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_plus.xml b/packages/SystemUI/res/drawable/ic_qs_plus.xml index 1f254d1ee86b..393f51c00781 100644 --- a/packages/SystemUI/res/drawable/ic_qs_plus.xml +++ b/packages/SystemUI/res/drawable/ic_qs_plus.xml @@ -17,8 +17,7 @@ android:height="24.0dp" android:viewportHeight="48.0" android:viewportWidth="48.0" - android:width="24.0dp" - android:tint="?android:attr/colorControlNormal" > + android:width="24.0dp" > <path android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml index 0673848e2862..b78d3bf1c35d 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml @@ -18,8 +18,7 @@ android:width="32.0dp" android:height="32.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" android:fillAlpha="0.3" diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml index fbf9e712e889..e055de77ebe5 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml @@ -18,8 +18,7 @@ android:width="32.0dp" android:height="32.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z" android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml index 3a5562313200..195849a932be 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="16.0dp" + android:width="32.0dp" android:height="32dp" android:viewportWidth="12.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml index e9f5a0b0a50e..8a488170e438 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml @@ -18,8 +18,7 @@ android:width="32.0dp" android:height="32.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z" android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml index 769d64891e01..39cc94cad4db 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml @@ -18,8 +18,7 @@ android:width="32.0dp" android:height="32.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" android:fillAlpha="0.3" diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml index ddd8065d7ff0..68c43074d33f 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="17.333334dp" + android:width="32dp" android:height="32dp" android:viewportWidth="13.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="13.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml index 1bec1b8aed9b..012e95e985ce 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml @@ -18,8 +18,7 @@ android:width="32.0dp" android:height="32.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml index 8e1f8eb41873..61ecc9c02a45 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="16.0dp" + android:width="32.0dp" android:height="32dp" android:viewportWidth="12.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml index e0c6b68cf618..54c52bfa4fc4 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml @@ -14,11 +14,10 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24.0dp" - android:height="24.0dp" + android:width="32.0dp" + android:height="32.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml index 1c068e5b4fb2..96e2fd4e5f82 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml @@ -17,8 +17,7 @@ android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:name="dot1" android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml index 0a85392078dc..dd5843d1183a 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml @@ -18,12 +18,11 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M21.799999,22.299999l-1.199999,-1.299999 0.000000,0.000000 -9.600000,-10.000000 0.000000,0.000000 -6.400000,-6.700000 -1.300000,1.300000 6.400000,6.700000 -8.700000,8.700000 16.900000,0.000000 2.600000,2.700001z"/> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M21.000000,1.000000l-8.600000,8.600000 8.600000,9.100000z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml index 4c904219cf14..dd0f2715fa29 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="6.6666665dp" + android:width="32dp" android:height="32dp" android:viewportWidth="5.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="5.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml index db4df7618496..326373ddc9e8 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml @@ -18,8 +18,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml index 6e5439d16d50..8baa4ebd0c26 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml @@ -18,8 +18,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml index 194edc3089ac..bf19a718e0fc 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml @@ -18,8 +18,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml index b57af5c265f3..01839e8589ef 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml @@ -18,8 +18,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml index 7d754a856ec7..48151ad78a6c 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml @@ -18,8 +18,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml index 64aadf94a582..3b47c0d20f3f 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="9.333333dp" + android:width="32dp" android:height="32dp" android:viewportWidth="7.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="7.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml index 31918a99617d..d694e6145327 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="8.0dp" + android:width="32.0dp" android:height="32dp" android:viewportWidth="6.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="6.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml index 4122b76da01a..236fdac09c4b 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="6.0dp" android:height="32dp" android:viewportWidth="6.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M6.000000,15.700000l-3.000000,5.599999 -3.000000,-5.599999z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml index 87660756989a..a381d03e272a 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="17.333334dp" + android:width="32dp" android:height="32dp" android:viewportWidth="13.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="13.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml index 5ff7d8575a77..3bed28a33609 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml @@ -14,11 +14,10 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24.0dp" - android:height="24.0dp" + android:width="32.0dp" + android:height="32.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml index 4e6500408060..c8c857c7ef0c 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml @@ -18,9 +18,8 @@ Copyright (C) 2014 The Android Open Source Project android:width="32dp" android:height="32dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M2.000000,22.000000l20.000000,0.000000L22.000000,2.000000L2.000000,22.000000zM20.000000,20.000000L6.800000,20.000000L20.000000,6.800000L20.000000,20.000000z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml index a3823ae08375..c510972a5df8 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="6.0dp" android:height="32dp" android:viewportWidth="6.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M0.000000,13.700000l3.000000,-5.700000 3.000000,5.700000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml index 2c10dc3f86ba..40bfbe694cca 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml @@ -14,11 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="8.0dp" + android:width="32.0dp" android:height="32dp" android:viewportWidth="6.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="6.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_vpn.xml b/packages/SystemUI/res/drawable/ic_qs_vpn.xml index e7ef02a29f6a..cf24e1277d6d 100644 --- a/packages/SystemUI/res/drawable/ic_qs_vpn.xml +++ b/packages/SystemUI/res/drawable/ic_qs_vpn.xml @@ -19,6 +19,6 @@ Copyright (C) 2014 The Android Open Source Project android:viewportWidth="24.0" android:viewportHeight="24.0"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M12.700000,10.000000c-0.800000,-2.300000 -3.000000,-4.000000 -5.700000,-4.000000c-3.300000,0.000000 -6.000000,2.700000 -6.000000,6.000000s2.700000,6.000000 6.000000,6.000000c2.600000,0.000000 4.800000,-1.700000 5.700000,-4.000000L17.000000,14.000000l0.000000,4.000000l4.000000,0.000000l0.000000,-4.000000l2.000000,0.000000l0.000000,-4.000000L12.700000,10.000000zM7.000000,14.000000c-1.100000,0.000000 -2.000000,-0.900000 -2.000000,-2.000000c0.000000,-1.100000 0.900000,-2.000000 2.000000,-2.000000s2.000000,0.900000 2.000000,2.000000C9.000000,13.100000 8.100000,14.000000 7.000000,14.000000z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml index fe963b153ffa..e6f929265709 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml @@ -17,8 +17,7 @@ android:width="24.0dp" android:height="24.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" android:fillAlpha="0.3" diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml index 82d2be2ea032..d423ccb2d5e2 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml @@ -17,8 +17,7 @@ android:width="24.0dp" android:height="24.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z" android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml index f30ba7620455..1982130fb1c6 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml @@ -17,8 +17,7 @@ android:width="24.0dp" android:height="24.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z" android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml index 8a17083d0148..b35011181a86 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml @@ -17,8 +17,7 @@ android:width="24.0dp" android:height="24.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml index fcd57d0b4de8..136a00435430 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml @@ -17,8 +17,7 @@ android:width="24.0dp" android:height="24.0dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml index bbff2e15ea35..bed37b1cbf1a 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml @@ -17,12 +17,11 @@ Copyright (C) 2014 The Android Open Source Project android:width="32.0dp" android:height="29.5dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M17.500000,16.500000L5.800000,3.400000c0.000000,0.000000 0.000000,0.000000 0.000000,0.000000l-2.700000,-3.000000L1.600000,1.800000l2.200000,2.500000c-2.000000,1.000000 -3.200000,2.000000 -3.400000,2.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l3.200000,-3.900000l2.400000,2.700000l1.500000,-1.400000L17.500000,16.500000L17.500000,16.500000z"/> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000c-1.900000,0.000000 -3.600000,0.300000 -5.200000,0.700000L18.700001,15.000000L25.600000,6.500000z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml index 071892a54698..2dcdb71194d1 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml @@ -17,8 +17,7 @@ android:width="26.0dp" android:height="24.0dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M21.0,8.5 diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml index c0e1037bd128..1bc743816bef 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32.0dp" android:height="29.5dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml index f6092955a35d..58561159e6a9 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32.0dp" android:height="29.5dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M13.100000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.500000,6.500000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml index f44b303d1b81..4a5e1f8fa1b1 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32.0dp" android:height="29.5dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml index 850f5b90afc3..965442d4c263 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32.0dp" android:height="29.5dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml index 8ccc1fd91968..b29d3f932b62 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml @@ -17,8 +17,7 @@ Copyright (C) 2014 The Android Open Source Project android:width="32.0dp" android:height="29.5dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml index 45cfc1c57b82..e59e7f4b61e3 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml @@ -17,9 +17,8 @@ Copyright (C) 2014 The Android Open Source Project android:width="32.0dp" android:height="29.5dp" android:viewportWidth="26.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path - android:fillColor="#4DFFFFFF" + android:fillColor="#FFFFFFFF" android:pathData="M13.000000,2.000000C7.700000,2.000000 3.700000,3.900000 0.400000,6.400000L13.000000,22.000000L25.600000,6.500000C22.299999,4.000000 18.299999,2.000000 13.000000,2.000000zM13.000000,18.600000L3.300000,7.000000l0.000000,0.000000l0.000000,0.000000C6.000000,5.300000 8.700000,4.000000 13.000000,4.000000s7.000000,1.400000 9.700000,3.000000l0.000000,0.000000l0.000000,0.000000L13.000000,18.600000z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_settings_20dp.xml b/packages/SystemUI/res/drawable/ic_settings_20dp.xml index 45ee94f55e8a..3170f86811ed 100644 --- a/packages/SystemUI/res/drawable/ic_settings_20dp.xml +++ b/packages/SystemUI/res/drawable/ic_settings_20dp.xml @@ -17,8 +17,7 @@ android:width="20dp" android:height="20dp" android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:viewportHeight="24.0"> <path android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z" android:fillColor="#ffffffff" /> diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml index 2ff0de4d5eed..09a67e1c41b5 100644 --- a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml +++ b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml @@ -20,8 +20,7 @@ android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_signal_airplane" android:translateX="21.9995" diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml index 4fe585c0954d..56ae4aa8d89b 100644 --- a/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_airplane_disable" > <target - android:name="root" - android:animation="@anim/ic_signal_airplane_disable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_signal_airplane_disable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml index 998727917b9b..b7ac0134b221 100644 --- a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml +++ b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml @@ -16,12 +16,10 @@ --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="root" - android:alpha="0.3" android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_signal_airplane" android:translateX="21.9995" diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml index d64b199f94d3..87dfba96af87 100644 --- a/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_airplane_enable" > <target - android:name="root" - android:animation="@anim/ic_signal_airplane_enable_animation_root" /> - <target android:name="ic_signal_airplane" android:animation="@anim/ic_signal_airplane_enable_animation_ic_signal_airplane" /> <target diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml index 542797a080c4..35844b72b9ec 100644 --- a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml +++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml @@ -20,8 +20,7 @@ android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_signal_flashlight" android:translateX="21.9995" diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml index 61e52876e928..e228b7ce7262 100644 --- a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_flashlight_disable" > <target - android:name="root" - android:animation="@anim/ic_signal_flashlight_disable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_signal_flashlight_disable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml index a5ba05bcfecb..c2215f12a3e9 100644 --- a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml +++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml @@ -16,12 +16,10 @@ --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="root" - android:alpha="0.3" android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_signal_flashlight" android:translateX="21.9995" diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml index 4bd9188a2fcd..220c65e0a3b2 100644 --- a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_flashlight_enable" > <target - android:name="root" - android:animation="@anim/ic_signal_flashlight_enable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_signal_flashlight_enable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml index e36f270d7560..439851d3500a 100644 --- a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml +++ b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml @@ -20,8 +20,7 @@ android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_signal_location" android:translateX="21.9995" diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml index a598b2d7e467..0e9d1cb79811 100644 --- a/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_location_disable" > <target - android:name="root" - android:animation="@anim/ic_signal_location_disable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_signal_location_disable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml index 46a72bc7e455..d4b8673e070f 100644 --- a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml +++ b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml @@ -16,12 +16,10 @@ --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="root" - android:alpha="0.3" android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" - android:tint="?android:attr/colorControlNormal" > + android:viewportWidth="48" > <group android:name="ic_signal_location" android:translateX="21.9995" diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml index 127af297819b..9f1d917536dd 100644 --- a/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_location_enable" > <target - android:name="root" - android:animation="@anim/ic_signal_location_enable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_signal_location_enable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml index a15a1271dace..9c2312686024 100644 --- a/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_workmode_disable" > <target - android:name="root" - android:animation="@anim/ic_signal_workmode_disable_animation_root" /> - <target android:name="mask" android:animation="@anim/ic_signal_workmode_disable_animation_mask" /> <target diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml index ad14505795d0..f96259480340 100644 --- a/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml +++ b/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml @@ -16,7 +16,6 @@ --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="root" - android:alpha="0.3" android:height="42dp" android:width="42dp" android:viewportHeight="42" diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml index 41d2b427d8e9..04ddfadd6d82 100644 --- a/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml +++ b/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml @@ -17,9 +17,6 @@ <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_signal_workmode_enable" > <target - android:name="root" - android:animation="@anim/ic_signal_workmode_enable_animation_root" /> - <target android:name="ic_signal_briefcase" android:animation="@anim/ic_signal_workmode_enable_animation_ic_signal_briefcase" /> <target diff --git a/packages/SystemUI/res/drawable/minor_a_b.xml b/packages/SystemUI/res/drawable/minor_a_b.xml index 0622aacd134e..4bb330cbcac5 100644 --- a/packages/SystemUI/res/drawable/minor_a_b.xml +++ b/packages/SystemUI/res/drawable/minor_a_b.xml @@ -17,12 +17,10 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="minor_a_b" - android:alpha="0.3" android:width="16dp" android:viewportWidth="16" android:height="8dp" - android:viewportHeight="8" - android:tint="?android:attr/colorControlNormal" > + android:viewportHeight="8" > <group android:name="dot_02" android:translateX="3.25" diff --git a/packages/SystemUI/res/drawable/minor_b_a.xml b/packages/SystemUI/res/drawable/minor_b_a.xml index ecb4341d915c..f61deec4b959 100644 --- a/packages/SystemUI/res/drawable/minor_b_a.xml +++ b/packages/SystemUI/res/drawable/minor_b_a.xml @@ -17,12 +17,10 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="minor_b_a" - android:alpha="0.3" android:width="16dp" android:viewportWidth="16" android:height="8dp" - android:viewportHeight="8" - android:tint="?android:attr/colorControlNormal" > + android:viewportHeight="8" > <group android:name="dot_02" android:translateX="8" diff --git a/packages/SystemUI/res/drawable/minor_b_c.xml b/packages/SystemUI/res/drawable/minor_b_c.xml index 7f59e340f0cf..867af6d5ff5b 100644 --- a/packages/SystemUI/res/drawable/minor_b_c.xml +++ b/packages/SystemUI/res/drawable/minor_b_c.xml @@ -17,12 +17,10 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="minor_b_c" - android:alpha="0.3" android:width="16dp" android:viewportWidth="16" android:height="8dp" - android:viewportHeight="8" - android:tint="?android:attr/colorControlNormal" > + android:viewportHeight="8" > <group android:name="dot_02" android:translateX="8" diff --git a/packages/SystemUI/res/drawable/minor_c_b.xml b/packages/SystemUI/res/drawable/minor_c_b.xml index 97309bcde701..b2e33cf8201a 100644 --- a/packages/SystemUI/res/drawable/minor_c_b.xml +++ b/packages/SystemUI/res/drawable/minor_c_b.xml @@ -17,12 +17,10 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="minor_c_b" - android:alpha="0.3" android:width="16dp" android:viewportWidth="16" android:height="8dp" - android:viewportHeight="8" - android:tint="?android:attr/colorControlNormal" > + android:viewportHeight="8" > <group android:name="dot_02" android:translateX="12.75" diff --git a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml b/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml new file mode 100644 index 000000000000..0b2bd22978a8 --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml @@ -0,0 +1,25 @@ +<!-- +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="24.0dp" + android:height="24.0dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M14.0,20.0l10.0,10.0 10.0,-10.0z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml index 2ac223b057fb..b7da30b03576 100644 --- a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml +++ b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml @@ -17,7 +17,8 @@ Copyright (C) 2014 The Android Open Source Project android:width="24.0dp" android:height="24.0dp" android:viewportWidth="72.0" - android:viewportHeight="72.0"> + android:viewportHeight="72.0" + android:tint="?android:attr/textColorPrimary"> <group android:translateX="52.0" android:translateY="42.0" > diff --git a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml index a85beb8b68c8..ea03a50e4460 100644 --- a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml +++ b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml @@ -15,5 +15,5 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#61FFFFFF" /> - <corners android:radius="8dp"/> + <corners android:radius="@dimen/recents_grid_task_view_rounded_corners_radius"/> </shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml b/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml index c6a2fdd089b4..1e41a31ae130 100644 --- a/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml +++ b/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml @@ -16,7 +16,6 @@ Copyright (C) 2015 The Android Open Source Project <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="27.0dp" android:height="22.0dp" - android:alpha="0.3" android:viewportWidth="27.0" android:viewportHeight="22.0"> <clip-path diff --git a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml index e85b76d3103f..46c761aaa24f 100644 --- a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml +++ b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml @@ -27,7 +27,7 @@ <LinearLayout android:id="@+id/date_time_group" android:layout_width="wrap_content" - android:layout_height="19dp" + android:layout_height="wrap_content" android:orientation="horizontal" android:focusable="true" > diff --git a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml index aaa84fd86d08..ff55f990857a 100644 --- a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml +++ b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml @@ -18,7 +18,8 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:paddingStart="8dp" android:paddingEnd="8dp" - android:paddingBottom="16dp" /> + android:paddingTop="8dp" + android:gravity="center" /> diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml index 50ee64a321b8..25d52263957b 100644 --- a/packages/SystemUI/res/layout/qs_detail.xml +++ b/packages/SystemUI/res/layout/qs_detail.xml @@ -20,10 +20,10 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/qs_detail_background" - android:paddingBottom="8dp" android:clickable="true" - android:visibility="invisible" - android:orientation="vertical"> + android:orientation="vertical" + android:paddingBottom="8dp" + android:visibility="invisible"> <com.android.systemui.ResizingSpace android:layout_width="match_parent" @@ -33,17 +33,16 @@ android:id="@+id/qs_detail_header" layout="@layout/qs_detail_header" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + /> <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/qs_detail_header_progress" - android:src="@drawable/indeterminate_anim" - android:alpha="0" - android:background="@color/qs_detail_progress_track" android:layout_width="match_parent" android:layout_height="wrap_content" - android:scaleType="fitXY" - android:translationY="8dp" + android:alpha="0" + android:background="@color/qs_detail_progress_track" + android:src="@drawable/indeterminate_anim" /> <com.android.systemui.qs.NonInterceptingScrollView @@ -51,12 +50,13 @@ android:layout_height="0dp" android:layout_weight="1" android:fillViewport="true"> + <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="match_parent"/> </com.android.systemui.qs.NonInterceptingScrollView> - <include layout="@layout/qs_detail_buttons" /> + <include layout="@layout/qs_detail_buttons"/> </com.android.systemui.qs.QSDetail> diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml index 7876ada2590d..6edf13566ad0 100644 --- a/packages/SystemUI/res/layout/qs_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_detail_item.xml @@ -29,7 +29,8 @@ android:layout_width="@dimen/qs_detail_item_icon_size" android:layout_height="@dimen/qs_detail_item_icon_size" android:layout_marginStart="@dimen/qs_detail_item_icon_marginStart" - android:layout_marginEnd="@dimen/qs_detail_item_icon_marginEnd" /> + android:layout_marginEnd="@dimen/qs_detail_item_icon_marginEnd" + android:tint="?android:attr/textColorPrimary"/> <LinearLayout android:layout_width="0dp" @@ -62,6 +63,7 @@ android:focusable="true" android:scaleType="center" android:contentDescription="@*android:string/media_route_controller_disconnect" + android:tint="?android:attr/textColorPrimary" android:src="@drawable/ic_qs_cancel" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml index 9a7e1b67ccd3..b9cdf28aa456 100644 --- a/packages/SystemUI/res/layout/qs_detail_items.xml +++ b/packages/SystemUI/res/layout/qs_detail_items.xml @@ -43,7 +43,8 @@ <ImageView android:id="@android:id/icon" android:layout_width="56dp" - android:layout_height="56dp"/> + android:layout_height="56dp" + android:tint="?android:attr/textColorSecondary" /> <TextView android:id="@android:id/title" diff --git a/packages/SystemUI/res/anim/ic_hotspot_enable_animation_root.xml b/packages/SystemUI/res/layout/qs_page_indicator.xml index 387ca290a1ca..02bd31a4c972 100644 --- a/packages/SystemUI/res/anim/ic_hotspot_enable_animation_root.xml +++ b/packages/SystemUI/res/layout/qs_page_indicator.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2014 The Android Open Source Project + 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. @@ -14,11 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. --> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="0.3" - android:valueTo="1.0" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> +<com.android.systemui.qs.PageIndicator + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/page_indicator" + android:layout_width="match_parent" + android:layout_height="48dp" + android:layout_gravity="center" + android:layout_marginTop="40dp" + android:layout_marginBottom="24dp" + android:focusable="true" + android:gravity="center" + android:importantForAccessibility="yes" + android:visibility="gone"/>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml index 8b6060f5eb8b..8ff1d1e3ba18 100644 --- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml +++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml @@ -28,15 +28,6 @@ android:layout_height="48dp" android:layout_gravity="bottom"> - <com.android.systemui.qs.PageIndicator - android:id="@+id/page_indicator" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:gravity="center" - android:importantForAccessibility="yes" - android:focusable="true" /> - </FrameLayout> </com.android.systemui.qs.PagedTileLayout> diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index 9e0a6fe4f6c5..895185bbfaac 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -26,10 +26,9 @@ <com.android.systemui.qs.QSPanel android:id="@+id/quick_settings_panel" android:background="#0000" - android:layout_marginTop="80dp" + android:layout_marginTop="52dp" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingBottom="8dp" /> + android:layout_height="wrap_content" /> <include layout="@layout/quick_status_bar_expanded_header" /> diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml index 5b0f0df47500..a093b8734dbb 100644 --- a/packages/SystemUI/res/layout/qs_tile_label.xml +++ b/packages/SystemUI/res/layout/qs_tile_label.xml @@ -18,11 +18,12 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="horizontal"> + android:orientation="horizontal" + android:paddingTop="16dp"> <TextView android:id="@+id/tile_label" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="?android:attr/textColorSecondary" + android:textColor="?android:attr/textColorPrimary" android:gravity="center_horizontal" android:minLines="2" android:padding="0dp" @@ -36,4 +37,4 @@ android:layout_marginLeft="@dimen/restricted_padlock_pading" android:scaleType="centerInside" android:visibility="gone" /> -</LinearLayout>
\ No newline at end of file +</LinearLayout> diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml index 080f553e123e..6988c765cf96 100644 --- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml +++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml @@ -17,6 +17,7 @@ xmlns:systemui="http://schemas.android.com/apk/res-auto" android:layout_height="48dp" android:layout_width="match_parent" + android:layout_marginBottom="24dp" android:paddingLeft="16dp" android:paddingRight="16dp" style="@style/BrightnessDialogContainer"> diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml index 53acb9f14ad9..4122707de740 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -23,30 +23,35 @@ android:layout_width="match_parent" android:layout_height="@dimen/status_bar_header_height" android:layout_gravity="@integer/notification_panel_layout_gravity" - android:clipChildren="false" - android:clipToPadding="false" android:baselineAligned="false" android:clickable="false" + android:clipChildren="false" + android:clipToPadding="false" + android:paddingTop="0dp" + android:paddingEnd="0dp" + android:paddingStart="0dp" > <LinearLayout android:layout_width="wrap_content" android:layout_height="48dp" - android:gravity="center" + android:layout_alignParentEnd="true" android:clipChildren="false" android:clipToPadding="false" - android:orientation="horizontal" - android:layout_alignParentEnd="true" - android:layout_marginTop="4dp" - android:layout_marginEnd="12dp"> + android:gravity="center" + android:paddingEnd="4dp" + android:orientation="horizontal"> - <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch" + <com.android.systemui.statusbar.phone.MultiUserSwitch + android:id="@+id/multi_user_switch" android:layout_width="48dp" android:layout_height="48dp" android:layout_alignParentEnd="true" - android:focusable="true" - android:background="@drawable/ripple_drawable" > - <ImageView android:id="@+id/multi_user_avatar" + android:background="@drawable/ripple_drawable" + android:focusable="true"> + + <ImageView + android:id="@+id/multi_user_avatar" android:layout_width="@dimen/multi_user_avatar_expanded_size" android:layout_height="@dimen/multi_user_avatar_expanded_size" android:layout_gravity="center" @@ -57,13 +62,42 @@ android:id="@android:id/edit" android:layout_width="48dp" android:layout_height="48dp" - android:clipToPadding="false" + android:background="?android:attr/selectableItemBackgroundBorderless" android:clickable="true" + android:clipToPadding="false" + android:contentDescription="@string/accessibility_quick_settings_edit" android:focusable="true" + android:padding="14dp" android:src="@drawable/ic_mode_edit" - android:background="?android:attr/selectableItemBackgroundBorderless" - android:contentDescription="@string/accessibility_quick_settings_edit" - android:padding="14dp" /> + android:tint="?android:attr/colorForeground"/> + + <LinearLayout + android:id="@+id/system_icons_super_container" + android:layout_width="wrap_content" + android:layout_height="@dimen/status_bar_header_height" + android:layout_alignWithParentIfMissing="true" + android:layout_toStartOf="@id/multi_user_switch" + android:background="@drawable/ripple_drawable"> + + <FrameLayout + android:id="@+id/system_icons_container" + android:layout_width="wrap_content" + android:layout_height="24dp" + android:layout_gravity="center_vertical"> + + <include layout="@layout/system_icons" /> + </FrameLayout> + + <TextView + android:id="@+id/battery_level" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginStart="@dimen/header_battery_margin_expanded" + android:importantForAccessibility="noHideDescendants" + android:textColor="?android:attr/textColorPrimary" + android:textSize="@dimen/battery_level_text_size"/> + </LinearLayout> <com.android.systemui.statusbar.AlphaOptimizedFrameLayout android:id="@+id/settings_button_container" @@ -78,16 +112,18 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/ripple_drawable" + android:contentDescription="@string/accessibility_quick_settings_settings" android:src="@drawable/ic_settings_20dp" - android:contentDescription="@string/accessibility_quick_settings_settings" /> + android:tint="?android:attr/colorForeground"/> + <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingStart="36dp" - android:alpha="0.3" - android:visibility="invisible" - android:src="@drawable/tuner" /> + android:src="@drawable/tuner" + android:tint="?android:attr/textColorTertiary" + android:visibility="invisible"/> </com.android.systemui.statusbar.AlphaOptimizedFrameLayout> @@ -106,23 +142,26 @@ <TextView android:id="@+id/header_emergency_calls_only" - android:layout_height="wrap_content" android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_alignParentTop="true" - android:paddingStart="16dp" + android:focusable="true" + android:gravity="center_vertical" android:paddingEnd="16dp" android:paddingTop="6dp" - android:visibility="gone" - android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly" - android:text="@*android:string/emergency_calls_only" android:singleLine="true" - android:gravity="center_vertical" - android:focusable="true" /> + android:text="@*android:string/emergency_calls_only" + android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly" + android:visibility="gone"/> <include android:id="@+id/date_time_alarm_group" layout="@layout/status_bar_alarm_group" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="12dp" android:layout_alignParentStart="true" android:layout_alignParentTop="true" /> @@ -130,38 +169,41 @@ android:id="@+id/quick_qs_panel" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="52dp" - android:layout_marginStart="12dp" - android:layout_marginEnd="12dp" android:layout_alignParentEnd="true" + android:layout_marginTop="54dp" + android:layout_marginBottom="24dp" + android:layout_alignParentTop="true" + android:accessibilityTraversalAfter="@+id/date_time_group" + android:accessibilityTraversalBefore="@id/expand_indicator" android:clipChildren="false" android:clipToPadding="false" - android:importantForAccessibility="yes" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" android:focusable="true" - android:accessibilityTraversalAfter="@+id/date_time_group" - android:accessibilityTraversalBefore="@id/expand_indicator" /> + android:importantForAccessibility="yes" + android:paddingTop="0dp"/> <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/qs_detail_header_progress" - android:src="@drawable/indeterminate_anim" - android:alpha="0" - android:background="@color/qs_detail_progress_track" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" + android:alpha="0" + android:background="@color/qs_detail_progress_track" + android:src="@drawable/indeterminate_anim" /> <TextView android:id="@+id/header_debug_info" - android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:fontFamily="sans-serif-condensed" + android:padding="2dp" + android:textColor="#00A040" android:textSize="11dp" android:textStyle="bold" - android:textColor="#00A040" - android:padding="2dp" + android:visibility="invisible" /> </com.android.systemui.statusbar.phone.QuickStatusBarHeader> diff --git a/packages/SystemUI/res/layout/recents_grid_task_view.xml b/packages/SystemUI/res/layout/recents_grid_task_view.xml index 53bec70bd096..1c9b9ac5f5f2 100644 --- a/packages/SystemUI/res/layout/recents_grid_task_view.xml +++ b/packages/SystemUI/res/layout/recents_grid_task_view.xml @@ -18,7 +18,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="true"> - <com.android.systemui.recents.views.TaskViewThumbnail + <com.android.systemui.recents.views.grid.GridTaskViewThumbnail android:id="@+id/task_view_thumbnail" android:layout_width="match_parent" android:layout_height="match_parent" /> diff --git a/packages/SystemUI/res/layout/split_clock_view.xml b/packages/SystemUI/res/layout/split_clock_view.xml index ae5136f2a399..8198f0333a94 100644 --- a/packages/SystemUI/res/layout/split_clock_view.xml +++ b/packages/SystemUI/res/layout/split_clock_view.xml @@ -28,6 +28,7 @@ android:singleLine="true" android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock" android:textSize="@dimen/qs_time_collapsed_size" + android:textColor="?android:attr/textColorPrimary" /> <TextClock android:id="@+id/am_pm_view" @@ -36,6 +37,7 @@ android:singleLine="true" android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock" android:textSize="@dimen/qs_time_collapsed_size" + android:textColor="?android:attr/textColorPrimary" android:importantForAccessibility="no" /> @@ -44,8 +46,9 @@ android:id="@+id/empty_time_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:visibility="invisible" + android:visibility="gone" android:singleLine="true" android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock" + android:textColor="?android:attr/textColorPrimary" /> </com.android.systemui.statusbar.policy.SplitClockView> diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 6784254796a2..63af3e0c9f30 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -42,7 +42,7 @@ <LinearLayout android:id="@+id/status_bar_contents" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingStart="@dimen/status_bar_padding_start" + android:paddingStart="6dp" android:paddingEnd="8dp" android:orientation="horizontal" > diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml index a02e9af674fa..745320e90fb6 100644 --- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml +++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml @@ -41,6 +41,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:src="@drawable/ic_access_alarms_small" + android:tint="?android:attr/textColorPrimary" android:paddingStart="6dp" android:gravity="center" android:visibility="gone" /> diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml index ca4f7278a5ae..2b4a0f59195e 100644 --- a/packages/SystemUI/res/layout/zen_mode_condition.xml +++ b/packages/SystemUI/res/layout/zen_mode_condition.xml @@ -63,6 +63,7 @@ android:scaleType="center" android:layout_toStartOf="@android:id/button2" android:contentDescription="@string/accessibility_quick_settings_less_time" + android:tint="?android:attr/textColorPrimary" android:src="@drawable/ic_qs_minus" /> <ImageView @@ -75,6 +76,7 @@ android:scaleType="center" android:layout_centerVertical="true" android:contentDescription="@string/accessibility_quick_settings_more_time" + android:tint="?android:attr/textColorPrimary" android:src="@drawable/ic_qs_plus" /> </RelativeLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index a2298663740e..7fb513cda395 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -40,8 +40,9 @@ <attr name="decayTime" format="integer" /> <attr name="orientation" /> </declare-styleable> + <attr name="frameColor" format="color" /> <declare-styleable name="BatteryMeterView"> - <attr name="frameColor" format="color" /> + <attr name="frameColor" /> </declare-styleable> <declare-styleable name="Clock"> <attr name="amPmStyle" format="enum"> @@ -60,7 +61,7 @@ <attr name="framePadding" format="dimension" /> <!-- {@deprecated Use a statelist in frameColor instead.} --> <attr name="activeFrameColor" format="color" /> - <attr name="frameColor" format="color" /> + <attr name="frameColor" /> <attr name="badgeDiameter" format="dimension" /> <attr name="badgeMargin" format="dimension" /> </declare-styleable> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 50ef392fe0f1..ac86439665b3 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -297,4 +297,11 @@ If < 0, uses the value from HardwarePropertiesManager#getDeviceTemperatures. --> <integer name="config_warningTemperature">-1</integer> + <!-- Accessibility actions --> + <item type="id" name="action_split_task_to_left" /> + <item type="id" name="action_split_task_to_right" /> + <item type="id" name="action_split_task_to_top" /> + <item type="id" name="action_open" /> + <item type="id" name="action_dimiss" /> + </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 6ffdbcb9380e..79529a7abcbc 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -164,7 +164,7 @@ <dimen name="close_handle_underlap">32dp</dimen> <!-- Height of the status bar header bar --> - <dimen name="status_bar_header_height">104dp</dimen> + <dimen name="status_bar_header_height">126dp</dimen> <!-- Height of the status bar header bar when expanded --> <dimen name="status_bar_header_height_expanded">116dp</dimen> @@ -204,8 +204,8 @@ <!-- The size of the gesture span needed to activate the "pull" notification expansion --> <dimen name="pull_span_min">25dp</dimen> - <dimen name="qs_tile_height">88dp</dimen> - <dimen name="qs_tile_margin">16dp</dimen> + <dimen name="qs_tile_height">80dp</dimen> + <dimen name="qs_tile_margin">36dp</dimen> <dimen name="qs_tile_margin_top">16dp</dimen> <dimen name="qs_quick_tile_size">48dp</dimen> <dimen name="qs_quick_tile_padding">12dp</dimen> @@ -421,7 +421,7 @@ <dimen name="qs_time_collapsed_size">14sp</dimen> <!-- The font size of the time when expanded in QS --> - <dimen name="qs_time_expanded_size">20sp</dimen> + <dimen name="qs_time_expanded_size">14sp</dimen> <!-- The font size of the "emergency calls only" label in QS --> <dimen name="qs_emergency_calls_only_text_size">12sp</dimen> diff --git a/packages/SystemUI/res/values/dimens_grid.xml b/packages/SystemUI/res/values/dimens_grid.xml index 0b9836ffcebb..5858443f6d8d 100644 --- a/packages/SystemUI/res/values/dimens_grid.xml +++ b/packages/SystemUI/res/values/dimens_grid.xml @@ -22,5 +22,6 @@ <dimen name="recents_grid_task_view_header_height">44dp</dimen> <dimen name="recents_grid_task_view_header_button_padding">8dp</dimen> <dimen name="recents_grid_task_view_focused_frame_thickness">8dp</dimen> + <dimen name="recents_grid_task_view_rounded_corners_radius">8dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index a17430a4da46..422431e7b31a 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -794,6 +794,16 @@ <string name="recents_multistack_add_stack_dialog_split_vertical">Split Vertical</string> <!-- Recents: MultiStack add stack split custom radio button. [CHAR LIMIT=NONE] --> <string name="recents_multistack_add_stack_dialog_split_custom">Split Custom</string> + <!-- Recents: Accessibility dismiss label --> + <string name="recents_accessibility_dismissed">Dismiss</string> + <!-- Recents: Accessibility open label --> + <string name="recents_accessibility_open">Open</string> + <!-- Recents: Accessibility split to the top --> + <string name="recents_accessibility_split_screen_top">Split screen to the top</string> + <!-- Recents: Accessibility split to the left --> + <string name="recents_accessibility_split_screen_left">Split screen to the left</string> + <!-- Recents: Accessibility split to the right --> + <string name="recents_accessibility_split_screen_right">Split screen to the right</string> <!-- Fully qualified activity class names to be blacklisted in Recents, add package names into overlay as needed --> <string-array name="recents_blacklist_array"> @@ -1022,10 +1032,10 @@ <string name="monitoring_title">Network monitoring</string> <!-- STOPSHIP Monitoring strings still need to be finalized and approved --> - <!-- Monitoring dialog subtitle for the section describing VPN [CHAR LIMIT=TODO]--> + <!-- Monitoring dialog subtitle for the section describing VPN [CHAR LIMIT=35]--> <string name="monitoring_subtitle_vpn">VPN</string> - <!-- Monitoring dialog subtitle for the section describing network logging [CHAR LIMIT=TODO]--> + <!-- Monitoring dialog subtitle for the section describing network logging [CHAR LIMIT=35]--> <string name="monitoring_subtitle_network_logging">Network Logging</string> <!-- Monitoring dialog disable vpn button [CHAR LIMIT=30] --> @@ -1041,7 +1051,7 @@ <string name="monitoring_description_do_header_with_name"><xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> uses <xliff:g id="device_owner_app" example="Google Mobile Management">%2$s</xliff:g> to manage your device.</string> <!-- Monitoring dialog: Part of text body explaining what a Device Owner app can do [CHAR LIMIT=130] --> - <string name="monitoring_description_do_body">Your administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.</string> + <string name="monitoring_description_do_body">Your admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.</string> <!-- Monitoring dialog: Space that separates the body text and the "learn more" link that follows it. [CHAR LIMIT=5] --> <string name="monitoring_description_do_learn_more_separator">" "</string> @@ -1055,18 +1065,18 @@ <!-- Monitoring dialog: Space that separates the VPN body text and the "Open VPN Settings" link that follows it. [CHAR LIMIT=5] --> <string name="monitoring_description_vpn_settings_separator">" "</string> - <!-- Monitoring dialog: Link to open the VPN settings page [CHAR LIMIT=TODO] --> + <!-- Monitoring dialog: Link to open the VPN settings page [CHAR LIMIT=60] --> <string name="monitoring_description_vpn_settings">Open VPN Settings</string> - <!-- Monitoring dialog: Network logging text [CHAR LIMIT=TODO] --> - <string name="monitoring_description_network_logging">Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information contact your admin.</string> + <!-- Monitoring dialog: Network logging text [CHAR LIMIT=400] --> + <string name="monitoring_description_network_logging">Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin.</string> <!-- Monitoring dialog VPN text [CHAR LIMIT=400] --> <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps, and websites.</string> <!-- Monitoring dialog VPN with profile owner text [CHAR LIMIT=400] --> - <string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your administrator.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string> + <string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string> <!-- Name for a generic legacy VPN connection [CHAR LIMIT=20] --> <string name="legacy_vpn_name">VPN</string> @@ -1081,7 +1091,7 @@ <string name="branded_monitoring_description_app_personal">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps, and websites.</string> <!-- Monitoring dialog text for single app (inside work profile) [CHAR LIMIT=400] --> - <string name="monitoring_description_app_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string> + <string name="monitoring_description_app_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nFor more information, contact your admin.</string> <!-- Monitoring dialog text for multiple apps (in personal and work profiles) [CHAR LIMIT=400] --> <string name="monitoring_description_app_personal_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nYou\'re also connected to <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network activity.</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index a9c858c0e721..6535a81d076b 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -93,37 +93,34 @@ <item name="android:textColor">#FF808080</item> </style> - <style name="TextAppearance.StatusBar.TextButton" - parent="@*android:style/TextAppearance.StatusBar"> - <item name="android:textAppearance">?android:attr/textAppearance</item> - <item name="android:textStyle">normal</item> - <item name="android:textColor">#FFFFFFFF</item> - </style> - <style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon"> <item name="android:textSize">@dimen/status_bar_clock_size</item> <item name="android:fontFamily">sans-serif-medium</item> <item name="android:textColor">@color/status_bar_clock_color</item> </style> - <style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar" /> + <style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar"> + <item name="android:textColor">?android:attr/textColorTertiary</item> + </style> <style name="TextAppearance.StatusBar.Expanded.Clock"> <item name="android:textSize">@dimen/qs_time_expanded_size</item> - <item name="android:fontFamily">sans-serif-medium</item> + <item name="android:fontFamily">sans-serif-condensed</item> <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textStyle">normal</item> </style> <style name="TextAppearance.StatusBar.Expanded.Date"> <item name="android:textSize">@dimen/qs_date_collapsed_size</item> <item name="android:textStyle">normal</item> <item name="android:textColor">?android:attr/textColorSecondary</item> + <item name="android:fontFamily">sans-serif-condensed</item> </style> <style name="TextAppearance.StatusBar.Expanded.AboveDateTime"> <item name="android:textSize">@dimen/qs_emergency_calls_only_text_size</item> <item name="android:textStyle">normal</item> - <item name="android:textColor">?android:attr/textColorSecondary</item> + <item name="android:textColor">?android:attr/textColorTertiary</item> </style> <style name="TextAppearance.StatusBar.Expanded.EmergencyCallsOnly" @@ -135,7 +132,7 @@ <style name="TextAppearance.StatusBar.Expanded.UserSwitcher"> <item name="android:textSize">16sp</item> <item name="android:textStyle">normal</item> - <item name="android:textColor">@color/qs_user_detail_name</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> </style> <style name="TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" /> @@ -172,7 +169,7 @@ <style name="TextAppearance.QS.DetailButton"> <item name="android:textSize">@dimen/qs_detail_button_text_size</item> - <item name="android:textColor">@color/qs_detail_button</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> <item name="android:textAllCaps">true</item> <item name="android:fontFamily">sans-serif-medium</item> <item name="android:gravity">center</item> @@ -184,7 +181,7 @@ <style name="TextAppearance.QS.DetailEmpty"> <item name="android:textSize">@dimen/qs_detail_empty_text_size</item> - <item name="android:textColor">@color/qs_subhead</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> </style> <style name="TextAppearance.QS.Subhead"> diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java index 07ef5e09fc58..5a6afca627ec 100755 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java @@ -292,12 +292,16 @@ public class BatteryMeterDrawable extends Drawable implements } int backgroundColor = getBackgroundColor(darkIntensity); int fillColor = getFillColor(darkIntensity); + setColors(fillColor, backgroundColor); + mOldDarkIntensity = darkIntensity; + } + + public void setColors(int fillColor, int backgroundColor) { mIconTint = fillColor; mFramePaint.setColor(backgroundColor); mBoltPaint.setColor(fillColor); mChargeColor = fillColor; invalidateSelf(); - mOldDarkIntensity = darkIntensity; } private int getBackgroundColor(float darkIntensity) { diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index ef1c25dc2d97..030250ae3b58 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -72,8 +72,6 @@ public class BatteryMeterView extends ImageView implements @Override public void onAttachedToWindow() { super.onAttachedToWindow(); - mBatteryController.addCallback(this); - mDrawable.startListening(); TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST); } @@ -100,9 +98,15 @@ public class BatteryMeterView extends ImageView implements public void setBatteryController(BatteryController mBatteryController) { this.mBatteryController = mBatteryController; mDrawable.setBatteryController(mBatteryController); + mBatteryController.addCallback(this); + mDrawable.startListening(); } public void setDarkIntensity(float f) { mDrawable.setDarkIntensity(f); } + + public void setRawColors(int fgColor, int bgColor) { + mDrawable.setColors(fgColor, bgColor); + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java index 63d1cc246a53..c7514a90dce3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java @@ -91,10 +91,6 @@ public class WorkLockActivity extends Activity { // Draw captions overlaid on the content view, so the whole window is one solid color. setOverlayWithDecorCaptionEnabled(true); - // Match task description to the task stack we are replacing so it's still recognizably the - // original task stack with the same icon and title text. - setTaskDescription(new TaskDescription(null, null, color)); - // Blank out the activity. When it is on-screen it will look like a Recents thumbnail with // redaction switched on. final View blankView = new View(this); @@ -127,6 +123,11 @@ public class WorkLockActivity extends Activity { return; } + @Override + public void setTaskDescription(TaskDescription taskDescription) { + // Use the previous activity's task description. + } + private final BroadcastReceiver mLockEventReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java index 728d558c03b1..978890301f44 100644 --- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java +++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java @@ -22,6 +22,7 @@ import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; +import android.media.PlayerBase; import android.net.Uri; import android.os.Looper; import android.os.PowerManager; @@ -81,6 +82,12 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener (AudioManager) mCmd.context.getSystemService(Context.AUDIO_SERVICE); try { MediaPlayer player = new MediaPlayer(); + if (mCmd.attributes == null) { + mCmd.attributes = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_NOTIFICATION) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build(); + } player.setAudioAttributes(mCmd.attributes); player.setDataSource(mCmd.context, mCmd.uri); player.setLooping(mCmd.looping); @@ -92,13 +99,11 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener if (mAudioManagerWithAudioFocus == null) { if (mDebug) Log.d(mTag, "requesting AudioFocus"); if (mCmd.looping) { - audioManager.requestAudioFocus(null, - AudioAttributes.toLegacyStreamType(mCmd.attributes), - AudioManager.AUDIOFOCUS_GAIN); + audioManager.requestAudioFocus(null, mCmd.attributes, + AudioManager.AUDIOFOCUS_GAIN, 0); } else { - audioManager.requestAudioFocus(null, - AudioAttributes.toLegacyStreamType(mCmd.attributes), - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); + audioManager.requestAudioFocus(null, mCmd.attributes, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); } mAudioManagerWithAudioFocus = audioManager; } else { @@ -296,6 +301,7 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener */ @Deprecated public void play(Context context, Uri uri, boolean looping, int stream) { + PlayerBase.deprecateStreamTypeForPlayback(stream, "NotificationPlayer", "play"); Command cmd = new Command(); cmd.requestTime = SystemClock.uptimeMillis(); cmd.code = PLAY; diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index a2d7d6be04e6..3103267344a5 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -16,14 +16,20 @@ package com.android.systemui.pip.phone; +import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.view.Display.DEFAULT_DISPLAY; import android.app.ActivityManager; +import android.app.ActivityManager.StackInfo; +import android.app.ActivityOptions; import android.app.IActivityManager; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.pm.ParceledListSlice; import android.os.Handler; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import android.view.IPinnedStackController; import android.view.IPinnedStackListener; @@ -49,6 +55,7 @@ public class PipManager { private final PinnedStackListener mPinnedStackListener = new PinnedStackListener(); private PipMenuActivityController mMenuController; + private PipMediaController mMediaController; private PipTouchHandler mTouchHandler; /** @@ -57,7 +64,11 @@ public class PipManager { TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onActivityPinned() { + if (!checkCurrentUserId(false /* debug */)) { + return; + } mTouchHandler.onActivityPinned(); + mMediaController.onActivityPinned(); } @Override @@ -66,8 +77,24 @@ public class PipManager { } @Override - public void onPinnedActivityRestartAttempt() { - // TODO(winsonc): Hide the menu and expand the PiP + public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) { + if (!checkCurrentUserId(false /* debug */)) { + return; + } + + // Expand the activity back to fullscreen only if it was attempted to be restarted from + // another package than the top activity in the stack + boolean expandPipToFullscreen = true; + if (sourceComponent != null) { + ComponentName topActivity = PipUtils.getTopPinnedActivity(mActivityManager); + expandPipToFullscreen = topActivity != null && topActivity.getPackageName().equals( + sourceComponent.getPackageName()); + } + if (expandPipToFullscreen) { + mTouchHandler.expandPinnedStackToFullscreen(); + } else { + Log.w(TAG, "Can not expand PiP to fullscreen via intent from the same package."); + } } }; @@ -91,7 +118,7 @@ public class PipManager { @Override public void onActionsChanged(ParceledListSlice actions) { mHandler.post(() -> { - mMenuController.setActions(actions); + mMenuController.setAppActions(actions); }); } @@ -127,7 +154,9 @@ public class PipManager { } SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener); - mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager); + mMediaController = new PipMediaController(context, mActivityManager); + mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager, + mMediaController); mTouchHandler = new PipTouchHandler(context, mMenuController, mActivityManager, mWindowManager); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java new file mode 100644 index 000000000000..22840138e152 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.pip.phone; + +import android.app.IActivityManager; +import android.app.RemoteAction; +import android.content.ComponentName; +import android.content.Context; +import android.graphics.drawable.Icon; +import android.media.session.MediaController; +import android.media.session.MediaController.TransportControls; +import android.media.session.MediaSession; +import android.media.session.MediaSessionManager; +import android.media.session.PlaybackState; + +import com.android.systemui.R; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Interfaces with the {@link MediaSessionManager} to compose the right set of actions to show (only + * if there are no actions from the PiP activity itself). The active media controller is only set + * when there is a media session from the top PiP activity. + */ +public class PipMediaController { + + /** + * A listener interface to receive notification on changes to the media actions. + */ + public interface ActionListener { + /** + * Called when the media actions changes. + */ + void onMediaActionsChanged(List<RemoteAction> actions); + } + + private final Context mContext; + private final IActivityManager mActivityManager; + + private final MediaSessionManager mMediaSessionManager; + private MediaController mMediaController; + + private RemoteAction mPauseAction; + private RemoteAction mPlayAction; + + private MediaController.Callback mPlaybackChangedListener = new MediaController.Callback() { + @Override + public void onPlaybackStateChanged(PlaybackState state) { + if (!mListeners.isEmpty()) { + notifyActionsChanged(getMediaActions()); + } + } + }; + + private ArrayList<ActionListener> mListeners = new ArrayList<>(); + + public PipMediaController(Context context, IActivityManager activityManager) { + mContext = context; + mActivityManager = activityManager; + + createMediaActions(); + mMediaSessionManager = + (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE); + mMediaSessionManager.addOnActiveSessionsChangedListener(controllers -> { + resolveActiveMediaController(controllers); + }, null); + } + + /** + * Handles when an activity is pinned. + */ + public void onActivityPinned() { + // Once we enter PiP, try to find the active media controller for the top most activity + resolveActiveMediaController(mMediaSessionManager.getActiveSessions(null)); + } + + /** + * Adds a new media action listener. + */ + public void addListener(ActionListener listener) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + listener.onMediaActionsChanged(getMediaActions()); + } + } + + /** + * Removes a media action listener. + */ + public void removeListener(ActionListener listener) { + listener.onMediaActionsChanged(Collections.EMPTY_LIST); + mListeners.remove(listener); + } + + /** + * Gets the set of media actions currently available. + */ + private List<RemoteAction> getMediaActions() { + if (mMediaController == null || mMediaController.getPlaybackState() == null) { + return Collections.EMPTY_LIST; + } + + ArrayList<RemoteAction> mediaActions = new ArrayList<>(); + int state = mMediaController.getPlaybackState().getState(); + boolean isPlaying = MediaSession.isActiveState(state); + long actions = mMediaController.getPlaybackState().getActions(); + if (!isPlaying && ((actions & PlaybackState.ACTION_PLAY) != 0)) { + mediaActions.add(mPauseAction); + } else if (isPlaying && ((actions & PlaybackState.ACTION_PAUSE) != 0)) { + mediaActions.add(mPlayAction); + } + return mediaActions; + } + + /** + * Creates the standard media buttons that we may show. + */ + private void createMediaActions() { + String pauseDescription = mContext.getString(R.string.pip_pause); + mPauseAction = new RemoteAction(Icon.createWithResource(mContext, + R.drawable.ic_pause_white_24dp), pauseDescription, pauseDescription, + action -> mMediaController.getTransportControls().pause()); + + String playDescription = mContext.getString(R.string.pip_play); + mPlayAction = new RemoteAction(Icon.createWithResource(mContext, + R.drawable.ic_play_arrow_white_24dp), playDescription, playDescription, + action -> mMediaController.getTransportControls().play()); + } + + /** + * Tries to find and set the active media controller for the top PiP activity. + */ + private void resolveActiveMediaController(List<MediaController> controllers) { + if (controllers != null) { + final ComponentName topActivity = PipUtils.getTopPinnedActivity(mActivityManager); + if (topActivity != null) { + for (int i = 0; i < controllers.size(); i++) { + final MediaController controller = controllers.get(i); + if (controller.getPackageName().equals(topActivity.getPackageName())) { + setActiveMediaController(controller); + return; + } + } + } + } + setActiveMediaController(null); + } + + /** + * Sets the active media controller for the top PiP activity. + */ + private void setActiveMediaController(MediaController controller) { + if (controller != mMediaController) { + if (mMediaController != null) { + mMediaController.unregisterCallback(mPlaybackChangedListener); + } + mMediaController = controller; + if (controller != null) { + controller.registerCallback(mPlaybackChangedListener); + } + if (!mListeners.isEmpty()) { + notifyActionsChanged(getMediaActions()); + } + + // TODO(winsonc): Consider if we want to close the PIP after a timeout (like on TV) + } + } + + /** + * Notifies all listeners that the actions have changed. + */ + private void notifyActionsChanged(List<RemoteAction> actions) { + if (!mListeners.isEmpty()) { + mListeners.forEach(l -> l.onMediaActionsChanged(actions)); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java index 0f7647dbfd8b..6ef30c0258c6 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java @@ -1,3 +1,19 @@ +/* + * 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.pip.phone; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; @@ -5,6 +21,7 @@ import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import android.app.ActivityManager.StackInfo; import android.app.ActivityOptions; import android.app.IActivityManager; +import android.app.RemoteAction; import android.content.Context; import android.content.Intent; import android.content.pm.ParceledListSlice; @@ -16,11 +33,20 @@ import android.os.UserHandle; import android.util.Log; import android.view.IWindowManager; +import com.android.systemui.pip.phone.PipMediaController.ActionListener; + import java.util.ArrayList; +import java.util.List; +/** + * Manages the PiP menu activity. + * + * The current media session provides actions whenever there are no valid actions provided by the + * current PiP activity. Otherwise, those actions always take precedence. + */ public class PipMenuActivityController { - private static final String TAG = "PipMenuActivityController"; + private static final String TAG = "PipMenuActController"; public static final String EXTRA_CONTROLLER_MESSENGER = "messenger"; public static final String EXTRA_ACTIONS = "actions"; @@ -59,9 +85,12 @@ public class PipMenuActivityController { private Context mContext; private IActivityManager mActivityManager; private IWindowManager mWindowManager; + private PipMediaController mMediaController; private ArrayList<Listener> mListeners = new ArrayList<>(); - private ParceledListSlice mActions; + private ParceledListSlice mAppActions; + private ParceledListSlice mMediaActions; + private boolean mVisible; private Messenger mToActivityMessenger; private Messenger mMessenger = new Messenger(new Handler() { @@ -70,13 +99,13 @@ public class PipMenuActivityController { switch (msg.what) { case MESSAGE_MENU_VISIBILITY_CHANGED: { boolean visible = msg.arg1 > 0; - mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible)); + onMenuVisibilityChanged(visible); break; } case MESSAGE_EXPAND_PIP: { mListeners.forEach(l -> l.onPipExpand()); // Preemptively mark the menu as invisible once we expand the PiP - mListeners.forEach(l -> l.onPipMenuVisibilityChanged(false)); + onMenuVisibilityChanged(false); break; } case MESSAGE_MINIMIZE_PIP: { @@ -86,14 +115,14 @@ public class PipMenuActivityController { case MESSAGE_DISMISS_PIP: { mListeners.forEach(l -> l.onPipDismiss()); // Preemptively mark the menu as invisible once we dismiss the PiP - mListeners.forEach(l -> l.onPipMenuVisibilityChanged(false)); + onMenuVisibilityChanged(false); break; } case MESSAGE_UPDATE_ACTIVITY_CALLBACK: { mToActivityMessenger = msg.replyTo; // Mark the menu as invisible once the activity finishes as well if (mToActivityMessenger == null) { - mListeners.forEach(l -> l.onPipMenuVisibilityChanged(false)); + onMenuVisibilityChanged(false); } break; } @@ -101,11 +130,20 @@ public class PipMenuActivityController { } }); + private ActionListener mMediaActionListener = new ActionListener() { + @Override + public void onMediaActionsChanged(List<RemoteAction> mediaActions) { + mMediaActions = new ParceledListSlice<>(mediaActions); + updateMenuActions(); + } + }; + public PipMenuActivityController(Context context, IActivityManager activityManager, - IWindowManager windowManager) { + IWindowManager windowManager, PipMediaController mediaController) { mContext = context; mActivityManager = activityManager; mWindowManager = windowManager; + mMediaController = mediaController; } /** @@ -137,7 +175,7 @@ public class PipMenuActivityController { pinnedStackInfo.taskIds.length > 0) { Intent intent = new Intent(mContext, PipMenuActivity.class); intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger); - intent.putExtra(EXTRA_ACTIONS, mActions); + intent.putExtra(EXTRA_ACTIONS, resolveMenuActions()); ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); options.setLaunchTaskId( pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); @@ -168,15 +206,31 @@ public class PipMenuActivityController { } /** - * Sets the {@param actions} associated with the PiP. + * Sets the menu actions to the actions provided by the current PiP activity. + */ + public void setAppActions(ParceledListSlice appActions) { + mAppActions = appActions; + updateMenuActions(); + } + + /** + * @return the best set of actions to show in the PiP menu. */ - public void setActions(ParceledListSlice actions) { - mActions = actions; + private ParceledListSlice resolveMenuActions() { + if (isValidActions(mAppActions)) { + return mAppActions; + } + return mMediaActions; + } + /** + * Updates the PiP menu activity with the best set of actions provided. + */ + private void updateMenuActions() { if (mToActivityMessenger != null) { Message m = Message.obtain(); m.what = PipMenuActivity.MESSAGE_UPDATE_ACTIONS; - m.obj = actions; + m.obj = resolveMenuActions(); try { mToActivityMessenger.send(m); } catch (RemoteException e) { @@ -184,4 +238,30 @@ public class PipMenuActivityController { } } } + + /** + * Returns whether the set of actions are valid. + */ + private boolean isValidActions(ParceledListSlice actions) { + return actions != null && actions.getList().size() > 0; + } + + /** + * Handles changes in menu visibility. + */ + private void onMenuVisibilityChanged(boolean visible) { + mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible)); + if (visible != mVisible) { + if (visible) { + // Once visible, start listening for media action changes. This call will trigger + // the menu actions to be updated again. + mMediaController.addListener(mMediaActionListener); + } else { + // Once hidden, stop listening for media action changes. This call will trigger + // the menu actions to be updated again. + mMediaController.removeListener(mMediaActionListener); + } + } + mVisible = visible; + } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 1476110384fb..12fda14b3ce2 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -487,7 +487,7 @@ public class PipTouchHandler implements TunerService.Tunable { /** * Resizes the pinned stack back to fullscreen. */ - private void expandPinnedStackToFullscreen() { + void expandPinnedStackToFullscreen() { BackgroundThread.getHandler().post(() -> { try { mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */, diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java new file mode 100644 index 000000000000..9c03830810aa --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.pip.phone; + +import static android.app.ActivityManager.StackId.PINNED_STACK_ID; + +import android.app.ActivityManager.StackInfo; +import android.app.IActivityManager; +import android.content.ComponentName; +import android.os.RemoteException; +import android.util.Log; + +public class PipUtils { + + private static final String TAG = "PipUtils"; + + /** + * @return the ComponentName of the top activity in the pinned stack, or null if none exists. + */ + public static ComponentName getTopPinnedActivity(IActivityManager activityManager) { + try { + StackInfo pinnedStackInfo = activityManager.getStackInfo(PINNED_STACK_ID); + if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null && + pinnedStackInfo.taskIds.length > 0) { + return pinnedStackInfo.topActivity; + } + } catch (RemoteException e) { + Log.w(TAG, "Unable to get pinned stack."); + } + return null; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index a6226565c4f9..56947e5b6231 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -590,7 +590,7 @@ public class PipManager { @Override public void onTaskStackChanged() { if (DEBUG) Log.d(TAG, "onTaskStackChanged()"); - if (!checkCurrentUserId()) { + if (!checkCurrentUserId(DEBUG)) { return; } if (mState != STATE_NO_PIP) { @@ -627,7 +627,7 @@ public class PipManager { @Override public void onActivityPinned() { if (DEBUG) Log.d(TAG, "onActivityPinned()"); - if (!checkCurrentUserId()) { + if (!checkCurrentUserId(DEBUG)) { return; } StackInfo stackInfo = getPinnedStackInfo(); @@ -658,9 +658,9 @@ public class PipManager { } @Override - public void onPinnedActivityRestartAttempt() { + public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) { if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()"); - if (!checkCurrentUserId()) { + if (!checkCurrentUserId(DEBUG)) { return; } // If PIPed activity is launched again by Launcher or intent, make it fullscreen. @@ -670,7 +670,7 @@ public class PipManager { @Override public void onPinnedStackAnimationEnded() { if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()"); - if (!checkCurrentUserId()) { + if (!checkCurrentUserId(DEBUG)) { return; } switch (mState) { @@ -693,26 +693,6 @@ public class PipManager { break; } } - - // {@link android.app.ITaskStackListener} isn't multi-user aware. - // Check the current uid and current SystemUI's running uid - // so we can handle the PIP status change only once. - private boolean checkCurrentUserId() { - try { - int processUserId = UserHandle.myUserId(); - int currentUserId = mActivityManager.getCurrentUser().id; - if (processUserId != currentUserId) { - if (DEBUG) { - Log.d(TAG, "UID mismatch. SystemUI is running uid=" + processUserId - + " and the current user is uid=" + currentUserId); - } - return false; - } - } catch (RemoteException e) { - Log.w(TAG, "Unable to get current user."); - } - return true; - } }; /** diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java index 26da551e8222..b22ea4c81f17 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java @@ -1,9 +1,12 @@ package com.android.systemui.qs; import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; import android.graphics.drawable.AnimatedVectorDrawable; import android.util.AttributeSet; import android.util.Log; +import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -49,9 +52,14 @@ public class PageIndicator extends ViewGroup { while (numPages < getChildCount()) { removeViewAt(getChildCount() - 1); } + TypedArray array = getContext().obtainStyledAttributes( + new int[]{android.R.attr.colorForeground}); + int color = array.getColor(0, 0); + array.recycle(); while (numPages > getChildCount()) { ImageView v = new ImageView(mContext); v.setImageResource(R.drawable.minor_a_b); + v.setImageTintList(ColorStateList.valueOf(color)); addView(v, new LayoutParams(mPageIndicatorWidth, mPageIndicatorHeight)); } // Refresh state. @@ -196,7 +204,7 @@ public class PageIndicator extends ViewGroup { for (int i = 0; i < N; i++) { getChildAt(i).measure(widthChildSpec, heightChildSpec); } - int width = (mPageIndicatorWidth - mPageDotWidth) * N + mPageDotWidth; + int width = (mPageIndicatorWidth - mPageDotWidth) * (N - 1) + mPageDotWidth; setMeasuredDimension(width, mPageIndicatorHeight); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index 1c242e9b6092..a231e791e3b0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -29,7 +29,6 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { private PageIndicator mPageIndicator; private int mNumPages; - private View mDecorGroup; private PageListener mPageListener; private int mPosition; @@ -145,14 +144,14 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); - mPageIndicator = (PageIndicator) findViewById(R.id.page_indicator); - mDecorGroup = findViewById(R.id.page_decor); - ((LayoutParams) mDecorGroup.getLayoutParams()).isDecor = true; - - mPages.add((TilePage) LayoutInflater.from(mContext) + mPages.add((TilePage) LayoutInflater.from(getContext()) .inflate(R.layout.qs_paged_page, this, false)); } + public void setPageIndicator(PageIndicator indicator) { + mPageIndicator = indicator; + } + @Override public int getOffsetTop(TileRecord tile) { final ViewGroup parent = (ViewGroup) tile.tileView.getParent(); @@ -196,7 +195,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { if (++index == mPages.size()) { if (DEBUG) Log.d(TAG, "Adding page for " + tile.tile.getClass().getSimpleName()); - mPages.add((TilePage) LayoutInflater.from(mContext) + mPages.add((TilePage) LayoutInflater.from(getContext()) .inflate(R.layout.qs_paged_page, this, false)); } } @@ -211,7 +210,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } if (DEBUG) Log.d(TAG, "Size: " + mNumPages); mPageIndicator.setNumPages(mNumPages); - mDecorGroup.setVisibility(mNumPages > 1 ? View.VISIBLE : View.GONE); + mPageIndicator.setVisibility(mNumPages > 1 ? View.VISIBLE : View.GONE); setAdapter(mAdapter); mAdapter.notifyDataSetChanged(); setCurrentItem(0, false); @@ -243,8 +242,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { maxHeight = height; } } - setMeasuredDimension(getMeasuredWidth(), maxHeight - + (mDecorGroup.getVisibility() != View.GONE ? mDecorGroup.getMeasuredHeight() : 0)); + setMeasuredDimension(getMeasuredWidth(), maxHeight); } private final Runnable mDistribute = new Runnable() { @@ -265,7 +263,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { public TilePage(Context context, AttributeSet attrs) { super(context, attrs); updateResources(); - setContentDescription(mContext.getString(R.string.accessibility_desc_quick_settings)); + setContentDescription(getContext().getString(R.string.accessibility_desc_quick_settings)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index fdefcf91da6d..409943d46926 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -194,6 +194,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha translationYBuilder.addFloat(label, "translationY", -yDiff, 0); mTopFiveQs.add(tileIcon); + mTopFiveQs.add(tileView.getBgCicle()); mAllViews.add(tileIcon); mAllViews.add(quickTileView); } else if (mFullRows && isIconInAnimatedRow(count)) { @@ -223,9 +224,10 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha // Make brightness appear static position and alpha in through second half. View brightness = mQsPanel.getBrightnessView(); if (brightness != null) { - firstPageBuilder.addFloat(brightness, "translationY", mQsPanel.getHeight(), 0); +// firstPageBuilder.addFloat(brightness, "translationY", mQsPanel.getHeight(), 0); mBrightnessAnimator = new TouchAnimator.Builder() .addFloat(brightness, "alpha", 0, 1) + .addFloat(mQsPanel.getPageIndicator(), "alpha", 0, 1) .setStartDelay(.5f) .build(); mAllViews.add(brightness); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index f4da5ecc09ce..91b4d0d55407 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -18,18 +18,12 @@ package com.android.systemui.qs; import android.content.Context; import android.graphics.Point; -import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; -import android.view.ViewGroup; import android.widget.FrameLayout; import com.android.systemui.R; -import com.android.systemui.plugins.qs.QS.HeightListener; import com.android.systemui.qs.customize.QSCustomizer; -import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; -import com.android.systemui.statusbar.phone.QSTileHost; -import com.android.systemui.statusbar.phone.QuickStatusBarHeader; /** * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader} @@ -95,7 +89,7 @@ public class QSContainerImpl extends FrameLayout { updateBottom(); } - void updateBottom() { + public void updateBottom() { int height = calculateContainerHeight(); setBottom(getTop() + height); mQSDetail.setBottom(getTop() + height); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java index 9c4a1498e9e5..f28a0e77af1e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java @@ -16,14 +16,20 @@ package com.android.systemui.qs; +import static com.android.systemui.qs.QSTile.getColorForState; + +import android.animation.ValueAnimator; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Resources; +import android.graphics.Color; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ImageView.ScaleType; + import com.android.systemui.R; import java.util.Objects; @@ -34,6 +40,8 @@ public class QSIconView extends ViewGroup { protected final int mIconSizePx; protected final int mTilePaddingBelowIconPx; private boolean mAnimationEnabled = true; + private int mState = -1; + private int mTint; public QSIconView(Context context) { super(context); @@ -65,7 +73,6 @@ public class QSIconView extends ViewGroup { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int w = getMeasuredWidth(); - final int h = getMeasuredHeight(); int top = 0; final int iconLeft = (w - mIcon.getMeasuredWidth()) / 2; layout(mIcon, iconLeft, top); @@ -100,8 +107,43 @@ public class QSIconView extends ViewGroup { } else { iv.clearColorFilter(); } + if (state.state != mState) { + int color = getColorForState(getContext(), state.state); + mState = state.state; + if (iv.isShown()) { + animateGrayScale(mTint, color, iv); + mTint = color; + } else { + setTint(iv, color); + mTint = color; + } + } + } + + public static void animateGrayScale(int fromColor, int toColor, ImageView iv) { + final float fromAlpha = Color.alpha(fromColor); + final float toAlpha = Color.alpha(toColor); + final float fromChannel = Color.red(fromColor); + final float toChannel = Color.red(toColor); + + ValueAnimator anim = ValueAnimator.ofFloat(0, 1); + anim.setDuration(350); + + anim.addUpdateListener(animation -> { + float fraction = animation.getAnimatedFraction(); + int alpha = (int) (fromAlpha + (toAlpha - fromAlpha) * fraction); + int channel = (int) (fromChannel + (toChannel - fromChannel) * fraction); + + setTint(iv, Color.argb(alpha, channel, channel, channel)); + }); + anim.start(); } + public static void setTint(ImageView iv, int color) { + iv.setImageTintList(ColorStateList.valueOf(color)); + } + + protected int getIconMeasureMode() { return MeasureSpec.EXACTLY; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 9feaa0aaf820..2de32cc6285d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -54,6 +54,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>(); protected final View mBrightnessView; private final H mHandler = new H(); + private final View mPageIndicator; private int mPanelPaddingBottom; private int mBrightnessPaddingTop; @@ -84,21 +85,31 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { setOrientation(VERTICAL); - mBrightnessView = LayoutInflater.from(context).inflate( - R.layout.quick_settings_brightness_dialog, this, false); - addView(mBrightnessView); - setupTileLayout(); mFooter = new QSFooter(this, context); addView(mFooter.getView()); + mPageIndicator = LayoutInflater.from(context).inflate( + R.layout.qs_page_indicator, this, false); + addView(mPageIndicator); + if (mTileLayout instanceof PagedTileLayout) { + ((PagedTileLayout) mTileLayout).setPageIndicator((PageIndicator) mPageIndicator); + } + updateResources(); + mBrightnessView = LayoutInflater.from(context).inflate( + R.layout.quick_settings_brightness_dialog, this, false); + addView(mBrightnessView); + mBrightnessController = new BrightnessController(getContext(), (ImageView) findViewById(R.id.brightness_icon), (ToggleSliderView) findViewById(R.id.brightness_slider)); + } + public View getPageIndicator() { + return mPageIndicator; } protected void setupTileLayout() { @@ -359,20 +370,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { }; r.tile.addCallback(callback); r.callback = callback; - final View.OnClickListener click = new View.OnClickListener() { - @Override - public void onClick(View v) { - onTileClick(r.tile); - } - }; - final View.OnLongClickListener longClick = new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - r.tile.longClick(); - return true; - } - }; - r.tileView.init(click, longClick); + r.tileView.init(v -> r.tile.click(), v -> r.tile.secondaryClick(), v -> { + r.tile.longClick(); + return true; + }); r.tile.refreshState(); mRecords.add(r); @@ -402,10 +403,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { }); } - protected void onTileClick(QSTile<?> tile) { - tile.click(); - } - public void closeDetail() { if (mCustomizePanel != null && mCustomizePanel.isShown()) { // Treat this as a detail panel for now, to make things easy. diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index f73241c4b65c..dad37b087f35 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.service.quicksettings.Tile; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; @@ -52,8 +53,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Objects; +import com.android.settingslib.Utils; + import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +import com.android.systemui.R; + /** * Base quick-settings tile, extend this to create a new tile. * @@ -79,7 +84,9 @@ public abstract class QSTile<TState extends State> { private String mTileSpec; public abstract TState newTileState(); + abstract protected void handleClick(); + abstract protected void handleUpdateState(TState state, Object arg); /** @@ -134,7 +141,9 @@ public abstract class QSTile<TState extends State> { return null; // optional } - protected DetailAdapter createDetailAdapter() { throw new UnsupportedOperationException(); } + protected DetailAdapter createDetailAdapter() { + throw new UnsupportedOperationException(); + } /** * Is a startup check whether this device currently supports this tile. @@ -319,6 +328,21 @@ public abstract class QSTile<TState extends State> { public abstract CharSequence getTileLabel(); + public static int getColorForState(Context context, int state) { + switch (state) { + case Tile.STATE_UNAVAILABLE: + return Utils.getDisabled(context, + Utils.getColorAttr(context, android.R.attr.textColorTertiary)); + case Tile.STATE_INACTIVE: + return Utils.getColorAttr(context, android.R.attr.textColorSecondary); + case Tile.STATE_ACTIVE: + return Utils.getColorAttr(context, android.R.attr.colorPrimary); + default: + Log.e("QSTile", "Invalid state " + state); + return 0; + } + } + protected final class H extends Handler { private static final int ADD_CALLBACK = 1; private static final int CLICK = 2; @@ -546,6 +570,7 @@ public abstract class QSTile<TState extends State> { public static class State { public Icon icon; + public int state = Tile.STATE_ACTIVE; public CharSequence label; public CharSequence contentDescription; public CharSequence dualLabelContentDescription; @@ -572,6 +597,7 @@ public abstract class QSTile<TState extends State> { || !Objects.equals(other.expandedAccessibilityClassName, expandedAccessibilityClassName) || !Objects.equals(other.disabledByPolicy, disabledByPolicy) + || !Objects.equals(other.state, state) || !Objects.equals(other.enforcedAdmin, enforcedAdmin); other.icon = icon; other.label = label; @@ -582,6 +608,7 @@ public abstract class QSTile<TState extends State> { other.expandedAccessibilityClassName = expandedAccessibilityClassName; other.autoMirrorDrawable = autoMirrorDrawable; other.disabledByPolicy = disabledByPolicy; + other.state = state; if (enforcedAdmin == null) { other.enforcedAdmin = null; } else if (other.enforcedAdmin == null) { @@ -609,6 +636,7 @@ public abstract class QSTile<TState extends State> { sb.append(",autoMirrorDrawable=").append(autoMirrorDrawable); sb.append(",disabledByPolicy=").append(disabledByPolicy); sb.append(",enforcedAdmin=").append(enforcedAdmin); + sb.append(",state=").append(state); return sb.append(']'); } } @@ -648,7 +676,6 @@ public abstract class QSTile<TState extends State> { public boolean connected; public boolean activityIn; public boolean activityOut; - public int overlayIconId; public boolean filter; public boolean isOverlayIconWide; @@ -657,12 +684,10 @@ public abstract class QSTile<TState extends State> { final SignalState o = (SignalState) other; final boolean changed = o.connected != connected || o.activityIn != activityIn || o.activityOut != activityOut - || o.overlayIconId != overlayIconId || o.isOverlayIconWide != isOverlayIconWide; o.connected = connected; o.activityIn = activityIn; o.activityOut = activityOut; - o.overlayIconId = overlayIconId; o.filter = filter; o.isOverlayIconWide = isOverlayIconWide; return super.copyTo(other) || changed; @@ -674,7 +699,6 @@ public abstract class QSTile<TState extends State> { rt.insert(rt.length() - 1, ",connected=" + connected); rt.insert(rt.length() - 1, ",activityIn=" + activityIn); rt.insert(rt.length() - 1, ",activityOut=" + activityOut); - rt.insert(rt.length() - 1, ",overlayIconId=" + overlayIconId); rt.insert(rt.length() - 1, ",filter=" + filter); rt.insert(rt.length() - 1, ",wideOverlayIcon=" + isOverlayIconWide); return rt; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java index 2b7fcc57d1f9..a177cc323486 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java @@ -15,31 +15,49 @@ */ package com.android.systemui.qs; +import android.animation.ValueAnimator; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; +import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.service.quicksettings.Tile; import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; import android.widget.LinearLayout; import android.widget.Switch; +import com.android.settingslib.Utils; + import com.android.systemui.R; public class QSTileBaseView extends LinearLayout { + private static final String TAG = "QSTileBaseView"; private final H mHandler = new H(); + private final ImageView mBg; protected QSIconView mIcon; protected RippleDrawable mRipple; private Drawable mTileBackground; private String mAccessibilityClass; private boolean mTileState; private boolean mCollapsedView; + private final int mColorActive; + private final int mColorInactive; + private final int mColorDisabled; + private int mCircleColor; public QSTileBaseView(Context context, QSIconView icon) { this(context, icon, false); @@ -47,8 +65,26 @@ public class QSTileBaseView extends LinearLayout { public QSTileBaseView(Context context, QSIconView icon, boolean collapsedView) { super(context); + // Default to Quick Tile padding, and QSTileView will specify its own padding. + int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding); + + FrameLayout frame = new FrameLayout(context); + frame.setForegroundGravity(Gravity.CENTER); + int size = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size); + addView(frame, new LayoutParams(size, size)); + mBg = new ImageView(getContext()); + mBg.setScaleType(ScaleType.FIT_CENTER); + mBg.setImageResource(R.drawable.ic_qs_circle); + frame.addView(mBg); mIcon = icon; - addView(mIcon); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + params.setMargins(0, padding, 0, padding); + frame.addView(mIcon, params); + mColorActive = Utils.getColorAttr(context, android.R.attr.textColorPrimary); + mColorDisabled = Utils.getDisabled(context, + Utils.getColorAttr(context, android.R.attr.textColorTertiary)); + mColorInactive = Utils.getColorAttr(context, android.R.attr.textColorSecondary); mTileBackground = newTileBackground(); if (mTileBackground instanceof RippleDrawable) { @@ -57,18 +93,20 @@ public class QSTileBaseView extends LinearLayout { setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); setBackground(mTileBackground); - // Default to Quick Tile padding, and QSTileView will specify its own padding. - int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding); - setPadding(0, padding, 0, padding); + setPadding(0, 0, 0, 0); setClipChildren(false); setClipToPadding(false); mCollapsedView = collapsedView; setFocusable(true); } + public View getBgCicle() { + return mBg; + } + protected Drawable newTileBackground() { - final int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless }; - final TypedArray ta = mContext.obtainStyledAttributes(attrs); + final int[] attrs = new int[]{android.R.attr.selectableItemBackgroundBorderless}; + final TypedArray ta = getContext().obtainStyledAttributes(attrs); final Drawable d = ta.getDrawable(0); ta.recycle(); return d; @@ -85,11 +123,12 @@ public class QSTileBaseView extends LinearLayout { // center the touch feedback on the center of the icon, and dial it down a bit final int cx = width / 2; final int cy = height / 2; - final int rad = (int)(mIcon.getHeight() * .85f); + final int rad = (int) (mIcon.getHeight() * .85f); mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad); } - public void init(OnClickListener click, OnLongClickListener longClick) { + public void init(OnClickListener click, OnClickListener secondaryClick, + OnLongClickListener longClick) { setClickable(true); setOnClickListener(click); setOnLongClickListener(longClick); @@ -128,6 +167,16 @@ public class QSTileBaseView extends LinearLayout { } protected void handleStateChanged(QSTile.State state) { + int circleColor = getCircleColor(state.state); + if (circleColor != mCircleColor) { + if (mBg.isShown()) { + QSIconView.animateGrayScale(mCircleColor, circleColor, mBg); + } else { + QSIconView.setTint(mBg, circleColor); + } + mCircleColor = circleColor; + } + mIcon.setIcon(state); if (mCollapsedView && !TextUtils.isEmpty(state.minimalContentDescription)) { setContentDescription(state.minimalContentDescription); @@ -144,6 +193,19 @@ public class QSTileBaseView extends LinearLayout { } } + private int getCircleColor(int state) { + switch (state) { + case Tile.STATE_ACTIVE: + return mColorActive; + case Tile.STATE_INACTIVE: + case Tile.STATE_UNAVAILABLE: + return mColorDisabled; + default: + Log.e(TAG, "Invalid state " + state); + return 0; + } + } + public QSIconView getIcon() { return mIcon; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java index e59873a5ef06..7126f3c8057f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java @@ -16,27 +16,34 @@ package com.android.systemui.qs; +import static com.android.systemui.qs.QSTile.getColorForState; + import android.content.Context; import android.content.res.Configuration; -import android.content.res.Resources; -import android.util.MathUtils; +import android.service.quicksettings.Tile; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; import android.view.Gravity; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; + import libcore.util.Objects; /** View that represents a standard quick settings tile. **/ public class QSTileView extends QSTileBaseView { - private final int mTileSpacingPx; - private int mTilePaddingTopPx; protected TextView mLabel; private ImageView mPadLock; + private int mState; + private OnClickListener mClick; + private OnClickListener mSecondaryClick; public QSTileView(Context context, QSIconView icon) { this(context, icon, false); @@ -45,13 +52,10 @@ public class QSTileView extends QSTileBaseView { public QSTileView(Context context, QSIconView icon, boolean collapsedView) { super(context, icon, collapsedView); - final Resources res = context.getResources(); - mTileSpacingPx = res.getDimensionPixelSize(R.dimen.qs_tile_spacing); - setClipChildren(false); + setClipToPadding(false); setClickable(true); - updateTopPadding(); setId(View.generateViewId()); createLabel(); setOrientation(VERTICAL); @@ -62,27 +66,17 @@ public class QSTileView extends QSTileBaseView { return mLabel; } - protected void updateTopPadding() { - Resources res = getResources(); - int padding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top); - int largePadding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top_large_text); - float largeFactor = (MathUtils.constrain(getResources().getConfiguration().fontScale, - 1.0f, FontSizeUtils.LARGE_TEXT_SCALE) - 1f) / (FontSizeUtils.LARGE_TEXT_SCALE - 1f); - mTilePaddingTopPx = Math.round((1 - largeFactor) * padding + largeFactor * largePadding); - setPadding(mTileSpacingPx, mTilePaddingTopPx + mTileSpacingPx, mTileSpacingPx, - mTileSpacingPx); - requestLayout(); - } - @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - updateTopPadding(); FontSizeUtils.updateFontSize(mLabel, R.dimen.qs_tile_text_size); } protected void createLabel() { - View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null); + ViewGroup view = (ViewGroup) LayoutInflater.from(getContext()) + .inflate(R.layout.qs_tile_label, null); + view.setClipChildren(false); + view.setClipToPadding(false); mLabel = (TextView) view.findViewById(R.id.tile_label); mPadLock = (ImageView) view.findViewById(R.id.restricted_padlock); addView(view); @@ -91,10 +85,32 @@ public class QSTileView extends QSTileBaseView { @Override protected void handleStateChanged(QSTile.State state) { super.handleStateChanged(state); - if (!Objects.equal(mLabel.getText(), state.label)) { + if (!Objects.equal(mLabel.getText(), state.label) || mState != state.state) { + if (state.state == Tile.STATE_UNAVAILABLE) { + int color = getColorForState(getContext(), state.state); + state.label = new SpannableStringBuilder().append(state.label, + new ForegroundColorSpan(color), + SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE); + } + mState = state.state; mLabel.setText(state.label); } mLabel.setEnabled(!state.disabledByPolicy); mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE); } + + @Override + public void init(OnClickListener click, OnClickListener secondaryClick, OnLongClickListener longClick) { + mClick = click; + mSecondaryClick = secondaryClick; + super.init(click, secondaryClick, longClick); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { + setOnClickListener(event.getY() < (getMeasuredHeight() / 2) ? mClick : mSecondaryClick); + } + return super.onTouchEvent(event); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index de3e19c7318a..16b351e5b701 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -56,7 +56,7 @@ public class QuickQSPanel extends QSPanel { } mTileLayout = new HeaderTileLayout(context); mTileLayout.setListening(mListening); - addView((View) mTileLayout, 1 /* Between brightness and footer */); + addView((View) mTileLayout, 0 /* Between brightness and footer */); } @Override @@ -113,11 +113,6 @@ public class QuickQSPanel extends QSPanel { } @Override - protected void onTileClick(QSTile<?> tile) { - tile.secondaryClick(); - } - - @Override public void onTuningChanged(String key, String newValue) { // No tunings for you. if (key.equals(QS_SHOW_BRIGHTNESS)) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java index b2bfa0603237..8555e316bee5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java @@ -33,7 +33,6 @@ public final class SignalTileView extends QSIconView { private FrameLayout mIconFrame; private ImageView mSignal; - private ImageView mOverlay; private ImageView mIn; private ImageView mOut; @@ -62,8 +61,6 @@ public final class SignalTileView extends QSIconView { mIconFrame = new FrameLayout(mContext); mSignal = new ImageView(mContext); mIconFrame.addView(mSignal); - mOverlay = new ImageView(mContext); - mIconFrame.addView(mOverlay, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); return mIconFrame; } @@ -109,17 +106,6 @@ public final class SignalTileView extends QSIconView { public void setIcon(QSTile.State state) { final SignalState s = (SignalState) state; setIcon(mSignal, s); - if (s.overlayIconId > 0) { - mOverlay.setVisibility(VISIBLE); - mOverlay.setImageResource(s.overlayIconId); - } else { - mOverlay.setVisibility(GONE); - } - if (s.overlayIconId > 0 && s.isOverlayIconWide) { - mSignal.setPaddingRelative(mWideOverlayIconStartPadding, 0, 0, 0); - } else { - mSignal.setPaddingRelative(0, 0, 0, 0); - } Drawable drawable = mSignal.getDrawable(); if (state.autoMirrorDrawable && drawable != null) { drawable.setAutoMirrored(true); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index 9e3889bea903..cff484645d97 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -15,15 +15,10 @@ */ package com.android.systemui.qs.external; -import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; - import android.app.ActivityManager; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.graphics.drawable.Drawable; @@ -39,14 +34,19 @@ import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; import android.util.Log; import android.view.IWindowManager; +import android.view.WindowManager; import android.view.WindowManagerGlobal; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.R; import com.android.systemui.qs.QSTile; import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener; import com.android.systemui.statusbar.phone.QSTileHost; import libcore.util.Objects; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; + public class CustomTile extends QSTile<QSTile.State> implements TileChangeListener { public static final String PREFIX = "custom("; @@ -63,7 +63,6 @@ public class CustomTile extends QSTile<QSTile.State> implements TileChangeListen private final IQSTileService mService; private final TileServiceManager mServiceManager; private final int mUser; - private Context mAppContext; private android.graphics.drawable.Icon mDefaultIcon; private boolean mListening; @@ -81,10 +80,6 @@ public class CustomTile extends QSTile<QSTile.State> implements TileChangeListen mService = mServiceManager.getTileService(); mServiceManager.setTileChangeListener(this); mUser = ActivityManager.getCurrentUser(); - try { - mAppContext = mContext.createPackageContext(mComponent.getPackageName(), 0); - } catch (NameNotFoundException e) { - } } private void setTileIcon() { @@ -287,27 +282,17 @@ public class CustomTile extends QSTile<QSTile.State> implements TileChangeListen if (mServiceManager.hasPendingBind()) { tileState = Tile.STATE_UNAVAILABLE; } + state.state = tileState; Drawable drawable; - boolean mHasRes = false; - android.graphics.drawable.Icon icon = mTile.getIcon(); try { - drawable = icon.loadDrawable(mAppContext); - mHasRes = icon.getType() == android.graphics.drawable.Icon.TYPE_RESOURCE; + drawable = mTile.getIcon().loadDrawable(mContext); } catch (Exception e) { Log.w(TAG, "Invalid icon, forcing into unavailable state"); tileState = Tile.STATE_UNAVAILABLE; - drawable = mDefaultIcon.loadDrawable(mAppContext); + drawable = mDefaultIcon.loadDrawable(mContext); } - final int color = TileColorPicker.getInstance(mContext).getColor(tileState); - drawable.setTint(color); - state.icon = mHasRes ? new DrawableIconWithRes(drawable, icon.getResId()) - : new DrawableIcon(drawable); + state.icon = new DrawableIcon(drawable); state.label = mTile.getLabel(); - if (tileState == Tile.STATE_UNAVAILABLE) { - state.label = new SpannableStringBuilder().append(state.label, - new ForegroundColorSpan(color), - SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE); - } if (mTile.getContentDescription() != null) { state.contentDescription = mTile.getContentDescription(); } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index e57cd58fe8fe..e8f90acdceb5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -23,6 +23,7 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.provider.Settings; import android.provider.Settings.Global; +import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.logging.MetricsLogger; @@ -92,6 +93,7 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> { } else { state.icon = mDisable; } + state.state = airplaneMode ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.contentDescription = state.label; state.minimalAccessibilityClassName = state.expandedAccessibilityClassName = Switch.class.getName(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java index 833375e91395..a82f55044bde 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java @@ -19,10 +19,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; -import android.os.Handler; import android.service.quicksettings.Tile; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -44,7 +41,6 @@ import com.android.systemui.BatteryMeterDrawable; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS.DetailAdapter; import com.android.systemui.qs.QSTile; -import com.android.systemui.qs.external.TileColorPicker; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.policy.BatteryController; @@ -105,6 +101,11 @@ public class BatteryTile extends QSTile<QSTile.State> implements BatteryControll @Override protected void handleClick() { + mBatteryController.setPowerSaveMode(!mPowerSave); + } + + @Override + protected void handleSecondaryClick() { showDetail(true); } @@ -118,26 +119,10 @@ public class BatteryTile extends QSTile<QSTile.State> implements BatteryControll int level = (arg != null) ? (Integer) arg : mLevel; String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); - state.icon = new Icon() { - @Override - public Drawable getDrawable(Context context) { - BatteryMeterDrawable drawable = - new BatteryMeterDrawable(context, - context.getColor(R.color.batterymeter_frame_color)); - drawable.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); - drawable.onPowerSaveChanged(mPowerSave); - final int color = TileColorPicker.getInstance(context).getColor(Tile.STATE_ACTIVE); - drawable.setColorFilter(new PorterDuffColorFilter(color, Mode.SRC_IN)); - return drawable; - } - - @Override - public int getPadding() { - return mHost.getContext().getResources().getDimensionPixelSize( - R.dimen.qs_battery_padding); - } - }; - state.label = percentage; + state.state = mCharging ? Tile.STATE_UNAVAILABLE + : mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; + state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver); + state.label = mContext.getString(R.string.battery_detail_switch_title); state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_battery, percentage) + "," + (mPowerSave ? mContext.getString(R.string.battery_saver_notification_title) @@ -153,7 +138,7 @@ public class BatteryTile extends QSTile<QSTile.State> implements BatteryControll mLevel = level; mPluggedIn = pluggedIn; mCharging = charging; - refreshState((Integer) level); + refreshState(level); if (mDetailShown) { mBatteryDetail.postBindView(); } @@ -213,11 +198,6 @@ public class BatteryTile extends QSTile<QSTile.State> implements BatteryControll mDrawable.onBatteryLevelChanged(100, false, false); mDrawable.onPowerSaveChanged(true); mDrawable.disableShowPercent(); - - final int color = TileColorPicker.getInstance(mCurrentView.getContext()) - .getColor(Tile.STATE_ACTIVE); - mDrawable.setColorFilter(new PorterDuffColorFilter(color, Mode.SRC_IN)); - ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable); Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle); checkbox.setChecked(mPowerSave); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index f83b27905dae..15f3c9099ac5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -22,6 +22,7 @@ import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.provider.Settings; +import android.service.quicksettings.Tile; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; @@ -74,7 +75,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { } @Override - protected void handleSecondaryClick() { + protected void handleClick() { // Secondary clicks are header clicks, just toggle. final boolean isEnabled = (Boolean)mState.value; MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled); @@ -87,7 +88,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { } @Override - protected void handleClick() { + protected void handleSecondaryClick() { if (!mController.canConfigBluetooth()) { mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)); return; @@ -140,11 +141,13 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { if (TextUtils.isEmpty(state.label)) { state.label = mContext.getString(R.string.quick_settings_bluetooth_label); } + state.state = Tile.STATE_ACTIVE; } else { state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_off); state.label = mContext.getString(R.string.quick_settings_bluetooth_label); state.contentDescription = mContext.getString( R.string.accessibility_quick_settings_bluetooth_off); + state.state = Tile.STATE_INACTIVE; } CharSequence bluetoothName = state.label; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 8afa91eb1026..d61e2f2bdac0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -19,6 +19,7 @@ package com.android.systemui.qs.tiles; import android.content.Context; import android.content.Intent; import android.provider.Settings; +import android.service.quicksettings.Tile; import android.util.Log; import android.view.View; import android.view.View.OnAttachStateChangeListener; @@ -93,6 +94,11 @@ public class CastTile extends QSTile<QSTile.BooleanState> { } @Override + protected void handleSecondaryClick() { + handleClick(); + } + + @Override protected void handleClick() { if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) { mHost.startRunnableDismissingKeyguard(new Runnable() { @@ -135,6 +141,7 @@ public class CastTile extends QSTile<QSTile.BooleanState> { if (!state.value && connecting) { state.label = mContext.getString(R.string.quick_settings_connecting); } + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off); mDetailAdapter.updateItems(devices); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 1406c9f59a32..5f7c803f53d7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -20,6 +20,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.service.quicksettings.Tile; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -86,6 +87,11 @@ public class CellularTile extends QSTile<QSTile.SignalState> { @Override protected void handleClick() { + mDataController.setMobileDataEnabled(!mDataController.isMobileDataEnabled()); + } + + @Override + protected void handleSecondaryClick() { MetricsLogger.action(mContext, getMetricsCategory()); if (mDataController.isMobileDataSupported()) { showDetail(true); @@ -111,10 +117,13 @@ public class CellularTile extends QSTile<QSTile.SignalState> { : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId : R.drawable.ic_qs_signal_no_signal; - state.icon = ResourceIcon.get(iconId); + if (cb.dataTypeIconId != 0) { + state.icon = ResourceIcon.get(cb.dataTypeIconId); + } else { + state.icon = ResourceIcon.get(iconId); + } state.isOverlayIconWide = cb.isDataTypeIconWide; state.autoMirrorDrawable = !cb.noSim; - state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) ? cb.dataTypeIconId : 0; state.filter = iconId != R.drawable.ic_qs_no_sim; state.activityIn = cb.enabled && cb.activityIn; state.activityOut = cb.enabled && cb.activityOut; @@ -148,6 +157,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> { = Button.class.getName(); state.value = mDataController.isMobileDataSupported() && mDataController.isMobileDataEnabled(); + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index 77f063dfc2eb..0a8afb0ff66c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -19,6 +19,7 @@ package com.android.systemui.qs.tiles; import android.content.Intent; import android.provider.Settings; import android.provider.Settings.Secure; +import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.logging.MetricsLogger; @@ -95,6 +96,7 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> { final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue(); final boolean enabled = value != 0; state.value = enabled; + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.quick_settings_inversion_label); state.icon = enabled ? mEnable : mDisable; state.minimalAccessibilityClassName = state.expandedAccessibilityClassName diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index 65432dc9ec31..aadc8e74c123 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -16,6 +16,7 @@ package com.android.systemui.qs.tiles; import android.content.DialogInterface; import android.content.Intent; +import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.logging.MetricsLogger; @@ -96,6 +97,7 @@ public class DataSaverTile extends QSTile<QSTile.BooleanState> implements protected void handleUpdateState(BooleanState state, Object arg) { state.value = arg instanceof Boolean ? (Boolean) arg : mDataSaverController.isDataSaverEnabled(); + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.data_saver); state.contentDescription = state.label; state.icon = ResourceIcon.get(state.value ? R.drawable.ic_data_saver diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 198375d391e7..a25b7ea3d16c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -25,6 +25,7 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Global; +import android.service.quicksettings.Tile; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnAttachStateChangeListener; @@ -121,7 +122,17 @@ public class DndTile extends QSTile<QSTile.BooleanState> { } @Override - public void handleClick() { + protected void handleClick() { + if (mState.value) { + mController.setZen(Global.ZEN_MODE_OFF, null, TAG); + } else { + int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS); + mController.setZen(zen, null, TAG); + } + } + + @Override + protected void handleSecondaryClick() { if (mController.isVolumeRestricted()) { // Collapse the panels, so the user can see the toast. mHost.collapsePanels(); @@ -131,13 +142,9 @@ public class DndTile extends QSTile<QSTile.BooleanState> { return; } MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); - if (mState.value) { - mController.setZen(Global.ZEN_MODE_OFF, null, TAG); - } else { - showDetail(true); - int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS); - mController.setZen(zen, null, TAG); - } + showDetail(true); + int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS); + mController.setZen(zen, null, TAG); } @Override @@ -151,6 +158,7 @@ public class DndTile extends QSTile<QSTile.BooleanState> { final boolean newValue = zen != Global.ZEN_MODE_OFF; final boolean valueChanged = state.value != newValue; state.value = newValue; + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME); switch (zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index 416c7cef8e5d..4bbc458c949d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -29,7 +29,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.qs.QSTile; -import com.android.systemui.qs.external.TileColorPicker; import com.android.systemui.statusbar.policy.FlashlightController; /** Quick settings tile: Control flashlight **/ @@ -47,11 +46,13 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements public FlashlightTile(Host host) { super(host); mFlashlightController = host.getFlashlightController(); + mFlashlightController.addCallback(this); } @Override protected void handleDestroy() { super.handleDestroy(); + mFlashlightController.removeCallback(this); } @Override @@ -107,17 +108,12 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements protected void handleUpdateState(BooleanState state, Object arg) { state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label); if (!mFlashlightController.isAvailable()) { - Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_disable) + Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_enable) .mutate(); - final int disabledColor = TileColorPicker.getInstance(mContext) - .getColor(Tile.STATE_UNAVAILABLE); - icon.setTint(disabledColor); state.icon = new DrawableIcon(icon); - state.label = new SpannableStringBuilder().append(state.label, - new ForegroundColorSpan(disabledColor), - SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE); state.contentDescription = mContext.getString( R.string.accessibility_quick_settings_flashlight_unavailable); + state.state = Tile.STATE_UNAVAILABLE; return; } if (arg instanceof Boolean) { @@ -134,6 +130,7 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements state.contentDescription = mContext.getString(R.string.quick_settings_flashlight_label); state.minimalAccessibilityClassName = state.expandedAccessibilityClassName = Switch.class.getName(); + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 99485bb90943..9d495cebde18 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -32,7 +32,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.qs.GlobalSetting; import com.android.systemui.qs.QSTile; -import com.android.systemui.qs.external.TileColorPicker; import com.android.systemui.statusbar.policy.HotspotController; /** Quick settings tile: Hotspot **/ @@ -126,11 +125,6 @@ public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> { boolean wasAirplane = state.isAirplaneMode; state.isAirplaneMode = mAirplaneMode.getValue() != 0; if (state.isAirplaneMode) { - final int disabledColor = TileColorPicker.getInstance(mContext) - .getColor(Tile.STATE_UNAVAILABLE); - state.label = new SpannableStringBuilder().append(state.label, - new ForegroundColorSpan(disabledColor), - SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE); state.icon = mUnavailable; } else if (wasAirplane) { state.icon = mDisableNoAnimation; @@ -138,6 +132,8 @@ public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> { state.minimalAccessibilityClassName = state.expandedAccessibilityClassName = Switch.class.getName(); state.contentDescription = state.label; + state.state = state.isAirplaneMode ? Tile.STATE_UNAVAILABLE + : state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index 8a9a696481e7..002e2a6a68e6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.os.UserManager; import android.provider.Settings; +import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.logging.MetricsLogger; @@ -115,6 +116,7 @@ public class LocationTile extends QSTile<QSTile.BooleanState> { state.contentDescription = mContext.getString( R.string.accessibility_quick_settings_location_off); } + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.minimalAccessibilityClassName = state.expandedAccessibilityClassName = Switch.class.getName(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index 10fde3042ce4..b8ba28d8e5c1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -19,6 +19,7 @@ package com.android.systemui.qs.tiles; import android.app.ActivityManager; import android.content.Intent; import android.provider.Settings; +import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.app.NightDisplayController; @@ -81,6 +82,7 @@ public class NightDisplayTile extends QSTile<QSTile.BooleanState> : R.drawable.ic_qs_night_display_off); state.minimalAccessibilityClassName = state.expandedAccessibilityClassName = Switch.class.getName(); + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index cec5f15ddd0d..9be67da13493 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.res.Configuration; import android.provider.Settings; +import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.logging.MetricsLogger; @@ -106,6 +107,7 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> { state.contentDescription = getAccessibilityString(rotationLocked); state.minimalAccessibilityClassName = state.expandedAccessibilityClassName = Switch.class.getName(); + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } public static boolean isCurrentOrientationLockPortrait(RotationLockController controller, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 3876c88ce4a2..7d9904176af9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; import android.provider.Settings; +import android.service.quicksettings.Tile; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -104,7 +105,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { } @Override - protected void handleSecondaryClick() { + protected void handleClick() { // Secondary clicks are header clicks, just toggle. mState.copyTo(mStateBeforeClick); MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); @@ -112,7 +113,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { } @Override - protected void handleClick() { + protected void handleSecondaryClick() { if (!mWifiController.canConfigWifi()) { mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_WIFI_SETTINGS)); return; @@ -191,6 +192,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { state.dualLabelContentDescription = wifiName; state.expandedAccessibilityClassName = Button.class.getName(); state.minimalAccessibilityClassName = Switch.class.getName(); + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index ce7fbd368cba..207deff7de96 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -18,6 +18,7 @@ package com.android.systemui.qs.tiles; import android.content.Intent; import android.provider.Settings; +import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.logging.MetricsLogger; @@ -108,6 +109,7 @@ public class WorkModeTile extends QSTile<QSTile.BooleanState> implements } state.minimalAccessibilityClassName = state.expandedAccessibilityClassName = Switch.class.getName(); + state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 711f0c679b6d..ff8d4bf68cc6 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -17,12 +17,33 @@ package com.android.systemui.recents; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; import android.os.SystemProperties; import com.android.systemui.R; import com.android.systemui.recents.misc.SystemServicesProxy; +import com.android.systemui.recents.model.TaskStack; + +/** + * Represents the dock regions for each orientation. + */ +class DockRegion { + public static TaskStack.DockState[] PHONE_LANDSCAPE = { + // We only allow docking to the left in landscape for now on small devices + TaskStack.DockState.LEFT + }; + public static TaskStack.DockState[] PHONE_PORTRAIT = { + // We only allow docking to the top for now on small devices + TaskStack.DockState.TOP + }; + public static TaskStack.DockState[] TABLET_LANDSCAPE = { + TaskStack.DockState.LEFT, + TaskStack.DockState.RIGHT + }; + public static TaskStack.DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT; +} /** * Application resources that can be retrieved from the application context and are not specifically @@ -63,12 +84,14 @@ public class RecentsConfiguration { // Recents will layout task views in a grid mode when there's enough space in the screen. public boolean isGridEnabled; + private final Context mAppContext; + public RecentsConfiguration(Context context) { // Load only resources that can not change after the first load either through developer // settings or via multi window SystemServicesProxy ssp = Recents.getSystemServices(); - Context appContext = context.getApplicationContext(); - Resources res = appContext.getResources(); + mAppContext = context.getApplicationContext(); + Resources res = mAppContext.getResources(); fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows); svelteLevel = res.getInteger(R.integer.recents_svelte_level); isGridEnabled = SystemProperties.getBoolean("ro.recents.grid", false); @@ -86,4 +109,20 @@ public class RecentsConfiguration { public RecentsActivityLaunchState getLaunchState() { return mLaunchState; } + + /** + * Returns the preferred dock states for the current orientation. + * @return a list of dock states for device and its orientation + */ + public TaskStack.DockState[] getDockStatesForCurrentOrientation() { + boolean isLandscape = mAppContext.getResources().getConfiguration().orientation == + Configuration.ORIENTATION_LANDSCAPE; + RecentsConfiguration config = Recents.getConfiguration(); + if (config.isLargeScreen) { + return isLandscape ? DockRegion.TABLET_LANDSCAPE : DockRegion.TABLET_PORTRAIT; + } else { + return isLandscape ? DockRegion.PHONE_LANDSCAPE : DockRegion.PHONE_PORTRAIT; + } + } + } diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java index b368bd353ad8..e57fa2d86a66 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java @@ -30,10 +30,17 @@ public class DragStartEvent extends EventBus.Event { public final Task task; public final TaskView taskView; public final Point tlOffset; + public final boolean isUserTouchInitiated; public DragStartEvent(Task task, TaskView taskView, Point tlOffset) { + this(task, taskView, tlOffset, true); + } + + public DragStartEvent(Task task, TaskView taskView, Point tlOffset, + boolean isUserTouchInitiated) { this.task = task; this.taskView = taskView; this.tlOffset = tlOffset; + this.isUserTouchInitiated = isUserTouchInitiated; } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index a2b86d1f42f5..49074a6f535d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -79,6 +79,7 @@ import android.view.accessibility.AccessibilityManager; import com.android.internal.app.AssistUtils; import com.android.internal.os.BackgroundThread; +import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.pip.tv.PipMenuActivity; import com.android.systemui.pip.tv.PipOnboardingActivity; @@ -152,11 +153,30 @@ public class SystemServicesProxy { public void onTaskStackChanged() { } public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { } public void onActivityPinned() { } - public void onPinnedActivityRestartAttempt() { } + public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) { } public void onPinnedStackAnimationEnded() { } public void onActivityForcedResizable(String packageName, int taskId) { } public void onActivityDismissingDockedStack() { } public void onTaskProfileLocked(int taskId, int userId) { } + + /** + * Checks that the current user matches the user's SystemUI process. Since + * {@link android.app.ITaskStackListener} is not multi-user aware, handlers of + * TaskStackListener should make this call to verify that we don't act on events from other + * user's processes. + */ + protected final boolean checkCurrentUserId(boolean debug) { + int processUserId = UserHandle.myUserId(); + int currentUserId = KeyguardUpdateMonitor.getCurrentUser(); + if (processUserId != currentUserId) { + if (debug) { + Log.d(TAG, "UID mismatch. SystemUI is running uid=" + processUserId + + " and the current user is uid=" + currentUserId); + } + return false; + } + return true; + } } /** @@ -178,9 +198,11 @@ public class SystemServicesProxy { } @Override - public void onPinnedActivityRestartAttempt() throws RemoteException{ + public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) + throws RemoteException{ mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT); - mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT); + mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, sourceComponent) + .sendToTarget(); } @Override @@ -1214,7 +1236,8 @@ public class SystemServicesProxy { } case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(); + mTaskStackListeners.get(i).onPinnedActivityRestartAttempt( + (ComponentName) msg.obj); } break; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java b/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java index d64a67600513..79a774f7fba0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java @@ -30,6 +30,7 @@ import android.graphics.drawable.Drawable; import android.util.Log; import com.android.systemui.R; +import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsConfiguration; /** @@ -90,8 +91,10 @@ class FakeShadowDrawable extends Drawable { mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mCornerShadowPaint.setStyle(Paint.Style.FILL); mCornerShadowPaint.setDither(true); - mCornerRadius = resources.getDimensionPixelSize( - R.dimen.recents_task_view_rounded_corners_radius); + mCornerRadius = Recents.getConfiguration().isGridEnabled ? + resources.getDimensionPixelSize( + R.dimen.recents_grid_task_view_rounded_corners_radius) : + resources.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); mCardBounds = new RectF(); mEdgeShadowPaint = new Paint(mCornerShadowPaint); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index ee79330f816a..8f9c457c255b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -454,7 +454,7 @@ public class RecentsView extends FrameLayout { } public final void onBusEvent(DragStartEvent event) { - updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(), + updateVisibleDockRegions(Recents.getConfiguration().getDockStatesForCurrentOrientation(), true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha, TaskStack.DockState.NONE.viewState.hintTextAlpha, true /* animateAlpha */, false /* animateBounds */); @@ -471,7 +471,8 @@ public class RecentsView extends FrameLayout { public final void onBusEvent(DragDropTargetChangedEvent event) { if (event.dropTarget == null || !(event.dropTarget instanceof TaskStack.DockState)) { - updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(), + updateVisibleDockRegions( + Recents.getConfiguration().getDockStatesForCurrentOrientation(), true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha, TaskStack.DockState.NONE.viewState.hintTextAlpha, true /* animateAlpha */, true /* animateBounds */); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java index d3ec9845856a..db0c95eb5997 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java @@ -28,7 +28,6 @@ import android.view.ViewDebug; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.systemui.recents.Recents; -import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.ConfigurationChangedEvent; import com.android.systemui.recents.events.activity.HideRecentsEvent; @@ -45,25 +44,6 @@ import com.android.systemui.recents.model.TaskStack; import java.util.ArrayList; /** - * Represents the dock regions for each orientation. - */ -class DockRegion { - public static TaskStack.DockState[] PHONE_LANDSCAPE = { - // We only allow docking to the left in landscape for now on small devices - TaskStack.DockState.LEFT - }; - public static TaskStack.DockState[] PHONE_PORTRAIT = { - // We only allow docking to the top for now on small devices - TaskStack.DockState.TOP - }; - public static TaskStack.DockState[] TABLET_LANDSCAPE = { - TaskStack.DockState.LEFT, - TaskStack.DockState.RIGHT - }; - public static TaskStack.DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT; -} - -/** * Handles touch events for a RecentsView. */ public class RecentsViewTouchHandler { @@ -111,20 +91,6 @@ public class RecentsViewTouchHandler { } /** - * Returns the preferred dock states for the current orientation. - */ - public TaskStack.DockState[] getDockStatesForCurrentOrientation() { - boolean isLandscape = mRv.getResources().getConfiguration().orientation == - Configuration.ORIENTATION_LANDSCAPE; - RecentsConfiguration config = Recents.getConfiguration(); - if (config.isLargeScreen) { - return isLandscape ? DockRegion.TABLET_LANDSCAPE : DockRegion.TABLET_PORTRAIT; - } else { - return isLandscape ? DockRegion.PHONE_LANDSCAPE : DockRegion.PHONE_PORTRAIT; - } - } - - /** * Returns the set of visible dock states for this current drag. */ public ArrayList<TaskStack.DockState> getVisibleDockStates() { @@ -162,10 +128,14 @@ public class RecentsViewTouchHandler { mRv.getLocationInWindow(recentsViewLocation); mTaskViewOffset.set(mTaskView.getLeft() - recentsViewLocation[0] + event.tlOffset.x, mTaskView.getTop() - recentsViewLocation[1] + event.tlOffset.y); - float x = mDownPos.x - mTaskViewOffset.x; - float y = mDownPos.y - mTaskViewOffset.y; - mTaskView.setTranslationX(x); - mTaskView.setTranslationY(y); + + // Change space coordinates relative to the view to RecentsView when user initiates a touch + if (event.isUserTouchInitiated) { + float x = mDownPos.x - mTaskViewOffset.x; + float y = mDownPos.y - mTaskViewOffset.y; + mTaskView.setTranslationX(x); + mTaskView.setTranslationY(y); + } mVisibleDockStates.clear(); if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask() @@ -176,7 +146,8 @@ public class RecentsViewTouchHandler { EventBus.getDefault().send(new ShowIncompatibleAppOverlayEvent()); } else { // Add the dock state drop targets (these take priority) - TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation(); + TaskStack.DockState[] dockStates = Recents.getConfiguration() + .getDockStatesForCurrentOrientation(); for (TaskStack.DockState dockState : dockStates) { registerDropTargetForCurrentDrag(dockState); dockState.update(mRv.getContext()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 3f28d9d49721..8ae7a838e7f3 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -266,8 +266,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm); mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller); mAnimationHelper = new TaskStackAnimationHelper(context, this); - mTaskCornerRadiusPx = res.getDimensionPixelSize( - R.dimen.recents_task_view_rounded_corners_radius); + mTaskCornerRadiusPx = Recents.getConfiguration().isGridEnabled ? + res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) : + res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); mDividerSize = ssp.getDockedDividerSize(context); mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation; mDisplayRect = ssp.getDisplayRect(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index e41a718d4a08..e941c3bacfcb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -183,6 +183,7 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks } setOutlineProvider(mViewBounds); setOnLongClickListener(this); + setAccessibilityDelegate(new TaskViewAccessibilityDelegate(this)); } /** Set callback */ @@ -257,6 +258,11 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks } @Override + public void addChildrenForAccessibility(ArrayList<View> outChildren) { + // Prevent any children from being focusable during talkback + } + + @Override public boolean hasOverlappingRendering() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java new file mode 100644 index 000000000000..759daf1e0f12 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.recents.views; + +import android.app.ActivityManager; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Point; +import android.os.Bundle; +import android.util.SparseArray; +import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; + +import com.android.systemui.R; +import com.android.systemui.recents.Recents; +import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent; +import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent; +import com.android.systemui.recents.misc.Utilities; +import com.android.systemui.recents.model.TaskStack; + +public class TaskViewAccessibilityDelegate extends View.AccessibilityDelegate { + private static final String TAG = "TaskViewAccessibilityDelegate"; + + private final TaskView mTaskView; + + protected static final int OPEN = R.id.action_open; + protected static final int DIMISS = R.id.action_dimiss; + protected static final int SPLIT_TASK_TOP = R.id.action_split_task_to_top; + protected static final int SPLIT_TASK_LEFT = R.id.action_split_task_to_left; + protected static final int SPLIT_TASK_RIGHT = R.id.action_split_task_to_right; + + protected final SparseArray<AccessibilityAction> mActions = new SparseArray<>(); + + public TaskViewAccessibilityDelegate(TaskView taskView) { + mTaskView = taskView; + Context context = taskView.getContext(); + mActions.put(OPEN, new AccessibilityAction(OPEN, + context.getString(R.string.recents_accessibility_open))); + mActions.put(DIMISS, new AccessibilityAction(DIMISS, + context.getString(R.string.recents_accessibility_dismissed))); + mActions.put(SPLIT_TASK_TOP, new AccessibilityAction(SPLIT_TASK_TOP, + context.getString(R.string.recents_accessibility_split_screen_top))); + mActions.put(SPLIT_TASK_LEFT, new AccessibilityAction(SPLIT_TASK_LEFT, + context.getString(R.string.recents_accessibility_split_screen_left))); + mActions.put(SPLIT_TASK_RIGHT, new AccessibilityAction(SPLIT_TASK_RIGHT, + context.getString(R.string.recents_accessibility_split_screen_right))); + } + + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.addAction(mActions.get(OPEN)); + info.addAction(mActions.get(DIMISS)); + if (ActivityManager.supportsSplitScreenMultiWindow() + && !Recents.getSystemServices().hasDockedTask()) { + TaskStack.DockState[] dockStates = Recents.getConfiguration() + .getDockStatesForCurrentOrientation(); + for (TaskStack.DockState dockState: dockStates) { + if (dockState == TaskStack.DockState.TOP) { + info.addAction(mActions.get(SPLIT_TASK_TOP)); + } else if (dockState == TaskStack.DockState.LEFT) { + info.addAction(mActions.get(SPLIT_TASK_LEFT)); + } else if (dockState == TaskStack.DockState.RIGHT) { + info.addAction(mActions.get(SPLIT_TASK_RIGHT)); + } + } + } + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (action == OPEN) { + mTaskView.onClick(host); + } else if (action == DIMISS) { + mTaskView.dismissTask(); + } else if (action == SPLIT_TASK_TOP) { + simulateDragIntoMultiwindow(TaskStack.DockState.TOP); + } else if (action == SPLIT_TASK_LEFT) { + simulateDragIntoMultiwindow(TaskStack.DockState.LEFT); + } else if (action == SPLIT_TASK_RIGHT) { + simulateDragIntoMultiwindow(TaskStack.DockState.RIGHT); + } else { + return super.performAccessibilityAction(host, action, args); + } + return true; + } + + /** Simulate a user drag event to split the screen to the respected side */ + private void simulateDragIntoMultiwindow(TaskStack.DockState dockState) { + int orientation = Utilities.getAppConfiguration(mTaskView.getContext()).orientation; + EventBus.getDefault().send(new DragStartEvent(mTaskView.getTask(), mTaskView, + new Point(0,0), false /* isUserTouchInitiated */)); + EventBus.getDefault().send(new DragEndEvent(mTaskView.getTask(), mTaskView, dockState)); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index c0cc83fa0243..0777163293d9 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -201,7 +201,9 @@ public class TaskViewHeader extends FrameLayout Resources res = context.getResources(); mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light); mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark); - mCornerRadius = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); + mCornerRadius = Recents.getConfiguration().isGridEnabled ? + res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) : + res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight); mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color); mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java index bae5daa8737c..792679bd1c34 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java @@ -60,11 +60,11 @@ public class TaskViewThumbnail extends View { // Drawing @ViewDebug.ExportedProperty(category="recents") - private Rect mTaskViewRect = new Rect(); + protected Rect mTaskViewRect = new Rect(); @ViewDebug.ExportedProperty(category="recents") - private Rect mThumbnailRect = new Rect(); + protected Rect mThumbnailRect = new Rect(); @ViewDebug.ExportedProperty(category="recents") - private float mThumbnailScale; + protected float mThumbnailScale; private float mFullscreenThumbnailScale; /** The height, in pixels, of the task view's title bar. */ private int mTitleBarHeight; @@ -72,14 +72,14 @@ public class TaskViewThumbnail extends View { private boolean mOverlayHeaderOnThumbnailActionBar = true; private ThumbnailData mThumbnailData; - private int mCornerRadius; + protected int mCornerRadius; @ViewDebug.ExportedProperty(category="recents") private float mDimAlpha; private Matrix mMatrix = new Matrix(); - private Paint mDrawPaint = new Paint(); + protected Paint mDrawPaint = new Paint(); private Paint mLockedPaint = new Paint(); - private Paint mBgFillPaint = new Paint(); - private BitmapShader mBitmapShader; + protected Paint mBgFillPaint = new Paint(); + protected BitmapShader mBitmapShader; private LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0); // Clip the top of the thumbnail against the opaque header bar that overlaps this view diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java new file mode 100644 index 000000000000..2c3e42b6c7d7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.recents.views.grid; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Path; +import android.util.AttributeSet; + +import com.android.systemui.R; +import com.android.systemui.recents.views.TaskViewThumbnail; + +public class GridTaskViewThumbnail extends TaskViewThumbnail { + + private Path mThumbnailOutline; + private Path mRestBackgroundOutline; + private Path mFullBackgroundOutline; + // True if either this view's size or thumbnail scale has changed and mThumbnailOutline should + // be updated. + private boolean mUpdateThumbnailOutline = true; + + public GridTaskViewThumbnail(Context context) { + this(context, null); + } + + public GridTaskViewThumbnail(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + mCornerRadius = getResources().getDimensionPixelSize( + R.dimen.recents_grid_task_view_rounded_corners_radius); + } + + /** + * Called when the task view frame changes, allowing us to move the contents of the header + * to match the frame changes. + */ + public void onTaskViewSizeChanged(int width, int height) { + mUpdateThumbnailOutline = true; + super.onTaskViewSizeChanged(width, height); + } + + /** + * Updates the scale of the bitmap relative to this view. + */ + public void updateThumbnailMatrix() { + mUpdateThumbnailOutline = true; + super.updateThumbnailMatrix(); + } + + private void updateThumbnailOutline() { + final int titleHeight = getResources().getDimensionPixelSize( + R.dimen.recents_grid_task_view_header_height); + final int viewWidth = mTaskViewRect.width(); + final int viewHeight = mTaskViewRect.height() - titleHeight; + final int thumbnailWidth = Math.min(viewWidth, + (int) (mThumbnailRect.width() * mThumbnailScale)); + final int thumbnailHeight = Math.min(viewHeight, + (int) (mThumbnailRect.height() * mThumbnailScale)); + // Draw the thumbnail, we only round the bottom corners: + // + // outerLeft outerRight + // <-----------------------> mRestBackgroundOutline + // _________________________ (thumbnailWidth < viewWidth) + // |_______________________| outerTop A ____ B + // | | ↑ | | + // | | | | | + // | | | | | + // | | | | | C + // \_______________________/ ↓ |__/ + // mCornerRadius outerBottom E D + // + // mRestBackgroundOutline (thumbnailHeight < viewHeight) + // A _________________________ B + // | | C + // F \_______________________/ + // E D + final int outerLeft = 0; + final int outerTop = 0; + final int outerRight = outerLeft + thumbnailWidth; + final int outerBottom = outerTop + thumbnailHeight; + mThumbnailOutline = new Path(); + mThumbnailOutline.moveTo(outerLeft, outerTop); + mThumbnailOutline.lineTo(outerRight, outerTop); + mThumbnailOutline.lineTo(outerRight, outerBottom - mCornerRadius); + mThumbnailOutline.arcTo(outerRight - 2 * mCornerRadius, outerBottom - 2 * mCornerRadius, + outerRight, outerBottom, 0, 90, false); + mThumbnailOutline.lineTo(outerLeft + mCornerRadius, outerBottom); + mThumbnailOutline.arcTo(outerLeft, outerBottom - 2 * mCornerRadius, + outerLeft + 2 * mCornerRadius, outerBottom, 90, 90, false); + mThumbnailOutline.lineTo(outerLeft, outerTop); + mThumbnailOutline.close(); + + if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) { + if (thumbnailWidth < viewWidth) { + final int l = Math.max(0, outerRight - mCornerRadius); + final int r = outerRight; + final int t = outerTop; + final int b = outerBottom; + mRestBackgroundOutline = new Path(); + mRestBackgroundOutline.moveTo(l, t); // A + mRestBackgroundOutline.lineTo(r, t); // B + mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C + mRestBackgroundOutline.arcTo(r - 2 * mCornerRadius, b - 2 * mCornerRadius, r, b, + 0, 90, false); // D + mRestBackgroundOutline.lineTo(l, b); // E + mRestBackgroundOutline.lineTo(l, t); // A + mRestBackgroundOutline.close(); + + } + if (thumbnailHeight < viewHeight) { + final int l = outerLeft; + final int r = outerRight; + final int t = Math.max(0, thumbnailHeight - mCornerRadius); + final int b = outerBottom; + mRestBackgroundOutline = new Path(); + mRestBackgroundOutline.moveTo(l, t); // A + mRestBackgroundOutline.lineTo(r, t); // B + mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C + mRestBackgroundOutline.arcTo(r - 2 * mCornerRadius, b - 2 * mCornerRadius, r, b, + 0, 90, false); // D + mRestBackgroundOutline.lineTo(l + mCornerRadius, b); // E + mRestBackgroundOutline.arcTo(l, b - 2 * mCornerRadius, l + 2 * mCornerRadius, b, + 90, 90, false); // F + mRestBackgroundOutline.lineTo(l, t); // A + mRestBackgroundOutline.close(); + + } + } else { + mFullBackgroundOutline = mThumbnailOutline; + } + } + + @Override + protected void onDraw(Canvas canvas) { + final int titleHeight = getResources().getDimensionPixelSize( + R.dimen.recents_grid_task_view_header_height); + final int viewWidth = mTaskViewRect.width(); + final int viewHeight = mTaskViewRect.height() - titleHeight; + final int thumbnailWidth = Math.min(viewWidth, + (int) (mThumbnailRect.width() * mThumbnailScale)); + final int thumbnailHeight = Math.min(viewHeight, + (int) (mThumbnailRect.height() * mThumbnailScale)); + + if (mUpdateThumbnailOutline) { + updateThumbnailOutline(); + mUpdateThumbnailOutline = false; + } + if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) { + // Draw the background, there will be some small overdraw with the thumbnail + if (thumbnailWidth < viewWidth) { + // Portrait thumbnail on a landscape task view + canvas.drawPath(mRestBackgroundOutline, mBgFillPaint); + } + if (thumbnailHeight < viewHeight) { + // Landscape thumbnail on a portrait task view + canvas.drawPath(mRestBackgroundOutline, mBgFillPaint); + } + canvas.drawPath(mThumbnailOutline, mDrawPaint); + } else { + canvas.drawPath(mFullBackgroundOutline, mBgFillPaint); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java index 78c26dd64986..02d1cc14fc41 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java @@ -105,11 +105,13 @@ public class TaskGridLayoutAlgorithm { if (maxTaskHeight >= maxTaskWidth / mAppAspectRatio + mTitleBarHeight) { // Width bound. taskWidth = maxTaskWidth; - taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight); + // Here we should round the height to the nearest integer. + taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight + 0.5); } else { // Height bound. taskHeight = maxTaskHeight; - taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio); + // Here we should round the width to the nearest integer. + taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio + 0.5); } size.set(0, 0, taskWidth, taskHeight); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 68d5cd41b363..d77e9eda5baa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -159,6 +159,7 @@ public class SignalClusterView public void setNetworkController(NetworkControllerImpl nc) { if (DEBUG) Log.d(TAG, "NetworkController=" + nc); mNC = nc; + mNC.addCallback(this); } public void setSecurityController(SecurityController sc) { @@ -214,7 +215,9 @@ public class SignalClusterView super.onAttachedToWindow(); for (PhoneState state : mPhoneStates) { - mMobileSignalGroup.addView(state.mMobileGroup); + if (state.mMobileGroup.getParent() == null) { + mMobileSignalGroup.addView(state.mMobileGroup); + } } int endPadding = mMobileSignalGroup.getChildCount() > 0 ? mMobileSignalGroupEndPadding : 0; @@ -224,7 +227,6 @@ public class SignalClusterView apply(); applyIconTint(); - mNC.addCallback(this); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index c0f245c10af6..3423a3c1b1b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -45,6 +45,7 @@ import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; import android.os.UserHandle; +import android.support.annotation.VisibleForTesting; import android.telecom.TelecomManager; import android.text.TextUtils; import android.util.Log; @@ -447,7 +448,8 @@ public class NavigationBarFragment extends Fragment implements Callbacks { return false; } - private boolean onHomeLongClick(View v) { + @VisibleForTesting + boolean onHomeLongClick(View v) { if (shouldDisableNavbarGestures()) { return false; } @@ -562,6 +564,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { public void setAssistManager(AssistManager assistManager) { mAssistManager = assistManager; + mAssistManager.onConfigurationChanged(); } public void setLightBarController(LightBarController lightBarController) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 191718ee45f9..001edb3a9ce3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -74,6 +74,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; +import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.Process; @@ -126,6 +127,7 @@ import com.android.systemui.EventLogTags; import com.android.systemui.Interpolators; import com.android.systemui.Prefs; import com.android.systemui.R; +import com.android.systemui.SysUiServiceProvider; import com.android.systemui.SystemUIApplication; import com.android.systemui.SystemUIFactory; import com.android.systemui.classifier.FalsingLog; @@ -847,6 +849,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mDozeServiceHost.firePowerSaveChanged(isPowerSave); } } + @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { // noop @@ -1029,8 +1032,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public static Handler getTimeTickHandler(Context context) { - return ((SystemUIApplication) context.getApplicationContext()) - .getComponent(PhoneStatusBar.class).getTimeTickHandler(); + PhoneStatusBar statusBar = ((SysUiServiceProvider) context.getApplicationContext()) + .getComponent(PhoneStatusBar.class); + return statusBar != null ? statusBar.getTimeTickHandler() : + new Handler(Looper.getMainLooper()); } protected void createNavigationBar() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java index 08a91bb76b3c..2fa961d1bb8f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java @@ -21,9 +21,13 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; +import android.graphics.Color; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; +import android.icu.text.NumberFormat; import android.os.UserManager; +import android.support.annotation.VisibleForTesting; import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; @@ -32,21 +36,25 @@ import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.keyguard.KeyguardStatusView; +import com.android.settingslib.Utils; +import com.android.systemui.BatteryMeterView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS.ActivityStarter; import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader; -import com.android.systemui.qs.QSPanel; import com.android.systemui.plugins.qs.QS.Callback; +import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QuickQSPanel; import com.android.systemui.qs.TouchAnimator; import com.android.systemui.qs.TouchAnimator.Builder; +import com.android.systemui.statusbar.SignalClusterView; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener; +import com.android.systemui.statusbar.policy.NetworkControllerImpl; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback; import com.android.systemui.statusbar.policy.UserInfoController; @@ -54,7 +62,8 @@ import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChange import com.android.systemui.tuner.TunerService; public class QuickStatusBarHeader extends BaseStatusBarHeader implements - NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener { + NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener, + BatteryStateChangeCallback { private static final String TAG = "QuickStatusBarHeader"; @@ -67,14 +76,14 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements private TextView mAlarmStatus; private View mAlarmStatusCollapsed; + private ViewGroup mDateTimeGroup; + private ViewGroup mDateTimeAlarmGroup; private QSPanel mQsPanel; private boolean mExpanded; private boolean mAlarmShowing; - private ViewGroup mDateTimeGroup; - private ViewGroup mDateTimeAlarmGroup; private TextView mEmergencyOnly; protected ExpandableIndicator mExpandIndicator; @@ -95,6 +104,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements protected View mEdit; private boolean mShowFullAlarm; private float mDateTimeTranslation; + private TextView mBatteryLevel; public QuickStatusBarHeader(Context context, AttributeSet attrs) { super(context, attrs); @@ -130,6 +140,8 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mAlarmStatus = (TextView) findViewById(R.id.alarm_status); mAlarmStatus.setOnClickListener(this); + mBatteryLevel = (TextView) findViewById(R.id.battery_level); + mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch); mMultiUserAvatar = (ImageView) mMultiUserSwitch.findViewById(R.id.multi_user_avatar); @@ -236,13 +248,11 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD); } - @Override @VisibleForTesting public void onDetachedFromWindow() { setListening(false); mHost.getUserInfoController().removeCallback(this); mHost.getNetworkController().removeEmergencyListener(this); - mHost.getUserInfoController().removeCallback(this); super.onDetachedFromWindow(); } @@ -325,6 +335,19 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements if (isAPhone) { mHost.getNetworkController().addEmergencyListener(this); } + + // Set the light/dark theming on the header status UI to match the current theme. + SignalClusterView cluster = (SignalClusterView) findViewById(R.id.signal_cluster); + cluster.setNetworkController((NetworkControllerImpl) host.getNetworkController()); + cluster.setSecurityController(host.getSecurityController()); + int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground); + float intensity = colorForeground / (float) Color.WHITE; + cluster.setIconTint(colorForeground, intensity, + new Rect(0, 0, 0, 0)); + BatteryMeterView battery = (BatteryMeterView) findViewById(R.id.battery); + battery.setBatteryController(host.getBatteryController()); + int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary); + battery.setRawColors(colorForeground, colorSecondary); } @Override @@ -367,7 +390,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements } public void setBatteryController(BatteryController batteryController) { - // Don't care + batteryController.addCallback(this); } public void setUserInfoController(UserInfoController userInfoController) { @@ -391,6 +414,17 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements } @Override + public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); + mBatteryLevel.setText(percentage); + } + + @Override + public void onPowerSaveChanged(boolean isPowerSave) { + // Don't care. + } + + @Override public void onUserInfoChanged(String name, Drawable picture, String userAccount) { mMultiUserAvatar.setImageDrawable(picture); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 2e279b233d7f..7e5a7da8c7db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -491,7 +491,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() { @Override public void run() { - mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE); + mPhoneStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE); } }; @@ -527,7 +527,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } } else { mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable); - mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE); + mPhoneStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index ed8c7ff96aac..b59cf6862292 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -224,7 +224,7 @@ class TelephonyIcons { static final int ICON_CARRIER_NETWORK_CHANGE = R.drawable.stat_sys_signal_carrier_network_change_animation; - static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled; + static final int ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled; static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte; static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g; diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index dec8ba6c05db..6516369d0e2e 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -17,6 +17,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.systemui.tests"> + <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" /> <uses-permission android:name="android.permission.INJECT_EVENTS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> @@ -28,6 +29,7 @@ <uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" /> <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" /> <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" /> + <uses-permission android:name="android.permission.ACCESS_VR_MANAGER" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java index 34743fff72b6..e140e98aee29 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java @@ -16,12 +16,17 @@ package com.android.systemui.statusbar.phone; import static org.mockito.Mockito.mock; +import android.content.Context; +import android.view.WindowManager; + import com.android.systemui.FragmentTestCase; +import com.android.systemui.assist.AssistManager; import com.android.systemui.recents.Recents; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; import org.junit.Before; +import org.junit.Test; public class NavigationBarFragmentTest extends FragmentTestCase { @@ -37,4 +42,17 @@ public class NavigationBarFragmentTest extends FragmentTestCase { mContext.putComponent(Divider.class, mock(Divider.class)); } + @Test + public void testHomeLongPress() { + mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class)); + NavigationBarFragment navigationBarFragment = (NavigationBarFragment) mFragment; + + AssistManager assistManager = new AssistManager(mContext.getComponent(PhoneStatusBar.class), + mContext); + navigationBarFragment.setAssistManager(assistManager); + + postAndWait(() -> mFragments.dispatchResume()); + navigationBarFragment.onHomeLongClick(navigationBarFragment.getView()); + } + } diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 62ea9e335107..88bc99fc14d7 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3303,6 +3303,14 @@ message MetricsEvent { RESERVED_FOR_LOGBUILDER_TIMESTAMP = 805; RESERVED_FOR_LOGBUILDER_PACKAGENAME = 806; + // ACTION: "Force stop" action on an app + ACTION_APP_FORCE_STOP = 807; + + // OPEN: Settings > Apps > Gear > Special Access > Install other apps + // CATEGORY: SETTINGS + // OS: 8.0 + MANAGE_EXTERNAL_SOURCES = 808; + // ---- End O Constants, all O constants go above this line ---- // Add new aosp constants above this line. diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto new file mode 100644 index 000000000000..c9d5c272d48c --- /dev/null +++ b/proto/src/task_snapshot.proto @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + syntax = "proto3"; + + package com.android.server.wm; + + option java_package = "com.android.server.wm"; + option java_outer_classname = "WindowManagerProtos"; + + message TaskSnapshotProto { + int32 orientation = 1; + int32 inset_left = 2; + int32 inset_top = 3; + int32 inset_right = 4; + int32 inset_bottom = 5; + }
\ No newline at end of file diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 31ecb75c6260..7e825860ead3 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -577,15 +577,18 @@ public class BackupManagerService { public ArrayList<String> fullPackages; public IBackupObserver observer; public boolean userInitiated; + public boolean nonIncrementalBackup; BackupParams(IBackupTransport transport, String dirName, ArrayList<String> kvPackages, - ArrayList<String> fullPackages, IBackupObserver observer, boolean userInitiated) { + ArrayList<String> fullPackages, IBackupObserver observer, boolean userInitiated, + boolean nonIncrementalBackup) { this.transport = transport; this.dirName = dirName; this.kvPackages = kvPackages; this.fullPackages = fullPackages; this.observer = observer; this.userInitiated = userInitiated; + this.nonIncrementalBackup = nonIncrementalBackup; } } @@ -794,7 +797,7 @@ public class BackupManagerService { try { String dirName = transport.transportDirName(); PerformBackupTask pbt = new PerformBackupTask(transport, dirName, - queue, oldJournal, null, null, false); + queue, oldJournal, null, null, false, false /* nonIncremental */); Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt); sendMessage(pbtMessage); } catch (Exception e) { @@ -1033,7 +1036,8 @@ public class BackupManagerService { mWakelock.acquire(); PerformBackupTask pbt = new PerformBackupTask(params.transport, params.dirName, - kvQueue, null, params.observer, params.fullPackages, true); + kvQueue, null, params.observer, params.fullPackages, true, + params.nonIncrementalBackup); Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt); sendMessage(pbtMessage); break; @@ -2492,7 +2496,7 @@ public class BackupManagerService { return token; } - public int requestBackup(String[] packages, IBackupObserver observer) { + public int requestBackup(String[] packages, IBackupObserver observer, int flags) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup"); if (packages == null || packages.length < 1) { @@ -2510,6 +2514,10 @@ public class BackupManagerService { ArrayList<String> fullBackupList = new ArrayList<>(); ArrayList<String> kvBackupList = new ArrayList<>(); for (String packageName : packages) { + if (PACKAGE_MANAGER_SENTINEL.equals(packageName)) { + kvBackupList.add(packageName); + continue; + } try { PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); @@ -2543,9 +2551,12 @@ public class BackupManagerService { sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED); return BackupManager.ERROR_TRANSPORT_ABORTED; } + + boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0; + Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP); msg.obj = new BackupParams(transport, dirName, kvBackupList, fullBackupList, observer, - true); + true, nonIncrementalBackup); mBackupHandler.sendMessage(msg); return BackupManager.SUCCESS; } @@ -2673,17 +2684,20 @@ public class BackupManagerService { ParcelFileDescriptor mNewState; int mStatus; boolean mFinished; - boolean mUserInitiated; + final boolean mUserInitiated; + final boolean mNonIncremental; public PerformBackupTask(IBackupTransport transport, String dirName, ArrayList<BackupRequest> queue, File journal, IBackupObserver observer, - ArrayList<String> pendingFullBackups, boolean userInitiated) { + ArrayList<String> pendingFullBackups, boolean userInitiated, + boolean nonIncremental) { mTransport = transport; mOriginalQueue = queue; mJournal = journal; mObserver = observer; mPendingFullBackups = pendingFullBackups; mUserInitiated = userInitiated; + mNonIncremental = nonIncremental; mStateDir = new File(mBaseStateDir, dirName); @@ -2748,6 +2762,10 @@ public class BackupManagerService { // the way. mQueue = (ArrayList<BackupRequest>) mOriginalQueue.clone(); + // When the transport is forcing non-incremental key/value payloads, we send the + // metadata only if it explicitly asks for it. + boolean skipPm = mNonIncremental; + // The app metadata pseudopackage might also be represented in the // backup queue if apps have been added/removed since the last time // we performed a backup. Drop it from the working queue now that @@ -2758,6 +2776,7 @@ public class BackupManagerService { Slog.i(TAG, "Metadata in queue; eliding"); } mQueue.remove(i); + skipPm = false; break; } } @@ -2785,22 +2804,27 @@ public class BackupManagerService { } } - // The package manager doesn't have a proper <application> etc, but since - // it's running here in the system process we can just set up its agent - // directly and use a synthetic BackupRequest. We always run this pass - // because it's cheap and this way we guarantee that we don't get out of - // step even if we're selecting among various transports at run time. - if (mStatus == BackupTransport.TRANSPORT_OK) { - PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( - mPackageManager); - mStatus = invokeAgentForBackup(PACKAGE_MANAGER_SENTINEL, - IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport); - addBackupTrace("PMBA invoke: " + mStatus); + if (skipPm) { + Slog.d(TAG, "Skipping backup of package metadata."); + executeNextState(BackupState.RUNNING_QUEUE); + } else { + // The package manager doesn't have a proper <application> etc, but since + // it's running here in the system process we can just set up its agent + // directly and use a synthetic BackupRequest. We always run this pass + // because it's cheap and this way we guarantee that we don't get out of + // step even if we're selecting among various transports at run time. + if (mStatus == BackupTransport.TRANSPORT_OK) { + PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( + mPackageManager); + mStatus = invokeAgentForBackup(PACKAGE_MANAGER_SENTINEL, + IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport); + addBackupTrace("PMBA invoke: " + mStatus); - // Because the PMBA is a local instance, it has already executed its - // backup callback and returned. Blow away the lingering (spurious) - // pending timeout message for it. - mBackupHandler.removeMessages(MSG_TIMEOUT); + // Because the PMBA is a local instance, it has already executed its + // backup callback and returned. Blow away the lingering (spurious) + // pending timeout message for it. + mBackupHandler.removeMessages(MSG_TIMEOUT); + } } if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) { @@ -3066,6 +3090,7 @@ public class BackupManagerService { if (DEBUG) Slog.d(TAG, "invokeAgentForBackup on " + packageName); addBackupTrace("invoking " + packageName); + File blankStateName = new File(mStateDir, "blank_state"); mSavedStateName = new File(mStateDir, packageName); mBackupDataName = new File(mDataDir, packageName + ".data"); mNewStateName = new File(mStateDir, packageName + ".new"); @@ -3088,9 +3113,10 @@ public class BackupManagerService { } // In a full backup, we pass a null ParcelFileDescriptor as - // the saved-state "file". This is by definition an incremental, - // so we build a saved state file to pass. - mSavedState = ParcelFileDescriptor.open(mSavedStateName, + // the saved-state "file". For key/value backups we pass the old state if + // an incremental backup is required, and a blank state otherwise. + mSavedState = ParcelFileDescriptor.open( + mNonIncremental ? blankStateName : mSavedStateName, ParcelFileDescriptor.MODE_READ_ONLY | ParcelFileDescriptor.MODE_CREATE); // Make an empty file if necessary @@ -3120,6 +3146,10 @@ public class BackupManagerService { e.toString()); agentErrorCleanup(); return BackupTransport.AGENT_ERROR; + } finally { + if (mNonIncremental) { + blankStateName.delete(); + } } // At this point the agent is off and running. The next thing to happen will diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java index 312b878b284c..d677f5ee04a8 100644 --- a/services/backup/java/com/android/server/backup/Trampoline.java +++ b/services/backup/java/com/android/server/backup/Trampoline.java @@ -338,9 +338,10 @@ public class Trampoline extends IBackupManager.Stub { } @Override - public int requestBackup(String[] packages, IBackupObserver observer) throws RemoteException { + public int requestBackup(String[] packages, IBackupObserver observer, int flags) + throws RemoteException { BackupManagerService svc = mService; - return (svc != null) ? svc.requestBackup(packages, observer) : null; + return (svc != null) ? svc.requestBackup(packages, observer, flags) : null; } @Override diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index 570843e3064b..1f6294533e95 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -881,11 +881,9 @@ public class AppOpsService extends IAppOpsService.Stub { } code = AppOpsManager.opToSwitch(code); UidState uidState = getUidStateLocked(uid, false); - if (uidState != null && uidState.opModes != null) { - final int uidMode = uidState.opModes.get(code); - if (uidMode != AppOpsManager.MODE_ALLOWED) { - return uidMode; - } + if (uidState != null && uidState.opModes != null + && uidState.opModes.indexOfKey(code) >= 0) { + return uidState.opModes.get(code); } Op op = getOpLocked(code, uid, resolvedPackageName, false); if (op == null) { @@ -2126,6 +2124,7 @@ public class AppOpsService extends IAppOpsService.Stub { UidState uidState = mUidStates.valueAt(i); pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); + needSep = true; SparseIntArray opModes = uidState.opModes; if (opModes != null) { @@ -2166,6 +2165,55 @@ public class AppOpsService extends IAppOpsService.Stub { } } } + if (needSep) { + pw.println(); + } + + final int userRestrictionCount = mOpUserRestrictions.size(); + for (int i = 0; i < userRestrictionCount; i++) { + IBinder token = mOpUserRestrictions.keyAt(i); + ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); + pw.println(" User restrictions for token " + token + ":"); + + final int restrictionCount = restrictionState.perUserRestrictions != null + ? restrictionState.perUserRestrictions.size() : 0; + if (restrictionCount > 0) { + pw.println(" Restricted ops:"); + for (int j = 0; j < restrictionCount; j++) { + int userId = restrictionState.perUserRestrictions.keyAt(j); + boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j); + if (restrictedOps == null) { + continue; + } + StringBuilder restrictedOpsValue = new StringBuilder(); + restrictedOpsValue.append("["); + final int restrictedOpCount = restrictedOps.length; + for (int k = 0; k < restrictedOpCount; k++) { + if (restrictedOps[k]) { + if (restrictedOpsValue.length() > 1) { + restrictedOpsValue.append(", "); + } + restrictedOpsValue.append(AppOpsManager.opToName(k)); + } + } + restrictedOpsValue.append("]"); + pw.print(" "); pw.print("user: "); pw.print(userId); + pw.print(" restricted ops: "); pw.println(restrictedOpsValue); + } + } + + final int excludedPackageCount = restrictionState.perUserExcludedPackages != null + ? restrictionState.perUserExcludedPackages.size() : 0; + if (excludedPackageCount > 0) { + pw.println(" Excluded packages:"); + for (int j = 0; j < excludedPackageCount; j++) { + int userId = restrictionState.perUserExcludedPackages.keyAt(j); + String[] packageNames = restrictionState.perUserExcludedPackages.valueAt(j); + pw.print(" "); pw.print("user: "); pw.print(userId); + pw.print(" packages: "); pw.println(Arrays.toString(packageNames)); + } + } + } } } diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 9f63e30d061a..97edb15a2469 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -18,6 +18,7 @@ package com.android.server; import android.Manifest; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -114,6 +115,7 @@ public class DeviceIdleController extends SystemService private AlarmManager mAlarmManager; private IBatteryStats mBatteryStats; + private ActivityManagerInternal mLocalActivityManager; private PowerManagerInternal mLocalPowerManager; private PowerManager mPowerManager; private ConnectivityService mConnectivityService; @@ -1272,6 +1274,11 @@ public class DeviceIdleController extends SystemService DeviceIdleController.this.setAlarmsActive(active); } + /** Is the app on any of the power save whitelists, whether system or user? */ + public boolean isAppOnWhitelist(int appid) { + return DeviceIdleController.this.isAppOnWhitelistInternal(appid); + } + /** * Returns the array of app ids whitelisted by user. Take care not to * modify this, as it is a reference to the original copy. But the reference @@ -1289,6 +1296,12 @@ public class DeviceIdleController extends SystemService mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); } + boolean isAppOnWhitelistInternal(int appid) { + synchronized (this) { + return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0; + } + } + int[] getPowerSaveWhitelistUserAppIds() { synchronized (this) { return mPowerSaveWhitelistUserAppIdArray; @@ -1362,6 +1375,7 @@ public class DeviceIdleController extends SystemService synchronized (this) { mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); mBatteryStats = BatteryStatsService.getService(); + mLocalActivityManager = getLocalService(ActivityManagerInternal.class); mLocalPowerManager = getLocalService(PowerManagerInternal.class); mPowerManager = getContext().getSystemService(PowerManager.class); mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, @@ -1431,6 +1445,7 @@ public class DeviceIdleController extends SystemService filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); getContext().registerReceiver(mReceiver, filter); + mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray); mDisplayManager.registerDisplayListener(mDisplayListener, null); @@ -1652,7 +1667,7 @@ public class DeviceIdleController extends SystemService } catch (RemoteException e) { } postTempActiveTimeoutMessage(appId, duration); - updateTempWhitelistAppIdsLocked(); + updateTempWhitelistAppIdsLocked(appId, true); if (mNetworkPolicyTempWhitelistCallback != null) { if (!sync) { mHandler.post(mNetworkPolicyTempWhitelistCallback); @@ -1698,7 +1713,7 @@ public class DeviceIdleController extends SystemService if (DEBUG) { Slog.d(TAG, "Removing UID " + uid + " from temp whitelist"); } - updateTempWhitelistAppIdsLocked(); + updateTempWhitelistAppIdsLocked(uid, false); if (mNetworkPolicyTempWhitelistCallback != null) { mHandler.post(mNetworkPolicyTempWhitelistCallback); } @@ -2318,6 +2333,13 @@ public class DeviceIdleController extends SystemService mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds); mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null, mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds); + if (mLocalActivityManager != null) { + if (DEBUG) { + Slog.d(TAG, "Setting activity manager whitelist to " + + Arrays.toString(mPowerSaveWhitelistAllAppIdArray)); + } + mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); + } if (mLocalPowerManager != null) { if (DEBUG) { Slog.d(TAG, "Setting wakelock whitelist to " @@ -2334,7 +2356,7 @@ public class DeviceIdleController extends SystemService } } - private void updateTempWhitelistAppIdsLocked() { + private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) { final int size = mTempWhitelistAppIdEndTimes.size(); if (mTempWhitelistAppIdArray.length != size) { mTempWhitelistAppIdArray = new int[size]; @@ -2342,6 +2364,14 @@ public class DeviceIdleController extends SystemService for (int i = 0; i < size; i++) { mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i); } + if (mLocalActivityManager != null) { + if (DEBUG) { + Slog.d(TAG, "Setting activity manager temp whitelist to " + + Arrays.toString(mTempWhitelistAppIdArray)); + } + mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, appId, + adding); + } if (mLocalPowerManager != null) { if (DEBUG) { Slog.d(TAG, "Setting wakelock temp whitelist to " @@ -2512,8 +2542,9 @@ public class DeviceIdleController extends SystemService pw.println(" Add (prefix with +) or remove (prefix with -) packages."); pw.println(" tempwhitelist"); pw.println(" Print packages that are temporarily whitelisted."); - pw.println(" tempwhitelist [-u] [package ..]"); - pw.println(" Temporarily place packages in whitelist for 10 seconds."); + pw.println(" tempwhitelist [-u USER] [-d DURATION] [package ..]"); + pw.println(" Temporarily place packages in whitelist for DURATION milliseconds."); + pw.println(" If no DURATION is specified, 10 seconds is used"); } class Shell extends ShellCommand { @@ -2796,6 +2827,7 @@ public class DeviceIdleController extends SystemService } } } else if ("tempwhitelist".equals(cmd)) { + long duration = 10000; String opt; while ((opt=shell.getNextOption()) != null) { if ("-u".equals(opt)) { @@ -2805,12 +2837,19 @@ public class DeviceIdleController extends SystemService return -1; } shell.userId = Integer.parseInt(opt); + } else if ("-d".equals(opt)) { + opt = shell.getNextArg(); + if (opt == null) { + pw.println("-d requires a duration"); + return -1; + } + duration = Long.parseLong(opt); } } String arg = shell.getNextArg(); if (arg != null) { try { - addPowerSaveTempWhitelistAppChecked(arg, 10000L, shell.userId, "shell"); + addPowerSaveTempWhitelistAppChecked(arg, duration, shell.userId, "shell"); } catch (RemoteException re) { pw.println("Failed: " + re); } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 62f4f19a6028..0834eb8f9cba 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -1360,6 +1360,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Bundle data = new Bundle(); state.fillInNotifierBundle(data); intent.putExtras(data); diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 11e1a9d9b05f..0a6c62f54564 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -505,7 +505,9 @@ public class AccountManagerService * @param ua UserAccount that currently hosts the account and application */ private void registerAccountTypesSupported(int uid, UserAccounts ua) { - /* Account types supported are drawn from the Android Manifest of the Application */ + return; + // TODO clean up the code, manifest entry is deprecated + /* String interestedPackages = null; try { String[] allPackages = mPackageManager.getPackagesForUid(uid); @@ -527,6 +529,7 @@ public class AccountManagerService // TODO request visibility // requestAccountVisibility(interestedPackages.split(";"), uid, ua); } + */ } /** @@ -536,6 +539,8 @@ public class AccountManagerService * @param visibleAccount to send to package */ private void sendNotification(String desiredPackage, Account visibleAccount) { + // TODO replace with callback + /* Intent intent = new Intent(); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.setAction(AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED); @@ -543,6 +548,7 @@ public class AccountManagerService // TODO update documentation, add account extra if new account became visible // intent.putExtra("android.accounts.KEY_ACCOUNT", (Account) visibleAccount); mContext.sendBroadcast(intent); + */ } @Override diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 7661127927e1..4b89b404f9b6 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -305,6 +305,7 @@ public final class ActiveServices { } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, + int id, Notification notification, int callingPid, int callingUid, String callingPackage, final int userId) throws TransactionTooLargeException { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service @@ -324,7 +325,6 @@ public final class ActiveServices { callerFg = true; } - ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false); @@ -343,10 +343,11 @@ public final class ActiveServices { return null; } - if (!r.startRequested) { + // Non-null notification means this is a start directly into the foreground + if (!r.startRequested && notification == null) { final long token = Binder.clearCallingIdentity(); try { - // Before going further -- if this app is not allowed to run in the + // Before going further -- if this app is not allowed to start services in the // background, then at this point we aren't going to let it period. final int allowed = mAm.checkAllowBackgroundLocked( r.appInfo.uid, r.packageName, callingPid, false); @@ -355,7 +356,14 @@ public final class ActiveServices { + service + " to " + r.name.flattenToShortString() + " from pid=" + callingPid + " uid=" + callingUid + " pkg=" + callingPackage); - return null; + if (allowed == ActivityManager.APP_START_MODE_DELAYED) { + // In this case we are silently disabling the app, to disrupt as + // little as possible existing apps. + return null; + } + // This app knows it is in the new model where this operation is not + // allowed, so tell it what has happened. + return new ComponentName("?", "app is in background"); } } finally { Binder.restoreCallingIdentity(token); @@ -450,7 +458,11 @@ public final class ActiveServices { } } - return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); + ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); + if (notification != null) { + setServiceForegroundInnerLocked(r, callingUid, notification, 0); + } + return cmp; } private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r, @@ -595,9 +607,8 @@ public final class ActiveServices { for (int i=services.mServicesByName.size()-1; i>=0; i--) { ServiceRecord service = services.mServicesByName.valueAt(i); if (service.appInfo.uid == uid && service.startRequested) { - if (service.appInfo.isEphemeralApp() || - mAm.mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, - uid, service.packageName) != AppOpsManager.MODE_ALLOWED) { + if (mAm.checkAllowBackgroundLocked(service.appInfo.uid, service.packageName, + -1, false) != ActivityManager.APP_START_MODE_NORMAL) { if (stopping == null) { stopping = new ArrayList<>(); stopping.add(service); @@ -696,50 +707,55 @@ public final class ActiveServices { try { ServiceRecord r = findServiceLocked(className, token, userId); if (r != null) { - if (id != 0) { - if (notification == null) { - throw new IllegalArgumentException("null notification"); - } - if (r.foregroundId != id) { - cancelForegroudNotificationLocked(r); - r.foregroundId = id; - } - notification.flags |= Notification.FLAG_FOREGROUND_SERVICE; - r.foregroundNoti = notification; - r.isForeground = true; - r.postNotification(); - if (r.app != null) { - updateServiceForegroundLocked(r.app, true); - } - getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r); - mAm.notifyPackageUse(r.serviceInfo.packageName, - PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE); - } else { - if (r.isForeground) { - r.isForeground = false; - if (r.app != null) { - mAm.updateLruProcessLocked(r.app, false, null); - updateServiceForegroundLocked(r.app, true); - } - } - if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) { - cancelForegroudNotificationLocked(r); - r.foregroundId = 0; - r.foregroundNoti = null; - } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { - r.stripForegroundServiceFlagFromNotification(); - if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) { - r.foregroundId = 0; - r.foregroundNoti = null; - } - } - } + setServiceForegroundInnerLocked(r, userId, notification, flags); } } finally { Binder.restoreCallingIdentity(origId); } } + private void setServiceForegroundInnerLocked(ServiceRecord r, int id, + Notification notification, int flags) { + if (id != 0) { + if (notification == null) { + throw new IllegalArgumentException("null notification"); + } + if (r.foregroundId != id) { + cancelForegroudNotificationLocked(r); + r.foregroundId = id; + } + notification.flags |= Notification.FLAG_FOREGROUND_SERVICE; + r.foregroundNoti = notification; + r.isForeground = true; + r.postNotification(); + if (r.app != null) { + updateServiceForegroundLocked(r.app, true); + } + getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r); + mAm.notifyPackageUse(r.serviceInfo.packageName, + PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE); + } else { + if (r.isForeground) { + r.isForeground = false; + if (r.app != null) { + mAm.updateLruProcessLocked(r.app, false, null); + updateServiceForegroundLocked(r.app, true); + } + } + if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) { + cancelForegroudNotificationLocked(r); + r.foregroundId = 0; + r.foregroundNoti = null; + } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { + r.stripForegroundServiceFlagFromNotification(); + if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) { + r.foregroundId = 0; + r.foregroundNoti = null; + } + } + } + } + private void cancelForegroudNotificationLocked(ServiceRecord r) { if (r.foregroundId != 0) { // First check to see if this app has any other active foreground services @@ -1444,6 +1460,8 @@ public final class ActiveServices { // If service is not currently running, can't yet bind. return false; } + if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested + + " rebind=" + rebind); if ((!i.requested || rebind) && i.apps.size() > 0) { try { bumpServiceExecutingLocked(r, execInFg, "bind"); @@ -1907,6 +1925,7 @@ public final class ActiveServices { mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants, si.getUriPermissionsLocked()); } + // TODO b/34123112; Insert ephemeral grant here bumpServiceExecutingLocked(r, execInFg, "start"); if (!oomAdjusted) { oomAdjusted = true; @@ -2014,6 +2033,7 @@ public final class ActiveServices { bumpServiceExecutingLocked(r, false, "bring down unbind"); mAm.updateOomAdjLocked(r.app); ibr.hasBound = false; + ibr.requested = false; r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent()); } catch (Exception e) { diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java index 43bb5ee8d3e4..88e0d0393450 100644 --- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java +++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java @@ -48,6 +48,7 @@ class ActivityManagerDebugConfig { static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false; static final boolean DEBUG_ANR = false; static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false; + static final boolean DEBUG_BACKGROUND_CHECK = DEBUG_ALL || false; static final boolean DEBUG_BACKUP = DEBUG_ALL || false; static final boolean DEBUG_BROADCAST = DEBUG_ALL || false; static final boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2a324ebafbd7..75ae43b02329 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -62,6 +62,7 @@ import static com.android.internal.util.XmlUtils.writeIntAttribute; import static com.android.internal.util.XmlUtils.writeLongAttribute; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR; +import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND; @@ -119,6 +120,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_B import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS; +import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED; import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS; import static com.android.server.am.ActivityStackSupervisor.ON_TOP; @@ -151,7 +153,6 @@ import android.app.ActivityManager.StackInfo; import android.app.ActivityManager.TaskSnapshot; import android.app.ActivityManager.TaskThumbnailInfo; import android.app.ActivityManagerInternal; -import android.app.ActivityManagerInternal.PictureInPictureArguments; import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityOptions; import android.app.ActivityThread; @@ -182,6 +183,7 @@ import android.app.Instrumentation; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.PictureInPictureArgs; import android.app.ProfilerInfo; import android.app.RemoteAction; import android.app.WaitResult; @@ -229,7 +231,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Bitmap; -import android.graphics.GraphicBuffer; import android.graphics.Point; import android.graphics.Rect; import android.location.LocationManager; @@ -310,7 +311,6 @@ import android.view.WindowManager; import com.google.android.collect.Lists; import com.google.android.collect.Maps; - import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.AssistUtils; @@ -341,6 +341,7 @@ import com.android.server.IntentResolver; import com.android.server.LocalServices; import com.android.server.LockGuard; import com.android.server.ServiceThread; +import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.Watchdog; @@ -384,10 +385,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import dalvik.system.VMRuntime; + import libcore.io.IoUtils; import libcore.util.EmptyArray; -import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED; public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { @@ -758,6 +759,23 @@ public class ActivityManagerService extends IActivityManager.Stub ProcessRecord mHeavyWeightProcess = null; /** + * Are we enforcing background restrictions? + */ + final boolean mEnforceBackgroundCheck; + + /** + * Non-persistent app uid whitelist for background restrictions + */ + int[] mBackgroundUidWhitelist = new int[] { + Process.BLUETOOTH_UID + }; + + /** + * Broadcast actions that will always be deliverable to unlaunched/background apps + */ + final ArraySet<String> mBackgroundLaunchBroadcasts; + + /** * All of the processes we currently have running organized by pid. * The keys are the pid running the application. * @@ -1135,6 +1153,16 @@ public class ActivityManagerService extends IActivityManager.Stub DeviceIdleController.LocalService mLocalDeviceIdleController; /** + * Set of app ids that are whitelisted for device idle and thus background check. + */ + int[] mDeviceIdleWhitelist = new int[0]; + + /** + * Set of app ids that are temporarily allowed to escape bg check due to high-pri message + */ + int[] mDeviceIdleTempWhitelist = new int[0]; + + /** * Information about and control over application operations */ final AppOpsService mAppOpsService; @@ -2590,6 +2618,19 @@ public class ActivityManagerService extends IActivityManager.Stub mPermissionReviewRequired = mContext.getResources().getBoolean( com.android.internal.R.bool.config_permissionReviewRequired); + mEnforceBackgroundCheck = SystemProperties.getBoolean("debug.bgcheck", false); + mBackgroundLaunchBroadcasts = SystemConfig.getInstance().getAllowImplicitBroadcasts(); + if (DEBUG_BACKGROUND_CHECK) { + Slog.d(TAG, "Enforcing O+ bg restrictions: " + mEnforceBackgroundCheck); + StringBuilder sb = new StringBuilder(200); + sb.append(" "); + for (String a : mBackgroundLaunchBroadcasts) { + sb.append(' '); sb.append(a); + } + Slog.d(TAG, "Background implicit broadcasts:"); + Slog.d(TAG, sb.toString()); + } + mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); mHandlerThread.start(); @@ -4190,7 +4231,7 @@ public class ActivityManagerService extends IActivityManager.Stub validateUid = mValidateUids.get(item.uid); if (validateUid == null && change != UidRecord.CHANGE_GONE && change != UidRecord.CHANGE_GONE_IDLE) { - validateUid = new UidRecord(item.uid); + validateUid = new UidRecord(item.uid, false); mValidateUids.put(item.uid, validateUid); } } @@ -5504,6 +5545,7 @@ public class ActivityManagerService extends IActivityManager.Stub final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED, Uri.fromParts("package", packageName, null)); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putExtra(Intent.EXTRA_UID, pkgUidF); intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF)); broadcastIntentInPackage("android", Process.SYSTEM_UID, intent, @@ -5524,11 +5566,9 @@ public class ActivityManagerService extends IActivityManager.Stub removeUriPermissionsForPackageLocked(packageName, userId, true); } - // Remove all zen rules created by this package; revoke it's zen access. + // Reset notification settings. INotificationManager inm = NotificationManager.getService(); - inm.removeAutomaticZenRules(packageName); - inm.setNotificationPolicyAccessGranted(packageName, false); - + inm.clearData(packageName, pkgUidF); } catch (RemoteException e) { } } finally { @@ -6279,10 +6319,13 @@ public class ActivityManagerService extends IActivityManager.Stub } UidRecord uidRec = mActiveUids.get(proc.uid); if (uidRec == null) { - uidRec = new UidRecord(proc.uid); + uidRec = new UidRecord(proc.uid, proc.persistent); // This is the first appearance of the uid, report it now! if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Creating new process uid: " + uidRec); + if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0) { + uidRec.setWhitelist = uidRec.curWhitelist = true; + } mActiveUids.put(proc.uid, uidRec); noteUidProcessState(uidRec.uid, uidRec.curProcState); enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE); @@ -7556,45 +7599,31 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void enterPictureInPictureMode(IBinder token) { - enterPictureInPictureMode(token, DEFAULT_DISPLAY, -1f /* aspectRatio */, - false /* checkAspectRatio */); - } - - @Override - public void enterPictureInPictureModeWithAspectRatio(IBinder token, float aspectRatio) { - enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio, true /* checkAspectRatio */); - } - - @Override - public void enterPictureInPictureModeOnMoveToBackground(IBinder token, - boolean enterPictureInPictureOnMoveToBg) { + public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureArgs args) { final long origId = Binder.clearCallingIdentity(); try { synchronized(this) { - final ActivityRecord r = ensureValidPictureInPictureActivityLocked( - "enterPictureInPictureModeOnMoveToBackground", token, -1f /* aspectRatio */, - false /* checkAspectRatio */, false /* checkActivityVisibility */); + final ActivityRecord r = ensureValidPictureInPictureActivityArgsLocked( + "enterPictureInPictureMode", token, args); - r.supportsPipOnMoveToBackground = enterPictureInPictureOnMoveToBg; - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } + // Activity supports picture-in-picture, now check that we can enter PiP at this + // point, if it is + if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode")) { + return false; + } - private void enterPictureInPictureMode(IBinder token, int displayId, float aspectRatio, - boolean checkAspectRatio) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized(this) { - final ActivityRecord r = ensureValidPictureInPictureActivityLocked( - "enterPictureInPictureMode", token, aspectRatio, checkAspectRatio, - true /* checkActivityVisibility */); final Runnable enterPipRunnable = () -> { - r.pictureInPictureArgs.aspectRatio = aspectRatio; - enterPictureInPictureModeLocked(r, displayId, r.pictureInPictureArgs, - true /* moveHomeStackToFront */, "enterPictureInPictureMode"); + // Only update the saved args from the args that are set + r.pictureInPictureArgs.copyOnlySet(args); + final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); + final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); + final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio) + ? mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, + aspectRatio) + : mWindowManager.getPictureInPictureDefaultBounds(DEFAULT_DISPLAY); + mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode", + bounds, true /* moveHomeStackToFront */); + mWindowManager.setPictureInPictureActions(actions); }; if (isKeyguardLocked()) { @@ -7625,35 +7654,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Enter picture in picture immediately otherwise enterPipRunnable.run(); } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - void enterPictureInPictureModeLocked(ActivityRecord r, int displayId, - PictureInPictureArguments pipArgs, boolean moveHomeStackToFront, String reason) { - final Rect bounds = isValidPictureInPictureAspectRatio(pipArgs.aspectRatio) - ? mWindowManager.getPictureInPictureBounds(displayId, pipArgs.aspectRatio) - : mWindowManager.getPictureInPictureDefaultBounds(displayId); - mStackSupervisor.moveActivityToPinnedStackLocked(r, reason, bounds, moveHomeStackToFront); - mWindowManager.setPictureInPictureActions(pipArgs.userActions); - } - - @Override - public void setPictureInPictureAspectRatio(IBinder token, float aspectRatio) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized(this) { - final ActivityRecord r = ensureValidPictureInPictureActivityLocked( - "setPictureInPictureAspectRatio", token, aspectRatio, - true /* checkAspectRatio */, false /* checkActivityVisibility */); - - r.pictureInPictureArgs.aspectRatio = aspectRatio; - if (r.getStack().getStackId() == PINNED_STACK_ID) { - // If the activity is already in picture-in-picture, update the pinned stack now - mWindowManager.setPictureInPictureAspectRatio(aspectRatio); - } + return true; } } finally { Binder.restoreCallingIdentity(origId); @@ -7661,26 +7662,21 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void setPictureInPictureActions(IBinder token, ParceledListSlice actionsList) { + public void setPictureInPictureArgs(IBinder token, final PictureInPictureArgs args) { final long origId = Binder.clearCallingIdentity(); try { synchronized(this) { - final ActivityRecord r = ensureValidPictureInPictureActivityLocked( - "setPictureInPictureActions", token, -1 /* aspectRatio */, - false /* checkAspectRatio */, false /* checkActivityVisibility */); + final ActivityRecord r = ensureValidPictureInPictureActivityArgsLocked( + "setPictureInPictureArgs", token, args); - final List<RemoteAction> actions = actionsList.getList(); - if (actions.size() > ActivityManager.getMaxNumPictureInPictureActions()) { - throw new IllegalArgumentException("setPictureInPictureActions: Invalid number" - + " of picture-in-picture actions. Only a maximum of " - + ActivityManager.getMaxNumPictureInPictureActions() - + " actions allowed"); - } - - r.pictureInPictureArgs.userActions = actions; + // Only update the saved args from the args that are set + r.pictureInPictureArgs.copyOnlySet(args); if (r.getStack().getStackId() == PINNED_STACK_ID) { // If the activity is already in picture-in-picture, update the pinned stack now - mWindowManager.setPictureInPictureActions(actions); + mWindowManager.setPictureInPictureAspectRatio( + r.pictureInPictureArgs.getAspectRatio()); + mWindowManager.setPictureInPictureActions( + r.pictureInPictureArgs.getActions()); } } } finally { @@ -7696,14 +7692,10 @@ public class ActivityManagerService extends IActivityManager.Stub * Checks the state of the system and the activity associated with the given {@param token} to * verify that picture-in-picture is supported for that activity. * - * @param checkAspectRatio whether or not to check {@param aspectRatio} is within a valid range - * @param checkActivityVisibility whether or not to enforce that the activity is currently - * visible - * * @return the activity record for the given {@param token} if all the checks pass. */ - private ActivityRecord ensureValidPictureInPictureActivityLocked(String caller, IBinder token, - float aspectRatio, boolean checkAspectRatio, boolean checkActivityVisibility) { + private ActivityRecord ensureValidPictureInPictureActivityArgsLocked(String caller, + IBinder token, PictureInPictureArgs args) { if (!mSupportsPictureInPicture) { throw new IllegalStateException(caller + ": Device doesn't support picture-in-picture mode."); @@ -7715,10 +7707,9 @@ public class ActivityManagerService extends IActivityManager.Stub + ": Can't find activity for token=" + token); } - if (!r.canEnterPictureInPicture(checkActivityVisibility)) { - throw new IllegalArgumentException(caller - + ": Current activity does not support picture-in-picture or is not " - + "visible r=" + r); + if (!r.supportsPictureInPicture()) { + throw new IllegalStateException(caller + + ": Current activity does not support picture-in-picture."); } if (r.getStack().isHomeStack()) { @@ -7726,12 +7717,20 @@ public class ActivityManagerService extends IActivityManager.Stub + ": Activities on the home stack not supported"); } - if (checkAspectRatio && !isValidPictureInPictureAspectRatio(aspectRatio)) { + if (args.hasSetAspectRatio() + && !isValidPictureInPictureAspectRatio(args.getAspectRatio())) { throw new IllegalArgumentException(String.format(caller + ": Aspect ratio is too extreme (must be between %f and %f).", mMinPipAspectRatio, mMaxPipAspectRatio)); } + if (args.hasSetActions() + && args.getActions().size() > ActivityManager.getMaxNumPictureInPictureActions()) { + throw new IllegalArgumentException(String.format(caller + ": Invalid number of" + + "picture-in-picture actions. Only a maximum of %d actions allowed", + ActivityManager.getMaxNumPictureInPictureActions())); + } + return r; } @@ -8026,9 +8025,97 @@ public class ActivityManagerService extends IActivityManager.Stub } } + // Unified app-op and target sdk check + int appRestrictedInBackgroundLocked(int uid, String packageName) { + if (packageName == null) { + packageName = mPackageManagerInt.getNameForUid(uid); + if (packageName == null) { + Slog.w(TAG, "No package known for uid " + uid); + return ActivityManager.APP_START_MODE_NORMAL; + } + } + + // !!! TODO: cache the package/versionCode lookups to fast path this + ApplicationInfo app = getPackageManagerInternalLocked().getApplicationInfo(packageName, + UserHandle.getUserId(uid)); + if (app != null) { + // Apps that target O+ are always subject to background check + if (mEnforceBackgroundCheck && app.targetSdkVersion >= Build.VERSION_CODES.O) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted"); + } + return ActivityManager.APP_START_MODE_DELAYED_RIGID; + } + // ...and legacy apps get an AppOp check + int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, + uid, packageName); + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop); + } + switch (appop) { + case AppOpsManager.MODE_ALLOWED: + return ActivityManager.APP_START_MODE_NORMAL; + case AppOpsManager.MODE_IGNORED: + return ActivityManager.APP_START_MODE_DELAYED; + default: + return ActivityManager.APP_START_MODE_DELAYED_RIGID; + } + } else { + Slog.w(TAG, "Unknown app " + packageName + " / " + uid); + } + return ActivityManager.APP_START_MODE_NORMAL; + } + + // Service launch is available to apps with run-in-background exemptions but + // some other background operations are not. If we're doing a check + // of service-launch policy, allow those callers to proceed unrestricted. + int appServicesRestrictedInBackgroundLocked(int uid, String packageName) { + if (packageName == null) { + packageName = mPackageManagerInt.getNameForUid(uid); + if (packageName == null) { + Slog.w(TAG, "No package known for uid " + uid); + return ActivityManager.APP_START_MODE_NORMAL; + } + } + + // Persistent app? NB: expects that persistent uids are always active. + final UidRecord uidRec = mActiveUids.get(uid); + if (uidRec != null && uidRec.persistent) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "App " + uid + "/" + packageName + + " is persistent; not restricted in background"); + } + return ActivityManager.APP_START_MODE_NORMAL; + } + + // Non-persistent but background whitelisted? + if (uidOnBackgroundWhitelist(uid)) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "App " + uid + "/" + packageName + + " on background whitelist; not restricted in background"); + } + return ActivityManager.APP_START_MODE_NORMAL; + } + + // Is this app on the battery whitelist? + if (isOnDeviceIdleWhitelistLocked(uid)) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "App " + uid + "/" + packageName + + " on idle whitelist; not restricted in background"); + } + return ActivityManager.APP_START_MODE_NORMAL; + } + + // None of the service-policy criteria apply, so we apply the common criteria + return appRestrictedInBackgroundLocked(uid, packageName); + } + int checkAllowBackgroundLocked(int uid, String packageName, int callingPid, boolean alwaysRestrict) { UidRecord uidRec = mActiveUids.get(uid); + if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + " pkg=" + + packageName + " rec=" + uidRec + " always=" + alwaysRestrict + " idle=" + + (uidRec != null ? uidRec.idle : false)); if (uidRec == null || alwaysRestrict || uidRec.idle) { boolean ephemeral; if (uidRec == null) { @@ -8042,6 +8129,7 @@ public class ActivityManagerService extends IActivityManager.Stub // We are hard-core about ephemeral apps not running in the background. return ActivityManager.APP_START_MODE_DISABLED; } else { + /** Don't want to allow this exception in the final background check impl? if (callingPid >= 0) { ProcessRecord proc; synchronized (mPidsSelfLocked) { @@ -8054,15 +8142,26 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManager.APP_START_MODE_NORMAL; } } - if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, - packageName) != AppOpsManager.MODE_ALLOWED) { - return ActivityManager.APP_START_MODE_DELAYED; - } + */ + + final int startMode = (alwaysRestrict) + ? appRestrictedInBackgroundLocked(uid, packageName) + : appServicesRestrictedInBackgroundLocked(uid, packageName); + if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + + " pkg=" + packageName + " startMode=" + startMode + + " onwhitelist=" + isOnDeviceIdleWhitelistLocked(uid)); + return startMode; } } return ActivityManager.APP_START_MODE_NORMAL; } + boolean isOnDeviceIdleWhitelistLocked(int uid) { + final int appId = UserHandle.getAppId(uid); + return Arrays.binarySearch(mDeviceIdleWhitelist, appId) >= 0 + || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0; + } + private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) { ProviderInfo pi = null; ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userHandle); @@ -8079,6 +8178,12 @@ public class ActivityManagerService extends IActivityManager.Stub return pi; } + void grantEphemeralAccessLocked(int userId, Intent intent, + int targetAppId, int ephemeralAppId) { + getPackageManagerInternalLocked(). + grantEphemeralAccess(userId, intent, targetAppId, ephemeralAppId); + } + private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) { final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); if (targetUris != null) { @@ -11651,6 +11756,16 @@ public class ActivityManagerService extends IActivityManager.Stub return r; } + private boolean uidOnBackgroundWhitelist(final int uid) { + final int N = mBackgroundUidWhitelist.length; + for (int i = 0; i < N; i++) { + if (uid == mBackgroundUidWhitelist[i]) { + return true; + } + } + return false; + } + final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated, String abiOverride) { ProcessRecord app; @@ -14977,6 +15092,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } } + pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist)); + pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist)); } if (dumpPackage == null) { pw.println(" mWakefulness=" @@ -17284,7 +17401,8 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public ComponentName startService(IApplicationThread caller, Intent service, - String resolvedType, String callingPackage, int userId) + String resolvedType, int id, Notification notification, + String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // Refuse possible leaked file descriptors @@ -17303,7 +17421,8 @@ public class ActivityManagerService extends IActivityManager.Stub final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(caller, service, - resolvedType, callingPid, callingUid, callingPackage, userId); + resolvedType, id, notification, + callingPid, callingUid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; } @@ -17317,7 +17436,7 @@ public class ActivityManagerService extends IActivityManager.Stub "startServiceInPackage: " + service + " type=" + resolvedType); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(null, service, - resolvedType, -1, uid, callingPackage, userId); + resolvedType, 0, null, -1, uid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; } @@ -18176,6 +18295,13 @@ public class ActivityManagerService extends IActivityManager.Stub } if (action != null) { + if (mBackgroundLaunchBroadcasts.contains(action)) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "Broadcast action " + action + " forcing include-background"); + } + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + } + switch (action) { case Intent.ACTION_UID_REMOVED: case Intent.ACTION_PACKAGE_REMOVED: @@ -19300,7 +19426,8 @@ public class ActivityManagerService extends IActivityManager.Stub UserHandle.USER_ALL); if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) { intent = new Intent(Intent.ACTION_LOCALE_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); if (initLocale || !mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } @@ -21623,12 +21750,18 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i=mActiveUids.size()-1; i>=0; i--) { final UidRecord uidRec = mActiveUids.valueAt(i); int uidChange = UidRecord.CHANGE_PROCSTATE; - if (uidRec.setProcState != uidRec.curProcState) { + if (uidRec.setProcState != uidRec.curProcState + || uidRec.setWhitelist != uidRec.curWhitelist) { if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec + ": proc state from " + uidRec.setProcState - + " to " + uidRec.curProcState); - if (ActivityManager.isProcStateBackground(uidRec.curProcState)) { - if (!ActivityManager.isProcStateBackground(uidRec.setProcState)) { + + " to " + uidRec.curProcState + ", whitelist from " + uidRec.setWhitelist + + " to " + uidRec.curWhitelist); + if (ActivityManager.isProcStateBackground(uidRec.curProcState) + && !uidRec.curWhitelist) { + // UID is now in the background (and not on the temp whitelist). Was it + // previously in the foreground (or on the temp whitelist)? + if (!ActivityManager.isProcStateBackground(uidRec.setProcState) + || uidRec.setWhitelist) { uidRec.lastBackgroundTime = nowElapsed; if (!mHandler.hasMessages(IDLE_UIDS_MSG)) { // Note: the background settle time is in elapsed realtime, while @@ -21646,6 +21779,7 @@ public class ActivityManagerService extends IActivityManager.Stub uidRec.lastBackgroundTime = 0; } uidRec.setProcState = uidRec.curProcState; + uidRec.setWhitelist = uidRec.curWhitelist; enqueueUidChangeLocked(uidRec, -1, uidChange); noteUidProcessState(uidRec.uid, uidRec.curProcState); } @@ -21789,6 +21923,20 @@ public class ActivityManagerService extends IActivityManager.Stub enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE); } + final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) { + boolean changed = false; + for (int i=mActiveUids.size()-1; i>=0; i--) { + final UidRecord uidRec = mActiveUids.valueAt(i); + if (UserHandle.getAppId(uidRec.uid) == appId && uidRec.curWhitelist != onWhitelist) { + uidRec.curWhitelist = onWhitelist; + changed = true; + } + } + if (changed) { + updateOomAdjLocked(); + } + } + final void trimApplications() { synchronized (this) { int i; @@ -22494,6 +22642,21 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void setDeviceIdleWhitelist(int[] appids) { + synchronized (ActivityManagerService.this) { + mDeviceIdleWhitelist = appids; + } + } + + @Override + public void updateDeviceIdleTempWhitelist(int[] appids, int changingAppId, boolean adding) { + synchronized (ActivityManagerService.this) { + mDeviceIdleTempWhitelist = appids; + setAppIdTempWhitelistStateLocked(changingAppId, adding); + } + } + + @Override public void updatePersistentConfigurationForUser(@NonNull Configuration values, int userId) { Preconditions.checkNotNull(values, "Configuration must not be null"); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index ed311303c04f..202868a3da42 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -171,7 +171,7 @@ final class ActivityManagerShellCommand extends ShellCommand { return runKill(pw); case "kill-all": return runKillAll(pw); - case "make-idle": + case "make-uid-idle": return runMakeIdle(pw); case "monitor": return runMonitor(pw); @@ -492,7 +492,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println("Starting service: " + intent); pw.flush(); ComponentName cn = mInterface.startService(null, intent, intent.getType(), - SHELL_PACKAGE_NAME, mUserId); + -1, null, SHELL_PACKAGE_NAME, mUserId); if (cn == null) { err.println("Error: Not found; no service started."); return -1; @@ -502,6 +502,9 @@ final class ActivityManagerShellCommand extends ShellCommand { } else if (cn.getPackageName().equals("!!")) { err.println("Error: " + cn.getClassName()); return -1; + } else if (cn.getPackageName().equals("?")) { + err.println("Error: " + cn.getClassName()); + return -1; } return 0; } @@ -2481,6 +2484,9 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" Kill all processes associated with the given application."); pw.println(" kill-all"); pw.println(" Kill all processes that are safe to kill (cached, etc)."); + pw.println(" make-uid-idle [--user <USER_ID> | all | current] <PACKAGE>"); + pw.println(" If the given application's uid is in the background and waiting to"); + pw.println(" become idle (not allowing background services), do that now."); pw.println(" monitor [--gdb <port>]"); pw.println(" Start monitoring for crashes or ANRs."); pw.println(" --gdb: start gdbserv on the given port at crash/ANR"); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 40428c4f1960..a968e0bb2a47 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -63,9 +63,9 @@ import static com.android.server.am.TaskRecord.INVALID_TASK_ID; import android.annotation.NonNull; import android.app.ActivityManager.TaskDescription; -import android.app.ActivityManagerInternal.PictureInPictureArguments; import android.app.ActivityOptions; import android.app.PendingIntent; +import android.app.PictureInPictureArgs; import android.app.ResultInfo; import android.content.ComponentName; import android.content.Intent; @@ -230,13 +230,10 @@ final class ActivityRecord implements AppWindowContainerListener { boolean frozenBeforeDestroy;// has been frozen but not yet destroyed. boolean immersive; // immersive mode (don't interrupt if possible) boolean forceNewConfig; // force re-create with new config next time - boolean supportsPipOnMoveToBackground; // Supports automatically entering picture-in-picture - // when this activity is hidden. This flag is requested by the activity. - private boolean enterPipOnMoveToBackground; // Flag to enter picture in picture when this - // activity is made invisible. This flag is set specifically when another task is being - // launched or moved to the front which may cause this activity to try and enter PiP - // when it is next made invisible. - PictureInPictureArguments pictureInPictureArgs = new PictureInPictureArguments(); // The PiP + boolean supportsPictureInPictureWhilePausing; // This flag is set by the system to indicate + // that the activity can enter picture in picture while pausing (ie. only when another + // task is brought to front or started) + PictureInPictureArgs pictureInPictureArgs = new PictureInPictureArgs(); // The PiP // arguments used when deferring the entering of picture-in-picture. int launchCount; // count of launches since last state long lastLaunchTime; // time of last launch of this activity @@ -454,12 +451,8 @@ final class ActivityRecord implements AppWindowContainerListener { if (info != null) { pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode)); } - if (supportsPipOnMoveToBackground) { - pw.println(prefix + "supportsPipOnMoveToBackground=1"); - pw.println(prefix + "enterPipOnMoveToBackground=" + - (enterPipOnMoveToBackground ? 1 : 0)); - pictureInPictureArgs.dump(pw, prefix); - } + pw.println(prefix + "supportsPictureInPictureWhilePausing: " + + supportsPictureInPictureWhilePausing); } private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) { @@ -821,23 +814,6 @@ final class ActivityRecord implements AppWindowContainerListener { } /** - * If this activity has requested that it auto-enter picture-in-picture and we can actually do - * this, then mark it to enter picture in picture at that point. - */ - void setEnterPipOnMoveToBackground(boolean enterPipOnInvisible) { - if (supportsPipOnMoveToBackground) { - enterPipOnMoveToBackground = enterPipOnInvisible; - } - } - - /** - * @return whether to enter PiP when this activity is made invisible. - */ - public boolean shouldEnterPictureInPictureOnInvisible() { - return enterPipOnMoveToBackground; - } - - /** * @return Stack value from current task, null if there is no task. */ ActivityStack getStack() { @@ -920,24 +896,34 @@ final class ActivityRecord implements AppWindowContainerListener { } /** - * @return whether this activity is currently allowed to enter PIP, if - * {@param checkActivityVisibility} is set, then the current activity visibility is taken into - * account. + * @return whether this activity is currently allowed to enter PIP, throwing an exception if + * the activity is not currently visible. */ - boolean canEnterPictureInPicture(boolean checkActivityVisibility) { - if (!checkActivityVisibility) { - return supportsPictureInPicture(); - } - - if (supportsPictureInPicture()) { - switch (state) { - case RESUMED: - case PAUSING: - case PAUSED: - return true; - } + boolean checkEnterPictureInPictureState(String caller) { + boolean isKeyguardLocked = service.isKeyguardLocked(); + boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null; + switch (state) { + case RESUMED: + // When visible, allow entering PiP if not on the lockscreen. If there is another + // PiP activity, the logic to handle that comes later in enterPictureInPictureMode() + return !isKeyguardLocked; + case PAUSING: + case PAUSED: + // When pausing, only allow enter PiP if not on the lockscreen and there is not + // already an existing PiP activity + return !isKeyguardLocked && !hasPinnedStack && supportsPictureInPictureWhilePausing; + case STOPPING: + // When stopping in a valid state, then only allow enter PiP as in the pause state. + // Otherwise, fall through to throw an exception if the caller is trying to enter + // PiP in an invalid stopping state. + if (supportsPictureInPictureWhilePausing) { + return !isKeyguardLocked && !hasPinnedStack; + } + default: + throw new IllegalStateException(caller + + ": Current activity is not visible (state=" + state.name() + ") " + + "r=" + this); } - return false; } boolean canGoInDockedStack() { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 451083672a96..d7b3728e9803 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1726,9 +1726,7 @@ final class ActivityStack extends ConfigurationContainer { + stackInvisible + " behindFullscreenActivity=" + behindFullscreenActivity + " mLaunchTaskBehind=" + r.mLaunchTaskBehind); - if (!enterPictureInPictureOnActivityInvisible(r)) { - makeInvisible(r, visibleBehind); - } + makeInvisible(r, visibleBehind); } } if (mStackId == FREEFORM_WORKSPACE_STACK_ID) { @@ -1887,35 +1885,6 @@ final class ActivityStack extends ConfigurationContainer { return false; } - /** - * Attempts to enter picture-in-picture if the activity that is being made invisible supports - * it. If not, then - * - * @return whether or not picture-in-picture mode was entered. - */ - private boolean enterPictureInPictureOnActivityInvisible(ActivityRecord r) { - final boolean hasPinnedStack = - mStackSupervisor.getStack(PINNED_STACK_ID) != null; - final boolean isKeyguardLocked = mService.isKeyguardLocked(); - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, " enterPictureInPictureOnInvisible=" - + r.shouldEnterPictureInPictureOnInvisible() - + " hasPinnedStack=" + hasPinnedStack - + " isKeyguardLocked=" + isKeyguardLocked); - if (!hasPinnedStack && !isKeyguardLocked && r.visible && - r.shouldEnterPictureInPictureOnInvisible()) { - r.setEnterPipOnMoveToBackground(false); - - // Enter picture in picture, but don't move the home stack to the front - // since it will affect the focused stack's visibility and occlude - // starting activities - mService.enterPictureInPictureModeLocked(r, r.getDisplayId(), - r.pictureInPictureArgs, false /* moveHomeStackToFront */, - "ensureActivitiesVisibleLocked"); - return true; - } - return false; - } - private void makeInvisible(ActivityRecord r, ActivityRecord visibleBehind) { if (!r.visible) { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r); @@ -1934,6 +1903,10 @@ final class ActivityStack extends ConfigurationContainer { "Scheduling invisibility: " + r); r.app.thread.scheduleWindowVisibility(r.appToken, false); } + + // Reset the flag indicating that an app can enter picture-in-picture once the + // activity is hidden + r.supportsPictureInPictureWhilePausing = false; break; case INITIALIZING: @@ -2215,15 +2188,16 @@ final class ActivityStack extends ConfigurationContainer { mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); - // We need to start pausing the current activity so the top one can be resumed... - final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0; - boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause); + // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity + // to be paused, while at the same time resuming the new resume activity + final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0; + boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); - pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause); + pausing |= startPausingLocked(userLeaving, false, next, false); } - if (pausing) { + if (pausing && !resumeWhilePausing) { if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, "resumeTopActivityLocked: Skip resume: need to start pausing"); // At this point we want to put the upcoming activity's process @@ -2724,10 +2698,10 @@ final class ActivityStack extends ConfigurationContainer { if (r.mLaunchTaskBehind) { transit = TRANSIT_TASK_OPEN_BEHIND; } else { - // If a new task is being launched, then mark the existing top activity to - // enter picture-in-picture if it supports auto-entering PiP + // If a new task is being launched, then mark the existing top activity as + // supporting picture-in-picture while pausing if (focusedTopActivity != null) { - focusedTopActivity.setEnterPipOnMoveToBackground(true); + focusedTopActivity.supportsPictureInPictureWhilePausing = true; } transit = TRANSIT_TASK_OPEN; } @@ -4273,10 +4247,10 @@ final class ActivityStack extends ConfigurationContainer { } else { updateTransitLocked(TRANSIT_TASK_TO_FRONT, options); } - // If a new task is moved to the front, then mark the existing top activity to enter - // picture-in-picture if it supports auto-entering PiP + // If a new task is moved to the front, then mark the existing top activity as supporting + // picture-in-picture while paused if (focusedTopActivity != null) { - focusedTopActivity.setEnterPipOnMoveToBackground(true); + focusedTopActivity.supportsPictureInPictureWhilePausing = true; } mStackSupervisor.resumeFocusedStackTopActivityLocked(); @@ -4994,8 +4968,8 @@ final class ActivityStack extends ConfigurationContainer { } } - void moveToFrontAndResumeStateIfNeeded( - ActivityRecord r, boolean moveToFront, boolean setResume, String reason) { + void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, + boolean setPause, String reason) { if (!moveToFront) { return; } @@ -5006,6 +4980,10 @@ final class ActivityStack extends ConfigurationContainer { if (setResume) { mResumedActivity = r; } + // If the activity was previously pausing, then ensure we transfer that as well + if (setPause) { + mPausingActivity = r; + } // Move the stack in which we are placing the activity to the front. The call will also // make sure the activity focus is set. moveToFront(reason); @@ -5026,6 +5004,7 @@ final class ActivityStack extends ConfigurationContainer { final boolean wasFocused = mStackSupervisor.isFocusedStack(prevStack) && (mStackSupervisor.topRunningActivityLocked() == r); final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r); + final boolean wasPaused = prevStack.mPausingActivity == r; final TaskRecord task = createTaskRecord( mStackSupervisor.getNextTaskIdForUserLocked(r.userId), @@ -5033,10 +5012,14 @@ final class ActivityStack extends ConfigurationContainer { r.setTask(task, null); task.addActivityToTop(r); mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack); - moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, "moveActivityToStack"); + moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, wasPaused, + "moveActivityToStack"); if (wasResumed) { prevStack.mResumedActivity = null; } + if (wasPaused) { + prevStack.mPausingActivity = null; + } } public int getStackId() { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 5ae0102d7126..14899b4d5256 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2674,6 +2674,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ActivityStack prevStack = task.getStack(); final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r); final boolean wasResumed = prevStack.mResumedActivity == r; + final boolean wasPaused = prevStack.mPausingActivity == r; // In some cases the focused stack isn't the front stack. E.g. pinned stack. // Whenever we are moving the top activity from the front stack we want to make sure to move // the stack to the front. @@ -2698,10 +2699,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D task.mTemporarilyUnresizable = false; task.reparent(stack.mStackId, toTop ? MAX_VALUE : 0, reason); + // Reset the resumed activity on the previous stack + if (wasResumed) { + prevStack.mResumedActivity = null; + } + // Reset the paused activity on the previous stack + if (wasPaused) { + prevStack.mPausingActivity = null; + } + // If the task had focus before (or we're requested to move focus), // move focus to the new stack by moving the stack to the front. - stack.moveToFrontAndResumeStateIfNeeded( - r, forceFocus || wasFocused || wasFront, wasResumed, reason); + stack.moveToFrontAndResumeStateIfNeeded(r, forceFocus || wasFocused || wasFront, wasResumed, + wasPaused, reason); return stack; } @@ -2852,8 +2862,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (task.mActivities.size() == 1) { // There is only one activity in the task. So, we can just move the task over to - // the stack without re-parenting the activity in a different task. - if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) { + // the stack without re-parenting the activity in a different task. We don't + // move the home stack forward if we are currently entering picture-in-picture + // while pausing because that changes the focused stack and may prevent the new + // starting activity from resuming. + if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE + && !r.supportsPictureInPictureWhilePausing) { // Move the home stack forward if the task we just moved to the pinned stack // was launched from home so home should be visible behind it. moveHomeStackToFront(reason); @@ -2865,6 +2879,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // reveal/leave the other activities in their original task stack.moveActivityToStack(r); } + + // Reset the state that indicates it can enter PiP while pausing after we've moved it + // to the pinned stack + r.supportsPictureInPictureWhilePausing = false; } finally { mWindowManager.continueSurfaceLayout(); } diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index c064cb02f21f..26d2ee2e1547 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -582,7 +582,10 @@ class ActivityStarter { // The activity was already running in the pinned stack so it wasn't started, but either // brought to the front or the new intent was delivered to it since it was already in // front. Notify anyone interested in this piece of information. - mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(); + final ComponentName sourceComponent = sourceRecord == null ? null : + sourceRecord.realActivity; + mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt( + sourceComponent); return; } } @@ -1128,7 +1131,8 @@ class ActivityStarter { mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName, mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId); - + mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent, + mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid)); if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) { mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE); } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 8104a43cee09..61e555bd8b21 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -1157,8 +1157,7 @@ public final class BroadcastQueue { if (!skip) { final int allowed = mService.checkAllowBackgroundLocked( - info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1, - true); + info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1, true); if (allowed != ActivityManager.APP_START_MODE_NORMAL) { // We won't allow this receiver to be launched if the app has been // completely disabled from launches, or it was not explicitly sent diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java index d035fa9d94c9..2990dffd8e5c 100644 --- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java +++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java @@ -97,7 +97,7 @@ class TaskChangeNotificationController { }; private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> { - l.onPinnedActivityRestartAttempt(); + l.onPinnedActivityRestartAttempt((ComponentName) m.obj); }; private final TaskStackConsumer mNotifyPinnedStackAnimationEnded = (l, m) -> { @@ -267,10 +267,11 @@ class TaskChangeNotificationController { * running in the pinned stack and the activity was not actually started, but the task is * either brought to the front or a new Intent is delivered to it. */ - void notifyPinnedActivityRestartAttempt() { + void notifyPinnedActivityRestartAttempt(ComponentName sourceComponent) { mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG); final Message msg = - mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG); + mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG, + sourceComponent); forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg); msg.sendToTarget(); } diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java index 7a62f2c4f8ad..9dde39e6e9ce 100644 --- a/services/core/java/com/android/server/am/TaskPersister.java +++ b/services/core/java/com/android/server/am/TaskPersister.java @@ -651,6 +651,8 @@ public class TaskPersister { "omitting from persistentTaskIds task=" + task); } } + mService.mWindowManager.removeObsoleteTaskFiles(persistentTaskIds, + mRecentTasks.usersWithRecentsLoadedLocked()); } removeObsoleteFiles(persistentTaskIds); } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 6f984a5cd036..e550ac88b0f1 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -800,6 +800,9 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta inRecents = false; mService.notifyTaskPersisterLocked(this, false); } + + // TODO: Use window container controller once tasks are better synced between AM and WM + mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId); } void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) { diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java index d1a15bdd3829..64e34174d1c3 100644 --- a/services/core/java/com/android/server/am/UidRecord.java +++ b/services/core/java/com/android/server/am/UidRecord.java @@ -26,10 +26,13 @@ import android.util.TimeUtils; */ public final class UidRecord { final int uid; + final boolean persistent; int curProcState; int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT; long lastBackgroundTime; boolean ephemeral; + boolean curWhitelist; + boolean setWhitelist; boolean idle; int numProcs; @@ -49,8 +52,9 @@ public final class UidRecord { ChangeItem pendingChange; - public UidRecord(int _uid) { + public UidRecord(int _uid, boolean _persist) { uid = _uid; + persistent = _persist; reset(); } @@ -69,6 +73,9 @@ public final class UidRecord { if (ephemeral) { sb.append(" ephemeral"); } + if (curWhitelist) { + sb.append(" whitelist"); + } if (lastBackgroundTime > 0) { sb.append(" bg:"); TimeUtils.formatDuration(SystemClock.elapsedRealtime()-lastBackgroundTime, sb); diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index f516e99a7969..5bf92d7e3322 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -419,7 +419,8 @@ final class UserController { if (userId != UserHandle.USER_SYSTEM) { Slog.d(TAG, "Initializing user #" + userId); Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE); - intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mInjector.broadcastIntentLocked(intent, null, new IIntentReceiver.Stub() { @Override diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java index 5f9efe704f77..85d1d1ef1d75 100644 --- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java +++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java @@ -23,6 +23,7 @@ import android.net.LinkProperties; import android.net.Network; import android.net.NetworkUtils; import android.net.RouteInfo; +import android.net.TrafficStats; import android.os.SystemClock; import android.system.ErrnoException; import android.system.Os; @@ -381,7 +382,12 @@ public class NetworkDiagnostics { protected void setupSocket( int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort) throws ErrnoException, IOException { - mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol); + final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE); + try { + mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol); + } finally { + TrafficStats.setThreadStatsTag(oldTag); + } // Setting SNDTIMEO is purely for defensive purposes. Os.setsockoptTimeval(mFileDescriptor, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(writeTimeout)); diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index c40780e0d588..fbda901ec402 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -779,6 +779,7 @@ public class NetworkMonitor extends StateMachine { int httpResponseCode = 599; String redirectUrl = null; final Stopwatch probeTimer = new Stopwatch().start(); + final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE); try { urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url); urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC); @@ -839,6 +840,7 @@ public class NetworkMonitor extends StateMachine { if (urlConnection != null) { urlConnection.disconnect(); } + TrafficStats.setThreadStatsTag(oldTag); } logValidationProbe(probeTimer.stop(), probeType, httpResponseCode); return new CaptivePortalProbeResult(httpResponseCode, redirectUrl, url.toString()); diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index 58c76ec7674a..34826b669347 100644 --- a/services/core/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.net.ProxyInfo; +import android.net.TrafficStats; import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; @@ -103,11 +104,15 @@ public class PacManager { String file; synchronized (mProxyLock) { if (Uri.EMPTY.equals(mPacUrl)) return; + final int oldTag = TrafficStats + .getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PAC); try { file = get(mPacUrl); } catch (IOException ioe) { file = null; Log.w(TAG, "Failed to load PAC file: " + ioe); + } finally { + TrafficStats.setThreadStatsTag(oldTag); } } if (file != null) { diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 0c801660ff88..bd88ddb03df0 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -16,6 +16,11 @@ package com.android.server.connectivity; +import static android.hardware.usb.UsbManager.USB_CONNECTED; +import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; +import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; +import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; + import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -208,13 +213,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); - mContext.registerReceiver(mStateReceiver, filter); + mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler()); filter = new IntentFilter(); filter.addAction(Intent.ACTION_MEDIA_SHARED); filter.addAction(Intent.ACTION_MEDIA_UNSHARED); filter.addDataScheme("file"); - mContext.registerReceiver(mStateReceiver, filter); + mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler()); mDhcpRange = context.getResources().getStringArray( com.android.internal.R.array.config_tether_dhcp_range); @@ -779,69 +784,84 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering private class StateReceiver extends BroadcastReceiver { @Override public void onReceive(Context content, Intent intent) { - String action = intent.getAction(); - if (action == null) { return; } + final String action = intent.getAction(); + if (action == null) return; + if (action.equals(UsbManager.ACTION_USB_STATE)) { - synchronized (Tethering.this.mPublicSync) { - boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); - mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false); - // start tethering if we have a request pending - if (usbConnected && mRndisEnabled && mUsbTetherRequested) { - tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB); - } - mUsbTetherRequested = false; - } + handleUsbAction(intent); } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( - ConnectivityManager.EXTRA_NETWORK_INFO); - if (networkInfo != null && - networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) { - if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); - mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); - } + handleConnectivityAction(intent); } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { - synchronized (Tethering.this.mPublicSync) { - int curState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, - WifiManager.WIFI_AP_STATE_DISABLED); - switch (curState) { - case WifiManager.WIFI_AP_STATE_ENABLING: - // We can see this state on the way to both enabled and failure states. - break; - case WifiManager.WIFI_AP_STATE_ENABLED: - // When the AP comes up and we've been requested to tether it, do so. - if (mWifiTetherRequested) { - tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI); - } - break; - case WifiManager.WIFI_AP_STATE_DISABLED: - case WifiManager.WIFI_AP_STATE_DISABLING: - case WifiManager.WIFI_AP_STATE_FAILED: - default: - if (DBG) { - Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" + - curState); - } - // Tell appropriate interface state machines that they should tear - // themselves down. - for (int i = 0; i < mTetherStates.size(); i++) { - TetherInterfaceStateMachine tism = - mTetherStates.valueAt(i).mStateMachine; - if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) { - tism.sendMessage( - TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED); - break; // There should be at most one of these. - } - } - // Regardless of whether we requested this transition, the AP has gone - // down. Don't try to tether again unless we're requested to do so. - mWifiTetherRequested = false; - break; - } - } + handleWifiApAction(intent); } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { updateConfiguration(); } } + + private void handleConnectivityAction(Intent intent) { + final NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( + ConnectivityManager.EXTRA_NETWORK_INFO); + if (networkInfo == null || + networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) { + return; + } + + if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString()); + mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); + } + + private void handleUsbAction(Intent intent) { + final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false); + final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false); + synchronized (Tethering.this.mPublicSync) { + mRndisEnabled = rndisEnabled; + // start tethering if we have a request pending + if (usbConnected && mRndisEnabled && mUsbTetherRequested) { + tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB); + } + mUsbTetherRequested = false; + } + } + + private void handleWifiApAction(Intent intent) { + final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); + synchronized (Tethering.this.mPublicSync) { + switch (curState) { + case WifiManager.WIFI_AP_STATE_ENABLING: + // We can see this state on the way to both enabled and failure states. + break; + case WifiManager.WIFI_AP_STATE_ENABLED: + // When the AP comes up and we've been requested to tether it, do so. + if (mWifiTetherRequested) { + tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI); + } + break; + case WifiManager.WIFI_AP_STATE_DISABLED: + case WifiManager.WIFI_AP_STATE_DISABLING: + case WifiManager.WIFI_AP_STATE_FAILED: + default: + if (DBG) { + Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" + + curState); + } + // Tell appropriate interface state machines that they should tear + // themselves down. + for (int i = 0; i < mTetherStates.size(); i++) { + TetherInterfaceStateMachine tism = + mTetherStates.valueAt(i).mStateMachine; + if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) { + tism.sendMessage( + TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED); + break; // There should be at most one of these. + } + } + // Regardless of whether we requested this transition, the AP has gone + // down. Don't try to tether again unless we're requested to do so. + mWifiTetherRequested = false; + break; + } + } + } } private void tetherMatchingInterfaces(boolean enable, int interfaceType) { @@ -891,10 +911,6 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering public int setUsbTethering(boolean enable) { if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); UsbManager usbManager = mContext.getSystemService(UsbManager.class); - if (usbManager == null) { - return enable ? ConnectivityManager.TETHER_ERROR_MASTER_ERROR - : ConnectivityManager.TETHER_ERROR_NO_ERROR; - } synchronized (mPublicSync) { if (enable) { @@ -1083,7 +1099,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering private final ArrayList<TetherInterfaceStateMachine> mNotifyList; private final IPv6TetheringCoordinator mIPv6TetheringCoordinator; - private int mPreviousMobileApn = ConnectivityManager.TYPE_NONE; + private int mPreviousMobileType = ConnectivityManager.TYPE_NONE; private static final int UPSTREAM_SETTLE_TIME_MS = 10000; @@ -1118,13 +1134,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering return false; } - protected boolean turnOnUpstreamMobileConnection(int apnType) { + protected boolean requestUpstreamMobileConnection(int apnType) { if (apnType == ConnectivityManager.TYPE_NONE) { return false; } - if (apnType != mPreviousMobileApn) { + if (apnType != mPreviousMobileType) { // Unregister any previous mobile upstream callback because // this request, if any, will be different. - turnOffUpstreamMobileConnection(); + unrequestUpstreamMobileConnection(); } if (mUpstreamNetworkMonitor.mobileNetworkRequested()) { @@ -1136,25 +1152,25 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering case ConnectivityManager.TYPE_MOBILE_DUN: case ConnectivityManager.TYPE_MOBILE: case ConnectivityManager.TYPE_MOBILE_HIPRI: - mPreviousMobileApn = apnType; + mPreviousMobileType = apnType; break; default: return false; } - // TODO: This should be called by the code that observes - // configuration changes, once the above code in this function - // is simplified (i.e. eradicated). - mUpstreamNetworkMonitor.mobileUpstreamRequiresDun( + // TODO: Replace this with a call to pass the current tethering + // configuration to mUpstreamNetworkMonitor and let it handle + // choosing APN type accordingly. + mUpstreamNetworkMonitor.updateMobileRequiresDun( apnType == ConnectivityManager.TYPE_MOBILE_DUN); mUpstreamNetworkMonitor.registerMobileNetworkRequest(); return true; } - protected void turnOffUpstreamMobileConnection() { + protected void unrequestUpstreamMobileConnection() { mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); - mPreviousMobileApn = ConnectivityManager.TYPE_NONE; + mPreviousMobileType = ConnectivityManager.TYPE_NONE; } protected boolean turnOnMasterTetherSettings() { @@ -1233,11 +1249,11 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering case ConnectivityManager.TYPE_MOBILE_DUN: case ConnectivityManager.TYPE_MOBILE_HIPRI: // If we're on DUN, put our own grab on it. - turnOnUpstreamMobileConnection(upType); + requestUpstreamMobileConnection(upType); break; case ConnectivityManager.TYPE_NONE: if (tryCell && - turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn)) { + requestUpstreamMobileConnection(mPreferredUpstreamMobileApn)) { // We think mobile should be coming up; don't set a retry. } else { sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); @@ -1250,7 +1266,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering * If we found NONE we don't want to do this as we want any previous * requests to keep trying to bring up something we can use. */ - turnOffUpstreamMobileConnection(); + unrequestUpstreamMobileConnection(); break; } @@ -1330,96 +1346,127 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } } - private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0); - private SimChangeBroadcastReceiver mBroadcastReceiver = null; + private class SimChangeListener { + private final Context mContext; + private final AtomicInteger mSimBcastGenerationNumber; + private BroadcastReceiver mBroadcastReceiver; + + SimChangeListener(Context ctx) { + mContext = ctx; + mSimBcastGenerationNumber = new AtomicInteger(0); + } + + public int generationNumber() { + return mSimBcastGenerationNumber.get(); + } + + public void startListening() { + if (DBG) Log.d(TAG, "startListening for SIM changes"); + + if (mBroadcastReceiver != null) return; - private void startListeningForSimChanges() { - if (DBG) Log.d(TAG, "startListeningForSimChanges"); - if (mBroadcastReceiver == null) { mBroadcastReceiver = new SimChangeBroadcastReceiver( mSimBcastGenerationNumber.incrementAndGet()); final IntentFilter filter = new IntentFilter(); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); - mContext.registerReceiver(mBroadcastReceiver, filter); + mContext.registerReceiver(mBroadcastReceiver, filter, null, + mTetherMasterSM.getHandler()); } - } - private void stopListeningForSimChanges() { - if (DBG) Log.d(TAG, "stopListeningForSimChanges"); - if (mBroadcastReceiver != null) { + public void stopListening() { + if (DBG) Log.d(TAG, "stopListening for SIM changes"); + + if (mBroadcastReceiver == null) return; + mSimBcastGenerationNumber.incrementAndGet(); mContext.unregisterReceiver(mBroadcastReceiver); mBroadcastReceiver = null; } - } - class SimChangeBroadcastReceiver extends BroadcastReceiver { - // used to verify this receiver is still current - final private int mGenerationNumber; + public boolean hasMobileHotspotProvisionApp() { + try { + if (!mContext.getResources().getString(com.android.internal.R.string. + config_mobile_hotspot_provision_app_no_ui).isEmpty()) { + Log.d(TAG, "re-evaluate provisioning"); + return true; + } + } catch (Resources.NotFoundException e) {} + Log.d(TAG, "no prov-check needed for new SIM"); + return false; + } - // we're interested in edge-triggered LOADED notifications, so - // ignore LOADED unless we saw an ABSENT state first - private boolean mSimAbsentSeen = false; + private boolean isSimCardAbsent(String state) { + return IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state); + } - public SimChangeBroadcastReceiver(int generationNumber) { - super(); - mGenerationNumber = generationNumber; + private boolean isSimCardLoaded(String state) { + return IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state); } - @Override - public void onReceive(Context context, Intent intent) { - if (DBG) { - Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber + - ", current generationNumber=" + mSimBcastGenerationNumber.get()); - } - if (mGenerationNumber != mSimBcastGenerationNumber.get()) return; + private void startProvisionIntent(int tetherType) { + final Intent startProvIntent = new Intent(); + startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType); + startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true); + startProvIntent.setComponent(TETHER_SERVICE); + mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT); + } + + private class SimChangeBroadcastReceiver extends BroadcastReceiver { + // used to verify this receiver is still current + final private int mGenerationNumber; - final String state = - intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); + // we're interested in edge-triggered LOADED notifications, so + // ignore LOADED unless we saw an ABSENT state first + private boolean mSimAbsentSeen = false; - Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" + - mSimAbsentSeen); - if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { - mSimAbsentSeen = true; + public SimChangeBroadcastReceiver(int generationNumber) { + mGenerationNumber = generationNumber; } - if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { - mSimAbsentSeen = false; - try { - if (mContext.getResources().getString(com.android.internal.R.string. - config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) { - ArrayList<Integer> tethered = new ArrayList<Integer>(); - synchronized (mPublicSync) { - for (int i = 0; i < mTetherStates.size(); i++) { - TetherState tetherState = mTetherStates.valueAt(i); - if (tetherState.mLastState != - IControlsTethering.STATE_TETHERED) { - continue; // Skip interfaces that aren't tethered. - } - String iface = mTetherStates.keyAt(i); - int interfaceType = ifaceNameToType(iface); - if (interfaceType != ConnectivityManager.TETHERING_INVALID) { - tethered.add(new Integer(interfaceType)); - } + @Override + public void onReceive(Context context, Intent intent) { + final int currentGenerationNumber = mSimBcastGenerationNumber.get(); + + if (DBG) { + Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber + + ", current generationNumber=" + currentGenerationNumber); + } + if (mGenerationNumber != currentGenerationNumber) return; + + final String state = intent.getStringExtra( + IccCardConstants.INTENT_KEY_ICC_STATE); + Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" + + mSimAbsentSeen); + + if (isSimCardAbsent(state)) { + if (!mSimAbsentSeen) mSimAbsentSeen = true; + return; + } + + if (isSimCardLoaded(state) && mSimAbsentSeen) { + mSimAbsentSeen = false; + + if (!hasMobileHotspotProvisionApp()) return; + + ArrayList<Integer> tethered = new ArrayList<Integer>(); + synchronized (mPublicSync) { + for (int i = 0; i < mTetherStates.size(); i++) { + TetherState tetherState = mTetherStates.valueAt(i); + if (tetherState.mLastState != IControlsTethering.STATE_TETHERED) { + continue; // Skip interfaces that aren't tethered. + } + String iface = mTetherStates.keyAt(i); + int interfaceType = ifaceNameToType(iface); + if (interfaceType != ConnectivityManager.TETHERING_INVALID) { + tethered.add(new Integer(interfaceType)); } } - for (int tetherType : tethered) { - Intent startProvIntent = new Intent(); - startProvIntent.putExtra( - ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType); - startProvIntent.putExtra( - ConnectivityManager.EXTRA_RUN_PROVISION, true); - startProvIntent.setComponent(TETHER_SERVICE); - mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT); - } - Log.d(TAG, "re-evaluate provisioning"); - } else { - Log.d(TAG, "no prov-check needed for new SIM"); } - } catch (Resources.NotFoundException e) { - Log.d(TAG, "no prov-check needed for new SIM"); - // not defined, do nothing + + for (int tetherType : tethered) { + startProvisionIntent(tetherType); + } } } } @@ -1455,12 +1502,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } class TetherModeAliveState extends TetherMasterUtilState { + final SimChangeListener simChange = new SimChangeListener(mContext); boolean mTryCell = true; @Override public void enter() { // TODO: examine if we should check the return value. turnOnMasterTetherSettings(); // may transition us out - startListeningForSimChanges(); + simChange.startListening(); mUpstreamNetworkMonitor.start(); mTryCell = true; // better try something first pass or crazy tests cases will fail @@ -1470,9 +1518,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering @Override public void exit() { - turnOffUpstreamMobileConnection(); + unrequestUpstreamMobileConnection(); mUpstreamNetworkMonitor.stop(); - stopListeningForSimChanges(); + simChange.stopListening(); notifyTetheredOfNewUpstreamIface(null); handleNewUpstreamNetworkState(null); } diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 4c950de2585e..23481dc2dbfd 100644 --- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -109,7 +109,7 @@ public class UpstreamNetworkMonitor { mNetworkMap.clear(); } - public void mobileUpstreamRequiresDun(boolean dunRequired) { + public void updateMobileRequiresDun(boolean dunRequired) { final boolean valueChanged = (mDunRequired != dunRequired); mDunRequired = dunRequired; if (valueChanged && mobileNetworkRequested()) { @@ -123,7 +123,10 @@ public class UpstreamNetworkMonitor { } public void registerMobileNetworkRequest() { - if (mMobileNetworkCallback != null) return; + if (mMobileNetworkCallback != null) { + Log.e(TAG, "registerMobileNetworkRequest() already registered"); + return; + } final NetworkRequest.Builder builder = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); @@ -139,11 +142,10 @@ public class UpstreamNetworkMonitor { // Therefore, to avoid duplicate notifications, we only register a no-op. mMobileNetworkCallback = new NetworkCallback(); - // TODO: Change the timeout from 0 (no onUnavailable callback) to use some - // moderate callback time (once timeout callbacks are implemented). This might - // be useful for updating some UI. Additionally, we should definitely log a - // message to aid in any subsequent debugging - if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest); + // TODO: Change the timeout from 0 (no onUnavailable callback) to some + // moderate callback timeout. This might be useful for updating some UI. + // Additionally, we log a message to aid in any subsequent debugging. + Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest); // The following use of the legacy type system cannot be removed until // after upstream selection no longer finds networks by legacy type. diff --git a/services/core/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java index bf7798591c67..62332c9235b0 100644 --- a/services/core/java/com/android/server/location/GpsXtraDownloader.java +++ b/services/core/java/com/android/server/location/GpsXtraDownloader.java @@ -16,22 +16,19 @@ package com.android.server.location; +import android.net.TrafficStats; import android.text.TextUtils; import android.util.Log; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; - -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.IOException; import java.util.Properties; import java.util.Random; import java.util.concurrent.TimeUnit; -import libcore.io.Streams; - /** * A class for downloading GPS XTRA data. * @@ -94,7 +91,12 @@ public class GpsXtraDownloader { // load balance our requests among the available servers while (result == null) { - result = doDownload(mXtraServers[mNextServerIndex]); + final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_GPS); + try { + result = doDownload(mXtraServers[mNextServerIndex]); + } finally { + TrafficStats.setThreadStatsTag(oldTag); + } // increment mNextServerIndex and wrap around if necessary mNextServerIndex++; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 901830291976..6c66a60d530f 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -702,16 +702,19 @@ public class NotificationManagerService extends SystemService { int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL); String pkgList[] = null; + int uidList[] = null; boolean removingPackage = queryRemove && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); if (DBG) Slog.i(TAG, "action=" + action + " removing=" + removingPackage); if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); + uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST); } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) { pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); reason = REASON_PACKAGE_SUSPENDED; } else if (queryRestart) { pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); + uidList = new int[] {intent.getIntExtra(Intent.EXTRA_UID, -1)}; } else { Uri uri = intent.getData(); if (uri == null) { @@ -743,8 +746,8 @@ public class NotificationManagerService extends SystemService { } } pkgList = new String[]{pkgName}; + uidList = new int[] {intent.getIntExtra(Intent.EXTRA_UID, -1)}; } - if (pkgList != null && (pkgList.length > 0)) { for (String pkgName : pkgList) { if (cancelNotifications) { @@ -756,7 +759,8 @@ public class NotificationManagerService extends SystemService { mListeners.onPackagesChanged(removingPackage, pkgList); mNotificationAssistants.onPackagesChanged(removingPackage, pkgList); mConditionProviders.onPackagesChanged(removingPackage, pkgList); - mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList); + mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList, uidList); + savePolicyFile(); } } }; @@ -1527,14 +1531,16 @@ public class NotificationManagerService extends SystemService { @Override public NotificationChannel getNotificationChannel(String pkg, String channelId) { checkCallerIsSystemOrSameApp(pkg); - return mRankingHelper.getNotificationChannel(pkg, Binder.getCallingUid(), channelId); + return mRankingHelper.getNotificationChannel( + pkg, Binder.getCallingUid(), channelId, false /* includeDeleted */); } @Override public NotificationChannel getNotificationChannelForPackage(String pkg, int uid, - String channelId) { + String channelId, boolean includeDeleted) { checkCallerIsSystem(); - return mRankingHelper.getNotificationChannel(pkg, uid, channelId); + return mRankingHelper.getNotificationChannel + (pkg, uid, channelId, includeDeleted); } @Override @@ -1566,17 +1572,42 @@ public class NotificationManagerService extends SystemService { @Override public ParceledListSlice<NotificationChannel> getNotificationChannelsForPackage(String pkg, - int uid) { + int uid, boolean includeDeleted) { checkCallerIsSystem(); - return mRankingHelper.getNotificationChannels(pkg, uid); + return mRankingHelper.getNotificationChannels(pkg, uid, includeDeleted); } @Override public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg) { checkCallerIsSystemOrSameApp(pkg); - return mRankingHelper.getNotificationChannels(pkg, Binder.getCallingUid()); + return mRankingHelper.getNotificationChannels( + pkg, Binder.getCallingUid(), false /* includeDeleted */); } + + @Override + public void clearData(String packageName, int uid) throws RemoteException { + checkCallerIsSystem(); + + // Cancel posted notifications + cancelAllNotificationsInt(MY_UID, MY_PID, packageName, null, 0, 0, true, + UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null); + + // Listener & assistant + mListeners.onPackagesChanged(true, new String[] {packageName}); + mNotificationAssistants.onPackagesChanged(true, new String[] {packageName}); + + // Zen + mConditionProviders.onPackagesChanged(true, new String[] {packageName}); + + // Reset notification preferences + mRankingHelper.onPackagesChanged(true, UserHandle.getCallingUserId(), + new String[] {packageName}, new int[] {uid}); + + savePolicyFile(); + } + + /** * System-only API for getting a list of current (i.e. not cleared) notifications. * @@ -2475,7 +2506,7 @@ public class NotificationManagerService extends SystemService { INotificationListener token, String pkg) throws RemoteException { ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token); int uid = mPackageManager.getPackageUid(pkg, 0, info.userid); - return mRankingHelper.getNotificationChannels(pkg, uid); + return mRankingHelper.getNotificationChannels(pkg, uid, false /* includeDeleted */); } }; @@ -2493,7 +2524,8 @@ public class NotificationManagerService extends SystemService { adjustment.getSignals().getParcelableArrayList(Adjustment.KEY_SNOOZE_CRITERIA); if (!TextUtils.isEmpty(overrideChannelId)) { n.setNotificationChannelOverride(mRankingHelper.getNotificationChannel( - n.sbn.getPackageName(), n.sbn.getUid(), overrideChannelId)); + n.sbn.getPackageName(), n.sbn.getUid(), overrideChannelId, + false /* includeDeleted */)); } n.setPeopleOverride(people); n.setSnoozeCriteria(snoozeCriterionList); @@ -2846,7 +2878,7 @@ public class NotificationManagerService extends SystemService { + " id=" + id + " notification=" + notification); } final NotificationChannel channel = mRankingHelper.getNotificationChannelWithFallback(pkg, - callingUid, notification.getChannel()); + callingUid, notification.getChannel(), false /* includeDeleted */); final StatusBarNotification n = new StatusBarNotification( pkg, opPkg, channel, id, tag, callingUid, callingPid, notification, user, null, System.currentTimeMillis()); diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index 5c1e99c67710..c2cef09e0599 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -27,8 +27,10 @@ public interface RankingConfig { boolean fromTargetApp); void updateNotificationChannel(String pkg, int uid, NotificationChannel channel); void updateNotificationChannelFromAssistant(String pkg, int uid, NotificationChannel channel); - NotificationChannel getNotificationChannel(String pkg, int uid, String channelId); - NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, String channelId); + NotificationChannel getNotificationChannel(String pkg, int uid, String channelId, boolean includeDeleted); + NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, String channelId, boolean includeDeleted); void deleteNotificationChannel(String pkg, int uid, String channelId); - ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid); + void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId); + void permanentlyDeleteNotificationChannels(String pkg, int uid); + ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid, boolean includeDeleted); } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 3fcce3c05c97..e44fb7f6b31c 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -18,6 +18,7 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_NONE; import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import android.app.Notification; @@ -29,7 +30,6 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.os.Build; -import android.os.Process; import android.os.UserHandle; import android.service.notification.NotificationListenerService.Ranking; import android.text.TextUtils; @@ -432,9 +432,13 @@ public class RankingHelper implements RankingConfig { if (IMPORTANCE_NONE == r.importance) { throw new IllegalArgumentException("Package blocked"); } - if (r.channels.containsKey(channel.getId()) || channel.getName().equals( - mContext.getString(R.string.default_notification_channel_label))) { - // Channel already exists, no-op. + NotificationChannel existing = r.channels.get(channel.getId()); + // Keep existing settings + if (existing != null) { + if (existing.isDeleted()) { + existing.setDeleted(false); + updateConfig(); + } return; } if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE @@ -471,7 +475,7 @@ public class RankingHelper implements RankingConfig { throw new IllegalArgumentException("Invalid package"); } NotificationChannel channel = r.channels.get(updatedChannel.getId()); - if (channel == null) { + if (channel == null || channel.isDeleted()) { throw new IllegalArgumentException("Channel does not exist"); } if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) { @@ -489,7 +493,7 @@ public class RankingHelper implements RankingConfig { throw new IllegalArgumentException("Invalid package"); } NotificationChannel channel = r.channels.get(updatedChannel.getId()); - if (channel == null) { + if (channel == null || channel.isDeleted()) { throw new IllegalArgumentException("Channel does not exist"); } @@ -519,6 +523,9 @@ public class RankingHelper implements RankingConfig { if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SHOW_BADGE) == 0) { channel.setShowBadge(updatedChannel.canShowBadge()); } + if (updatedChannel.isDeleted()) { + updatedChannel.setDeleted(true); + } r.channels.put(channel.getId(), channel); updateConfig(); @@ -526,13 +533,13 @@ public class RankingHelper implements RankingConfig { @Override public NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, - String channelId) { + String channelId, boolean includeDeleted) { Record r = getOrCreateRecord(pkg, uid); if (channelId == null) { channelId = NotificationChannel.DEFAULT_CHANNEL_ID; } NotificationChannel channel = r.channels.get(channelId); - if (channel != null) { + if (channel != null && (includeDeleted || !channel.isDeleted())) { return channel; } else { return r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID); @@ -540,16 +547,21 @@ public class RankingHelper implements RankingConfig { } @Override - public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId) { + public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId, + boolean includeDeleted) { Preconditions.checkNotNull(pkg); Record r = getOrCreateRecord(pkg, uid); if (r == null) { - throw new IllegalArgumentException("Invalid package"); + return null; } if (channelId == null) { channelId = NotificationChannel.DEFAULT_CHANNEL_ID; } - return r.channels.get(channelId); + final NotificationChannel nc = r.channels.get(channelId); + if (nc != null && (includeDeleted || !nc.isDeleted())) { + return nc; + } + return null; } @Override @@ -558,24 +570,57 @@ public class RankingHelper implements RankingConfig { Preconditions.checkNotNull(channelId); Record r = getRecord(pkg, uid); if (r == null) { - throw new IllegalArgumentException("Invalid package"); + return; + } + NotificationChannel channel = r.channels.get(channelId); + if (channel != null) { + channel.setDeleted(true); + } + } + + @Override + @VisibleForTesting + public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) { + Preconditions.checkNotNull(pkg); + Preconditions.checkNotNull(channelId); + Record r = getRecord(pkg, uid); + if (r == null) { + return; + } + r.channels.remove(channelId); + } + + @Override + public void permanentlyDeleteNotificationChannels(String pkg, int uid) { + Preconditions.checkNotNull(pkg); + Record r = getRecord(pkg, uid); + if (r == null) { + return; } - if (r != null) { - r.channels.remove(channelId); + int N = r.channels.size() - 1; + for (int i = N; i >= 0; i--) { + String key = r.channels.keyAt(i); + if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) { + r.channels.remove(key); + } } } @Override - public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid) { + public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid, + boolean includeDeleted) { Preconditions.checkNotNull(pkg); List<NotificationChannel> channels = new ArrayList<>(); Record r = getRecord(pkg, uid); if (r == null) { - throw new IllegalArgumentException("Invalid package"); + return ParceledListSlice.emptyList(); } int N = r.channels.size(); for (int i = 0; i < N; i++) { - channels.add(r.channels.valueAt(i)); + final NotificationChannel nc = r.channels.valueAt(i); + if (includeDeleted || !nc.isDeleted()) { + channels.add(nc); + } } return new ParceledListSlice<>(channels); } @@ -738,30 +783,46 @@ public class RankingHelper implements RankingConfig { return packageBans; } - public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList) { - if (removingPackage || pkgList == null || pkgList.length == 0) { + public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList, + int[] uidList) { + if (pkgList == null || pkgList.length == 0) { return; // nothing to do } boolean updated = false; - for (String pkg : pkgList) { - final Record r = mRestoredWithoutUids.get(pkg); - if (r != null) { + if (removingPackage) { + // Remove notification settings for uninstalled package + int size = Math.min(pkgList.length, uidList.length); + for (int i = 0; i < size; i++) { + final String pkg = pkgList[i]; + final int uid = uidList[i]; + mRecords.remove(recordKey(pkg, uid)); + mRestoredWithoutUids.remove(pkg); + updated = true; + } + } else { + for (String pkg : pkgList) { + // Package install + final Record r = mRestoredWithoutUids.get(pkg); + if (r != null) { + try { + r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId); + mRestoredWithoutUids.remove(pkg); + mRecords.put(recordKey(r.pkg, r.uid), r); + updated = true; + } catch (NameNotFoundException e) { + // noop + } + } + // Package upgrade try { - r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId); - mRestoredWithoutUids.remove(pkg); - mRecords.put(recordKey(r.pkg, r.uid), r); - updated = true; + Record fullRecord = getRecord(pkg, + mPm.getPackageUidAsUser(pkg, changeUserId)); + if (fullRecord != null) { + clampDefaultChannel(fullRecord); + } } catch (NameNotFoundException e) { - // noop } } - try { - Record fullRecord = getRecord(pkg, - mPm.getPackageUidAsUser(pkg, changeUserId)); - if (fullRecord != null) { - clampDefaultChannel(fullRecord); - } - } catch (NameNotFoundException e) {} } if (updated) { diff --git a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java index 1e3e0caa1ece..3d946e02161a 100644 --- a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java +++ b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java @@ -17,6 +17,7 @@ package com.android.server.pm; import android.content.Context; +import android.content.Intent; import android.content.pm.EphemeralApplicationInfo; import android.content.pm.PackageParser; import android.content.pm.PackageUserState; @@ -27,10 +28,13 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Binder; import android.os.Environment; +import android.os.UserHandle; import android.provider.Settings; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; +import android.util.SparseIntArray; import android.util.Xml; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.ArrayUtils; @@ -51,6 +55,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -62,7 +67,7 @@ import java.util.Set; class EphemeralApplicationRegistry { private static final boolean DEBUG = false; - private static final boolean ENABLED = false; + private static final boolean ENABLED = true; private static final String LOG_TAG = "EphemeralAppRegistry"; @@ -90,6 +95,16 @@ class EphemeralApplicationRegistry { @GuardedBy("mService.mPackages") private SparseArray<List<UninstalledEphemeralAppState>> mUninstalledEphemeralApps; + /** + * Automatic grants for access to instant app metadata. + * The key is the target application UID. + * The value is a set of instant app UIDs. + * UserID -> TargetAppId -> InstantAppId + */ + private SparseArray<SparseArray<SparseBooleanArray>> mEphemeralGrants; + /** The set of all installed instant apps. UserID -> AppID */ + private SparseArray<SparseBooleanArray> mInstalledEphemeralAppUids; + public EphemeralApplicationRegistry(PackageManagerService service) { mService = service; } @@ -188,7 +203,11 @@ class EphemeralApplicationRegistry { } // Propagate permissions before removing any state - propagateEphemeralAppPermissionsIfNeeded(pkg, userId); + // TODO: Fix this later + // propagateEphemeralAppPermissionsIfNeeded(pkg, userId); + if (pkg.applicationInfo.isEphemeralApp()) { + addEphemeralAppLPw(userId, ps.appId); + } // Remove the in-memory state if (mUninstalledEphemeralApps != null) { @@ -248,9 +267,11 @@ class EphemeralApplicationRegistry { if (pkg.applicationInfo.isEphemeralApp()) { // Add a record for an uninstalled ephemeral app addUninstalledEphemeralAppLPw(pkg, userId); + removeEphemeralAppLPw(userId, ps.appId); } else { // Deleting an app prunes all ephemeral state such as cookie deleteDir(getEphemeralApplicationDir(pkg.packageName, userId)); + removeAppLPw(userId, ps.appId); } } } @@ -262,9 +283,114 @@ class EphemeralApplicationRegistry { if (mUninstalledEphemeralApps != null) { mUninstalledEphemeralApps.remove(userId); } + if (mInstalledEphemeralAppUids != null) { + mInstalledEphemeralAppUids.remove(userId); + } + if (mEphemeralGrants != null) { + mEphemeralGrants.remove(userId); + } deleteDir(getEphemeralApplicationsDir(userId)); } + public boolean isEphemeralAccessGranted(int userId, int targetAppId, int ephemeralAppId) { + if (mEphemeralGrants == null) { + return false; + } + final SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId); + if (targetAppList == null) { + return false; + } + final SparseBooleanArray ephemeralGrantList = targetAppList.get(targetAppId); + if (ephemeralGrantList == null) { + return false; + } + return ephemeralGrantList.get(ephemeralAppId); + } + + public void grantEphemeralAccessLPw(int userId, Intent intent, + int targetAppId, int ephemeralAppId) { + if (mInstalledEphemeralAppUids == null) { + return; // no ephemeral apps installed; no need to grant + } + SparseBooleanArray ephemeralAppList = mInstalledEphemeralAppUids.get(userId); + if (ephemeralAppList == null || !ephemeralAppList.get(ephemeralAppId)) { + return; // ephemeral app id isn't installed; no need to grant + } + if (ephemeralAppList.get(targetAppId)) { + return; // target app id is an ephemeral app; no need to grant + } + if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) { + final Set<String> categories = intent.getCategories(); + if (categories != null && categories.contains(Intent.CATEGORY_BROWSABLE)) { + return; // launched via VIEW/BROWSABLE intent; no need to grant + } + } + if (mEphemeralGrants == null) { + mEphemeralGrants = new SparseArray<>(); + } + SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId); + if (targetAppList == null) { + targetAppList = new SparseArray<>(); + mEphemeralGrants.put(userId, targetAppList); + } + SparseBooleanArray ephemeralGrantList = targetAppList.get(targetAppId); + if (ephemeralGrantList == null) { + ephemeralGrantList = new SparseBooleanArray(); + targetAppList.put(targetAppId, ephemeralGrantList); + } + ephemeralGrantList.put(ephemeralAppId, true /*granted*/); + } + + public void addEphemeralAppLPw(int userId, int ephemeralAppId) { + if (mInstalledEphemeralAppUids == null) { + mInstalledEphemeralAppUids = new SparseArray<>(); + } + SparseBooleanArray ephemeralAppList = mInstalledEphemeralAppUids.get(userId); + if (ephemeralAppList == null) { + ephemeralAppList = new SparseBooleanArray(); + mInstalledEphemeralAppUids.put(userId, ephemeralAppList); + } + ephemeralAppList.put(ephemeralAppId, true /*installed*/); + } + + private void removeEphemeralAppLPw(int userId, int ephemeralAppId) { + // remove from the installed list + if (mInstalledEphemeralAppUids == null) { + return; // no ephemeral apps on the system + } + final SparseBooleanArray ephemeralAppList = mInstalledEphemeralAppUids.get(userId); + if (ephemeralAppList == null) { + Slog.w(LOG_TAG, "Remove ephemeral not in install list"); + return; + } else { + ephemeralAppList.delete(ephemeralAppId); + } + // remove any grants + if (mEphemeralGrants == null) { + return; // no grants on the system + } + final SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId); + if (targetAppList == null) { + return; // no grants for this user + } + final int numApps = targetAppList.size(); + for (int i = targetAppList.size() - 1; i >= 0; --i) { + targetAppList.valueAt(i).delete(ephemeralAppId); + } + } + + private void removeAppLPw(int userId, int targetAppId) { + // remove from the installed list + if (mEphemeralGrants == null) { + return; // no grants on the system + } + final SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId); + if (targetAppList == null) { + return; // no grants for this user + } + targetAppList.delete(targetAppId); + } + private void addUninstalledEphemeralAppLPw(PackageParser.Package pkg, int userId) { EphemeralApplicationInfo uninstalledApp = createEphemeralAppInfoForPackage(pkg, userId); if (uninstalledApp == null) { diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 2ddf6dbde8aa..a74e14150001 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -231,11 +231,15 @@ public class LauncherAppsService extends SystemService { long ident = injectClearCallingIdentity(); try { UserInfo callingUserInfo = mUm.getUserInfo(callingUserId); + if (callingUserInfo.isManagedProfile()) { + throw new SecurityException(message + " for another profile " + targetUserId); + } + UserInfo targetUserInfo = mUm.getUserInfo(targetUserId); if (targetUserInfo == null || targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID || targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) { - throw new SecurityException(message); + throw new SecurityException(message + " for unrelated profile " + targetUserId); } } finally { injectRestoreCallingIdentity(ident); @@ -289,7 +293,7 @@ public class LauncherAppsService extends SystemService { @Override public ActivityInfo resolveActivity(ComponentName component, UserHandle user) throws RemoteException { - ensureInUserProfiles(user, "Cannot resolve activity for unrelated profile " + user); + ensureInUserProfiles(user, "Cannot resolve activity"); if (!isUserEnabled(user)) { return null; } @@ -315,7 +319,7 @@ public class LauncherAppsService extends SystemService { private ParceledListSlice<ResolveInfo> queryActivitiesForUser(Intent intent, UserHandle user) { - ensureInUserProfiles(user, "Cannot retrieve activities for unrelated profile " + user); + ensureInUserProfiles(user, "Cannot retrieve activities"); if (!isUserEnabled(user)) { return null; } @@ -356,7 +360,7 @@ public class LauncherAppsService extends SystemService { @Override public boolean isPackageEnabled(String packageName, UserHandle user) throws RemoteException { - ensureInUserProfiles(user, "Cannot check package for unrelated profile " + user); + ensureInUserProfiles(user, "Cannot check package"); if (!isUserEnabled(user)) { return false; } @@ -377,7 +381,7 @@ public class LauncherAppsService extends SystemService { @Override public ApplicationInfo getApplicationInfo(String packageName, int flags, UserHandle user) throws RemoteException { - ensureInUserProfiles(user, "Cannot check package for unrelated profile " + user); + ensureInUserProfiles(user, "Cannot check package"); if (!isUserEnabled(user)) { return null; } @@ -399,7 +403,7 @@ public class LauncherAppsService extends SystemService { private void ensureShortcutPermission(@NonNull String callingPackage, int userId) { verifyCallingPackage(callingPackage); - ensureInUserProfiles(userId, "Cannot access shortcuts for unrelated profile " + userId); + ensureInUserProfiles(userId, "Cannot access shortcuts"); if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(), callingPackage)) { @@ -475,7 +479,7 @@ public class LauncherAppsService extends SystemService { public boolean startShortcut(String callingPackage, String packageName, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int userId) { verifyCallingPackage(callingPackage); - ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId); + ensureInUserProfiles(userId, "Cannot start activity"); if (!isUserEnabled(userId)) { throw new IllegalStateException("Cannot start a shortcut for disabled profile " @@ -528,7 +532,7 @@ public class LauncherAppsService extends SystemService { @Override public boolean isActivityEnabled(ComponentName component, UserHandle user) throws RemoteException { - ensureInUserProfiles(user, "Cannot check component for unrelated profile " + user); + ensureInUserProfiles(user, "Cannot check component"); if (!isUserEnabled(user)) { return false; } @@ -549,7 +553,7 @@ public class LauncherAppsService extends SystemService { @Override public void startActivityAsUser(ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException { - ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user); + ensureInUserProfiles(user, "Cannot start activity"); if (!isUserEnabled(user)) { throw new IllegalStateException("Cannot start activity for disabled profile " + user); } @@ -602,7 +606,7 @@ public class LauncherAppsService extends SystemService { @Override public void showAppDetailsAsUser(ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException { - ensureInUserProfiles(user, "Cannot show app details for unrelated profile " + user); + ensureInUserProfiles(user, "Cannot show app details"); if (!isUserEnabled(user)) { throw new IllegalStateException("Cannot show app details for disabled profile " + user); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 666988963171..e3fa0c4b2e1f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -68,6 +68,7 @@ import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY; import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES; 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_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL; import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN; import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST; import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR; @@ -80,7 +81,6 @@ import static android.content.pm.PackageParser.isApkFile; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDWR; - import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT; import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME; @@ -2224,6 +2224,7 @@ public class PackageManagerService extends IPackageManager.Stub { Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this); + mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this); File dataDir = Environment.getDataDirectory(); mAppInstallDir = new File(dataDir, "app"); @@ -2806,8 +2807,6 @@ public class PackageManagerService extends IPackageManager.Stub { setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent); } - mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this); - // Read and update the usage of dex files. // Do this at the end of PM init so that all the packages have their // data directory reconciled. @@ -3257,6 +3256,31 @@ public class PackageManagerService extends IPackageManager.Stub { if (p == null) { return null; } + // Filter out ephemeral app metadata: + // * The system/shell/root can see metadata for any app + // * An installed app can see metadata for 1) other installed apps + // and 2) ephemeral apps that have explicitly interacted with it + // * Ephemeral apps can only see their own metadata + final int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); + if (callingAppId != Process.SYSTEM_UID + && callingAppId != Process.SHELL_UID + && callingAppId != Process.ROOT_UID) { + final String ephemeralPackageName = getEphemeralPackageName(Binder.getCallingUid()); + if (ephemeralPackageName != null) { + // ephemeral apps can only get information on themselves + if (!ephemeralPackageName.equals(p.packageName)) { + return null; + } + } else { + if (p.applicationInfo.isEphemeralApp()) { + // only get access to the ephemeral app if we've been granted access + if (!mEphemeralApplicationRegistry.isEphemeralAccessGranted( + userId, callingAppId, ps.appId)) { + return null; + } + } + } + } final PermissionsState permissionsState = ps.getPermissionsState(); @@ -3336,22 +3360,19 @@ public class PackageManagerService extends IPackageManager.Stub { // reader synchronized (mPackages) { - // Normalize package name to hanlde renamed packages + // Normalize package name to handle renamed packages packageName = normalizePackageNameLPr(packageName); final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0; - PackageParser.Package p = null; if (matchFactoryOnly) { final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName); if (ps != null) { return generatePackageInfo(ps, flags, userId); } } - if (p == null) { - p = mPackages.get(packageName); - if (matchFactoryOnly && p != null && !isSystemApp(p)) { - return null; - } + PackageParser.Package p = mPackages.get(packageName); + if (matchFactoryOnly && p != null && !isSystemApp(p)) { + return null; } if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getPackageInfo " + packageName + ": " + p); @@ -3745,6 +3766,19 @@ public class PackageManagerService extends IPackageManager.Stub { } /** + * Update given intent when being used to request {@link ResolveInfo}. + */ + private Intent updateIntentForResolve(Intent intent) { + if (intent.getSelector() != null) { + intent = intent.getSelector(); + } + if (DEBUG_PREFERRED) { + intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); + } + return intent; + } + + /** * Update given flags when being used to request {@link ResolveInfo}. */ int updateFlagsForResolve(int flags, int userId, Object cookie) { @@ -5128,6 +5162,26 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override + public ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) { + if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.SYSTEM_UID)) { + throw new SecurityException( + "findPersistentPreferredActivity can only be run by the system"); + } + if (!sUserManager.exists(userId)) { + return null; + } + intent = updateIntentForResolve(intent); + final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver()); + final int flags = updateFlagsForResolve(0, userId, intent); + final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags, + userId); + synchronized (mPackages) { + return findPersistentPreferredActivityLP(intent, resolvedType, flags, query, false, + userId); + } + } + + @Override public void setLastChosenActivity(Intent intent, String resolvedType, int flags, IntentFilter filter, int match, ComponentName activity) { final int userId = UserHandle.getCallingUserId(); @@ -5393,13 +5447,9 @@ public class PackageManagerService extends IPackageManager.Stub { boolean removeMatches, boolean debug, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForResolve(flags, userId, intent); + intent = updateIntentForResolve(intent); // writer synchronized (mPackages) { - if (intent.getSelector() != null) { - intent = intent.getSelector(); - } - if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); - // Try to find a matching persistent preferred activity. ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query, debug, userId); @@ -5965,7 +6015,7 @@ public class PackageManagerService extends IPackageManager.Stub { int status = (int)(packedStatus >> 32); int linkGeneration = (int)(packedStatus & 0xFFFFFFFF); if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { - if (DEBUG_DOMAIN_VERIFICATION) { + if (DEBUG_DOMAIN_VERIFICATION || debug) { Slog.i(TAG, " + always: " + info.activityInfo.packageName + " : linkgen=" + linkGeneration); } @@ -5974,18 +6024,18 @@ public class PackageManagerService extends IPackageManager.Stub { info.preferredOrder = linkGeneration; alwaysList.add(info); } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { - if (DEBUG_DOMAIN_VERIFICATION) { + if (DEBUG_DOMAIN_VERIFICATION || debug) { Slog.i(TAG, " + never: " + info.activityInfo.packageName); } neverList.add(info); } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) { - if (DEBUG_DOMAIN_VERIFICATION) { + if (DEBUG_DOMAIN_VERIFICATION || debug) { Slog.i(TAG, " + always-ask: " + info.activityInfo.packageName); } alwaysAskList.add(info); } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED || status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK) { - if (DEBUG_DOMAIN_VERIFICATION) { + if (DEBUG_DOMAIN_VERIFICATION || debug) { Slog.i(TAG, " + ask: " + info.activityInfo.packageName); } undefinedList.add(info); @@ -8839,6 +8889,10 @@ public class PackageManagerService extends IPackageManager.Stub { // Modify state for the given package setting commitPackageSettings(pkg, pkgSetting, user, scanFlags, (policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/); + if (isEphemeral(pkg)) { + final int userId = user == null ? 0 : user.getIdentifier(); + mEphemeralApplicationRegistry.addEphemeralAppLPw(userId, pkgSetting.appId); + } } return pkg; } @@ -12143,7 +12197,7 @@ public class PackageManagerService extends IPackageManager.Stub { IActivityManager am = ActivityManager.getService(); if (am != null) { try { - am.startService(null, intent, null, mContext.getOpPackageName(), + am.startService(null, intent, null, -1, null, mContext.getOpPackageName(), UserHandle.USER_SYSTEM); } catch (RemoteException e) { } @@ -16627,7 +16681,8 @@ public class PackageManagerService extends IPackageManager.Stub { extras, 0, null, null, removedUsers); if (dataRemoved && !isRemovedPackageSystemUpdate) { sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, - removedPackage, extras, 0, null, null, removedUsers); + removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, + null, null, removedUsers); } } if (removedAppId >= 0) { @@ -19581,7 +19636,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); count = 0; for (PackageSetting ps : allPackageSettings) { final long status = ps.getDomainVerificationStatusForUser(userId); - if (status >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) { + if (status >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED + && !DEBUG_DOMAIN_VERIFICATION) { continue; } pw.println(prefix + "Package: " + ps.name); @@ -21042,6 +21098,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); "Cannot move system application"); } + final boolean isInternalStorage = VolumeInfo.ID_PRIVATE_INTERNAL.equals(volumeUuid); + final boolean allow3rdPartyOnInternal = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allow3rdPartyAppOnInternal); + if (isInternalStorage && !allow3rdPartyOnInternal) { + throw new PackageManagerException(MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL, + "3rd party apps are not allowed on internal storage"); + } + if (pkg.applicationInfo.isExternalAsec()) { currentAsec = true; currentVolumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL; @@ -21924,6 +21988,15 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); responseObj, origIntent, resolvedType, launchIntent, callingPackage, userId); } + @Override + public void grantEphemeralAccess(int userId, Intent intent, + int targetAppId, int ephemeralAppId) { + synchronized (mPackages) { + mEphemeralApplicationRegistry.grantEphemeralAccessLPw(userId, intent, + targetAppId, ephemeralAppId); + } + } + public String getSetupWizardPackageName() { return mSetupWizardPackage; } diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java index a156356e825e..6e967267e51d 100644 --- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java +++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java @@ -203,19 +203,13 @@ class ShortcutRequestPinProcessor { // Next, validate the incoming shortcut, etc. final PinItemRequest request; if (inShortcut != null) { - request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity, - true /* ignoreIfAlreadyPinned */); + request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity); } else { int launcherUid = mService.injectGetPackageUid( confirmActivity.first.getPackageName(), launcherUserId); request = new PinItemRequest(inAppWidget, new PinItemRequestInner(this, resultIntent, launcherUid)); } - - if (request == null) { - sendResultIntent(resultIntent, null); - return true; - } return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request); } @@ -238,23 +232,17 @@ class ShortcutRequestPinProcessor { mService.throwIfUserLockedL(launcherUserId); // Next, validate the incoming shortcut, etc. - PinItemRequest request = requestPinShortcutLocked(inShortcut, null, - Pair.create(defaultLauncher, launcherUserId), false /* ignoreIfAlreadyPinned */); - if (request == null) { - return null; - } + final PinItemRequest request = requestPinShortcutLocked(inShortcut, null, + Pair.create(defaultLauncher, launcherUserId)); return new Intent().putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request); } /** * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)}. - * - * @param ignoreIfAlreadyPinned if true and the {@param inShortcut} is already pinned for - * {@param confirmActivity}, null is returned instead. */ + @NonNull private PinItemRequest requestPinShortcutLocked(ShortcutInfo inShortcut, - IntentSender resultIntent, Pair<ComponentName, Integer> confirmActivity, - boolean ignoreIfAlreadyPinned) { + IntentSender resultIntentOriginal, Pair<ComponentName, Integer> confirmActivity) { final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked( inShortcut.getPackage(), inShortcut.getUserId()); @@ -272,16 +260,20 @@ class ShortcutRequestPinProcessor { final String launcherPackage = confirmActivity.first.getPackageName(); final int launcherUserId = confirmActivity.second; + IntentSender resultIntentToSend = resultIntentOriginal; + if (existsAlready) { validateExistingShortcut(existing); final boolean isAlreadyPinned = mService.getLauncherShortcutsLocked( launcherPackage, existing.getUserId(), launcherUserId).hasPinned(existing); - // See if it's already pinned. - if (ignoreIfAlreadyPinned && isAlreadyPinned) { - Log.i(TAG, "Launcher's already pinning shortcut " + existing.getId() - + " for package " + existing.getPackage()); - return null; + if (isAlreadyPinned) { + // When the shortcut is already pinned by this launcher, the request will always + // succeed, so just send the result at this point. + sendResultIntent(resultIntentOriginal, null); + + // So, do not send the intent again. + resultIntentToSend = null; } // Pass a clone, not the original. @@ -289,7 +281,7 @@ class ShortcutRequestPinProcessor { shortcutForLauncher = existing.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); if (!isAlreadyPinned) { - // FLAG_PINNED is still set, if it's pinned by other launchers. + // FLAG_PINNED may still be set, if it's pinned by other launchers. shortcutForLauncher.clearFlags(ShortcutInfo.FLAG_PINNED); } } else { @@ -320,8 +312,8 @@ class ShortcutRequestPinProcessor { // Create a request object. final PinShortcutRequestInner inner = - new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntent, - launcherPackage, launcherUserId, + new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, + resultIntentToSend, launcherPackage, launcherUserId, mService.injectGetPackageUid(launcherPackage, launcherUserId), existsAlready); @@ -410,6 +402,16 @@ class ShortcutRequestPinProcessor { return false; } + final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked( + launcherPackage, appUserId, launcherUserId); + launcher.attemptToRestoreIfNeededAndSave(); + if (launcher.hasPinned(original)) { + if (DEBUG) { + Slog.d(TAG, "Shortcut " + original + " already pinned."); + } + return true; + } + final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked( appPackageName, appUserId); final ShortcutInfo current = ps.findShortcutById(shortcutId); @@ -447,9 +449,6 @@ class ShortcutRequestPinProcessor { Slog.d(TAG, "Pinning " + shortcutId); } - final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked( - launcherPackage, appUserId, launcherUserId); - launcher.attemptToRestoreIfNeededAndSave(); launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId); if (current == null) { diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java index 90c711a47941..a3837b28b168 100644 --- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java +++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java @@ -338,9 +338,11 @@ public class DeviceStorageMonitorService extends SystemService { mTotalMemory = (long)mDataFileStats.getBlockCount() * mDataFileStats.getBlockSize(); mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW); - mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK); - mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL); mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL); diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java new file mode 100644 index 000000000000..15edaaf93af6 --- /dev/null +++ b/services/core/java/com/android/server/vr/CompatibilityDisplay.java @@ -0,0 +1,119 @@ + +package com.android.server.vr; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.hardware.display.DisplayManager; +import android.hardware.display.VirtualDisplay; +import android.os.Build; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.service.vr.IVrStateCallbacks; +import android.service.vr.IVrManager; +import android.util.Log; + +import com.android.server.vr.VrManagerService; + +/** + * Creates a 2D Virtual Display while VR Mode is enabled. This display will be used to run and + * render 2D app within a VR experience. For example, bringing up the 2D calculator app in VR. + */ +class CompatibilityDisplay { + private final static String TAG = "CompatDisplay"; + private final static boolean DEBUG = false; + + // TODO: Go over these values and figure out what is best + private final static int HEIGHT = 960; + private final static int WIDTH = 720; + private final static int DPI = 320; + + private final DisplayManager mDisplayManager; + private final IVrManager mVrManager; + + // TODO: Lock initially created when VrStateCallback was connected through Binder. This may not + // be necessary with the direct access to VrManager. + private final Object vdLock = new Object(); + + private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() { + @Override + public void onVrStateChanged(boolean enabled) { + if (enabled != mIsVrModeEnabled) { + mIsVrModeEnabled = enabled; + if (enabled) { + // TODO: Consider not creating the display until ActivityManager needs one on + // which to display a 2D application. + startVirtualDisplay(); + } else { + stopVirtualDisplay(); + } + } + } + }; + + private VirtualDisplay mVirtualDisplay; + private boolean mIsVrModeEnabled; + + public CompatibilityDisplay(DisplayManager displayManager, IVrManager vrManager) { + mDisplayManager = displayManager; + mVrManager = vrManager; + } + + /** + * Initializes the compabilitiy display by listening to VR mode changes. + */ + public void init() { + startVrModeListener(); + } + + private void startVrModeListener() { + if (mVrManager != null) { + try { + mVrManager.registerListener(mVrStateCallbacks); + } catch (RemoteException e) { + Log.e(TAG, "Could not register VR State listener.", e); + } + } + } + + private void startVirtualDisplay() { + if (DEBUG) { + Log.d(TAG, "Starting VD, DM:" + mDisplayManager); + } + + if (mDisplayManager == null) { + Log.w(TAG, "Cannot create virtual display because mDisplayManager == null"); + return; + } + + synchronized (vdLock) { + if (mVirtualDisplay != null) { + Log.e(TAG, "Starting the virtual display when one already exists", new Exception()); + return; + } + + mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", WIDTH, HEIGHT, + DPI, + null /* Surface */, 0 /* flags */); + } + + if (DEBUG) { + Log.d(TAG, "VD created: " + mVirtualDisplay); + } + } + + private void stopVirtualDisplay() { + if (DEBUG) { + Log.i(TAG, "Santos, stopping VD"); + } + + synchronized (vdLock) { + if (mVirtualDisplay != null) { + mVirtualDisplay.release(); + mVirtualDisplay = null; + } + } + } +} diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index 84cf0c6e9042..57587b08c26b 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -31,6 +31,7 @@ import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.hardware.display.DisplayManager; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -51,6 +52,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; + import com.android.internal.R; import com.android.server.LocalServices; import com.android.server.SystemConfig; @@ -136,6 +138,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager(); /** Tracks the state of the screen and keyguard UI.*/ private int mSystemSleepFlags = FLAG_NONE; + private CompatibilityDisplay mCompatibilityDisplay; private static final int MSG_VR_STATE_CHANGE = 0; private static final int MSG_PENDING_VR_STATE_CHANGE = 1; @@ -493,6 +496,11 @@ public class VrManagerService extends SystemService implements EnabledComponentC mComponentObserver.rebuildAll(); } + + DisplayManager dm = + (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE); + mCompatibilityDisplay = new CompatibilityDisplay(dm, mVrManager); + mCompatibilityDisplay.init(); } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { synchronized (mLock) { mVrModeAllowed = true; diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index bfb4269f7806..08f9b4585e98 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -333,7 +333,9 @@ class PinnedStackController { */ void setActions(List<RemoteAction> actions) { mActions.clear(); - mActions.addAll(actions); + if (actions != null) { + mActions.addAll(actions); + } notifyActionsChanged(mActions); } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index df8679dae54f..10ecf3bb1ae3 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -22,11 +22,13 @@ import android.annotation.Nullable; import android.app.ActivityManager.StackId; import android.app.ActivityManager.TaskSnapshot; import android.graphics.GraphicBuffer; +import android.os.Environment; import android.util.ArraySet; import android.view.WindowManagerPolicy.StartingSurface; import com.android.internal.annotations.VisibleForTesting; +import java.io.File; import java.io.PrintWriter; /** @@ -45,14 +47,21 @@ import java.io.PrintWriter; class TaskSnapshotController { private final WindowManagerService mService; - private final TaskSnapshotCache mCache = new TaskSnapshotCache(); + private final TaskSnapshotCache mCache = new TaskSnapshotCache(); + private final TaskSnapshotPersister mPersister = new TaskSnapshotPersister( + Environment::getDataSystemCeDirectory); + private final TaskSnapshotLoader mLoader = new TaskSnapshotLoader(mPersister); private final ArraySet<Task> mTmpTasks = new ArraySet<>(); TaskSnapshotController(WindowManagerService service) { mService = service; } + void systemReady() { + mPersister.start(); + } + void onTransitionStarting() { if (!ENABLE_TASK_SNAPSHOTS) { return; @@ -69,6 +78,7 @@ class TaskSnapshotController { final TaskSnapshot snapshot = snapshotTask(task); if (snapshot != null) { mCache.putSnapshot(task, snapshot); + mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot); if (task.getController() != null) { task.getController().reportSnapshotChanged(snapshot); } @@ -141,6 +151,17 @@ class TaskSnapshotController { mCache.cleanCache(wtoken); } + void notifyTaskRemovedFromRecents(int taskId, int userId) { + mPersister.onTaskRemovedFromRecents(taskId, userId); + } + + /** + * See {@link TaskSnapshotPersister#removeObsoleteFiles} + */ + void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) { + mPersister.removeObsoleteFiles(persistentTaskIds, runningUserIds); + } + void dump(PrintWriter pw, String prefix) { mCache.dump(pw, prefix); } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java new file mode 100644 index 000000000000..43408229289e --- /dev/null +++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; + +import android.app.ActivityManager.TaskSnapshot; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.BitmapFactory.Options; +import android.graphics.GraphicBuffer; +import android.graphics.Rect; +import android.util.Slog; + +import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +/** + * Loads a persisted {@link TaskSnapshot} from disk. + * <p> + * Do not hold the window manager lock when accessing this class. + * <p> + * Test class: {@link TaskSnapshotPersisterLoaderTest} + */ +class TaskSnapshotLoader { + + private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotLoader" : TAG_WM; + + private final TaskSnapshotPersister mPersister; + + TaskSnapshotLoader(TaskSnapshotPersister persister) { + mPersister = persister; + } + + /** + * Loads a task from the disk. + * <p> + * Do not hold the window manager lock when calling this method, as we directly read data from + * disk here, which might be slow. + * + * @param taskId The id of the task to load. + * @param userId The id of the user the task belonged to. + * @return The loaded {@link TaskSnapshot} or {@code null} if it couldn't be loaded. + */ + TaskSnapshot loadTask(int taskId, int userId) { + final File protoFile = mPersister.getProtoFile(taskId, userId); + final File bitmapFile = mPersister.getBitmapFile(taskId, userId); + if (!protoFile.exists() || !bitmapFile.exists()) { + return null; + } + try { + final byte[] bytes = Files.readAllBytes(protoFile.toPath()); + final TaskSnapshotProto proto = TaskSnapshotProto.parseFrom(bytes); + final Options options = new Options(); + options.inPreferredConfig = Config.HARDWARE; + final Bitmap bitmap = BitmapFactory.decodeFile(bitmapFile.getPath(), options); + if (bitmap == null) { + Slog.w(TAG, "Failed to load bitmap: " + bitmapFile.getPath()); + return null; + } + final GraphicBuffer buffer = bitmap.createGraphicBufferHandle(); + if (buffer == null) { + Slog.w(TAG, "Failed to retrieve gralloc buffer for bitmap: " + + bitmapFile.getPath()); + return null; + } + return new TaskSnapshot(buffer, proto.orientation, + new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom)); + } catch (IOException e) { + Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId); + return null; + } + } +} diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java new file mode 100644 index 000000000000..3a06c3859ca5 --- /dev/null +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; + +import android.annotation.TestApi; +import android.app.ActivityManager.TaskSnapshot; +import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; +import android.os.Process; +import android.os.SystemClock; +import android.util.ArraySet; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.AtomicFile; +import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayDeque; + +/** + * Persists {@link TaskSnapshot}s to disk. + * <p> + * Test class: {@link TaskSnapshotPersisterLoaderTest} + */ +class TaskSnapshotPersister { + + private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotPersister" : TAG_WM; + private static final String SNAPSHOTS_DIRNAME = "snapshots"; + private static final long DELAY_MS = 100; + private static final String PROTO_EXTENSION = ".proto"; + private static final String BITMAP_EXTENSION = ".png"; + + @GuardedBy("mLock") + private final ArrayDeque<WriteQueueItem> mWriteQueue = new ArrayDeque<>(); + @GuardedBy("mLock") + private boolean mQueueIdling; + private boolean mStarted; + private final Object mLock = new Object(); + private final DirectoryResolver mDirectoryResolver; + + /** + * The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was + * called. + */ + @GuardedBy("mLock") + private final ArraySet<Integer> mPersistedTaskIdsSinceLastRemoveObsolete = new ArraySet<>(); + + TaskSnapshotPersister(DirectoryResolver resolver) { + mDirectoryResolver = resolver; + } + + /** + * Starts persisting. + */ + void start() { + if (!mStarted) { + mStarted = true; + mPersister.start(); + } + } + + /** + * Persists a snapshot of a task to disk. + * + * @param taskId The id of the task that needs to be persisted. + * @param userId The id of the user this tasks belongs to. + * @param snapshot The snapshot to persist. + */ + void persistSnapshot(int taskId, int userId, TaskSnapshot snapshot) { + synchronized (mLock) { + mPersistedTaskIdsSinceLastRemoveObsolete.add(taskId); + sendToQueueLocked(new StoreWriteQueueItem(taskId, userId, snapshot)); + } + } + + /** + * Callend when a task has been removed. + * + * @param taskId The id of task that has been removed. + * @param userId The id of the user the task belonged to. + */ + void onTaskRemovedFromRecents(int taskId, int userId) { + synchronized (mLock) { + mPersistedTaskIdsSinceLastRemoveObsolete.remove(taskId); + sendToQueueLocked(new DeleteWriteQueueItem(taskId, userId)); + } + } + + /** + * In case a write/delete operation was lost because the system crashed, this makes sure to + * clean up the directory to remove obsolete files. + * + * @param persistentTaskIds A set of task ids that exist in our in-memory model. + * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory + * model. + */ + void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) { + synchronized (mLock) { + mPersistedTaskIdsSinceLastRemoveObsolete.clear(); + sendToQueueLocked(new RemoveObsoleteFilesQueueItem(persistentTaskIds, runningUserIds)); + } + } + + @TestApi + void waitForQueueEmpty() { + while (true) { + synchronized (mLock) { + if (mWriteQueue.isEmpty() && mQueueIdling) { + return; + } + } + SystemClock.sleep(100); + } + } + + @GuardedBy("mLock") + private void sendToQueueLocked(WriteQueueItem item) { + mWriteQueue.offer(item); + mLock.notifyAll(); + } + + private File getDirectory(int userId) { + return new File(mDirectoryResolver.getSystemDirectoryForUser(userId), SNAPSHOTS_DIRNAME); + } + + File getProtoFile(int taskId, int userId) { + return new File(getDirectory(userId), taskId + PROTO_EXTENSION); + } + + File getBitmapFile(int taskId, int userId) { + return new File(getDirectory(userId), taskId + BITMAP_EXTENSION); + } + + private boolean createDirectory(int userId) { + final File dir = getDirectory(userId); + return dir.exists() || dir.mkdirs(); + } + + private void deleteSnapshot(int taskId, int userId) { + final File protoFile = getProtoFile(taskId, userId); + final File bitmapFile = getBitmapFile(taskId, userId); + protoFile.delete(); + bitmapFile.delete(); + } + + interface DirectoryResolver { + File getSystemDirectoryForUser(int userId); + } + + private Thread mPersister = new Thread("TaskSnapshotPersister") { + public void run() { + android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + while (true) { + WriteQueueItem next; + synchronized (mLock) { + next = mWriteQueue.poll(); + } + if (next != null) { + next.write(); + SystemClock.sleep(DELAY_MS); + } + synchronized (mLock) { + if (!mWriteQueue.isEmpty()) { + continue; + } + try { + mQueueIdling = true; + mLock.wait(); + mQueueIdling = false; + } catch (InterruptedException e) { + } + } + } + } + }; + + private abstract class WriteQueueItem { + abstract void write(); + } + + private class StoreWriteQueueItem extends WriteQueueItem { + private final int mTaskId; + private final int mUserId; + private final TaskSnapshot mSnapshot; + + StoreWriteQueueItem(int taskId, int userId, TaskSnapshot snapshot) { + mTaskId = taskId; + mUserId = userId; + mSnapshot = snapshot; + } + + @Override + void write() { + if (!createDirectory(mUserId)) { + Slog.e(TAG, "Unable to create snapshot directory for user dir=" + + getDirectory(mUserId)); + } + boolean failed = false; + if (!writeProto()) { + failed = true; + } + if (!writeBuffer()) { + writeBuffer(); + failed = true; + } + if (failed) { + deleteSnapshot(mTaskId, mUserId); + } + } + + boolean writeProto() { + final TaskSnapshotProto proto = new TaskSnapshotProto(); + proto.orientation = mSnapshot.getOrientation(); + proto.insetLeft = mSnapshot.getContentInsets().left; + proto.insetTop = mSnapshot.getContentInsets().top; + proto.insetRight = mSnapshot.getContentInsets().right; + proto.insetBottom = mSnapshot.getContentInsets().bottom; + final byte[] bytes = TaskSnapshotProto.toByteArray(proto); + final File file = getProtoFile(mTaskId, mUserId); + final AtomicFile atomicFile = new AtomicFile(file); + FileOutputStream fos = null; + try { + fos = atomicFile.startWrite(); + fos.write(bytes); + atomicFile.finishWrite(fos); + } catch (IOException e) { + atomicFile.failWrite(fos); + Slog.e(TAG, "Unable to open " + file + " for persisting. " + e); + return false; + } + return true; + } + + boolean writeBuffer() { + final File file = getBitmapFile(mTaskId, mUserId); + final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot()); + try { + FileOutputStream fos = new FileOutputStream(file); + bitmap.compress(CompressFormat.PNG, 0 /* quality */, fos); + fos.close(); + } catch (IOException e) { + Slog.e(TAG, "Unable to open " + file + " for persisting. " + e); + return false; + } + return true; + } + } + + private class DeleteWriteQueueItem extends WriteQueueItem { + private final int mTaskId; + private final int mUserId; + + DeleteWriteQueueItem(int taskId, int userId) { + mTaskId = taskId; + mUserId = userId; + } + + @Override + void write() { + deleteSnapshot(mTaskId, mUserId); + } + } + + @VisibleForTesting + class RemoveObsoleteFilesQueueItem extends WriteQueueItem { + private final ArraySet<Integer> mPersistentTaskIds; + private final int[] mRunningUserIds; + + @VisibleForTesting + RemoveObsoleteFilesQueueItem(ArraySet<Integer> persistentTaskIds, + int[] runningUserIds) { + mPersistentTaskIds = persistentTaskIds; + mRunningUserIds = runningUserIds; + } + + @Override + void write() { + final ArraySet<Integer> newPersistedTaskIds; + synchronized (mLock) { + newPersistedTaskIds = new ArraySet<>(mPersistedTaskIdsSinceLastRemoveObsolete); + } + for (int userId : mRunningUserIds) { + final File dir = getDirectory(userId); + final String[] files = dir.list(); + if (files == null) { + continue; + } + for (String file : files) { + final int taskId = getTaskId(file); + if (!mPersistentTaskIds.contains(taskId) + && !newPersistedTaskIds.contains(taskId)) { + new File(dir, file).delete(); + } + } + } + } + + @VisibleForTesting + int getTaskId(String fileName) { + if (!fileName.endsWith(PROTO_EXTENSION) && !fileName.endsWith(BITMAP_EXTENSION)) { + return -1; + } + final int end = fileName.lastIndexOf('.'); + if (end == -1) { + return -1; + } + try { + return Integer.parseInt(fileName.substring(0, end)); + } catch (NumberFormatException e) { + return -1; + } + } + } +} diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 71edbb788969..9a6cd2cb41f8 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3903,6 +3903,20 @@ public class WindowManagerService extends IWindowManager.Stub } /** + * In case a task write/delete operation was lost because the system crashed, this makes sure to + * clean up the directory to remove obsolete files. + * + * @param persistentTaskIds A set of task ids that exist in our in-memory model. + * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory + * model. + */ + public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) { + synchronized (mWindowMap) { + mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds); + } + } + + /** * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. * In portrait mode, it grabs the full screenshot. * @@ -5347,6 +5361,7 @@ public class WindowManagerService extends IWindowManager.Stub public void systemReady() { mPolicy.systemReady(); + mTaskSnapshotController.systemReady(); } // ------------------------------------------------------------- @@ -6986,6 +7001,18 @@ public class WindowManagerService extends IWindowManager.Stub } } + /** + * Called when a task has been removed from the recent tasks list. + * <p> + * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window + * container may not exist when this happens. + */ + public void notifyTaskRemovedFromRecents(int taskId, int userId) { + synchronized (mWindowMap) { + mTaskSnapshotController.notifyTaskRemovedFromRecents(taskId, userId); + } + } + @Override public int getDockedDividerInsetsLw() { return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets(); diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp index 179fba073e75..9f528b1bec6a 100644 --- a/services/core/jni/com_android_server_tv_TvInputHal.cpp +++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp @@ -327,7 +327,7 @@ JTvInputHal::~JTvInputHal() { JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper) { // TODO(b/31632518) - sp<ITvInput> tvInput = ITvInput::getService("tv.input"); + sp<ITvInput> tvInput = ITvInput::getService(); if (tvInput == nullptr) { ALOGE("Couldn't get tv.input service."); return nullptr; diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index 8dd05b19ea7a..2624f0b3a21e 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -30,6 +30,7 @@ import android.net.DhcpResults; import android.net.InterfaceConfiguration; import android.net.LinkAddress; import android.net.NetworkUtils; +import android.net.TrafficStats; import android.net.metrics.IpConnectivityLog; import android.net.metrics.DhcpClientEvent; import android.net.metrics.DhcpErrorEvent; @@ -303,6 +304,7 @@ public class DhcpClient extends StateMachine { } private boolean initUdpSocket() { + final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_DHCP); try { mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1); @@ -314,6 +316,8 @@ public class DhcpClient extends StateMachine { } catch(SocketException|ErrnoException e) { Log.e(TAG, "Error creating UDP socket", e); return false; + } finally { + TrafficStats.setThreadStatsTag(oldTag); } return true; } diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java index 6802cffc0207..ba1621d7d6bc 100644 --- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java +++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java @@ -22,6 +22,7 @@ import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkUtils; +import android.net.TrafficStats; import android.system.ErrnoException; import android.system.Os; import android.system.StructGroupReq; @@ -563,6 +564,7 @@ public class RouterAdvertisementDaemon { private boolean createSocket() { final int SEND_TIMEOUT_MS = 300; + final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NEIGHBOR); try { mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); // Setting SNDTIMEO is purely for defensive purposes. @@ -574,6 +576,8 @@ public class RouterAdvertisementDaemon { } catch (ErrnoException | IOException e) { Log.e(TAG, "Failed to create RA daemon socket: " + e); return false; + } finally { + TrafficStats.setThreadStatsTag(oldTag); } return true; diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java index f8061f6feb00..59ac427f4251 100644 --- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java @@ -15,6 +15,7 @@ */ package com.android.server.notification; +import static junit.framework.Assert.assertNull; import static junit.framework.Assert.fail; import org.junit.Before; @@ -34,6 +35,7 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; import android.net.Uri; import android.os.Build; import android.os.UserHandle; @@ -49,6 +51,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -166,7 +171,7 @@ public class RankingHelperTest { serializer.flush(); for (String channelId : channelIds) { - mHelper.deleteNotificationChannel(pkg, uid, channelId); + mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId); } return baos; } @@ -246,26 +251,23 @@ public class RankingHelperTest { channel2.enableVibration(true); channel2.setVibrationPattern(new long[] {100, 67, 145, 156}); - mHelper.createNotificationChannel(pkg, uid, channel1, false); + mHelper.createNotificationChannel(pkg, uid, channel1, true); mHelper.createNotificationChannel(pkg, uid, channel2, false); ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(), channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); - mHelper.deleteNotificationChannel(pkg, uid, channel1.getId()); - mHelper.deleteNotificationChannel(pkg, uid, channel2.getId()); - mHelper.deleteNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID); - XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), null); parser.nextTag(); mHelper.readXml(parser, false); - assertEquals(channel1, mHelper.getNotificationChannel(pkg, uid, channel1.getId())); - compareChannels(channel2, mHelper.getNotificationChannel(pkg, uid, channel2.getId())); - assertNotNull( - mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID)); + assertEquals(channel1, mHelper.getNotificationChannel(pkg, uid, channel1.getId(), false)); + compareChannels(channel2, + mHelper.getNotificationChannel(pkg, uid, channel2.getId(), false)); + assertNotNull(mHelper.getNotificationChannel( + pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false)); } @Test @@ -284,8 +286,8 @@ public class RankingHelperTest { parser.nextTag(); mHelper.readXml(parser, false); - final NotificationChannel updated = - mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID); + final NotificationChannel updated = mHelper.getNotificationChannel( + pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false); assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance()); assertFalse(updated.canBypassDnd()); assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,updated.getLockscreenVisibility()); @@ -298,8 +300,8 @@ public class RankingHelperTest { new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN); mHelper.createNotificationChannel(pkg, uid, channel1, true); - final NotificationChannel defaultChannel = - mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID); + final NotificationChannel defaultChannel = mHelper.getNotificationChannel( + pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false); defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mHelper.updateNotificationChannel(pkg, uid, defaultChannel); @@ -313,7 +315,7 @@ public class RankingHelperTest { mHelper.readXml(parser, false); assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel( - pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID).getImportance()); + pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); } @Test @@ -331,8 +333,8 @@ public class RankingHelperTest { parser.nextTag(); mHelper.readXml(parser, false); - final NotificationChannel updated1 = - mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID); + final NotificationChannel updated1 = mHelper.getNotificationChannel( + pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false); assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance()); assertTrue(updated1.canBypassDnd()); assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility()); @@ -340,8 +342,8 @@ public class RankingHelperTest { | NotificationChannel.USER_LOCKED_PRIORITY | NotificationChannel.USER_LOCKED_VISIBILITY, updated1.getUserLockedFields()); - final NotificationChannel updated2 = - mHelper.getNotificationChannel(pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID); + final NotificationChannel updated2 = mHelper.getNotificationChannel( + pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID, false); // clamped assertEquals(NotificationManager.IMPORTANCE_LOW, updated2.getImportance()); assertFalse(updated2.canBypassDnd()); @@ -378,7 +380,7 @@ public class RankingHelperTest { mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test @@ -399,7 +401,7 @@ public class RankingHelperTest { mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test @@ -421,7 +423,7 @@ public class RankingHelperTest { mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test @@ -442,7 +444,7 @@ public class RankingHelperTest { mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test @@ -463,7 +465,7 @@ public class RankingHelperTest { mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test @@ -484,7 +486,7 @@ public class RankingHelperTest { mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test @@ -503,7 +505,7 @@ public class RankingHelperTest { mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test @@ -529,13 +531,13 @@ public class RankingHelperTest { mHelper.updateNotificationChannel(pkg, uid, channel2); // all fields should be changed - assertEquals(channel2, mHelper.getNotificationChannel(pkg, uid, channel.getId())); + assertEquals(channel2, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false)); } @Test public void testGetChannelWithFallback() throws Exception { NotificationChannel channel = - mHelper.getNotificationChannelWithFallback(pkg, uid, "garbage"); + mHelper.getNotificationChannelWithFallback(pkg, uid, "garbage", false); assertEquals(NotificationChannel.DEFAULT_CHANNEL_ID, channel.getId()); } @@ -557,7 +559,7 @@ public class RankingHelperTest { mHelper.createNotificationChannel(pkg, uid, channel, true); NotificationChannel savedChannel = - mHelper.getNotificationChannel(pkg, uid, channel.getId()); + mHelper.getNotificationChannel(pkg, uid, channel.getId(), false); assertEquals(channel.getName(), savedChannel.getName()); assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); @@ -584,7 +586,7 @@ public class RankingHelperTest { mHelper.createNotificationChannel(pkg, uid, channel, true); NotificationChannel savedChannel = - mHelper.getNotificationChannel(pkg, uid, channel.getId()); + mHelper.getNotificationChannel(pkg, uid, channel.getId(), false); assertEquals(channel.getName(), savedChannel.getName()); assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); @@ -592,4 +594,168 @@ public class RankingHelperTest { assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); } + + @Test + public void testGetDeletedChannel() throws Exception { + NotificationChannel channel = + new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + channel.setSound(new Uri.Builder().scheme("test").build()); + channel.setLights(true); + channel.setBypassDnd(true); + channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); + channel.enableVibration(true); + channel.setVibrationPattern(new long[] {100, 67, 145, 156}); + + mHelper.createNotificationChannel(pkg, uid, channel, true); + mHelper.deleteNotificationChannel(pkg, uid, channel.getId()); + + // Does not return deleted channel + NotificationChannel response = + mHelper.getNotificationChannel(pkg, uid, channel.getId(), false); + assertNull(response); + + // Returns deleted channel + response = mHelper.getNotificationChannel(pkg, uid, channel.getId(), true); + compareChannels(channel, response); + assertTrue(response.isDeleted()); + } + + @Test + public void testGetDeletedChannels() throws Exception { + Map<String, NotificationChannel> channelMap = new HashMap<>(); + NotificationChannel channel = + new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + channel.setSound(new Uri.Builder().scheme("test").build()); + channel.setLights(true); + channel.setBypassDnd(true); + channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); + channel.enableVibration(true); + channel.setVibrationPattern(new long[] {100, 67, 145, 156}); + channelMap.put(channel.getId(), channel); + NotificationChannel channel2 = + new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); + channelMap.put(channel2.getId(), channel2); + mHelper.createNotificationChannel(pkg, uid, channel, true); + mHelper.createNotificationChannel(pkg, uid, channel2, true); + + mHelper.deleteNotificationChannel(pkg, uid, channel.getId()); + + // Returns only non-deleted channels + List<NotificationChannel> channels = + mHelper.getNotificationChannels(pkg, uid, false).getList(); + assertEquals(2, channels.size()); // Default channel + non-deleted channel + for (NotificationChannel nc : channels) { + if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { + compareChannels(channel2, nc); + } + } + + // Returns deleted channels too + channels = mHelper.getNotificationChannels(pkg, uid, true).getList(); + assertEquals(3, channels.size()); // Includes default channel + for (NotificationChannel nc : channels) { + if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { + compareChannels(channelMap.get(nc.getId()), nc); + } + } + } + + @Test + public void testUpdateDeletedChannels() throws Exception { + NotificationChannel channel = + new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + mHelper.createNotificationChannel(pkg, uid, channel, true); + + mHelper.deleteNotificationChannel(pkg, uid, channel.getId()); + + channel.setSound(new Uri.Builder().scheme("test").build()); + try { + mHelper.updateNotificationChannel(pkg, uid, channel); + fail("Updated deleted channel"); + } catch (IllegalArgumentException e) { + // :) + } + + try { + mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel); + fail("Updated deleted channel"); + } catch (IllegalArgumentException e) { + // :) + } + } + + @Test + public void testCreateDeletedChannel() throws Exception { + long[] vibration = new long[] {100, 67, 145, 156}; + NotificationChannel channel = + new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + channel.setVibrationPattern(vibration); + + mHelper.createNotificationChannel(pkg, uid, channel, true); + mHelper.deleteNotificationChannel(pkg, uid, channel.getId()); + + NotificationChannel newChannel = new NotificationChannel( + channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); + newChannel.setVibrationPattern(new long[] {100}); + + mHelper.createNotificationChannel(pkg, uid, newChannel, true); + + // No long deleted, using old settings + compareChannels(channel, + mHelper.getNotificationChannel(pkg, uid, newChannel.getId(), false)); + } + + @Test + public void testCreateChannel_alreadyExists() throws Exception { + long[] vibration = new long[] {100, 67, 145, 156}; + NotificationChannel channel = + new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + channel.setVibrationPattern(vibration); + + mHelper.createNotificationChannel(pkg, uid, channel, true); + + NotificationChannel newChannel = new NotificationChannel( + channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); + newChannel.setVibrationPattern(new long[] {100}); + + mHelper.createNotificationChannel(pkg, uid, newChannel, true); + + // Old settings not overridden + compareChannels(channel, + mHelper.getNotificationChannel(pkg, uid, newChannel.getId(), false)); + } + + @Test + public void testPermanentlyDeleteChannels() throws Exception { + NotificationChannel channel1 = + new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); + NotificationChannel channel2 = + new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + + mHelper.createNotificationChannel(pkg, uid, channel1, true); + mHelper.createNotificationChannel(pkg, uid, channel2, false); + + mHelper.permanentlyDeleteNotificationChannels(pkg, uid); + + // Only default channel remains + assertEquals(1, mHelper.getNotificationChannels(pkg, uid, true).getList().size()); + } + + @Test + public void testOnPackageChanged_packageRemoval() throws Exception { + // Deleted + NotificationChannel channel1 = + new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); + mHelper.createNotificationChannel(pkg, uid, channel1, true); + + mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid}); + + assertEquals(0, mHelper.getNotificationChannels(pkg, uid, true).getList().size()); + + // Not deleted + mHelper.createNotificationChannel(pkg, uid, channel1, true); + + mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid}); + assertEquals(2, mHelper.getNotificationChannels(pkg, uid, false).getList().size()); + } } diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index 228b8e0d82fb..167b33ac31a7 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -618,9 +618,16 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected static final UserInfo USER_INFO_11 = new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED); + /* + * Cheat: USER_P0 is a sub profile of USER_0, but it doesn't have the MANAGED_PROFILE flag set. + * Due to a change made to LauncherApps (b/34340531), work profile apps a no longer able + * to see the main profile, which would break tons of unit tests. We avoid it by not setting + * MANAGED_PROFILE for P0. + * We cover this negative case in CTS. (i.e. CTS has tests to make sure maanged profile + * can't access main profile's shortcuts.) + */ protected static final UserInfo USER_INFO_P0 = withProfileGroupId( - new UserInfo(USER_P0, "userP0", - UserInfo.FLAG_MANAGED_PROFILE), 0); + new UserInfo(USER_P0, "userP0", UserInfo.FLAG_INITIALIZED), 0); protected BiPredicate<String, Integer> mDefaultLauncherChecker = (callingPackage, userId) -> diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java index df275d20b3c0..96e89485874b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java @@ -22,6 +22,9 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Matchers.notNull; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -238,7 +241,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { * - Launcher supports the feature. * - Shortcut doesn't pre-exist. */ - private void checkRequestPinShortcut(@Nullable PendingIntent resultIntent) { + private void checkRequestPinShortcut(@Nullable IntentSender resultIntent) { setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0)); setDefaultLauncher(USER_10, mMainActivityFetcher.apply(LAUNCHER_2, USER_10)); @@ -254,8 +257,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertNull(s.getActivity()); - assertTrue(mManager.requestPinShortcut(s, - resultIntent == null ? null : resultIntent.getIntentSender())); + assertTrue(mManager.requestPinShortcut(s, resultIntent)); verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class)); @@ -294,9 +296,9 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { // This method is always called, even with PI == null. if (resultIntent == null) { - verify(mServiceContext, times(1)).sendIntentSender(eq(null)); + verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); } else { - verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); } runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { @@ -314,11 +316,12 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { checkRequestPinShortcut(/* resultIntent=*/ null); } - public void testRequestPinShortcut_withCallback() { - final PendingIntent resultIntent = - PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0); + private IntentSender makeResultIntent() { + return PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0).getIntentSender(); + } - checkRequestPinShortcut(resultIntent); + public void testRequestPinShortcut_withCallback() { + checkRequestPinShortcut(makeResultIntent()); } public void testRequestPinShortcut_explicitTargetActivity() { @@ -578,8 +581,15 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { public void testRequestPinShortcut_dynamicExists_alreadyPinned() { setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0)); + final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32); + runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { - assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1")))); + final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, "s1") + .setShortLabel("Title-" + "s1") + .setIcon(res32x32) + .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class)); + final ShortcutInfo s = b.build(); + assertTrue(mManager.setDynamicShortcuts(list(s))); }); runWithCaller(LAUNCHER_1, USER_0, () -> { @@ -590,14 +600,66 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertWith(getCallerShortcuts()) .haveIds("s1") .areAllDynamic() - .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main")) + .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllPinned(); assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("s1"), - /* resultIntent=*/ null)); + makeResultIntent())); // The intent should be sent right away. - verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); + }); + + // Already pinned. + runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { + assertWith(getCallerShortcuts()) + .haveIds("s1") + .areAllDynamic() + .areAllEnabled() + .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) + .areAllPinned(); + }); + + // ... But the launcher will still receive the request. + runWithCaller(LAUNCHER_1, USER_0, () -> { + // Check the intent passed to startActivityAsUser(). + final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); + + verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0)); + + assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage); + + // Check the request object. + final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue()); + + assertPinItemRequest(request); + + assertWith(request.getShortcutInfo()) + .haveIds("s1") + .areAllDynamic() + .areAllPinned() // Note it's pinned already. + .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) + .areAllWithNoIntent(); + + assertAllHaveIcon(list(request.getShortcutInfo())); + + reset(mServiceContext); + + // Accept the request. + assertTrue(request.accept()); + + // The intent is only sent once, so times(1). + verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); + }); + + // Still pinned. + runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { + assertWith(getCallerShortcuts()) + .haveIds("s1") + .areAllDynamic() + .areAllEnabled() + .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) + .areAllPinned(); }); } @@ -621,10 +683,65 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { .areAllPinned(); assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("ms1"), - /* resultIntent=*/ null)); + makeResultIntent())); // The intent should be sent right away. - verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); + }); + + // Already pinned. + runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { + assertWith(getCallerShortcuts()) + .haveIds("ms1") + .areAllManifest() + .areAllEnabled() + .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, + ShortcutActivity.class.getName())) + .areAllPinned(); + }); + + // ... But the launcher will still receive the request. + runWithCaller(LAUNCHER_1, USER_0, () -> { + // Check the intent passed to startActivityAsUser(). + final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); + + verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0)); + + assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage); + + // Check the request object. + final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue()); + + assertPinItemRequest(request); + + assertWith(request.getShortcutInfo()) + .haveIds("ms1") + .areAllManifest() + .areAllPinned() // Note it's pinned already. + .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, + ShortcutActivity.class.getName())) + .areAllWithNoIntent(); + + assertAllHaveIcon(list(request.getShortcutInfo())); + + reset(mServiceContext); + + // Accept the request. + assertTrue(request.accept()); + + // The intent is only sent once, so times(1). + verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); + }); + + // Still pinned. + runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { + assertWith(getCallerShortcuts()) + .haveIds("ms1") + .areAllManifest() + .areAllEnabled() + .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, + ShortcutActivity.class.getName())) + .areAllPinned(); }); } diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java index 84a7c198cede..cfa35c2c50a2 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java @@ -83,7 +83,8 @@ public class ShortcutManagerTest9 extends BaseShortcutManagerTest { private void assertPinItemRequest(PinItemRequest actualRequest, String className) { assertNotNull(actualRequest); assertEquals(PinItemRequest.REQUEST_TYPE_APPWIDGET, actualRequest.getRequestType()); - assertEquals(className, actualRequest.getAppWidgetProviderInfo().provider.getClassName()); + assertEquals(className, actualRequest.getAppWidgetProviderInfo(getTestContext()) + .provider.getClassName()); } public void testNotForeground() { diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java new file mode 100644 index 000000000000..8d6d2daeb6a2 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE; +import static android.graphics.GraphicBuffer.USAGE_SW_READ_RARELY; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import android.app.ActivityManager.TaskSnapshot; +import android.content.pm.UserInfo; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.GraphicBuffer; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.os.SystemClock; +import android.os.UserManager; +import android.platform.test.annotations.Presubmit; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; +import android.util.ArraySet; + +import com.android.internal.util.Predicate; +import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; + +/** + * Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader} + * + * runtest frameworks-services -c com.android.server.wm.TaskSnapshotPersisterLoaderTest + */ +@MediumTest +@Presubmit +@RunWith(AndroidJUnit4.class) +public class TaskSnapshotPersisterLoaderTest { + + private static final String TEST_USER_NAME = "TaskSnapshotPersisterTest User"; + private static final Rect TEST_INSETS = new Rect(10, 20, 30, 40); + + private TaskSnapshotPersister mPersister; + private TaskSnapshotLoader mLoader; + private static int sTestUserId; + private static File sFilesDir; + private static UserManager sUserManager; + + @BeforeClass + public static void setUpUser() { + sUserManager = UserManager.get(InstrumentationRegistry.getContext()); + sTestUserId = createUser(TEST_USER_NAME, 0); + sFilesDir = InstrumentationRegistry.getContext().getFilesDir(); + } + + @AfterClass + public static void tearDownUser() { + removeUser(sTestUserId); + } + + @Before + public void setUp() throws Exception { + mPersister = new TaskSnapshotPersister( + userId -> sFilesDir); + mLoader = new TaskSnapshotLoader(mPersister); + mPersister.start(); + } + + @After + public void tearDown() throws Exception { + cleanDirectory(); + } + + @Test + public void testPersistAndLoadSnapshot() { + mPersister.persistSnapshot(1 , sTestUserId, createSnapshot()); + mPersister.waitForQueueEmpty(); + final File[] files = new File[] { new File(sFilesDir.getPath() + "/snapshots/1.proto"), + new File(sFilesDir.getPath() + "/snapshots/1.png") }; + assertTrueForFiles(files, File::exists, " must exist"); + final TaskSnapshot snapshot = mLoader.loadTask(1, sTestUserId); + assertNotNull(snapshot); + assertEquals(TEST_INSETS, snapshot.getContentInsets()); + assertNotNull(snapshot.getSnapshot()); + assertEquals(Configuration.ORIENTATION_PORTRAIT, snapshot.getOrientation()); + } + + private void assertTrueForFiles(File[] files, Predicate<File> predicate, String message) { + for (File file : files) { + assertTrue(file.getName() + message, predicate.apply(file)); + } + } + + @Test + public void testTaskRemovedFromRecents() { + mPersister.persistSnapshot(1, sTestUserId, createSnapshot()); + mPersister.onTaskRemovedFromRecents(1, sTestUserId); + mPersister.waitForQueueEmpty(); + assertFalse(new File(sFilesDir.getPath() + "/snapshots/1.proto").exists()); + assertFalse(new File(sFilesDir.getPath() + "/snapshots/1.png").exists()); + } + + /** + * Tests that persisting a couple of snapshots is being throttled. + */ + @Test + public void testThrottling() { + long ms = SystemClock.elapsedRealtime(); + mPersister.persistSnapshot(1, sTestUserId, createSnapshot()); + mPersister.persistSnapshot(2, sTestUserId, createSnapshot()); + mPersister.persistSnapshot(3, sTestUserId, createSnapshot()); + mPersister.persistSnapshot(4, sTestUserId, createSnapshot()); + mPersister.persistSnapshot(5, sTestUserId, createSnapshot()); + mPersister.persistSnapshot(6, sTestUserId, createSnapshot()); + mPersister.waitForQueueEmpty(); + assertTrue(SystemClock.elapsedRealtime() - ms > 500); + } + + @Test + public void testGetTaskId() { + RemoveObsoleteFilesQueueItem removeObsoleteFilesQueueItem = + mPersister.new RemoveObsoleteFilesQueueItem(new ArraySet<>(), new int[] {}); + assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("blablablulp")); + assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("nothing.err")); + assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("/invalid/")); + assertEquals(12, removeObsoleteFilesQueueItem.getTaskId("12.png")); + assertEquals(12, removeObsoleteFilesQueueItem.getTaskId("12.proto")); + assertEquals(1, removeObsoleteFilesQueueItem.getTaskId("1.png")); + } + + @Test + public void testRemoveObsoleteFiles() { + mPersister.persistSnapshot(1, sTestUserId, createSnapshot()); + mPersister.persistSnapshot(2, sTestUserId, createSnapshot()); + final ArraySet<Integer> taskIds = new ArraySet<>(); + taskIds.add(1); + mPersister.removeObsoleteFiles(taskIds, new int[] { sTestUserId }); + mPersister.waitForQueueEmpty(); + final File[] existsFiles = new File[] { + new File(sFilesDir.getPath() + "/snapshots/1.proto"), + new File(sFilesDir.getPath() + "/snapshots/1.png") }; + final File[] nonExistsFiles = new File[] { + new File(sFilesDir.getPath() + "/snapshots/2.proto"), + new File(sFilesDir.getPath() + "/snapshots/2.png") }; + assertTrueForFiles(existsFiles, File::exists, " must exist"); + assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist"); + } + + @Test + public void testRemoveObsoleteFiles_addedOneInTheMeantime() { + mPersister.persistSnapshot(1, sTestUserId, createSnapshot()); + final ArraySet<Integer> taskIds = new ArraySet<>(); + taskIds.add(1); + mPersister.removeObsoleteFiles(taskIds, new int[] { sTestUserId }); + mPersister.persistSnapshot(2, sTestUserId, createSnapshot()); + mPersister.waitForQueueEmpty(); + final File[] existsFiles = new File[] { + new File(sFilesDir.getPath() + "/snapshots/1.proto"), + new File(sFilesDir.getPath() + "/snapshots/1.png"), + new File(sFilesDir.getPath() + "/snapshots/2.proto"), + new File(sFilesDir.getPath() + "/snapshots/2.png") }; + assertTrueForFiles(existsFiles, File::exists, " must exist"); + } + + private TaskSnapshot createSnapshot() { + GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888, + USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY); + Canvas c = buffer.lockCanvas(); + c.drawColor(Color.RED); + buffer.unlockCanvasAndPost(c); + return new TaskSnapshot(buffer, Configuration.ORIENTATION_PORTRAIT, TEST_INSETS); + } + + private static int createUser(String name, int flags) { + UserInfo user = sUserManager.createUser(name, flags); + if (user == null) { + Assert.fail("Error while creating the test user: " + TEST_USER_NAME); + } + return user.id; + } + + private static void removeUser(int userId) { + if (!sUserManager.removeUser(userId)) { + Assert.fail("Error while removing the test user: " + TEST_USER_NAME); + } + } + + private void cleanDirectory() { + for (File file : new File(sFilesDir, "snapshots").listFiles()) { + if (!file.isDirectory()) { + file.delete(); + } + } + } +} diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index d243bf23ac93..6dfb48bfbcf9 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -106,6 +106,7 @@ public class UsageStatsService extends SystemService implements private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES; private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. + private static final boolean ENABLE_KERNEL_UPDATES = false; private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); long mAppIdleScreenThresholdMillis; @@ -241,7 +242,7 @@ public class UsageStatsService extends SystemService implements postOneTimeCheckIdleStates(); } - if (KERNEL_COUNTER_FILE.exists()) { + if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) { try { ActivityManager.getService().registerUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index 7f182a4f4ee0..4aff3d54834a 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -556,7 +556,9 @@ public class UsbPortManager { private void sendPortChangedBroadcastLocked(PortInfo portInfo) { final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.addFlags( + Intent.FLAG_RECEIVER_FOREGROUND | + Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putExtra(UsbManager.EXTRA_PORT, portInfo.mUsbPort); intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus); diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java index e03a14f41ce2..2e99b6e9bd19 100644 --- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java @@ -971,7 +971,9 @@ class UsbProfileGroupSettingsManager { public void accessoryAttached(UsbAccessory accessory) { Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags( + Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); ArrayList<ResolveInfo> matches; String defaultPackage = null; @@ -1364,7 +1366,9 @@ class UsbProfileGroupSettingsManager { private static Intent createDeviceAttachedIntent(UsbDevice device) { Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); intent.putExtra(UsbManager.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags( + Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); return intent; } } diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java index 24d5f0955e9a..7a55be43ffd5 100644 --- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java @@ -182,6 +182,7 @@ class UsbSettingsManager { } Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putExtra(UsbManager.EXTRA_DEVICE, device); if (DEBUG) { @@ -204,6 +205,7 @@ class UsbSettingsManager { } Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 288c9aba3f8a..c0a86d6d3ece 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -878,39 +878,6 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string"; /** - * A list of component name of carrier signalling receivers which are interested in intent - * android.intent.action.CARRIER_SIGNAL_REDIRECTED. - * Example: - * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameA</item> - * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameB</item> - * @hide - */ - public static final String KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY = - "signal_redirection_receiver_string_array"; - - /** - * A list of component name of carrier signalling receivers which are interested in intent - * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED. - * Example: - * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameA</item> - * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameB</item> - * @hide - */ - public static final String KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY = - "signal_dcfailure_receiver_string_array"; - - /** - * A list of component name of carrier signalling receivers which are interested in intent - * android.intent.action.CARRIER_SIGNAL_PCO_VALUE. - * Example: - * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameA</item> - * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameB</item> - * @hide - */ - public static final String KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY = - "signal_pco_receiver_string_array"; - - /** * Defines carrier-specific actions which act upon * android.intent.action.CARRIER_SIGNAL_REDIRECTED, used for customization of the * default carrier app @@ -963,6 +930,42 @@ public class CarrierConfigManager { "carrier_default_redirection_url_string_array"; /** + * Each config includes the componentName of the carrier app, followed by a list of interesting + * signals(declared in the manifest) which could wake up the app. + * @see com.android.internal.telephony.TelephonyIntents + * Example: + * <item>com.google.android.carrierAPK/.CarrierSignalReceiverA: + * android.intent.action.CARRIER_SIGNAL_REDIRECTED, + * android.intent.action.CARRIER_SIGNAL_PCO_VALUE + * </item> + * <item>com.google.android.carrierAPK/.CarrierSignalReceiverB: + * android.intent.action.CARRIER_SIGNAL_PCO_VALUE + * </item> + * @hide + */ + public static final String KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY = + "carrier_app_wake_signal_config"; + + /** + * Each config includes the componentName of the carrier app, followed by a list of interesting + * signals for the app during run-time. The list of signals(intents) are targeting on run-time + * broadcast receivers only, aiming to avoid unnecessary wake-ups and should not be declared in + * the app's manifest. + * @see com.android.internal.telephony.TelephonyIntents + * Example: + * <item>com.google.android.carrierAPK/.CarrierSignalReceiverA: + * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED, + * android.intent.action.CARRIER_SIGNAL_PCO_VALUE + * </item> + * <item>com.google.android.carrierAPK/.CarrierSignalReceiverB: + * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED + * </item> + * @hide + */ + public static final String KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY = + "carrier_app_no_wake_signal_config"; + + /** * Determines whether the carrier supports making non-emergency phone calls while the phone is * in emergency callback mode. Default value is {@code true}, meaning that non-emergency calls * are allowed in emergency callback mode. @@ -1413,10 +1416,14 @@ public class CarrierConfigManager { sDefaults.putString(KEY_RCS_CONFIG_SERVER_URL_STRING, ""); // Carrier Signalling Receivers - sDefaults.putStringArray(KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY, null); - sDefaults.putStringArray(KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY, null); - sDefaults.putStringArray(KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY, null); sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, ""); + sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY, + new String[]{ + "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" + + "android.intent.action.CARRIER_SIGNAL_REDIRECTED" + }); + sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null); + // Default carrier app configurations sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY, diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index eb838fa7e8c1..a3f7c18f54bd 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5809,10 +5809,17 @@ public class TelephonyManager { * Set the allowed carrier list for slotId * Require system privileges. In the future we may add this to carrier APIs. * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * + * <p>This method works only on devices with {@link + * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled. + * * @return The number of carriers set successfully. Should be length of * carrierList on success; -1 on error. * @hide */ + @SystemApi public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) { try { ITelephony service = getITelephony(); @@ -5821,6 +5828,8 @@ public class TelephonyManager { } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e); + } catch (NullPointerException e) { + Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e); } return -1; } @@ -5829,10 +5838,17 @@ public class TelephonyManager { * Get the allowed carrier list for slotId. * Require system privileges. In the future we may add this to carrier APIs. * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} + * + * <p>This method returns valid data on devices with {@link + * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled. + * * @return List of {@link android.telephony.CarrierIdentifier}; empty list * means all carriers are allowed. * @hide */ + @SystemApi public List<CarrierIdentifier> getAllowedCarriers(int slotId) { try { ITelephony service = getITelephony(); @@ -5841,6 +5857,8 @@ public class TelephonyManager { } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e); + } catch (NullPointerException e) { + Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e); } return new ArrayList<CarrierIdentifier>(0); } diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index bcc68b38dd2b..b6e701eb5225 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -19,6 +19,7 @@ package android.test.mock; import android.annotation.SystemApi; import android.app.IApplicationThread; import android.app.IServiceConnection; +import android.app.Notification; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -513,6 +514,12 @@ public class MockContext extends Context { } @Override + public ComponentName startServiceInForeground(Intent service, + int id, Notification notification) { + throw new UnsupportedOperationException(); + } + + @Override public boolean stopService(Intent service) { throw new UnsupportedOperationException(); } @@ -525,6 +532,13 @@ public class MockContext extends Context { /** @hide */ @Override + public ComponentName startServiceInForegroundAsUser(Intent service, + int id, Notification notification, UserHandle user) { + throw new UnsupportedOperationException(); + } + + /** @hide */ + @Override public boolean stopServiceAsUser(Intent service, UserHandle user) { throw new UnsupportedOperationException(); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index d62c30da583d..46b64031ee8a 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1103,6 +1103,29 @@ public class ConnectivityServiceTest extends AndroidTestCase { UNAVAILABLE } + private static class CallbackInfo { + public final CallbackState state; + public final Network network; + public final Object arg; + public CallbackInfo(CallbackState s, Network n, Object o) { + state = s; network = n; arg = o; + } + public String toString() { + return String.format("%s (%s)", state, network); + } + @Override + public boolean equals(Object o) { + if (!(o instanceof CallbackInfo)) return false; + // Ignore timeMs, since it's unpredictable. + CallbackInfo other = (CallbackInfo) o; + return (state == other.state) && Objects.equals(network, other.network); + } + @Override + public int hashCode() { + return Objects.hash(state, network); + } + } + /** * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks * this class receives, by calling expectCallback() exactly once each time a callback is @@ -1114,21 +1137,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { // the linger timeout. private final static int TIMEOUT_MS = 50; - private class CallbackInfo { - public final CallbackState state; - public final Network network; - public Object arg; - public CallbackInfo(CallbackState s, Network n, Object o) { - state = s; network = n; arg = o; - } - public String toString() { return String.format("%s (%s)", state, network); } - public boolean equals(Object o) { - if (!(o instanceof CallbackInfo)) return false; - // Ignore timeMs, since it's unpredictable. - CallbackInfo other = (CallbackInfo) o; - return state == other.state && Objects.equals(network, other.network); - } - } private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>(); protected void setLastCallback(CallbackState state, Network network, Object o) { @@ -1155,17 +1163,24 @@ public class ConnectivityServiceTest extends AndroidTestCase { setLastCallback(CallbackState.LOST, network, null); } - void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) { - CallbackInfo expected = new CallbackInfo( - state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0); - CallbackInfo actual; + CallbackInfo nextCallback(int timeoutMs) { + CallbackInfo cb = null; try { - actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); - assertEquals("Unexpected callback:", expected, actual); + cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { - fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms"); - actual = null; // Or the compiler can't tell it's never used uninitialized. } + if (cb == null) { + // LinkedBlockingQueue.poll() returns null if it timeouts. + fail("Did not receive callback after " + timeoutMs + "ms"); + } + return cb; + } + + void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) { + CallbackInfo expected = new CallbackInfo( + state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0); + CallbackInfo actual = nextCallback(timeoutMs); + assertEquals("Unexpected callback:", expected, actual); if (state == CallbackState.LOSING) { String msg = String.format( "Invalid linger time value %d, must be between %d and %d", diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java index 00420e9e1005..b4d48712cfe0 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java @@ -73,8 +73,8 @@ public class UpstreamNetworkMonitorTest { assertFalse(unm.mobileNetworkRequested()); // Given a null Context, and therefore a null ConnectivityManager, // these would cause an exception, if they actually attempted anything. - unm.mobileUpstreamRequiresDun(true); - unm.mobileUpstreamRequiresDun(false); + unm.updateMobileRequiresDun(true); + unm.updateMobileRequiresDun(false); } @Test @@ -109,7 +109,7 @@ public class UpstreamNetworkMonitorTest { assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); - mUNM.mobileUpstreamRequiresDun(false); + mUNM.updateMobileRequiresDun(false); assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); @@ -135,7 +135,7 @@ public class UpstreamNetworkMonitorTest { assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); - mUNM.mobileUpstreamRequiresDun(true); + mUNM.updateMobileRequiresDun(true); assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp index 565d2f0a0549..d0026a28ba16 100644 --- a/tools/aapt/AaptConfig.cpp +++ b/tools/aapt/AaptConfig.cpp @@ -131,6 +131,22 @@ bool parse(const String8& str, ConfigDescription* out) { part = parts[index].string(); } + if (parseWideColorGamut(part, &config)) { + index++; + if (index == N) { + goto success; + } + part = parts[index].string(); + } + + if (parseHdr(part, &config)) { + index++; + if (index == N) { + goto success; + } + part = parts[index].string(); + } + if (parseOrientation(part, &config)) { index++; if (index == N) { @@ -250,7 +266,9 @@ void applyVersionForCompatibility(ConfigDescription* config) { uint16_t minSdk = 0; if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE) - == ResTable_config::UI_MODE_TYPE_VR_HEADSET) { + == ResTable_config::UI_MODE_TYPE_VR_HEADSET + || config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT + || config->colorimetry & ResTable_config::MASK_HDR) { minSdk = SDK_O; } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) { minSdk = SDK_MNC; @@ -431,6 +449,46 @@ bool parseScreenRound(const char* name, ResTable_config* out) { return false; } +bool parseWideColorGamut(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT) + | ResTable_config::WIDE_COLOR_GAMUT_ANY; + return true; + } else if (strcmp(name, "widecg") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT) + | ResTable_config::WIDE_COLOR_GAMUT_YES; + return true; + } else if (strcmp(name, "nowidecg") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT) + | ResTable_config::WIDE_COLOR_GAMUT_NO; + return true; + } + return false; +} + +bool parseHdr(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_HDR) + | ResTable_config::HDR_ANY; + return true; + } else if (strcmp(name, "highdr") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_HDR) + | ResTable_config::HDR_YES; + return true; + } else if (strcmp(name, "lowdr") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_HDR) + | ResTable_config::HDR_NO; + return true; + } + return false; +} + bool parseOrientation(const char* name, ResTable_config* out) { if (strcmp(name, kWildcardName) == 0) { if (out) out->orientation = out->ORIENTATION_ANY; diff --git a/tools/aapt/AaptConfig.h b/tools/aapt/AaptConfig.h index 04c763f20d31..a6dd252281f5 100644 --- a/tools/aapt/AaptConfig.h +++ b/tools/aapt/AaptConfig.h @@ -61,6 +61,8 @@ bool parseScreenHeightDp(const char* str, android::ResTable_config* out = NULL); bool parseScreenLayoutSize(const char* str, android::ResTable_config* out = NULL); bool parseScreenLayoutLong(const char* str, android::ResTable_config* out = NULL); bool parseScreenRound(const char* name, android::ResTable_config* out = NULL); +bool parseWideColorGamut(const char* name, android::ResTable_config* out = NULL); +bool parseHdr(const char* name, android::ResTable_config* out = NULL); bool parseOrientation(const char* str, android::ResTable_config* out = NULL); bool parseUiModeType(const char* str, android::ResTable_config* out = NULL); bool parseUiModeNight(const char* str, android::ResTable_config* out = NULL); diff --git a/tools/aapt/tests/AaptConfig_test.cpp b/tools/aapt/tests/AaptConfig_test.cpp index 8bb38bac6d42..23f61e9e4b70 100644 --- a/tools/aapt/tests/AaptConfig_test.cpp +++ b/tools/aapt/tests/AaptConfig_test.cpp @@ -98,3 +98,33 @@ TEST(AaptConfigTest, TestParsingRoundQualifier) { EXPECT_EQ(SDK_MNC, config.sdkVersion); EXPECT_EQ(String8("notround-v23"), config.toString()); } + +TEST(AaptConfigTest, WideColorGamutQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("widecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES, + config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("widecg-v26"), config.toString()); + + EXPECT_TRUE(TestParse("nowidecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO, + config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("nowidecg-v26"), config.toString()); +} + +TEST(AaptConfigTest, HdrQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("highdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_YES, + config.colorimetry & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("highdr-v26"), config.toString()); + + EXPECT_TRUE(TestParse("lowdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_NO, + config.colorimetry & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("lowdr-v26"), config.toString()); +}
\ No newline at end of file diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp index b1bd4012c1df..5bea3ad1bbad 100644 --- a/tools/aapt2/ConfigDescription.cpp +++ b/tools/aapt2/ConfigDescription.cpp @@ -20,15 +20,16 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "Locale.h" #include "SdkConstants.h" -#include "util/StringPiece.h" #include "util/Util.h" -namespace aapt { - using android::ResTable_config; +using android::StringPiece; + +namespace aapt { static const char* kWildcardName = "any"; @@ -205,6 +206,52 @@ static bool parseScreenRound(const char* name, ResTable_config* out) { return false; } +static bool parseWideColorGamut(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_ANY; + return true; + } else if (strcmp(name, "widecg") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_YES; + return true; + } else if (strcmp(name, "nowidecg") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_NO; + return true; + } + return false; +} + +static bool parseHdr(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_ANY; + return true; + } else if (strcmp(name, "highdr") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_YES; + return true; + } else if (strcmp(name, "lowdr") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_NO; + return true; + } + return false; +} + static bool parseOrientation(const char* name, ResTable_config* out) { if (strcmp(name, kWildcardName) == 0) { if (out) out->orientation = out->ORIENTATION_ANY; @@ -686,6 +733,20 @@ bool ConfigDescription::Parse(const StringPiece& str, ConfigDescription* out) { } } + if (parseWideColorGamut(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseHdr(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + if (parseOrientation(part_iter->c_str(), &config)) { ++part_iter; if (part_iter == parts_end) { @@ -778,7 +839,9 @@ void ConfigDescription::ApplyVersionForCompatibility( ConfigDescription* config) { uint16_t min_sdk = 0; if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE) - == ResTable_config::UI_MODE_TYPE_VR_HEADSET) { + == ResTable_config::UI_MODE_TYPE_VR_HEADSET || + config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT || + config->colorimetry & ResTable_config::MASK_HDR) { min_sdk = SDK_O; } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) { min_sdk = SDK_MARSHMALLOW; @@ -849,6 +912,12 @@ bool ConfigDescription::HasHigherPrecedenceThan( if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) { return !(o.screenLayout2 & MASK_SCREENROUND); } + if ((colorimetry | o.colorimetry) & MASK_HDR) { + return !(o.colorimetry & MASK_HDR); + } + if ((colorimetry | o.colorimetry) & MASK_WIDE_COLOR_GAMUT) { + return !(o.colorimetry & MASK_WIDE_COLOR_GAMUT); + } if (orientation || o.orientation) return (!o.orientation); if ((uiMode | o.uiMode) & MASK_UI_MODE_TYPE) { return !(o.uiMode & MASK_UI_MODE_TYPE); @@ -895,6 +964,9 @@ bool ConfigDescription::ConflictsWith(const ConfigDescription& o) const { !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) || !pred(screenLayout2 & MASK_SCREENROUND, o.screenLayout2 & MASK_SCREENROUND) || + !pred(colorimetry & MASK_HDR, o.colorimetry & MASK_HDR) || + !pred(colorimetry & MASK_WIDE_COLOR_GAMUT, + o.colorimetry & MASK_WIDE_COLOR_GAMUT) || !pred(orientation, o.orientation) || !pred(touchscreen, o.touchscreen) || !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) || diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h index 97d0f38a5af1..65c96175091c 100644 --- a/tools/aapt2/ConfigDescription.h +++ b/tools/aapt2/ConfigDescription.h @@ -20,8 +20,7 @@ #include <ostream> #include "androidfw/ResourceTypes.h" - -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -42,7 +41,7 @@ struct ConfigDescription : public android::ResTable_config { * The resulting configuration has the appropriate sdkVersion defined * for backwards compatibility. */ - static bool Parse(const StringPiece& str, ConfigDescription* out = nullptr); + static bool Parse(const android::StringPiece& str, ConfigDescription* out = nullptr); /** * If the configuration uses an axis that was added after diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp index 1d22ce03ef1c..b88838ae26f5 100644 --- a/tools/aapt2/ConfigDescription_test.cpp +++ b/tools/aapt2/ConfigDescription_test.cpp @@ -18,9 +18,12 @@ #include <string> +#include "androidfw/StringPiece.h" + #include "SdkConstants.h" #include "test/Test.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -99,6 +102,36 @@ TEST(ConfigDescriptionTest, TestParsingRoundQualifier) { EXPECT_EQ(std::string("notround-v23"), config.toString().string()); } +TEST(ConfigDescriptionTest, TestWideColorGamutQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("widecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES, + config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("widecg-v26"), config.toString().string()); + + EXPECT_TRUE(TestParse("nowidecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO, + config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("nowidecg-v26"), config.toString().string()); +} + +TEST(ConfigDescriptionTest, TestHdrQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("highdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_YES, + config.colorimetry & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("highdr-v26"), config.toString().string()); + + EXPECT_TRUE(TestParse("lowdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_NO, + config.colorimetry & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("lowdr-v26"), config.toString().string()); +} + TEST(ConfigDescriptionTest, ParseVrAttribute) { ConfigDescription config; EXPECT_TRUE(TestParse("vrheadset", &config)); diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h index 5bc86a9fdbaf..50e8b33ab9b1 100644 --- a/tools/aapt2/Diagnostics.h +++ b/tools/aapt2/Diagnostics.h @@ -22,9 +22,9 @@ #include <string> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "Source.h" -#include "util/StringPiece.h" #include "util/Util.h" namespace aapt { @@ -38,7 +38,7 @@ struct DiagMessage { public: DiagMessage() = default; - explicit DiagMessage(const StringPiece& src) : source_(src) {} + explicit DiagMessage(const android::StringPiece& src) : source_(src) {} explicit DiagMessage(const Source& src) : source_(src) {} @@ -59,6 +59,12 @@ struct DiagMessage { std::stringstream message_; }; +template <> +inline DiagMessage& DiagMessage::operator<<(const ::std::u16string& value) { + message_ << android::StringPiece16(value); + return *this; +} + struct IDiagnostics { virtual ~IDiagnostics() = default; diff --git a/tools/aapt2/Flags.cpp b/tools/aapt2/Flags.cpp index c98cd374602f..84977ab424cc 100644 --- a/tools/aapt2/Flags.cpp +++ b/tools/aapt2/Flags.cpp @@ -21,20 +21,22 @@ #include <string> #include <vector> -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" + #include "util/Util.h" +using android::StringPiece; + namespace aapt { Flags& Flags::RequiredFlag(const StringPiece& name, const StringPiece& description, std::string* value) { auto func = [value](const StringPiece& arg) -> bool { - *value = arg.ToString(); + *value = arg.to_string(); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, true, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false}); return *this; } @@ -42,12 +44,11 @@ Flags& Flags::RequiredFlagList(const StringPiece& name, const StringPiece& description, std::vector<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - value->push_back(arg.ToString()); + value->push_back(arg.to_string()); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, true, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false}); return *this; } @@ -55,12 +56,11 @@ Flags& Flags::OptionalFlag(const StringPiece& name, const StringPiece& description, Maybe<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - *value = arg.ToString(); + *value = arg.to_string(); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false}); return *this; } @@ -68,12 +68,11 @@ Flags& Flags::OptionalFlagList(const StringPiece& name, const StringPiece& description, std::vector<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - value->push_back(arg.ToString()); + value->push_back(arg.to_string()); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false}); return *this; } @@ -81,12 +80,11 @@ Flags& Flags::OptionalFlagList(const StringPiece& name, const StringPiece& description, std::unordered_set<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - value->insert(arg.ToString()); + value->insert(arg.to_string()); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false}); return *this; } @@ -97,8 +95,7 @@ Flags& Flags::OptionalSwitch(const StringPiece& name, return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 0, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 0, false}); return *this; } @@ -141,7 +138,7 @@ bool Flags::Parse(const StringPiece& command, for (size_t i = 0; i < args.size(); i++) { StringPiece arg = args[i]; if (*(arg.data()) != '-') { - args_.push_back(arg.ToString()); + args_.push_back(arg.to_string()); continue; } diff --git a/tools/aapt2/Flags.h b/tools/aapt2/Flags.h index 9feff6b4faca..3b3ae710dc7b 100644 --- a/tools/aapt2/Flags.h +++ b/tools/aapt2/Flags.h @@ -23,32 +23,30 @@ #include <unordered_set> #include <vector> +#include "androidfw/StringPiece.h" + #include "util/Maybe.h" -#include "util/StringPiece.h" namespace aapt { class Flags { public: - Flags& RequiredFlag(const StringPiece& name, const StringPiece& description, + Flags& RequiredFlag(const android::StringPiece& name, const android::StringPiece& description, std::string* value); - Flags& RequiredFlagList(const StringPiece& name, - const StringPiece& description, + Flags& RequiredFlagList(const android::StringPiece& name, const android::StringPiece& description, std::vector<std::string>* value); - Flags& OptionalFlag(const StringPiece& name, const StringPiece& description, + Flags& OptionalFlag(const android::StringPiece& name, const android::StringPiece& description, Maybe<std::string>* value); - Flags& OptionalFlagList(const StringPiece& name, - const StringPiece& description, + Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description, std::vector<std::string>* value); - Flags& OptionalFlagList(const StringPiece& name, - const StringPiece& description, + Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description, std::unordered_set<std::string>* value); - Flags& OptionalSwitch(const StringPiece& name, const StringPiece& description, + Flags& OptionalSwitch(const android::StringPiece& name, const android::StringPiece& description, bool* value); - void Usage(const StringPiece& command, std::ostream* out); + void Usage(const android::StringPiece& command, std::ostream* out); - bool Parse(const StringPiece& command, const std::vector<StringPiece>& args, + bool Parse(const android::StringPiece& command, const std::vector<android::StringPiece>& args, std::ostream* outError); const std::vector<std::string>& GetArgs(); @@ -57,7 +55,7 @@ class Flags { struct Flag { std::string name; std::string description; - std::function<bool(const StringPiece& value)> action; + std::function<bool(const android::StringPiece& value)> action; bool required; size_t num_args; diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp index 78f56c7a5b93..7664fac44be1 100644 --- a/tools/aapt2/Locale.cpp +++ b/tools/aapt2/Locale.cpp @@ -72,7 +72,7 @@ static inline bool is_number(const std::string& str) { return std::all_of(std::begin(str), std::end(str), ::isdigit); } -bool LocaleValue::InitFromFilterString(const StringPiece& str) { +bool LocaleValue::InitFromFilterString(const android::StringPiece& str) { // A locale (as specified in the filter) is an underscore separated name such // as "en_US", "en_Latn_US", or "en_US_POSIX". std::vector<std::string> parts = util::SplitAndLowercase(str, '_'); diff --git a/tools/aapt2/Locale.h b/tools/aapt2/Locale.h index fc6c448ac1dc..3d73b2eb17bf 100644 --- a/tools/aapt2/Locale.h +++ b/tools/aapt2/Locale.h @@ -21,8 +21,7 @@ #include <vector> #include "androidfw/ResourceTypes.h" - -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -40,7 +39,7 @@ struct LocaleValue { /** * Initialize this LocaleValue from a config string. */ - bool InitFromFilterString(const StringPiece& config); + bool InitFromFilterString(const android::StringPiece& config); /** * Initialize this LocaleValue from parts of a vector. diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index a2b216d01b11..74d40194e955 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -17,7 +17,7 @@ #include <iostream> #include <vector> -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -33,10 +33,10 @@ int PrintVersion() { return 0; } -extern int Compile(const std::vector<StringPiece>& args); -extern int Link(const std::vector<StringPiece>& args); -extern int Dump(const std::vector<StringPiece>& args); -extern int Diff(const std::vector<StringPiece>& args); +extern int Compile(const std::vector<android::StringPiece>& args); +extern int Link(const std::vector<android::StringPiece>& args); +extern int Dump(const std::vector<android::StringPiece>& args); +extern int Diff(const std::vector<android::StringPiece>& args); } // namespace aapt @@ -45,12 +45,12 @@ int main(int argc, char** argv) { argv += 1; argc -= 1; - std::vector<aapt::StringPiece> args; + std::vector<android::StringPiece> args; for (int i = 1; i < argc; i++) { args.push_back(argv[i]); } - aapt::StringPiece command(argv[0]); + android::StringPiece command(argv[0]); if (command == "compile" || command == "c") { return aapt::Compile(args); } else if (command == "link" || command == "l") { diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp index 3eef7aa71a92..fdabce17433c 100644 --- a/tools/aapt2/Resource.cpp +++ b/tools/aapt2/Resource.cpp @@ -19,6 +19,8 @@ #include <map> #include <string> +using android::StringPiece; + namespace aapt { StringPiece ToString(ResourceType type) { diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h index 13330b548d2c..1950ea35a652 100644 --- a/tools/aapt2/Resource.h +++ b/tools/aapt2/Resource.h @@ -24,11 +24,11 @@ #include <tuple> #include <vector> +#include "androidfw/StringPiece.h" #include "utils/JenkinsHash.h" #include "ConfigDescription.h" #include "Source.h" -#include "util/StringPiece.h" namespace aapt { @@ -63,13 +63,13 @@ enum class ResourceType { kXml, }; -StringPiece ToString(ResourceType type); +android::StringPiece ToString(ResourceType type); /** * Returns a pointer to a valid ResourceType, or nullptr if * the string was invalid. */ -const ResourceType* ParseResourceType(const StringPiece& str); +const ResourceType* ParseResourceType(const android::StringPiece& str); /** * A resource's name. This can uniquely identify @@ -81,7 +81,7 @@ struct ResourceName { std::string entry; ResourceName() = default; - ResourceName(const StringPiece& p, ResourceType t, const StringPiece& e); + ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e); int compare(const ResourceName& other) const; @@ -96,15 +96,15 @@ struct ResourceName { * of the original string. */ struct ResourceNameRef { - StringPiece package; + android::StringPiece package; ResourceType type = ResourceType::kRaw; - StringPiece entry; + android::StringPiece entry; ResourceNameRef() = default; ResourceNameRef(const ResourceNameRef&) = default; ResourceNameRef(ResourceNameRef&&) = default; ResourceNameRef(const ResourceName& rhs); // NOLINT(implicit) - ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e); + ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e); ResourceNameRef& operator=(const ResourceNameRef& rhs) = default; ResourceNameRef& operator=(ResourceNameRef&& rhs) = default; ResourceNameRef& operator=(const ResourceName& rhs); @@ -258,9 +258,9 @@ inline ::std::ostream& operator<<(::std::ostream& out, // ResourceName implementation. // -inline ResourceName::ResourceName(const StringPiece& p, ResourceType t, - const StringPiece& e) - : package(p.ToString()), type(t), entry(e.ToString()) {} +inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t, + const android::StringPiece& e) + : package(p.to_string()), type(t), entry(e.to_string()) {} inline int ResourceName::compare(const ResourceName& other) const { int cmp = package.compare(other.package); @@ -311,8 +311,8 @@ inline std::string ResourceName::ToString() const { inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) : package(rhs.package), type(rhs.type), entry(rhs.entry) {} -inline ResourceNameRef::ResourceNameRef(const StringPiece& p, ResourceType t, - const StringPiece& e) +inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t, + const android::StringPiece& e) : package(p), type(t), entry(e) {} inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) { diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index b16def4025ff..79379fe4b5ee 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -29,6 +29,8 @@ #include "util/Util.h" #include "xml/XmlPullParser.h" +using android::StringPiece; + namespace aapt { constexpr const char* sXliffNamespaceUri = @@ -101,7 +103,7 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, StringPiece trimmed_comment = util::TrimWhitespace(res->comment); if (trimmed_comment.size() != res->comment.size()) { // Only if there was a change do we re-assign. - res->comment = trimmed_comment.ToString(); + res->comment = trimmed_comment.to_string(); } if (res->symbol_state) { @@ -297,7 +299,7 @@ bool ResourceParser::ParseResources(xml::XmlPullParser* parser) { // Extract the product name if it exists. if (Maybe<StringPiece> maybe_product = xml::FindNonEmptyAttribute(parser, "product")) { - parsed_resource.product = maybe_product.value().ToString(); + parsed_resource.product = maybe_product.value().to_string(); } // Parse the resource regardless of product. @@ -383,7 +385,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, // Items have their type encoded in the type attribute. if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) { - resource_type = maybe_type.value().ToString(); + resource_type = maybe_type.value().to_string(); } else { diag_->Error(DiagMessage(source_.WithLine(parser->line_number())) << "<item> must have a 'type' attribute"); @@ -419,7 +421,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, } out_resource->name.type = ResourceType::kId; - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); out_resource->value = util::make_unique<Id>(); return true; } @@ -436,7 +438,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, } out_resource->name.type = item_iter->second.type; - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); // Only use the implicit format for this type if it wasn't overridden. if (!resource_format) { @@ -461,7 +463,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, return false; } - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); } // Call the associated parse method. The type will be filled in by the @@ -484,7 +486,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, } out_resource->name.type = *parsed_type; - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); out_resource->value = ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString); if (!out_resource->value) { @@ -718,7 +720,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, const size_t depth = parser->depth(); while (xml::XmlPullParser::NextChildNode(parser, depth)) { if (parser->event() == xml::XmlPullParser::Event::kComment) { - comment = util::TrimWhitespace(parser->comment()).ToString(); + comment = util::TrimWhitespace(parser->comment()).to_string(); continue; } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) { // Skip text. @@ -754,7 +756,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource child_resource; child_resource.name.type = *parsed_type; - child_resource.name.entry = maybe_name.value().ToString(); + child_resource.name.entry = maybe_name.value().to_string(); child_resource.id = next_id; child_resource.comment = std::move(comment); child_resource.source = item_source; @@ -899,7 +901,7 @@ bool ResourceParser::ParseAttrImpl(xml::XmlPullParser* parser, const size_t depth = parser->depth(); while (xml::XmlPullParser::NextChildNode(parser, depth)) { if (parser->event() == xml::XmlPullParser::Event::kComment) { - comment = util::TrimWhitespace(parser->comment()).ToString(); + comment = util::TrimWhitespace(parser->comment()).to_string(); continue; } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) { // Skip text. @@ -1288,7 +1290,7 @@ bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser, const size_t depth = parser->depth(); while (xml::XmlPullParser::NextChildNode(parser, depth)) { if (parser->event() == xml::XmlPullParser::Event::kComment) { - comment = util::TrimWhitespace(parser->comment()).ToString(); + comment = util::TrimWhitespace(parser->comment()).to_string(); continue; } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) { // Ignore text. diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h index 11b1e5b787ca..c12dacf1c707 100644 --- a/tools/aapt2/ResourceParser.h +++ b/tools/aapt2/ResourceParser.h @@ -20,6 +20,7 @@ #include <memory> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "ConfigDescription.h" #include "Diagnostics.h" @@ -27,7 +28,6 @@ #include "ResourceValues.h" #include "StringPool.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #include "xml/XmlPullParser.h" namespace aapt { @@ -101,7 +101,7 @@ class ResourceParser { bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, bool weak); Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser, - const StringPiece& tag); + const android::StringPiece& tag); bool ParseStyle(xml::XmlPullParser* parser, ParsedResource* out_resource); bool ParseStyleItem(xml::XmlPullParser* parser, Style* style); bool ParseDeclareStyleable(xml::XmlPullParser* parser, diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 2463911445e7..5762fb035a81 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -25,6 +25,8 @@ #include "test/Test.h" #include "xml/XmlPullParser.h" +using android::StringPiece; + namespace aapt { constexpr const char* kXmlPreamble = diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 4e6a50ae149b..dd78750db290 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -28,6 +28,8 @@ #include <string> #include <tuple> +using android::StringPiece; + namespace aapt { static bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, @@ -87,7 +89,7 @@ ResourceTablePackage* ResourceTable::FindOrCreatePackage( std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>(); - new_package->name = name.ToString(); + new_package->name = name.to_string(); return packages.emplace(iter, std::move(new_package))->get(); } diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index a0c3217df610..0fe966c5089b 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -25,7 +25,9 @@ #include "StringPool.h" #include "io/File.h" -#include <android-base/macros.h> +#include "android-base/macros.h" +#include "androidfw/StringPiece.h" + #include <functional> #include <map> #include <memory> @@ -68,9 +70,8 @@ class ResourceConfigValue { */ std::unique_ptr<Value> value; - ResourceConfigValue(const ConfigDescription& config, - const StringPiece& product) - : config(config), product(product.ToString()) {} + ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product) + : config(config), product(product.to_string()) {} private: DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue); @@ -105,13 +106,13 @@ class ResourceEntry { */ std::vector<std::unique_ptr<ResourceConfigValue>> values; - explicit ResourceEntry(const StringPiece& name) : name(name.ToString()) {} + explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {} ResourceConfigValue* FindValue(const ConfigDescription& config); ResourceConfigValue* FindValue(const ConfigDescription& config, - const StringPiece& product); + const android::StringPiece& product); ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config, - const StringPiece& product); + const android::StringPiece& product); std::vector<ResourceConfigValue*> findAllValues( const ConfigDescription& config); std::vector<ResourceConfigValue*> FindValuesIf( @@ -150,8 +151,8 @@ class ResourceTableType { explicit ResourceTableType(const ResourceType type) : type(type) {} - ResourceEntry* FindEntry(const StringPiece& name); - ResourceEntry* FindOrCreateEntry(const StringPiece& name); + ResourceEntry* FindEntry(const android::StringPiece& name); + ResourceEntry* FindOrCreateEntry(const android::StringPiece& name); private: DISALLOW_COPY_AND_ASSIGN(ResourceTableType); @@ -195,22 +196,19 @@ class ResourceTable { Value* incoming); bool AddResource(const ResourceNameRef& name, const ConfigDescription& config, - const StringPiece& product, std::unique_ptr<Value> value, + const android::StringPiece& product, std::unique_ptr<Value> value, IDiagnostics* diag); bool AddResource(const ResourceNameRef& name, const ResourceId& res_id, - const ConfigDescription& config, const StringPiece& product, + const ConfigDescription& config, const android::StringPiece& product, std::unique_ptr<Value> value, IDiagnostics* diag); - bool AddFileReference(const ResourceNameRef& name, - const ConfigDescription& config, const Source& source, - const StringPiece& path, IDiagnostics* diag); + bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config, + const Source& source, const android::StringPiece& path, IDiagnostics* diag); - bool AddFileReferenceAllowMangled(const ResourceNameRef& name, - const ConfigDescription& config, - const Source& source, - const StringPiece& path, io::IFile* file, - IDiagnostics* diag); + bool AddFileReferenceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config, + const Source& source, const android::StringPiece& path, + io::IFile* file, IDiagnostics* diag); /** * Same as AddResource, but doesn't verify the validity of the name. This is @@ -219,18 +217,13 @@ class ResourceTable { * mangled * names. */ - bool AddResourceAllowMangled(const ResourceNameRef& name, - const ConfigDescription& config, - const StringPiece& product, - std::unique_ptr<Value> value, + bool AddResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config, + const android::StringPiece& product, std::unique_ptr<Value> value, IDiagnostics* diag); - bool AddResourceAllowMangled(const ResourceNameRef& name, - const ResourceId& id, - const ConfigDescription& config, - const StringPiece& product, - std::unique_ptr<Value> value, - IDiagnostics* diag); + bool AddResourceAllowMangled(const ResourceNameRef& name, const ResourceId& id, + const ConfigDescription& config, const android::StringPiece& product, + std::unique_ptr<Value> value, IDiagnostics* diag); bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id, const Symbol& symbol, IDiagnostics* diag); @@ -273,28 +266,23 @@ class ResourceTable { * represent the * 'current' package before it is known to the ResourceTable. */ - ResourceTablePackage* FindPackage(const StringPiece& name); + ResourceTablePackage* FindPackage(const android::StringPiece& name); ResourceTablePackage* FindPackageById(uint8_t id); - ResourceTablePackage* CreatePackage(const StringPiece& name, - Maybe<uint8_t> id = {}); + ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {}); private: - ResourceTablePackage* FindOrCreatePackage(const StringPiece& name); + ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name); bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id, - const ConfigDescription& config, - const StringPiece& product, std::unique_ptr<Value> value, - const char* valid_chars, - const CollisionResolverFunc& conflict_resolver, - IDiagnostics* diag); - - bool AddFileReferenceImpl(const ResourceNameRef& name, - const ConfigDescription& config, - const Source& source, const StringPiece& path, - io::IFile* file, const char* valid_chars, - IDiagnostics* diag); + const ConfigDescription& config, const android::StringPiece& product, + std::unique_ptr<Value> value, const char* valid_chars, + const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag); + + bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config, + const Source& source, const android::StringPiece& path, io::IFile* file, + const char* valid_chars, IDiagnostics* diag); bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id, const Symbol& symbol, const char* valid_chars, diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index fce9b338d726..11239673272e 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -26,6 +26,9 @@ #include "util/Files.h" #include "util/Util.h" +using android::StringPiece; +using android::StringPiece16; + namespace aapt { namespace ResourceUtils { @@ -59,7 +62,7 @@ Maybe<ResourceName> ToResourceName( name_out.entry = util::Utf16ToUtf8(StringPiece16(name_in.name, name_in.nameLen)); } else if (name_in.name8) { - name_out.entry = StringPiece(name_in.name8, name_in.nameLen).ToString(); + name_out.entry.assign(name_in.name8, name_in.nameLen); } else { return {}; } @@ -303,9 +306,7 @@ Maybe<Reference> ParseXmlAttributeName(const StringPiece& str) { p++; } - ref.name = - ResourceName(package.ToString(), ResourceType::kAttr, - name.empty() ? trimmed_str.ToString() : name.ToString()); + ref.name = ResourceName(package, ResourceType::kAttr, name.empty() ? trimmed_str : name); return Maybe<Reference>(std::move(ref)); } diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h index 9766f6a7b2fa..bd3a8e3e0bc8 100644 --- a/tools/aapt2/ResourceUtils.h +++ b/tools/aapt2/ResourceUtils.h @@ -20,10 +20,11 @@ #include <functional> #include <memory> +#include "androidfw/StringPiece.h" + #include "NameMangler.h" #include "Resource.h" #include "ResourceValues.h" -#include "util/StringPiece.h" namespace aapt { namespace ResourceUtils { @@ -37,8 +38,8 @@ namespace ResourceUtils { * individual extracted piece to verify that the pieces are valid. * Returns false if there was no package but a ':' was present. */ -bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, - StringPiece* out_type, StringPiece* out_entry); +bool ExtractResourceName(const android::StringPiece& str, android::StringPiece* out_package, + android::StringPiece* out_type, android::StringPiece* out_entry); /** * Returns true if the string was parsed as a resource name @@ -46,7 +47,7 @@ bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, * `out_resource` set to the parsed resource name and `out_private` set to true * if a '*' prefix was present. */ -bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_resource, +bool ParseResourceName(const android::StringPiece& str, ResourceNameRef* out_resource, bool* out_private = nullptr); /* @@ -57,28 +58,27 @@ bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_resource, * If '+' was present in the reference, `out_create` is set to true. * If '*' was present in the reference, `out_private` is set to true. */ -bool ParseReference(const StringPiece& str, ResourceNameRef* out_reference, +bool ParseReference(const android::StringPiece& str, ResourceNameRef* out_reference, bool* out_create = nullptr, bool* out_private = nullptr); /* * Returns true if the string is in the form of a resource reference * (@[+][package:]type/name). */ -bool IsReference(const StringPiece& str); +bool IsReference(const android::StringPiece& str); /* * Returns true if the string was parsed as an attribute reference * (?[package:][type/]name), * with `out_reference` set to the parsed reference. */ -bool ParseAttributeReference(const StringPiece& str, - ResourceNameRef* out_reference); +bool ParseAttributeReference(const android::StringPiece& str, ResourceNameRef* out_reference); /** * Returns true if the string is in the form of an attribute * reference(?[package:][type/]name). */ -bool IsAttributeReference(const StringPiece& str); +bool IsAttributeReference(const android::StringPiece& str); /** * Convert an android::ResTable::resource_name to an aapt::ResourceName struct. @@ -90,22 +90,22 @@ Maybe<ResourceName> ToResourceName( * Returns a boolean value if the string is equal to TRUE, true, True, FALSE, * false, or False. */ -Maybe<bool> ParseBool(const StringPiece& str); +Maybe<bool> ParseBool(const android::StringPiece& str); /** * Returns a uint32_t if the string is an integer. */ -Maybe<uint32_t> ParseInt(const StringPiece& str); +Maybe<uint32_t> ParseInt(const android::StringPiece& str); /** * Returns an ID if it the string represented a valid ID. */ -Maybe<ResourceId> ParseResourceId(const StringPiece& str); +Maybe<ResourceId> ParseResourceId(const android::StringPiece& str); /** * Parses an SDK version, which can be an integer, or a letter from A-Z. */ -Maybe<int> ParseSdkVersion(const StringPiece& str); +Maybe<int> ParseSdkVersion(const android::StringPiece& str); /* * Returns a Reference, or None Maybe instance if the string `str` was parsed as @@ -118,8 +118,7 @@ Maybe<int> ParseSdkVersion(const StringPiece& str); * ?[package:]style/<entry> or * <package>:[style/]<entry> */ -Maybe<Reference> ParseStyleParentReference(const StringPiece& str, - std::string* out_error); +Maybe<Reference> ParseStyleParentReference(const android::StringPiece& str, std::string* out_error); /* * Returns a Reference if the string `str` was parsed as a valid XML attribute @@ -128,7 +127,7 @@ Maybe<Reference> ParseStyleParentReference(const StringPiece& str, * * package:entry */ -Maybe<Reference> ParseXmlAttributeName(const StringPiece& str); +Maybe<Reference> ParseXmlAttributeName(const android::StringPiece& str); /* * Returns a Reference object if the string was parsed as a resource or @@ -137,52 +136,52 @@ Maybe<Reference> ParseXmlAttributeName(const StringPiece& str); * if * the '+' was present in the string. */ -std::unique_ptr<Reference> TryParseReference(const StringPiece& str, +std::unique_ptr<Reference> TryParseReference(const android::StringPiece& str, bool* out_create = nullptr); /* * Returns a BinaryPrimitve object representing @null or @empty if the string * was parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a color if the string was parsed * as one. */ -std::unique_ptr<BinaryPrimitive> TryParseColor(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseColor(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a boolean if the string was * parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseBool(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseBool(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing an integer if the string was * parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseInt(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseInt(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a floating point number * (float, dimension, etc) if the string was parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseFloat(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseFloat(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing an enum symbol if the string was * parsed as one. */ std::unique_ptr<BinaryPrimitive> TryParseEnumSymbol(const Attribute* enum_attr, - const StringPiece& str); + const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a flag symbol if the string was * parsed as one. */ std::unique_ptr<BinaryPrimitive> TryParseFlagSymbol(const Attribute* enum_attr, - const StringPiece& str); + const android::StringPiece& str); /* * Try to convert a string to an Item for the given attribute. The attribute * will @@ -191,11 +190,11 @@ std::unique_ptr<BinaryPrimitive> TryParseFlagSymbol(const Attribute* enum_attr, * reference to an ID that must be created (@+id/foo). */ std::unique_ptr<Item> TryParseItemForAttribute( - const StringPiece& value, const Attribute* attr, + const android::StringPiece& value, const Attribute* attr, const std::function<void(const ResourceName&)>& on_create_reference = {}); std::unique_ptr<Item> TryParseItemForAttribute( - const StringPiece& value, uint32_t type_mask, + const android::StringPiece& value, uint32_t type_mask, const std::function<void(const ResourceName&)>& on_create_reference = {}); uint32_t AndroidTypeToAttributeTypeMask(uint16_t type); diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp index f9c500b42c13..048c69252e47 100644 --- a/tools/aapt2/ResourceUtils_test.cpp +++ b/tools/aapt2/ResourceUtils_test.cpp @@ -48,8 +48,7 @@ TEST(ResourceUtilsTest, ParseResourceName) { EXPECT_EQ(ResourceNameRef("android", ResourceType::kColor, "foo"), actual); EXPECT_TRUE(actual_priv); - EXPECT_FALSE( - ResourceUtils::ParseResourceName(StringPiece(), &actual, &actual_priv)); + EXPECT_FALSE(ResourceUtils::ParseResourceName(android::StringPiece(), &actual, &actual_priv)); } TEST(ResourceUtilsTest, ParseReferenceWithNoPackage) { diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h index ea73615e372a..d380f8d0583d 100644 --- a/tools/aapt2/ResourceValues.h +++ b/tools/aapt2/ResourceValues.h @@ -22,6 +22,7 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "Diagnostics.h" #include "Resource.h" @@ -73,7 +74,7 @@ struct Value { */ const std::string& GetComment() const { return comment_; } - void SetComment(const StringPiece& str) { comment_ = str.ToString(); } + void SetComment(const android::StringPiece& str) { comment_ = str.to_string(); } void SetComment(std::string&& str) { comment_ = std::move(str); } diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index c7f920ac6c58..e8067143dc75 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -21,6 +21,8 @@ #include <unordered_map> #include <vector> +using android::StringPiece; + namespace aapt { static const char* sDevelopmentSdkCodeName = "O"; diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h index 5352b5398544..98ba94badfed 100644 --- a/tools/aapt2/SdkConstants.h +++ b/tools/aapt2/SdkConstants.h @@ -19,6 +19,8 @@ #include <utility> +#include "androidfw/StringPiece.h" + #include "Resource.h" namespace aapt { @@ -52,7 +54,7 @@ enum { size_t FindAttributeSdkLevel(const ResourceId& id); size_t FindAttributeSdkLevel(const ResourceName& name); -std::pair<StringPiece, int> GetDevelopmentSdkCodeNameAndVersion(); +std::pair<android::StringPiece, int> GetDevelopmentSdkCodeNameAndVersion(); } // namespace aapt diff --git a/tools/aapt2/Source.h b/tools/aapt2/Source.h index 459a8e603b6b..d7f2a668477c 100644 --- a/tools/aapt2/Source.h +++ b/tools/aapt2/Source.h @@ -20,8 +20,9 @@ #include <ostream> #include <string> +#include "androidfw/StringPiece.h" + #include "util/Maybe.h" -#include "util/StringPiece.h" namespace aapt { @@ -35,12 +36,11 @@ struct Source { Source() = default; - inline Source(const StringPiece& path) - : path(path.ToString()) { // NOLINT(implicit) + inline Source(const android::StringPiece& path) : path(path.to_string()) { // NOLINT(implicit) } - inline Source(const StringPiece& path, size_t line) - : path(path.ToString()), line(line) {} + inline Source(const android::StringPiece& path, size_t line) + : path(path.to_string()), line(line) {} inline Source WithLine(size_t line) const { return Source(path, line); } }; diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp index 30328299bb84..d968d73c44ee 100644 --- a/tools/aapt2/StringPool.cpp +++ b/tools/aapt2/StringPool.cpp @@ -22,11 +22,13 @@ #include "android-base/logging.h" #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "util/BigBuffer.h" -#include "util/StringPiece.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { StringPool::Ref::Ref() : entry_(nullptr) {} @@ -140,7 +142,7 @@ StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, } Entry* entry = new Entry(); - entry->value = str.ToString(); + entry->value = str.to_string(); entry->context = context; entry->index = strings_.size(); entry->ref_ = 0; diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h index a4f556ca52e4..d0ce489dae26 100644 --- a/tools/aapt2/StringPool.h +++ b/tools/aapt2/StringPool.h @@ -23,9 +23,10 @@ #include <unordered_map> #include <vector> +#include "androidfw/StringPiece.h" + #include "ConfigDescription.h" #include "util/BigBuffer.h" -#include "util/StringPiece.h" namespace aapt { @@ -149,14 +150,14 @@ class StringPool { * Adds a string to the pool, unless it already exists. Returns * a reference to the string in the pool. */ - Ref MakeRef(const StringPiece& str); + Ref MakeRef(const android::StringPiece& str); /** * Adds a string to the pool, unless it already exists, with a context * object that can be used when sorting the string pool. Returns * a reference to the string in the pool. */ - Ref MakeRef(const StringPiece& str, const Context& context); + Ref MakeRef(const android::StringPiece& str, const Context& context); /** * Adds a style to the string pool and returns a reference to it. @@ -208,11 +209,11 @@ class StringPool { static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8); - Ref MakeRefImpl(const StringPiece& str, const Context& context, bool unique); + Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique); std::vector<std::unique_ptr<Entry>> strings_; std::vector<std::unique_ptr<StyleEntry>> styles_; - std::unordered_multimap<StringPiece, Entry*> indexed_strings_; + std::unordered_multimap<android::StringPiece, Entry*> indexed_strings_; }; // diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp index e1394fc0221f..f64a8cf20928 100644 --- a/tools/aapt2/StringPool_test.cpp +++ b/tools/aapt2/StringPool_test.cpp @@ -18,9 +18,14 @@ #include <string> +#include "androidfw/StringPiece.h" + #include "test/Test.h" #include "util/Util.h" +using android::StringPiece; +using android::StringPiece16; + namespace aapt { TEST(StringPoolTest, InsertOneString) { @@ -236,8 +241,7 @@ TEST(StringPoolTest, Flatten) { EXPECT_EQ(StringPiece16(u"goodbye"), util::GetString16(test, 1)); EXPECT_EQ(StringPiece(sLongString), util::GetString(test, 2)); - EXPECT_EQ(util::Utf8ToUtf16(sLongString), - util::GetString16(test, 2).ToString()); + EXPECT_EQ(util::Utf8ToUtf16(sLongString), util::GetString16(test, 2).to_string()); size_t len; EXPECT_TRUE(test.stringAt(3, &len) != nullptr || diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp index f0b18e65cc1a..8027f4289169 100644 --- a/tools/aapt2/compile/Compile.cpp +++ b/tools/aapt2/compile/Compile.cpp @@ -19,6 +19,12 @@ #include <fstream> #include <string> +#include "android-base/errors.h" +#include "android-base/file.h" +#include "androidfw/StringPiece.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" + #include "ConfigDescription.h" #include "Diagnostics.h" #include "Flags.h" @@ -38,11 +44,7 @@ #include "xml/XmlDom.h" #include "xml/XmlPullParser.h" -#include "android-base/errors.h" -#include "android-base/file.h" -#include "google/protobuf/io/coded_stream.h" -#include "google/protobuf/io/zero_copy_stream_impl_lite.h" - +using android::StringPiece; using google::protobuf::io::CopyingOutputStreamAdaptor; using google::protobuf::io::ZeroCopyOutputStream; @@ -103,9 +105,8 @@ static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, name = name.substr(0, dot_pos); } - return ResourcePathData{Source(path), dir_str.ToString(), - name.ToString(), extension.ToString(), - config_str.ToString(), config}; + return ResourcePathData{Source(path), dir_str.to_string(), name.to_string(), + extension.to_string(), config_str.to_string(), config}; } struct CompileOptions { diff --git a/tools/aapt2/compile/IdAssigner.h b/tools/aapt2/compile/IdAssigner.h index 371ec01818cd..9640eb8c50ff 100644 --- a/tools/aapt2/compile/IdAssigner.h +++ b/tools/aapt2/compile/IdAssigner.h @@ -19,11 +19,11 @@ #include <unordered_map> +#include "android-base/macros.h" + #include "Resource.h" #include "process/IResourceTableConsumer.h" -#include "android-base/macros.h" - namespace aapt { /** @@ -40,8 +40,7 @@ class IdAssigner : public IResourceTableConsumer { bool Consume(IAaptContext* context, ResourceTable* table) override; private: - const std::unordered_map<ResourceName, ResourceId>* assigned_id_map_ = - nullptr; + const std::unordered_map<ResourceName, ResourceId>* assigned_id_map_ = nullptr; }; } // namespace aapt diff --git a/tools/aapt2/compile/NinePatch.cpp b/tools/aapt2/compile/NinePatch.cpp index eab5c97c437c..c931da48c889 100644 --- a/tools/aapt2/compile/NinePatch.cpp +++ b/tools/aapt2/compile/NinePatch.cpp @@ -21,10 +21,12 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" -#include "util/StringPiece.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { // Colors in the format 0xAARRGGBB (the way 9-patch expects it). diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp index 7ab05b58b8b9..5e15c88410ee 100644 --- a/tools/aapt2/compile/Png.cpp +++ b/tools/aapt2/compile/Png.cpp @@ -15,18 +15,21 @@ */ #include "Png.h" -#include "Source.h" -#include "util/BigBuffer.h" -#include "util/Util.h" -#include <androidfw/ResourceTypes.h> #include <png.h> #include <zlib.h> + #include <iostream> #include <sstream> #include <string> #include <vector> +#include "androidfw/ResourceTypes.h" + +#include "Source.h" +#include "util/BigBuffer.h" +#include "util/Util.h" + namespace aapt { constexpr bool kDebug = false; diff --git a/tools/aapt2/compile/Png.h b/tools/aapt2/compile/Png.h index aff1da3f05d2..a82005115850 100644 --- a/tools/aapt2/compile/Png.h +++ b/tools/aapt2/compile/Png.h @@ -56,7 +56,7 @@ class Png { */ class PngChunkFilter : public io::InputStream { public: - explicit PngChunkFilter(const StringPiece& data); + explicit PngChunkFilter(const android::StringPiece& data); bool Next(const void** buffer, int* len) override; void BackUp(int count) override; @@ -71,7 +71,7 @@ class PngChunkFilter : public io::InputStream { private: bool ConsumeWindow(const void** buffer, int* len); - StringPiece data_; + android::StringPiece data_; size_t window_start_ = 0; size_t window_end_ = 0; bool error_ = false; diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/tools/aapt2/compile/PngChunkFilter.cpp index 4cbefb9496ae..edec12317fdd 100644 --- a/tools/aapt2/compile/PngChunkFilter.cpp +++ b/tools/aapt2/compile/PngChunkFilter.cpp @@ -16,8 +16,11 @@ #include "compile/Png.h" +#include "androidfw/StringPiece.h" + #include "io/Io.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp index 055a725213b7..5035f816f0fa 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp @@ -23,6 +23,8 @@ #include "ValueVisitor.h" #include "compile/Pseudolocalizer.h" +using android::StringPiece; + namespace aapt { std::unique_ptr<StyledString> PseudolocalizeStyledString( diff --git a/tools/aapt2/compile/Pseudolocalizer.cpp b/tools/aapt2/compile/Pseudolocalizer.cpp index f89288f73333..15a3d8c289e2 100644 --- a/tools/aapt2/compile/Pseudolocalizer.cpp +++ b/tools/aapt2/compile/Pseudolocalizer.cpp @@ -18,6 +18,8 @@ #include "util/Util.h" +using android::StringPiece; + namespace aapt { // String basis to generate expansion @@ -40,10 +42,8 @@ static const char kArgEnd = '}'; class PseudoMethodNone : public PseudoMethodImpl { public: - std::string Text(const StringPiece& text) override { return text.ToString(); } - std::string Placeholder(const StringPiece& text) override { - return text.ToString(); - } + std::string Text(const StringPiece& text) override { return text.to_string(); } + std::string Placeholder(const StringPiece& text) override { return text.to_string(); } }; class PseudoMethodBidi : public PseudoMethodImpl { @@ -116,7 +116,7 @@ std::string Pseudolocalizer::Text(const StringPiece& text) { } size_t size = nextpos - lastpos; if (size) { - std::string chunk = text.substr(lastpos, size).ToString(); + std::string chunk = text.substr(lastpos, size).to_string(); if (pseudo) { chunk = impl_->Text(chunk); } else if (str[lastpos] == kArgStart && str[nextpos - 1] == kArgEnd) { @@ -437,7 +437,7 @@ std::string PseudoMethodAccent::Text(const StringPiece& source) { std::string PseudoMethodAccent::Placeholder(const StringPiece& source) { // Surround a placeholder with brackets - return kPlaceholderOpen + source.ToString() + kPlaceholderClose; + return kPlaceholderOpen + source.to_string() + kPlaceholderClose; } std::string PseudoMethodBidi::Text(const StringPiece& source) { @@ -467,7 +467,7 @@ std::string PseudoMethodBidi::Text(const StringPiece& source) { std::string PseudoMethodBidi::Placeholder(const StringPiece& source) { // Surround a placeholder with directionality change sequence - return kRlm + kRlo + source.ToString() + kPdf + kRlm; + return kRlm + kRlo + source.to_string() + kPdf + kRlm; } } // namespace aapt diff --git a/tools/aapt2/compile/Pseudolocalizer.h b/tools/aapt2/compile/Pseudolocalizer.h index a6d2ad037d50..6cf003b24157 100644 --- a/tools/aapt2/compile/Pseudolocalizer.h +++ b/tools/aapt2/compile/Pseudolocalizer.h @@ -20,10 +20,10 @@ #include <memory> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "ResourceValues.h" #include "StringPool.h" -#include "util/StringPiece.h" namespace aapt { @@ -32,8 +32,8 @@ class PseudoMethodImpl { virtual ~PseudoMethodImpl() {} virtual std::string Start() { return {}; } virtual std::string End() { return {}; } - virtual std::string Text(const StringPiece& text) = 0; - virtual std::string Placeholder(const StringPiece& text) = 0; + virtual std::string Text(const android::StringPiece& text) = 0; + virtual std::string Placeholder(const android::StringPiece& text) = 0; }; class Pseudolocalizer { @@ -48,7 +48,7 @@ class Pseudolocalizer { void SetMethod(Method method); std::string Start() { return impl_->Start(); } std::string End() { return impl_->End(); } - std::string Text(const StringPiece& text); + std::string Text(const android::StringPiece& text); private: std::unique_ptr<PseudoMethodImpl> impl_; diff --git a/tools/aapt2/compile/Pseudolocalizer_test.cpp b/tools/aapt2/compile/Pseudolocalizer_test.cpp index 92eb3b58515f..d3b7b02d1abb 100644 --- a/tools/aapt2/compile/Pseudolocalizer_test.cpp +++ b/tools/aapt2/compile/Pseudolocalizer_test.cpp @@ -19,6 +19,8 @@ #include "test/Test.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { // In this context, 'Axis' represents a particular field in the configuration, diff --git a/tools/aapt2/diff/Diff.cpp b/tools/aapt2/diff/Diff.cpp index 593e7ab119f1..de0fe404b867 100644 --- a/tools/aapt2/diff/Diff.cpp +++ b/tools/aapt2/diff/Diff.cpp @@ -24,6 +24,8 @@ #include "process/SymbolTable.h" #include "unflatten/BinaryResourceParser.h" +using android::StringPiece; + namespace aapt { class DiffContext : public IAaptContext { diff --git a/tools/aapt2/dump/Dump.cpp b/tools/aapt2/dump/Dump.cpp index 2920c2abb57a..bcede72037b2 100644 --- a/tools/aapt2/dump/Dump.cpp +++ b/tools/aapt2/dump/Dump.cpp @@ -16,6 +16,8 @@ #include <vector> +#include "androidfw/StringPiece.h" + #include "Debug.h" #include "Diagnostics.h" #include "Flags.h" @@ -24,7 +26,8 @@ #include "proto/ProtoSerialize.h" #include "unflatten/BinaryResourceParser.h" #include "util/Files.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { diff --git a/tools/aapt2/flatten/Archive.cpp b/tools/aapt2/flatten/Archive.cpp index 47de0a3b8d6c..5c96a4dbd4e2 100644 --- a/tools/aapt2/flatten/Archive.cpp +++ b/tools/aapt2/flatten/Archive.cpp @@ -22,10 +22,12 @@ #include <vector> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "ziparchive/zip_writer.h" #include "util/Files.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -36,7 +38,7 @@ class DirectoryWriter : public IArchiveWriter { DirectoryWriter() = default; bool Open(IDiagnostics* diag, const StringPiece& out_dir) { - dir_ = out_dir.ToString(); + dir_ = out_dir.to_string(); file::FileType type = file::GetFileType(dir_); if (type == file::FileType::kNonexistant) { diag->Error(DiagMessage() << "directory " << dir_ << " does not exist"); diff --git a/tools/aapt2/flatten/Archive.h b/tools/aapt2/flatten/Archive.h index 4fcb3ffa2b78..f0681bdd1167 100644 --- a/tools/aapt2/flatten/Archive.h +++ b/tools/aapt2/flatten/Archive.h @@ -22,12 +22,12 @@ #include <string> #include <vector> +#include "androidfw/StringPiece.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "Diagnostics.h" #include "util/BigBuffer.h" #include "util/Files.h" -#include "util/StringPiece.h" namespace aapt { @@ -46,7 +46,7 @@ class IArchiveWriter : public google::protobuf::io::CopyingOutputStream { public: virtual ~IArchiveWriter() = default; - virtual bool StartEntry(const StringPiece& path, uint32_t flags) = 0; + virtual bool StartEntry(const android::StringPiece& path, uint32_t flags) = 0; virtual bool WriteEntry(const BigBuffer& buffer) = 0; virtual bool WriteEntry(const void* data, size_t len) = 0; virtual bool FinishEntry() = 0; @@ -57,11 +57,11 @@ class IArchiveWriter : public google::protobuf::io::CopyingOutputStream { } }; -std::unique_ptr<IArchiveWriter> CreateDirectoryArchiveWriter( - IDiagnostics* diag, const StringPiece& path); +std::unique_ptr<IArchiveWriter> CreateDirectoryArchiveWriter(IDiagnostics* diag, + const android::StringPiece& path); -std::unique_ptr<IArchiveWriter> CreateZipFileArchiveWriter( - IDiagnostics* diag, const StringPiece& path); +std::unique_ptr<IArchiveWriter> CreateZipFileArchiveWriter(IDiagnostics* diag, + const android::StringPiece& path); } // namespace aapt diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp index 2c83bb384cc5..ffc2de141860 100644 --- a/tools/aapt2/flatten/XmlFlattener_test.cpp +++ b/tools/aapt2/flatten/XmlFlattener_test.cpp @@ -23,6 +23,8 @@ #include "util/BigBuffer.h" #include "util/Util.h" +using android::StringPiece16; + namespace aapt { class XmlFlattenerTest : public ::testing::Test { diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h index 644f59f8f3ba..3d5b5b11707e 100644 --- a/tools/aapt2/io/File.h +++ b/tools/aapt2/io/File.h @@ -110,7 +110,7 @@ class IFileCollection { public: virtual ~IFileCollection() = default; - virtual IFile* FindFile(const StringPiece& path) = 0; + virtual IFile* FindFile(const android::StringPiece& path) = 0; virtual std::unique_ptr<IFileCollectionIterator> Iterator() = 0; }; diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp index 828f34e9c883..027cbd041fa6 100644 --- a/tools/aapt2/io/FileSystem.cpp +++ b/tools/aapt2/io/FileSystem.cpp @@ -16,14 +16,16 @@ #include "io/FileSystem.h" +#include "androidfw/StringPiece.h" #include "utils/FileMap.h" #include "Source.h" #include "util/Files.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { namespace io { @@ -54,13 +56,11 @@ IFile* FileCollectionIterator::Next() { } IFile* FileCollection::InsertFile(const StringPiece& path) { - return (files_[path.ToString()] = - util::make_unique<RegularFile>(Source(path))) - .get(); + return (files_[path.to_string()] = util::make_unique<RegularFile>(Source(path))).get(); } IFile* FileCollection::FindFile(const StringPiece& path) { - auto iter = files_.find(path.ToString()); + auto iter = files_.find(path.to_string()); if (iter != files_.end()) { return iter->second.get(); } diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h index 84f851ff694b..dfd37172004b 100644 --- a/tools/aapt2/io/FileSystem.h +++ b/tools/aapt2/io/FileSystem.h @@ -59,8 +59,8 @@ class FileCollection : public IFileCollection { /** * Adds a file located at path. Returns the IFile representation of that file. */ - IFile* InsertFile(const StringPiece& path); - IFile* FindFile(const StringPiece& path) override; + IFile* InsertFile(const android::StringPiece& path); + IFile* FindFile(const android::StringPiece& path) override; std::unique_ptr<IFileCollectionIterator> Iterator() override; private: diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp index f4a128eca9d1..62b436fe4dc7 100644 --- a/tools/aapt2/io/ZipArchive.cpp +++ b/tools/aapt2/io/ZipArchive.cpp @@ -22,6 +22,8 @@ #include "Source.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { namespace io { @@ -107,7 +109,7 @@ std::unique_ptr<ZipFileCollection> ZipFileCollection::Create( std::string zip_entry_path = std::string(reinterpret_cast<const char*>(zip_entry_name.name), zip_entry_name.name_length); - std::string nested_path = path.ToString() + "@" + zip_entry_path; + std::string nested_path = path.to_string() + "@" + zip_entry_path; collection->files_[zip_entry_path] = util::make_unique<ZipFile>( collection->handle_, zip_data, Source(nested_path)); } @@ -120,7 +122,7 @@ std::unique_ptr<ZipFileCollection> ZipFileCollection::Create( } IFile* ZipFileCollection::FindFile(const StringPiece& path) { - auto iter = files_.find(path.ToString()); + auto iter = files_.find(path.to_string()); if (iter != files_.end()) { return iter->second.get(); } diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h index 85ca1aed4edc..634adad8af32 100644 --- a/tools/aapt2/io/ZipArchive.h +++ b/tools/aapt2/io/ZipArchive.h @@ -21,8 +21,9 @@ #include <map> +#include "androidfw/StringPiece.h" + #include "io/File.h" -#include "util/StringPiece.h" namespace aapt { namespace io { @@ -64,10 +65,10 @@ class ZipFileCollectionIterator : public IFileCollectionIterator { */ class ZipFileCollection : public IFileCollection { public: - static std::unique_ptr<ZipFileCollection> Create(const StringPiece& path, + static std::unique_ptr<ZipFileCollection> Create(const android::StringPiece& path, std::string* outError); - io::IFile* FindFile(const StringPiece& path) override; + io::IFile* FindFile(const android::StringPiece& path) override; std::unique_ptr<IFileCollectionIterator> Iterator() override; ~ZipFileCollection() override; diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp index 2951e5cff6d7..a0ef00b1ea1f 100644 --- a/tools/aapt2/java/AnnotationProcessor.cpp +++ b/tools/aapt2/java/AnnotationProcessor.cpp @@ -20,6 +20,8 @@ #include "util/Util.h" +using android::StringPiece; + namespace aapt { void AnnotationProcessor::AppendCommentLine(std::string& comment) { @@ -54,7 +56,7 @@ void AnnotationProcessor::AppendComment(const StringPiece& comment) { for (StringPiece line : util::Tokenize(comment, '\n')) { line = util::TrimWhitespace(line); if (!line.empty()) { - std::string lineCopy = line.ToString(); + std::string lineCopy = line.to_string(); AppendCommentLine(lineCopy); } } diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h index 666a7f356768..99cd44fd2cc1 100644 --- a/tools/aapt2/java/AnnotationProcessor.h +++ b/tools/aapt2/java/AnnotationProcessor.h @@ -20,7 +20,7 @@ #include <sstream> #include <string> -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -58,7 +58,7 @@ class AnnotationProcessor { * configurations, * we need to collect all the comments. */ - void AppendComment(const StringPiece& comment); + void AppendComment(const android::StringPiece& comment); void AppendNewLine(); @@ -66,7 +66,7 @@ class AnnotationProcessor { * Writes the comments and annotations to the stream, with the given prefix * before each line. */ - void WriteToStream(std::ostream* out, const StringPiece& prefix) const; + void WriteToStream(std::ostream* out, const android::StringPiece& prefix) const; private: enum : uint32_t { diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp index f1f1f925480c..53d6ea1a79c5 100644 --- a/tools/aapt2/java/ClassDefinition.cpp +++ b/tools/aapt2/java/ClassDefinition.cpp @@ -16,7 +16,9 @@ #include "java/ClassDefinition.h" -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -43,7 +45,7 @@ void ClassDefinition::WriteToStream(const StringPiece& prefix, bool final, } *out << "final class " << name_ << " {\n"; - std::string new_prefix = prefix.ToString(); + std::string new_prefix = prefix.to_string(); new_prefix.append(kIndent); for (const std::unique_ptr<ClassMember>& member : members_) { diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h index d8b61d919fd8..64e4b2987be3 100644 --- a/tools/aapt2/java/ClassDefinition.h +++ b/tools/aapt2/java/ClassDefinition.h @@ -21,10 +21,10 @@ #include <string> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "Resource.h" #include "java/AnnotationProcessor.h" -#include "util/StringPiece.h" #include "util/Util.h" namespace aapt { @@ -41,7 +41,7 @@ class ClassMember { virtual bool empty() const = 0; - virtual void WriteToStream(const StringPiece& prefix, bool final, + virtual void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const { processor_.WriteToStream(out, prefix); } @@ -53,12 +53,12 @@ class ClassMember { template <typename T> class PrimitiveMember : public ClassMember { public: - PrimitiveMember(const StringPiece& name, const T& val) - : name_(name.ToString()), val_(val) {} + PrimitiveMember(const android::StringPiece& name, const T& val) + : name_(name.to_string()), val_(val) {} bool empty() const override { return false; } - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { ClassMember::WriteToStream(prefix, final, out); @@ -79,12 +79,12 @@ class PrimitiveMember : public ClassMember { template <> class PrimitiveMember<std::string> : public ClassMember { public: - PrimitiveMember(const StringPiece& name, const std::string& val) - : name_(name.ToString()), val_(val) {} + PrimitiveMember(const android::StringPiece& name, const std::string& val) + : name_(name.to_string()), val_(val) {} bool empty() const override { return false; } - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { ClassMember::WriteToStream(prefix, final, out); @@ -106,14 +106,13 @@ using StringMember = PrimitiveMember<std::string>; template <typename T> class PrimitiveArrayMember : public ClassMember { public: - explicit PrimitiveArrayMember(const StringPiece& name) - : name_(name.ToString()) {} + explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {} void AddElement(const T& val) { elements_.push_back(val); } bool empty() const override { return false; } - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { ClassMember::WriteToStream(prefix, final, out); @@ -147,22 +146,18 @@ enum class ClassQualifier { None, Static }; class ClassDefinition : public ClassMember { public: - static bool WriteJavaFile(const ClassDefinition* def, - const StringPiece& package, bool final, - std::ostream* out); + static bool WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package, + bool final, std::ostream* out); - ClassDefinition(const StringPiece& name, ClassQualifier qualifier, - bool createIfEmpty) - : name_(name.ToString()), - qualifier_(qualifier), - create_if_empty_(createIfEmpty) {} + ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty) + : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {} void AddMember(std::unique_ptr<ClassMember> member) { members_.push_back(std::move(member)); } bool empty() const override; - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override; private: diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 6e7c707847b9..b71dc485633b 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -23,6 +23,7 @@ #include <tuple> #include "android-base/logging.h" +#include "androidfw/StringPiece.h" #include "NameMangler.h" #include "Resource.h" @@ -32,7 +33,8 @@ #include "java/AnnotationProcessor.h" #include "java/ClassDefinition.h" #include "process/SymbolTable.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -58,7 +60,7 @@ static bool IsValidSymbol(const StringPiece& symbol) { * Replace those with '_'. */ static std::string Transform(const StringPiece& symbol) { - std::string output = symbol.ToString(); + std::string output = symbol.to_string(); for (char& c : output) { if (c == '.' || c == '-') { c = '_'; diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h index 190e73b66b9e..5cf556ea5707 100644 --- a/tools/aapt2/java/JavaClassGenerator.h +++ b/tools/aapt2/java/JavaClassGenerator.h @@ -20,10 +20,11 @@ #include <ostream> #include <string> +#include "androidfw/StringPiece.h" + #include "ResourceTable.h" #include "ResourceValues.h" #include "process/IResourceTableConsumer.h" -#include "util/StringPiece.h" namespace aapt { @@ -69,22 +70,20 @@ class JavaClassGenerator { * We need to generate these symbols in a separate file. * Returns true on success. */ - bool Generate(const StringPiece& packageNameToGenerate, std::ostream* out); + bool Generate(const android::StringPiece& packageNameToGenerate, std::ostream* out); - bool Generate(const StringPiece& packageNameToGenerate, - const StringPiece& outputPackageName, std::ostream* out); + bool Generate(const android::StringPiece& packageNameToGenerate, + const android::StringPiece& outputPackageName, std::ostream* out); const std::string& getError() const; private: - bool AddMembersToTypeClass(const StringPiece& packageNameToGenerate, - const ResourceTablePackage* package, - const ResourceTableType* type, + bool AddMembersToTypeClass(const android::StringPiece& packageNameToGenerate, + const ResourceTablePackage* package, const ResourceTableType* type, ClassDefinition* outTypeClassDef); - void AddMembersToStyleableClass(const StringPiece& packageNameToGenerate, - const std::string& entryName, - const Styleable* styleable, + void AddMembersToStyleableClass(const android::StringPiece& packageNameToGenerate, + const std::string& entryName, const Styleable* styleable, ClassDefinition* outStyleableClassDef); bool SkipSymbol(SymbolState state); diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp index 3d3d24e6aab5..55c5cb26892f 100644 --- a/tools/aapt2/java/JavaClassGenerator_test.cpp +++ b/tools/aapt2/java/JavaClassGenerator_test.cpp @@ -22,6 +22,8 @@ #include "test/Test.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) { diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp index db84f295db2a..de8e59aed6da 100644 --- a/tools/aapt2/java/ManifestClassGenerator.cpp +++ b/tools/aapt2/java/ManifestClassGenerator.cpp @@ -24,6 +24,8 @@ #include "util/Maybe.h" #include "xml/XmlDom.h" +using android::StringPiece; + namespace aapt { static Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag, diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp index 5518fe2cae37..b029b20bcf15 100644 --- a/tools/aapt2/jni/aapt2_jni.cpp +++ b/tools/aapt2/jni/aapt2_jni.cpp @@ -26,6 +26,8 @@ #include "util/Util.h" +using android::StringPiece; + namespace aapt { extern int Compile(const std::vector<StringPiece> &args); extern int Link(const std::vector<StringPiece> &args); @@ -65,9 +67,8 @@ static std::vector<ScopedUtfChars> list_to_utfchars(JNIEnv *env, jobject obj) { * The returned pieces can only be used while the original ones have not been * destroyed. */ -static std::vector<aapt::StringPiece> extract_pieces( - const std::vector<ScopedUtfChars> &strings) { - std::vector<aapt::StringPiece> pieces; +static std::vector<StringPiece> extract_pieces(const std::vector<ScopedUtfChars> &strings) { + std::vector<StringPiece> pieces; std::for_each( strings.begin(), strings.end(), @@ -80,8 +81,7 @@ JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile( JNIEnv *env, jclass aapt_obj, jobject arguments_obj) { std::vector<ScopedUtfChars> compile_args_jni = list_to_utfchars(env, arguments_obj); - std::vector<aapt::StringPiece> compile_args = - extract_pieces(compile_args_jni); + std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni); aapt::Compile(compile_args); } @@ -89,7 +89,7 @@ JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink( JNIEnv *env, jclass aapt_obj, jobject arguments_obj) { std::vector<ScopedUtfChars> link_args_jni = list_to_utfchars(env, arguments_obj); - std::vector<aapt::StringPiece> link_args = extract_pieces(link_args_jni); + std::vector<StringPiece> link_args = extract_pieces(link_args_jni); aapt::Link(link_args); } diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp index b525758004f0..c3ce0760f554 100644 --- a/tools/aapt2/link/Link.cpp +++ b/tools/aapt2/link/Link.cpp @@ -23,6 +23,7 @@ #include "android-base/errors.h" #include "android-base/file.h" +#include "androidfw/StringPiece.h" #include "google/protobuf/io/coded_stream.h" #include "AppInfo.h" @@ -51,9 +52,9 @@ #include "split/TableSplitter.h" #include "unflatten/BinaryResourceParser.h" #include "util/Files.h" -#include "util/StringPiece.h" #include "xml/XmlDom.h" +using android::StringPiece; using ::google::protobuf::io::CopyingOutputStreamAdaptor; namespace aapt { @@ -121,7 +122,7 @@ class LinkContext : public IAaptContext { } void SetCompilationPackage(const StringPiece& package_name) { - compilation_package_ = package_name.ToString(); + compilation_package_ = package_name.to_string(); } uint8_t GetPackageId() override { return package_id_; } @@ -2011,14 +2012,14 @@ int Link(const std::vector<StringPiece>& args) { for (std::string& extra_package : extra_java_packages) { // A given package can actually be a colon separated list of packages. for (StringPiece package : util::Split(extra_package, ':')) { - options.extra_java_packages.insert(package.ToString()); + options.extra_java_packages.insert(package.to_string()); } } if (product_list) { for (StringPiece product : util::Tokenize(product_list.value(), ',')) { if (product != "" && product != "default") { - options.products.insert(product.ToString()); + options.products.insert(product.to_string()); } } } diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 4185937e6e38..e5eaf2fe62a8 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -25,6 +25,8 @@ #include "xml/XmlActionExecutor.h" #include "xml/XmlDom.h" +using android::StringPiece; + namespace aapt { /** @@ -293,7 +295,7 @@ static bool RenameManifestPackage(const StringPiece& package_override, CHECK(attr != nullptr); std::string original_package = std::move(attr->value); - attr->value = package_override.ToString(); + attr->value = package_override.to_string(); FullyQualifiedClassNameVisitor visitor(original_package); manifest_el->Accept(&visitor); diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index fc6970c8c5bd..12a304a39f4b 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -18,6 +18,8 @@ #include "test/Test.h" +using android::StringPiece; + namespace aapt { struct ManifestFixerTest : public ::testing::Test { diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index be787b2727ad..ea68b61f89c4 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -30,6 +30,8 @@ #include "util/Util.h" #include "xml/XmlUtil.h" +using android::StringPiece; + namespace aapt { namespace { @@ -192,8 +194,7 @@ class EmptyDeclStack : public xml::IPackageDeclStack { const StringPiece& alias, const StringPiece& local_package) const override { if (alias.empty()) { - return xml::ExtractedPackage{local_package.ToString(), - true /* private */}; + return xml::ExtractedPackage{local_package.to_string(), true /* private */}; } return {}; } diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index d808da31d3b3..7e7b9fb86948 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -24,6 +24,8 @@ #include "ValueVisitor.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table, @@ -351,9 +353,8 @@ std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile( const std::string& package, const FileReference& file_ref) { StringPiece prefix, entry, suffix; if (util::ExtractResFilePathParts(*file_ref.path, &prefix, &entry, &suffix)) { - std::string mangled_entry = - NameMangler::MangleEntry(package, entry.ToString()); - std::string newPath = prefix.ToString() + mangled_entry + suffix.ToString(); + std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string()); + std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string(); std::unique_ptr<FileReference> new_file_ref = util::make_unique<FileReference>( master_table_->string_pool.MakeRef(newPath)); diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h index 4ab83c3f2de3..c96b1b0b4dfb 100644 --- a/tools/aapt2/link/TableMerger.h +++ b/tools/aapt2/link/TableMerger.h @@ -96,8 +96,8 @@ class TableMerger { * An io::IFileCollection is needed in order to find the referenced Files and * process them. */ - bool MergeAndMangle(const Source& src, const StringPiece& package, - ResourceTable* table, io::IFileCollection* collection); + bool MergeAndMangle(const Source& src, const android::StringPiece& package, ResourceTable* table, + io::IFileCollection* collection); /** * Merges a compiled file that belongs to this same or empty package. This is diff --git a/tools/aapt2/link/VersionCollapser_test.cpp b/tools/aapt2/link/VersionCollapser_test.cpp index 1b5592f717d9..44babb21ae6e 100644 --- a/tools/aapt2/link/VersionCollapser_test.cpp +++ b/tools/aapt2/link/VersionCollapser_test.cpp @@ -18,6 +18,8 @@ #include "test/Test.h" +using android::StringPiece; + namespace aapt { static std::unique_ptr<ResourceTable> BuildTableWithConfigs( diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index 767384d8d956..1a3da73b8ce0 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -25,6 +25,8 @@ #include "ValueVisitor.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { void SymbolTable::AppendSource(std::unique_ptr<ISymbolSource> source) { diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h index 25f756522580..cf597bb4e679 100644 --- a/tools/aapt2/process/SymbolTable.h +++ b/tools/aapt2/process/SymbolTable.h @@ -154,7 +154,7 @@ class AssetManagerSymbolSource : public ISymbolSource { public: AssetManagerSymbolSource() = default; - bool AddAssetPath(const StringPiece& path); + bool AddAssetPath(const android::StringPiece& path); std::unique_ptr<SymbolTable::Symbol> FindByName( const ResourceName& name) override; diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp index 0d0e46da4ec8..7230b55e10e3 100644 --- a/tools/aapt2/proto/TableProtoSerializer.cpp +++ b/tools/aapt2/proto/TableProtoSerializer.cpp @@ -22,7 +22,7 @@ #include "proto/ProtoSerialize.h" #include "util/BigBuffer.h" -#include <android-base/logging.h> +#include "android-base/logging.h" using google::protobuf::io::CodedOutputStream; using google::protobuf::io::CodedInputStream; @@ -239,7 +239,7 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { if (type->id) { pb_type->set_id(type->id.value()); } - pb_type->set_name(ToString(type->type).ToString()); + pb_type->set_name(ToString(type->type).to_string()); for (auto& entry : type->entries) { pb::Entry* pb_entry = pb_type->add_entries(); diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp index 7aad86fa7257..38cfd2e61054 100644 --- a/tools/aapt2/split/TableSplitter.cpp +++ b/tools/aapt2/split/TableSplitter.cpp @@ -21,6 +21,7 @@ #include <set> #include <unordered_map> #include <vector> + #include "android-base/logging.h" #include "ConfigDescription.h" diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index 9377306dc1b6..6888cf32fab8 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -37,95 +37,86 @@ class ResourceTableBuilder { StringPool* string_pool() { return &table_->string_pool; } - ResourceTableBuilder& SetPackageId(const StringPiece& package_name, - uint8_t id) { + ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id) { ResourceTablePackage* package = table_->CreatePackage(package_name, id); CHECK(package != nullptr); return *this; } - ResourceTableBuilder& AddSimple(const StringPiece& name, - const ResourceId& id = {}) { + ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {}) { return AddValue(name, id, util::make_unique<Id>()); } - ResourceTableBuilder& AddSimple(const StringPiece& name, - const ConfigDescription& config, + ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ConfigDescription& config, const ResourceId& id = {}) { return AddValue(name, config, id, util::make_unique<Id>()); } - ResourceTableBuilder& AddReference(const StringPiece& name, - const StringPiece& ref) { + ResourceTableBuilder& AddReference(const android::StringPiece& name, + const android::StringPiece& ref) { return AddReference(name, {}, ref); } - ResourceTableBuilder& AddReference(const StringPiece& name, - const ResourceId& id, - const StringPiece& ref) { + ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id, + const android::StringPiece& ref) { return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref))); } - ResourceTableBuilder& AddString(const StringPiece& name, - const StringPiece& str) { + ResourceTableBuilder& AddString(const android::StringPiece& name, + const android::StringPiece& str) { return AddString(name, {}, str); } - ResourceTableBuilder& AddString(const StringPiece& name, const ResourceId& id, - const StringPiece& str) { + ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id, + const android::StringPiece& str) { return AddValue( name, id, util::make_unique<String>(table_->string_pool.MakeRef(str))); } - ResourceTableBuilder& AddString(const StringPiece& name, const ResourceId& id, + ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id, const ConfigDescription& config, - const StringPiece& str) { + const android::StringPiece& str) { return AddValue(name, config, id, util::make_unique<String>( table_->string_pool.MakeRef(str))); } - ResourceTableBuilder& AddFileReference(const StringPiece& name, - const StringPiece& path) { + ResourceTableBuilder& AddFileReference(const android::StringPiece& name, + const android::StringPiece& path) { return AddFileReference(name, {}, path); } - ResourceTableBuilder& AddFileReference(const StringPiece& name, - const ResourceId& id, - const StringPiece& path) { + ResourceTableBuilder& AddFileReference(const android::StringPiece& name, const ResourceId& id, + const android::StringPiece& path) { return AddValue(name, id, util::make_unique<FileReference>( table_->string_pool.MakeRef(path))); } - ResourceTableBuilder& AddFileReference(const StringPiece& name, - const StringPiece& path, + ResourceTableBuilder& AddFileReference(const android::StringPiece& name, + const android::StringPiece& path, const ConfigDescription& config) { return AddValue(name, config, {}, util::make_unique<FileReference>( table_->string_pool.MakeRef(path))); } - ResourceTableBuilder& AddValue(const StringPiece& name, - std::unique_ptr<Value> value) { + ResourceTableBuilder& AddValue(const android::StringPiece& name, std::unique_ptr<Value> value) { return AddValue(name, {}, std::move(value)); } - ResourceTableBuilder& AddValue(const StringPiece& name, const ResourceId& id, + ResourceTableBuilder& AddValue(const android::StringPiece& name, const ResourceId& id, std::unique_ptr<Value> value) { return AddValue(name, {}, id, std::move(value)); } - ResourceTableBuilder& AddValue(const StringPiece& name, - const ConfigDescription& config, - const ResourceId& id, - std::unique_ptr<Value> value) { + ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config, + const ResourceId& id, std::unique_ptr<Value> value) { ResourceName res_name = ParseNameOrDie(name); CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value), &diagnostics_)); return *this; } - ResourceTableBuilder& SetSymbolState(const StringPiece& name, - const ResourceId& id, + ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id, SymbolState state) { ResourceName res_name = ParseNameOrDie(name); Symbol symbol; @@ -144,8 +135,8 @@ class ResourceTableBuilder { std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>(); }; -inline std::unique_ptr<Reference> BuildReference( - const StringPiece& ref, const Maybe<ResourceId>& id = {}) { +inline std::unique_ptr<Reference> BuildReference(const android::StringPiece& ref, + const Maybe<ResourceId>& id = {}) { std::unique_ptr<Reference> reference = util::make_unique<Reference>(ParseNameOrDie(ref)); reference->id = id; @@ -174,7 +165,7 @@ class ValueBuilder { return *this; } - ValueBuilder& SetComment(const StringPiece& str) { + ValueBuilder& SetComment(const android::StringPiece& str) { value_->SetComment(str); return *this; } @@ -199,7 +190,7 @@ class AttributeBuilder { return *this; } - AttributeBuilder& AddItem(const StringPiece& name, uint32_t value) { + AttributeBuilder& AddItem(const android::StringPiece& name, uint32_t value) { attr_->symbols.push_back(Attribute::Symbol{ Reference(ResourceName({}, ResourceType::kId, name)), value}); return *this; @@ -217,18 +208,18 @@ class StyleBuilder { public: StyleBuilder() = default; - StyleBuilder& SetParent(const StringPiece& str) { + StyleBuilder& SetParent(const android::StringPiece& str) { style_->parent = Reference(ParseNameOrDie(str)); return *this; } - StyleBuilder& AddItem(const StringPiece& str, std::unique_ptr<Item> value) { + StyleBuilder& AddItem(const android::StringPiece& str, std::unique_ptr<Item> value) { style_->entries.push_back( Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)}); return *this; } - StyleBuilder& AddItem(const StringPiece& str, const ResourceId& id, + StyleBuilder& AddItem(const android::StringPiece& str, const ResourceId& id, std::unique_ptr<Item> value) { AddItem(str, std::move(value)); style_->entries.back().key.id = id; @@ -247,8 +238,7 @@ class StyleableBuilder { public: StyleableBuilder() = default; - StyleableBuilder& AddItem(const StringPiece& str, - const Maybe<ResourceId>& id = {}) { + StyleableBuilder& AddItem(const android::StringPiece& str, const Maybe<ResourceId>& id = {}) { styleable_->entries.push_back(Reference(ParseNameOrDie(str))); styleable_->entries.back().id = id; return *this; @@ -262,7 +252,7 @@ class StyleableBuilder { std::unique_ptr<Styleable> styleable_ = util::make_unique<Styleable>(); }; -inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const StringPiece& str) { +inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str) { std::stringstream in; in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str; StdErrDiagnostics diag; @@ -273,7 +263,7 @@ inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const StringPiece& str) { } inline std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName( - IAaptContext* context, const StringPiece& str) { + IAaptContext* context, const android::StringPiece& str) { std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str); doc->file.name.package = context->GetCompilationPackage(); return doc; diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index 36892017f2d3..248921f3afea 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -21,6 +21,7 @@ #include "android-base/logging.h" #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "gtest/gtest.h" #include "ConfigDescription.h" @@ -30,7 +31,6 @@ #include "ValueVisitor.h" #include "io/File.h" #include "process/IResourceTableConsumer.h" -#include "util/StringPiece.h" // // GTEST 1.7 doesn't explicitly cast to bool, which causes explicit operators to @@ -68,23 +68,22 @@ inline IDiagnostics* GetDiagnostics() { return &diag; } -inline ResourceName ParseNameOrDie(const StringPiece& str) { +inline ResourceName ParseNameOrDie(const android::StringPiece& str) { ResourceNameRef ref; CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name"; return ref.ToResourceName(); } -inline ConfigDescription ParseConfigOrDie(const StringPiece& str) { +inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) { ConfigDescription config; CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration"; return config; } template <typename T> -T* GetValueForConfigAndProduct(ResourceTable* table, - const StringPiece& res_name, +T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name, const ConfigDescription& config, - const StringPiece& product) { + const android::StringPiece& product) { Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name)); if (result) { @@ -98,19 +97,19 @@ T* GetValueForConfigAndProduct(ResourceTable* table, } template <typename T> -T* GetValueForConfig(ResourceTable* table, const StringPiece& res_name, +T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name, const ConfigDescription& config) { return GetValueForConfigAndProduct<T>(table, res_name, config, {}); } template <typename T> -T* GetValue(ResourceTable* table, const StringPiece& res_name) { +T* GetValue(ResourceTable* table, const android::StringPiece& res_name) { return GetValueForConfig<T>(table, res_name, {}); } class TestFile : public io::IFile { public: - explicit TestFile(const StringPiece& path) : source_(path) {} + explicit TestFile(const android::StringPiece& path) : source_(path) {} std::unique_ptr<io::IData> OpenAsData() override { return {}; } diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h index 7986329ab640..63e5f1628581 100644 --- a/tools/aapt2/test/Context.h +++ b/tools/aapt2/test/Context.h @@ -70,8 +70,8 @@ class Context : public IAaptContext { class ContextBuilder { public: - ContextBuilder& SetCompilationPackage(const StringPiece& package) { - context_->compilation_package_ = package.ToString(); + ContextBuilder& SetCompilationPackage(const android::StringPiece& package) { + context_->compilation_package_ = package.to_string(); return *this; } @@ -103,9 +103,8 @@ class ContextBuilder { class StaticSymbolSourceBuilder { public: - StaticSymbolSourceBuilder& AddPublicSymbol( - const StringPiece& name, ResourceId id, - std::unique_ptr<Attribute> attr = {}) { + StaticSymbolSourceBuilder& AddPublicSymbol(const android::StringPiece& name, ResourceId id, + std::unique_ptr<Attribute> attr = {}) { std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(id, std::move(attr), true); symbol_source_->name_map_[ParseNameOrDie(name)] = symbol.get(); @@ -114,7 +113,7 @@ class StaticSymbolSourceBuilder { return *this; } - StaticSymbolSourceBuilder& AddSymbol(const StringPiece& name, ResourceId id, + StaticSymbolSourceBuilder& AddSymbol(const android::StringPiece& name, ResourceId id, std::unique_ptr<Attribute> attr = {}) { std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(id, std::move(attr), false); diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp index f034607ea8f5..aa840e2e3c8d 100644 --- a/tools/aapt2/util/Files.cpp +++ b/tools/aapt2/util/Files.cpp @@ -35,6 +35,8 @@ #include <direct.h> #endif +using android::StringPiece; + namespace aapt { namespace file { @@ -72,10 +74,9 @@ FileType GetFileType(const StringPiece& path) { inline static int MkdirImpl(const StringPiece& path) { #ifdef _WIN32 - return _mkdir(path.ToString().c_str()); + return _mkdir(path.to_string().c_str()); #else - return mkdir(path.ToString().c_str(), - S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP); + return mkdir(path.to_string().c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP); #endif } @@ -184,7 +185,7 @@ bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_arglist, std::string* out_error) { std::string contents; - if (!android::base::ReadFileToString(path.ToString(), &contents)) { + if (!android::base::ReadFileToString(path.to_string(), &contents)) { if (out_error) *out_error = "failed to read argument-list file"; return false; } @@ -192,7 +193,7 @@ bool AppendArgsFromFile(const StringPiece& path, for (StringPiece line : util::Tokenize(contents, ' ')) { line = util::TrimWhitespace(line); if (!line.empty()) { - out_arglist->push_back(line.ToString()); + out_arglist->push_back(line.to_string()); } } return true; diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h index a157dbd80893..95c492f3b3af 100644 --- a/tools/aapt2/util/Files.h +++ b/tools/aapt2/util/Files.h @@ -22,12 +22,12 @@ #include <vector> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "utils/FileMap.h" #include "Diagnostics.h" #include "Maybe.h" #include "Source.h" -#include "util/StringPiece.h" namespace aapt { namespace file { @@ -50,51 +50,49 @@ enum class FileType { kSocket, }; -FileType GetFileType(const StringPiece& path); +FileType GetFileType(const android::StringPiece& path); /* * Appends a path to `base`, separated by the directory separator. */ -void AppendPath(std::string* base, StringPiece part); +void AppendPath(std::string* base, android::StringPiece part); /* * Makes all the directories in `path`. The last element in the path * is interpreted as a directory. */ -bool mkdirs(const StringPiece& path); +bool mkdirs(const android::StringPiece& path); /** * Returns all but the last part of the path. */ -StringPiece GetStem(const StringPiece& path); +android::StringPiece GetStem(const android::StringPiece& path); /** * Returns the last part of the path with extension. */ -StringPiece GetFilename(const StringPiece& path); +android::StringPiece GetFilename(const android::StringPiece& path); /** * Returns the extension of the path. This is the entire string after * the first '.' of the last part of the path. */ -StringPiece GetExtension(const StringPiece& path); +android::StringPiece GetExtension(const android::StringPiece& path); /** * Converts a package name (com.android.app) to a path: com/android/app */ -std::string PackageToPath(const StringPiece& package); +std::string PackageToPath(const android::StringPiece& package); /** * Creates a FileMap for the file at path. */ -Maybe<android::FileMap> MmapPath(const StringPiece& path, - std::string* out_error); +Maybe<android::FileMap> MmapPath(const android::StringPiece& path, std::string* out_error); /** * Reads the file at path and appends each line to the outArgList vector. */ -bool AppendArgsFromFile(const StringPiece& path, - std::vector<std::string>* out_arglist, +bool AppendArgsFromFile(const android::StringPiece& path, std::vector<std::string>* out_arglist, std::string* out_error); /* @@ -120,7 +118,7 @@ class FileFilter { * - Otherwise the full string is matched. * - match is not case-sensitive. */ - bool SetPattern(const StringPiece& pattern); + bool SetPattern(const android::StringPiece& pattern); /** * Applies the filter, returning true for pass, false for fail. diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp index d5c0c8a7a5fe..cf2232254ec4 100644 --- a/tools/aapt2/util/Util.cpp +++ b/tools/aapt2/util/Util.cpp @@ -15,9 +15,6 @@ */ #include "util/Util.h" -#include "util/BigBuffer.h" -#include "util/Maybe.h" -#include "util/StringPiece.h" #include <utils/Unicode.h> #include <algorithm> @@ -25,6 +22,14 @@ #include <string> #include <vector> +#include "androidfw/StringPiece.h" + +#include "util/BigBuffer.h" +#include "util/Maybe.h" + +using android::StringPiece; +using android::StringPiece16; + namespace aapt { namespace util { @@ -36,7 +41,7 @@ static std::vector<std::string> SplitAndTransform( StringPiece::const_iterator current; do { current = std::find(start, end, sep); - parts.emplace_back(str.substr(start, current).ToString()); + parts.emplace_back(str.substr(start, current).to_string()); if (f) { std::string& part = parts.back(); std::transform(part.begin(), part.end(), part.begin(), f); @@ -162,7 +167,7 @@ Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, } if (util::IsJavaClassName(classname)) { - return classname.ToString(); + return classname.to_string(); } if (package.empty()) { diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h index 05e9cc5d28ca..f8fa80ed7d66 100644 --- a/tools/aapt2/util/Util.h +++ b/tools/aapt2/util/Util.h @@ -24,11 +24,11 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "utils/ByteOrder.h" #include "util/BigBuffer.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #ifdef _WIN32 // TODO(adamlesinski): remove once http://b/32447322 is resolved. @@ -44,26 +44,24 @@ namespace aapt { namespace util { -std::vector<std::string> Split(const StringPiece& str, char sep); -std::vector<std::string> SplitAndLowercase(const StringPiece& str, char sep); +std::vector<std::string> Split(const android::StringPiece& str, char sep); +std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep); /** * Returns true if the string starts with prefix. */ -bool StartsWith(const StringPiece& str, const StringPiece& prefix); +bool StartsWith(const android::StringPiece& str, const android::StringPiece& prefix); /** * Returns true if the string ends with suffix. */ -bool EndsWith(const StringPiece& str, const StringPiece& suffix); +bool EndsWith(const android::StringPiece& str, const android::StringPiece& suffix); /** * Creates a new StringPiece16 that points to a substring * of the original string without leading or trailing whitespace. */ -StringPiece TrimWhitespace(const StringPiece& str); - -StringPiece TrimWhitespace(const StringPiece& str); +android::StringPiece TrimWhitespace(const android::StringPiece& str); /** * UTF-16 isspace(). It basically checks for lower range characters that are @@ -75,18 +73,18 @@ inline bool isspace16(char16_t c) { return c < 0x0080 && isspace(c); } * Returns an iterator to the first character that is not alpha-numeric and that * is not in the allowedChars set. */ -StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( - const StringPiece& str, const StringPiece& allowed_chars); +android::StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( + const android::StringPiece& str, const android::StringPiece& allowed_chars); /** * Tests that the string is a valid Java class name. */ -bool IsJavaClassName(const StringPiece& str); +bool IsJavaClassName(const android::StringPiece& str); /** * Tests that the string is a valid Java package name. */ -bool IsJavaPackageName(const StringPiece& str); +bool IsJavaPackageName(const android::StringPiece& str); /** * Converts the class name to a fully qualified class name from the given @@ -97,8 +95,8 @@ bool IsJavaPackageName(const StringPiece& str); * .a.b --> package.a.b * asdf.adsf --> asdf.adsf */ -Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, - const StringPiece& class_name); +Maybe<std::string> GetFullyQualifiedClassName(const android::StringPiece& package, + const android::StringPiece& class_name); /** * Makes a std::unique_ptr<> with the template parameter inferred by the @@ -138,7 +136,7 @@ template <typename Container> * stored as UTF-8, * the conversion to UTF-16 happens within ResStringPool. */ -StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); +android::StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); /** * Helper method to extract a UTF-8 string from a StringPool. If the string is @@ -159,11 +157,11 @@ std::string GetString(const android::ResStringPool& pool, size_t idx); * which will * break the string interpolation. */ -bool VerifyJavaStringFormat(const StringPiece& str); +bool VerifyJavaStringFormat(const android::StringPiece& str); class StringBuilder { public: - StringBuilder& Append(const StringPiece& str); + StringBuilder& Append(const android::StringPiece& str); const std::string& ToString() const; const std::string& Error() const; @@ -194,8 +192,8 @@ inline StringBuilder::operator bool() const { return error_.empty(); } /** * Converts a UTF8 string to a UTF16 string. */ -std::u16string Utf8ToUtf16(const StringPiece& utf8); -std::string Utf16ToUtf8(const StringPiece16& utf16); +std::u16string Utf8ToUtf16(const android::StringPiece& utf8); +std::string Utf16ToUtf8(const android::StringPiece16& utf16); /** * Writes the entire BigBuffer to the output stream. @@ -220,22 +218,22 @@ class Tokenizer { iterator& operator++(); - StringPiece operator*() { return token_; } + android::StringPiece operator*() { return token_; } bool operator==(const iterator& rhs) const; bool operator!=(const iterator& rhs) const; private: friend class Tokenizer; - iterator(StringPiece s, char sep, StringPiece tok, bool end); + iterator(android::StringPiece s, char sep, android::StringPiece tok, bool end); - StringPiece str_; + android::StringPiece str_; char separator_; - StringPiece token_; + android::StringPiece token_; bool end_; }; - Tokenizer(StringPiece str, char sep); + Tokenizer(android::StringPiece str, char sep); iterator begin() { return begin_; } @@ -246,9 +244,7 @@ class Tokenizer { const iterator end_; }; -inline Tokenizer Tokenize(const StringPiece& str, char sep) { - return Tokenizer(str, sep); -} +inline Tokenizer Tokenize(const android::StringPiece& str, char sep) { return Tokenizer(str, sep); } inline uint16_t HostToDevice16(uint16_t value) { return htods(value); } @@ -267,8 +263,8 @@ inline uint32_t DeviceToHost32(uint32_t value) { return dtohl(value); } * * Returns true if successful. */ -bool ExtractResFilePathParts(const StringPiece& path, StringPiece* out_prefix, - StringPiece* out_entry, StringPiece* out_suffix); +bool ExtractResFilePathParts(const android::StringPiece& path, android::StringPiece* out_prefix, + android::StringPiece* out_entry, android::StringPiece* out_suffix); } // namespace util diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp index cac3de4696ab..e49aee5d50ed 100644 --- a/tools/aapt2/util/Util_test.cpp +++ b/tools/aapt2/util/Util_test.cpp @@ -20,6 +20,8 @@ #include "test/Test.h" +using android::StringPiece; + namespace aapt { TEST(UtilTest, TrimOnlyWhitespace) { diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index 960d3614305e..fab2f19fc0ac 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -29,6 +29,9 @@ #include "XmlPullParser.h" #include "util/Util.h" +using android::StringPiece; +using android::StringPiece16; + namespace aapt { namespace xml { @@ -52,10 +55,10 @@ static void SplitName(const char* name, std::string* out_ns, if (*p == 0) { out_ns->clear(); - *out_name = StringPiece(name).ToString(); + out_name->assign(name); } else { - *out_ns = StringPiece(name, (p - name)).ToString(); - *out_name = StringPiece(p + 1).ToString(); + out_ns->assign(name, (p - name)); + out_name->assign(p + 1); } } @@ -83,11 +86,11 @@ static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); if (prefix) { - ns->namespace_prefix = StringPiece(prefix).ToString(); + ns->namespace_prefix = prefix; } if (uri) { - ns->namespace_uri = StringPiece(uri).ToString(); + ns->namespace_uri = uri; } AddToStack(stack, parser, std::move(ns)); @@ -117,7 +120,7 @@ static void XMLCALL StartElementHandler(void* user_data, const char* name, while (*attrs) { Attribute attribute; SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); - attribute.value = StringPiece(*attrs++).ToString(); + attribute.value = *attrs++; // Insert in sorted order. auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), @@ -153,14 +156,14 @@ static void XMLCALL CharacterDataHandler(void* user_data, const char* s, if (!currentParent->children.empty()) { Node* last_child = currentParent->children.back().get(); if (Text* text = NodeCast<Text>(last_child)) { - text->text += StringPiece(s, len).ToString(); + text->text.append(s, len); return; } } } std::unique_ptr<Text> text = util::make_unique<Text>(); - text->text = StringPiece(s, len).ToString(); + text->text.assign(s, len); AddToStack(stack, parser, std::move(text)); } @@ -495,15 +498,14 @@ void PackageAwareVisitor::Visit(Namespace* ns) { Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias( const StringPiece& alias, const StringPiece& local_package) const { if (alias.empty()) { - return ExtractedPackage{local_package.ToString(), false /* private */}; + return ExtractedPackage{local_package.to_string(), false /* private */}; } const auto rend = package_decls_.rend(); for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) { if (alias == iter->prefix) { if (iter->package.package.empty()) { - return ExtractedPackage{local_package.ToString(), - iter->package.private_namespace}; + return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; } return iter->package; } diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h index 720fe357bfa1..90cdfb6932b1 100644 --- a/tools/aapt2/xml/XmlDom.h +++ b/tools/aapt2/xml/XmlDom.h @@ -22,10 +22,11 @@ #include <string> #include <vector> +#include "androidfw/StringPiece.h" + #include "Diagnostics.h" #include "Resource.h" #include "ResourceValues.h" -#include "util/StringPiece.h" #include "util/Util.h" #include "xml/XmlUtil.h" @@ -100,13 +101,13 @@ class Element : public BaseNode<Element> { std::string name; std::vector<Attribute> attributes; - Attribute* FindAttribute(const StringPiece& ns, const StringPiece& name); - xml::Element* FindChild(const StringPiece& ns, const StringPiece& name); - xml::Element* FindChildWithAttribute(const StringPiece& ns, - const StringPiece& name, - const StringPiece& attr_ns, - const StringPiece& attr_name, - const StringPiece& attr_value); + Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name); + xml::Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name); + xml::Element* FindChildWithAttribute(const android::StringPiece& ns, + const android::StringPiece& name, + const android::StringPiece& attr_ns, + const android::StringPiece& attr_name, + const android::StringPiece& attr_value); std::vector<xml::Element*> GetChildElements(); std::unique_ptr<Node> Clone() override; }; @@ -190,8 +191,7 @@ class PackageAwareVisitor : public Visitor, public IPackageDeclStack { void Visit(Namespace* ns) override; Maybe<ExtractedPackage> TransformPackageAlias( - const StringPiece& alias, - const StringPiece& local_package) const override; + const android::StringPiece& alias, const android::StringPiece& local_package) const override; private: struct PackageDecl { diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp index e59fa86788cd..c2a9c8283a6d 100644 --- a/tools/aapt2/xml/XmlPullParser.cpp +++ b/tools/aapt2/xml/XmlPullParser.cpp @@ -22,6 +22,8 @@ #include "xml/XmlPullParser.h" #include "xml/XmlUtil.h" +using android::StringPiece; + namespace aapt { namespace xml { @@ -136,15 +138,14 @@ const std::string& XmlPullParser::namespace_uri() const { Maybe<ExtractedPackage> XmlPullParser::TransformPackageAlias( const StringPiece& alias, const StringPiece& local_package) const { if (alias.empty()) { - return ExtractedPackage{local_package.ToString(), false /* private */}; + return ExtractedPackage{local_package.to_string(), false /* private */}; } const auto end_iter = package_aliases_.rend(); for (auto iter = package_aliases_.rbegin(); iter != end_iter; ++iter) { if (alias == iter->prefix) { if (iter->package.package.empty()) { - return ExtractedPackage{local_package.ToString(), - iter->package.private_namespace}; + return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; } return iter->package; } @@ -188,19 +189,18 @@ size_t XmlPullParser::attribute_count() const { /** * Extracts the namespace and name of an expanded element or attribute name. */ -static void SplitName(const char* name, std::string& out_ns, - std::string& out_name) { +static void SplitName(const char* name, std::string* out_ns, std::string* out_name) { const char* p = name; while (*p != 0 && *p != kXmlNamespaceSep) { p++; } if (*p == 0) { - out_ns = std::string(); - out_name = name; + out_ns->clear(); + out_name->assign(name); } else { - out_ns = StringPiece(name, (p - name)).ToString(); - out_name = p + 1; + out_ns->assign(name, (p - name)); + out_name->assign(p + 1); } } @@ -224,11 +224,11 @@ void XMLCALL XmlPullParser::StartElementHandler(void* user_data, EventData data = {Event::kStartElement, XML_GetCurrentLineNumber(parser->parser_), parser->depth_++}; - SplitName(name, data.data1, data.data2); + SplitName(name, &data.data1, &data.data2); while (*attrs) { Attribute attribute; - SplitName(*attrs++, attribute.namespace_uri, attribute.name); + SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); attribute.value = *attrs++; // Insert in sorted order. @@ -245,9 +245,8 @@ void XMLCALL XmlPullParser::CharacterDataHandler(void* user_data, const char* s, int len) { XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data); - parser->event_queue_.push( - EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_), - parser->depth_, StringPiece(s, len).ToString()}); + parser->event_queue_.push(EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_), + parser->depth_, std::string(s, len)}); } void XMLCALL XmlPullParser::EndElementHandler(void* user_data, @@ -257,7 +256,7 @@ void XMLCALL XmlPullParser::EndElementHandler(void* user_data, EventData data = {Event::kEndElement, XML_GetCurrentLineNumber(parser->parser_), --(parser->depth_)}; - SplitName(name, data.data1, data.data2); + SplitName(name, &data.data1, &data.data2); // Move the data into the queue (no copy). parser->event_queue_.push(std::move(data)); diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h index ff58d604e35e..cdeeefd13976 100644 --- a/tools/aapt2/xml/XmlPullParser.h +++ b/tools/aapt2/xml/XmlPullParser.h @@ -28,11 +28,11 @@ #include <vector> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "Resource.h" #include "process/IResourceTableConsumer.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #include "xml/XmlUtil.h" namespace aapt { @@ -119,8 +119,7 @@ class XmlPullParser : public IPackageDeclStack { * 'package' will be set to 'defaultPackage'. */ Maybe<ExtractedPackage> TransformPackageAlias( - const StringPiece& alias, - const StringPiece& local_package) const override; + const android::StringPiece& alias, const android::StringPiece& local_package) const override; // // Remaining methods are for retrieving information about attributes @@ -146,8 +145,7 @@ class XmlPullParser : public IPackageDeclStack { const_iterator begin_attributes() const; const_iterator end_attributes() const; size_t attribute_count() const; - const_iterator FindAttribute(StringPiece namespace_uri, - StringPiece name) const; + const_iterator FindAttribute(android::StringPiece namespace_uri, android::StringPiece name) const; private: DISALLOW_COPY_AND_ASSIGN(XmlPullParser); @@ -190,16 +188,16 @@ class XmlPullParser : public IPackageDeclStack { /** * Finds the attribute in the current element within the global namespace. */ -Maybe<StringPiece> FindAttribute(const XmlPullParser* parser, - const StringPiece& name); +Maybe<android::StringPiece> FindAttribute(const XmlPullParser* parser, + const android::StringPiece& name); /** * Finds the attribute in the current element within the global namespace. The * attribute's value * must not be the empty string. */ -Maybe<StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser, - const StringPiece& name); +Maybe<android::StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser, + const android::StringPiece& name); // // Implementation @@ -299,13 +297,13 @@ inline bool XmlPullParser::Attribute::operator!=(const Attribute& rhs) const { } inline XmlPullParser::const_iterator XmlPullParser::FindAttribute( - StringPiece namespace_uri, StringPiece name) const { + android::StringPiece namespace_uri, android::StringPiece name) const { const auto end_iter = end_attributes(); const auto iter = std::lower_bound( begin_attributes(), end_iter, - std::pair<StringPiece, StringPiece>(namespace_uri, name), + std::pair<android::StringPiece, android::StringPiece>(namespace_uri, name), [](const Attribute& attr, - const std::pair<StringPiece, StringPiece>& rhs) -> bool { + const std::pair<android::StringPiece, android::StringPiece>& rhs) -> bool { int cmp = attr.namespace_uri.compare( 0, attr.namespace_uri.size(), rhs.first.data(), rhs.first.size()); if (cmp < 0) return true; diff --git a/tools/aapt2/xml/XmlPullParser_test.cpp b/tools/aapt2/xml/XmlPullParser_test.cpp index 4f18cd218cd9..1cce4850cac5 100644 --- a/tools/aapt2/xml/XmlPullParser_test.cpp +++ b/tools/aapt2/xml/XmlPullParser_test.cpp @@ -18,8 +18,11 @@ #include <sstream> +#include "androidfw/StringPiece.h" + #include "test/Test.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { diff --git a/tools/aapt2/xml/XmlUtil.cpp b/tools/aapt2/xml/XmlUtil.cpp index d00f7f2fe0aa..fb8cee8b5634 100644 --- a/tools/aapt2/xml/XmlUtil.cpp +++ b/tools/aapt2/xml/XmlUtil.cpp @@ -21,6 +21,8 @@ #include "util/Maybe.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { namespace xml { @@ -42,7 +44,7 @@ Maybe<ExtractedPackage> ExtractPackageFromNamespace( if (package.empty()) { return {}; } - return ExtractedPackage{package.ToString(), false /* is_private */}; + return ExtractedPackage{package.to_string(), false /* is_private */}; } else if (util::StartsWith(namespace_uri, kSchemaPrivatePrefix)) { StringPiece schema_prefix = kSchemaPrivatePrefix; @@ -52,7 +54,7 @@ Maybe<ExtractedPackage> ExtractPackageFromNamespace( if (package.empty()) { return {}; } - return ExtractedPackage{package.ToString(), true /* is_private */}; + return ExtractedPackage{package.to_string(), true /* is_private */}; } else if (namespace_uri == kSchemaAuto) { return ExtractedPackage{std::string(), true /* is_private */}; diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h index 536540162d07..1650ac2124ac 100644 --- a/tools/aapt2/xml/XmlUtil.h +++ b/tools/aapt2/xml/XmlUtil.h @@ -74,7 +74,7 @@ Maybe<ExtractedPackage> ExtractPackageFromNamespace( * * http://schemas.android.com/apk/prv/res/<package> */ -std::string BuildPackageNamespace(const StringPiece& package, +std::string BuildPackageNamespace(const android::StringPiece& package, bool private_reference = false); /** @@ -90,7 +90,7 @@ struct IPackageDeclStack { * package declaration. */ virtual Maybe<ExtractedPackage> TransformPackageAlias( - const StringPiece& alias, const StringPiece& local_package) const = 0; + const android::StringPiece& alias, const android::StringPiece& local_package) const = 0; }; /** @@ -100,8 +100,7 @@ struct IPackageDeclStack { * the namespace of the package declaration was private. */ void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack, - const StringPiece& local_package, - Reference* in_ref); + const android::StringPiece& local_package, Reference* in_ref); } // namespace xml } // namespace aapt diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index d32693575ef0..50efc7f7db86 100644 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java @@ -248,17 +248,14 @@ public class FontFamily_Delegate { // ---- delegate methods ---- @LayoutlibDelegate /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex) { - if (thisFontFamily.mBuilderPtr == 0) { - throw new IllegalStateException("Unable to call addFont after freezing."); - } - final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mBuilderPtr); + final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mNativePtr); return delegate != null && delegate.addFont(path, ttcIndex); } // ---- native methods ---- @LayoutlibDelegate - /*package*/ static long nInitBuilder(String lang, int variant) { + /*package*/ static long nCreateFamily(String lang, int variant) { // TODO: support lang. This is required for japanese locale. FontFamily_Delegate delegate = new FontFamily_Delegate(); // variant can be 0, 1 or 2. @@ -273,11 +270,6 @@ public class FontFamily_Delegate { } @LayoutlibDelegate - /*package*/ static long nCreateFamily(long builderPtr) { - return builderPtr; - } - - @LayoutlibDelegate /*package*/ static void nUnrefFamily(long nativePtr) { // Removing the java reference for the object doesn't mean that it's freed for garbage // collection. Typeface_Delegate may still hold a reference for it. @@ -285,22 +277,22 @@ public class FontFamily_Delegate { } @LayoutlibDelegate - /*package*/ static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) { + /*package*/ static boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex) { assert false : "The only client of this method has been overriden."; return false; } @LayoutlibDelegate - /*package*/ static boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font, + /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, int ttcIndex, List<FontListParser.Axis> listOfAxis, int weight, boolean isItalic) { assert false : "The only client of this method has been overriden."; return false; } - static boolean addFont(long builderPtr, final String path, final int weight, + static boolean addFont(long nativeFamily, final String path, final int weight, final boolean isItalic) { - final FontFamily_Delegate delegate = getDelegate(builderPtr); + final FontFamily_Delegate delegate = getDelegate(nativeFamily); if (delegate != null) { if (sFontLocation == null) { delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, isItalic)); @@ -312,8 +304,8 @@ public class FontFamily_Delegate { } @LayoutlibDelegate - /*package*/ static boolean nAddFontFromAsset(long builderPtr, AssetManager mgr, String path) { - FontFamily_Delegate ffd = sManager.getDelegate(builderPtr); + /*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) { + FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily); if (ffd == null) { return false; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java index a554b6da31eb..5cd34f6e000f 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java @@ -212,10 +212,9 @@ public final class Typeface_Delegate { Map<String, ByteBuffer> bufferForPath) { FontFamily fontFamily = new FontFamily(family.lang, family.variant); for (FontListParser.Font font : family.fonts) { - FontFamily_Delegate.addFont(fontFamily.mBuilderPtr, font.fontName, font.weight, + FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.fontName, font.weight, font.isItalic); } - fontFamily.freeze(); return fontFamily; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 663e56d2ccdf..68680d5d8d9c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -40,6 +40,7 @@ import org.xmlpull.v1.XmlPullParserException; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.Notification; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -1820,6 +1821,13 @@ public final class BridgeContext extends Context { } @Override + public ComponentName startServiceInForeground(Intent service, + int id, Notification notification) { + // pass + return null; + } + + @Override public boolean stopService(Intent arg0) { // pass return false; @@ -1832,6 +1840,13 @@ public final class BridgeContext extends Context { } @Override + public ComponentName startServiceInForegroundAsUser(Intent service, + int id, Notification notification, UserHandle user) { + // pass + return null; + } + + @Override public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { // pass return false; diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index 741eb27558ed..7ba86fdc5c30 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -339,8 +339,7 @@ public final class CreateInfo implements ICreateInfo { */ private final static String[] PROMOTED_FIELDS = new String[] { "android.graphics.drawable.VectorDrawable#mVectorState", - "android.view.Choreographer#mLastFrameTimeNanos", - "android.graphics.FontFamily#mBuilderPtr" + "android.view.Choreographer#mLastFrameTimeNanos" }; /** diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 3a4567112704..8cf7a24efb0a 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -709,6 +709,16 @@ public class WifiConfiguration implements Parcelable { /** * @hide + * Indicate that a WifiConfiguration is temporary and should not be saved + * nor considered by AutoJoin. + */ + @SystemApi + public boolean isEphemeral() { + return ephemeral; + } + + /** + * @hide * A hint about whether or not the network represented by this WifiConfiguration * is metered. This is hinted at via the meteredHint bit on DHCP results set in * {@link com.android.server.wifi.WifiStateMachine}, or via a network score in diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java index 71124bb2314f..36e4717c16e4 100755 --- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java +++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java @@ -43,7 +43,7 @@ import java.util.Map; */ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { private static final String TAG = "WifiNetworkScoreCache"; - private static final boolean DBG = false; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); // A Network scorer returns a score in the range [-128, +127] // We treat the lowest possible score as though there were no score, effectively allowing the @@ -83,18 +83,28 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { if (networks == null || networks.isEmpty()) { return; } - Log.d(TAG, "updateScores list size=" + networks.size()); + if (DBG) { + Log.d(TAG, "updateScores list size=" + networks.size()); + } + + boolean changed = false; synchronized(mNetworkCache) { for (ScoredNetwork network : networks) { String networkKey = buildNetworkKey(network); - if (networkKey == null) continue; + if (networkKey == null) { + if (DBG) { + Log.d(TAG, "Failed to build network key for ScoredNetwork" + network); + } + continue; + } mNetworkCache.put(networkKey, network); + changed = true; } } synchronized (mCacheLock) { - if (mListener != null) { + if (mListener != null && changed) { mListener.post(networks); } } @@ -170,25 +180,49 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { return score; } - private ScoredNetwork getScoredNetwork(ScanResult result) { + @Nullable + public ScoredNetwork getScoredNetwork(ScanResult result) { String key = buildNetworkKey(result); if (key == null) return null; - //find it synchronized(mNetworkCache) { ScoredNetwork network = mNetworkCache.get(key); return network; } } - private String buildNetworkKey(ScoredNetwork network) { - if (network == null || network.networkKey == null) return null; - if (network.networkKey.wifiKey == null) return null; - if (network.networkKey.type == NetworkKey.TYPE_WIFI) { - String key = network.networkKey.wifiKey.ssid; + /** Returns the ScoredNetwork for the given key. */ + @Nullable + public ScoredNetwork getScoredNetwork(NetworkKey networkKey) { + String key = buildNetworkKey(networkKey); + if (key == null) { + if (DBG) { + Log.d(TAG, "Could not build key string for Network Key: " + networkKey); + } + return null; + } + synchronized (mNetworkCache) { + return mNetworkCache.get(key); + } + } + + private String buildNetworkKey(ScoredNetwork network) { + if (network == null) { + return null; + } + return buildNetworkKey(network.networkKey); + } + + private String buildNetworkKey(NetworkKey networkKey) { + if (networkKey == null) { + return null; + } + if (networkKey.wifiKey == null) return null; + if (networkKey.type == NetworkKey.TYPE_WIFI) { + String key = networkKey.wifiKey.ssid; if (key == null) return null; - if (network.networkKey.wifiKey.bssid != null) { - key = key + network.networkKey.wifiKey.bssid; + if (networkKey.wifiKey.bssid != null) { + key = key + networkKey.wifiKey.bssid; } return key; } |