Merge "Switch to WifiManager.{start,stop}SoftAp()" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 6b24196..bed93cd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3035,8 +3035,8 @@
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
- field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
- field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android:accounts:key_legacy_not_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android:accounts:key_legacy_visible";
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
@@ -3682,7 +3682,6 @@
method public void onLowMemory();
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
- method public void onMovedToDisplay(int, android.content.res.Configuration);
method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
@@ -3944,7 +3943,7 @@
field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6
- field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82
+ field public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; // 0x82
field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -4031,6 +4030,7 @@
method public static android.app.ActivityOptions makeTaskLaunchBehind();
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public void requestUsageTimeReport(android.app.PendingIntent);
+ method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
method public android.app.ActivityOptions setLaunchDisplayId(int);
method public android.os.Bundle toBundle();
@@ -4818,6 +4818,7 @@
method public void onFragmentDetached(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentPaused(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentPreAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context);
+ method public void onFragmentPreCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
method public void onFragmentResumed(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentSaveInstanceState(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
method public void onFragmentStarted(android.app.FragmentManager, android.app.Fragment);
@@ -4850,11 +4851,10 @@
method public abstract android.app.FragmentTransaction hide(android.app.Fragment);
method public abstract boolean isAddToBackStackAllowed();
method public abstract boolean isEmpty();
- method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable);
method public abstract android.app.FragmentTransaction remove(android.app.Fragment);
method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
- method public abstract android.app.FragmentTransaction setAllowOptimization(boolean);
+ method public abstract android.app.FragmentTransaction runOnCommit(java.lang.Runnable);
method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int);
method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence);
method public abstract android.app.FragmentTransaction setBreadCrumbTitle(int);
@@ -4862,6 +4862,7 @@
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
+ method public abstract android.app.FragmentTransaction setReorderingAllowed(boolean);
method public abstract android.app.FragmentTransaction setTransition(int);
method public abstract android.app.FragmentTransaction setTransitionStyle(int);
method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -4955,7 +4956,7 @@
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 android.app.Instrumentation.ActivityResult onStartActivity(android.content.Intent);
method public final android.app.Activity waitForActivity();
method public final android.app.Activity waitForActivityWithTimeout(long);
}
@@ -4975,7 +4976,7 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
- method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
+ method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -4983,6 +4984,7 @@
method public boolean isKeyguardLocked();
method public boolean isKeyguardSecure();
method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
+ method public void requestDismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback);
}
public static abstract class KeyguardManager.KeyguardDismissCallback {
@@ -6113,17 +6115,6 @@
method public void onDetached();
}
- public final class WallpaperColors implements android.os.Parcelable {
- ctor public WallpaperColors(android.os.Parcel);
- ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
- ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
- method public int describeContents();
- method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
- method public boolean supportsDarkText();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
- }
-
public final class WallpaperInfo implements android.os.Parcelable {
ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6146,8 +6137,6 @@
}
public class WallpaperManager {
- method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
- method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
method public void clear() throws java.io.IOException;
method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6162,7 +6151,6 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
- method public android.app.WallpaperColors getWallpaperColors(int);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6171,7 +6159,6 @@
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
- method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6196,16 +6183,12 @@
field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
}
- public static abstract interface WallpaperManager.OnColorsChangedListener {
- method public abstract void onColorsChanged(android.app.WallpaperColors, int);
- }
-
}
package android.app.admin {
public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
- method public java.lang.String getIpAddress();
+ method public java.net.InetAddress getInetAddress();
method public int getPort();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
@@ -6548,8 +6531,8 @@
public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
method public java.lang.String getHostname();
- method public java.lang.String[] getIpAddresses();
- method public int getIpAddressesCount();
+ method public java.net.InetAddress[] getInetAddresses();
+ method public int getTotalResolvedAddressCount();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
}
@@ -8217,8 +8200,10 @@
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
+ field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
+ field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f
}
public final class ScanSettings implements android.os.Parcelable {
@@ -8289,21 +8274,21 @@
method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
}
- public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+ public final class BluetoothLeDeviceFilter implements android.companion.DeviceFilter {
method public int describeContents();
method public static int getRenamePrefixLengthLimit();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothLeDeviceFilter> CREATOR;
}
- public static final class BluetoothLEDeviceFilter.Builder {
- ctor public BluetoothLEDeviceFilter.Builder();
- method public android.companion.BluetoothLEDeviceFilter build();
- method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int);
- method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+ public static final class BluetoothLeDeviceFilter.Builder {
+ ctor public BluetoothLeDeviceFilter.Builder();
+ method public android.companion.BluetoothLeDeviceFilter build();
+ method public android.companion.BluetoothLeDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
}
public final class CompanionDeviceManager {
@@ -14769,18 +14754,16 @@
field public static final int RGBX_8888 = 2; // 0x2
field public static final int RGB_565 = 4; // 0x4
field public static final int RGB_888 = 3; // 0x3
- field public static final long USAGE0_CPU_READ = 2L; // 0x2L
- field public static final long USAGE0_CPU_READ_OFTEN = 6L; // 0x6L
- field public static final long USAGE0_CPU_WRITE = 32L; // 0x20L
- field public static final long USAGE0_CPU_WRITE_OFTEN = 96L; // 0x60L
- field public static final long USAGE0_GPU_COLOR_OUTPUT = 2048L; // 0x800L
- field public static final long USAGE0_GPU_CUBEMAP = 8192L; // 0x2000L
- field public static final long USAGE0_GPU_DATA_BUFFER = 16384L; // 0x4000L
- field public static final long USAGE0_GPU_SAMPLED_IMAGE = 1024L; // 0x400L
- field public static final long USAGE0_GPU_STORAGE_IMAGE = 3072L; // 0xc00L
- field public static final long USAGE0_PROTECTED_CONTENT = 262144L; // 0x40000L
- field public static final long USAGE0_SENSOR_DIRECT_DATA = 536870912L; // 0x20000000L
- field public static final long USAGE0_VIDEO_ENCODE = 2097152L; // 0x200000L
+ field public static final long USAGE_CPU_READ_OFTEN = 3L; // 0x3L
+ field public static final long USAGE_CPU_READ_RARELY = 2L; // 0x2L
+ field public static final long USAGE_CPU_WRITE_OFTEN = 48L; // 0x30L
+ field public static final long USAGE_CPU_WRITE_RARELY = 32L; // 0x20L
+ field public static final long USAGE_GPU_COLOR_OUTPUT = 512L; // 0x200L
+ field public static final long USAGE_GPU_DATA_BUFFER = 16777216L; // 0x1000000L
+ field public static final long USAGE_GPU_SAMPLED_IMAGE = 256L; // 0x100L
+ field public static final long USAGE_PROTECTED_CONTENT = 16384L; // 0x4000L
+ field public static final long USAGE_SENSOR_DIRECT_DATA = 8388608L; // 0x800000L
+ field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L
}
public final class Sensor {
@@ -34438,7 +34421,6 @@
}
public class FontsContract {
- method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
method public static void requestFonts(android.content.Context, android.provider.FontRequest, android.os.Handler, android.os.CancellationSignal, android.provider.FontsContract.FontRequestCallback);
@@ -37730,12 +37712,10 @@
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
method public android.view.SurfaceHolder getSurfaceHolder();
- method public void invalidateColors();
method public boolean isPreview();
method public boolean isVisible();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
- method public android.app.WallpaperColors onComputeWallpaperColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -45609,7 +45589,6 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method protected void onLayout(boolean, int, int, int, int);
method protected void onMeasure(int, int);
- method public void onMovedToDisplay(int, android.content.res.Configuration);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPointerCaptureChange(boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
@@ -48937,7 +48916,6 @@
method public int getRendererRequestedPriority();
method public deprecated float getScale();
method public android.webkit.WebSettings getSettings();
- method public android.view.textclassifier.TextClassifier getTextClassifier();
method public java.lang.String getTitle();
method public java.lang.String getUrl();
method public android.webkit.WebChromeClient getWebChromeClient();
@@ -48984,7 +48962,6 @@
method public void setNetworkAvailable(boolean);
method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
method public void setRendererPriorityPolicy(int, boolean);
- method public void setTextClassifier(android.view.textclassifier.TextClassifier);
method public deprecated void setVerticalScrollbarOverlay(boolean);
method public void setWebChromeClient(android.webkit.WebChromeClient);
method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index 4bf4e65..a7b3132 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3164,8 +3164,8 @@
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
- field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
- field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android:accounts:key_legacy_not_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android:accounts:key_legacy_visible";
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
@@ -3815,7 +3815,6 @@
method public void onLowMemory();
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
- method public void onMovedToDisplay(int, android.content.res.Configuration);
method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
@@ -4093,7 +4092,7 @@
field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6
- field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82
+ field public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; // 0x82
field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -4180,6 +4179,7 @@
method public static android.app.ActivityOptions makeTaskLaunchBehind();
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public void requestUsageTimeReport(android.app.PendingIntent);
+ method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
method public android.app.ActivityOptions setLaunchDisplayId(int);
method public android.os.Bundle toBundle();
@@ -4986,6 +4986,7 @@
method public void onFragmentDetached(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentPaused(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentPreAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context);
+ method public void onFragmentPreCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
method public void onFragmentResumed(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentSaveInstanceState(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
method public void onFragmentStarted(android.app.FragmentManager, android.app.Fragment);
@@ -5018,11 +5019,10 @@
method public abstract android.app.FragmentTransaction hide(android.app.Fragment);
method public abstract boolean isAddToBackStackAllowed();
method public abstract boolean isEmpty();
- method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable);
method public abstract android.app.FragmentTransaction remove(android.app.Fragment);
method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
- method public abstract android.app.FragmentTransaction setAllowOptimization(boolean);
+ method public abstract android.app.FragmentTransaction runOnCommit(java.lang.Runnable);
method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int);
method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence);
method public abstract android.app.FragmentTransaction setBreadCrumbTitle(int);
@@ -5030,6 +5030,7 @@
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
+ method public abstract android.app.FragmentTransaction setReorderingAllowed(boolean);
method public abstract android.app.FragmentTransaction setTransition(int);
method public abstract android.app.FragmentTransaction setTransitionStyle(int);
method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -5135,7 +5136,7 @@
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 android.app.Instrumentation.ActivityResult onStartActivity(android.content.Intent);
method public final android.app.Activity waitForActivity();
method public final android.app.Activity waitForActivityWithTimeout(long);
}
@@ -5155,7 +5156,7 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
- method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
+ method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -5163,6 +5164,7 @@
method public boolean isKeyguardLocked();
method public boolean isKeyguardSecure();
method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
+ method public void requestDismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback);
}
public static abstract class KeyguardManager.KeyguardDismissCallback {
@@ -6322,17 +6324,6 @@
method public void setPersistentVrModeEnabled(boolean);
}
- public final class WallpaperColors implements android.os.Parcelable {
- ctor public WallpaperColors(android.os.Parcel);
- ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
- ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
- method public int describeContents();
- method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
- method public boolean supportsDarkText();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
- }
-
public final class WallpaperInfo implements android.os.Parcelable {
ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6355,8 +6346,6 @@
}
public class WallpaperManager {
- method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
- method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
method public void clear() throws java.io.IOException;
method public void clear(int) throws java.io.IOException;
method public void clearWallpaper();
@@ -6373,7 +6362,6 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
- method public android.app.WallpaperColors getWallpaperColors(int);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6382,7 +6370,6 @@
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
- method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6410,16 +6397,12 @@
field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
}
- public static abstract interface WallpaperManager.OnColorsChangedListener {
- method public abstract void onColorsChanged(android.app.WallpaperColors, int);
- }
-
}
package android.app.admin {
public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
- method public java.lang.String getIpAddress();
+ method public java.net.InetAddress getInetAddress();
method public int getPort();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
@@ -6796,8 +6779,8 @@
public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
method public java.lang.String getHostname();
- method public java.lang.String[] getIpAddresses();
- method public int getIpAddressesCount();
+ method public java.net.InetAddress[] getInetAddresses();
+ method public int getTotalResolvedAddressCount();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
}
@@ -8707,8 +8690,10 @@
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
+ field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
+ field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f
}
public final class ScanSettings implements android.os.Parcelable {
@@ -8788,21 +8773,21 @@
method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
}
- public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+ public final class BluetoothLeDeviceFilter implements android.companion.DeviceFilter {
method public int describeContents();
method public static int getRenamePrefixLengthLimit();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothLeDeviceFilter> CREATOR;
}
- public static final class BluetoothLEDeviceFilter.Builder {
- ctor public BluetoothLEDeviceFilter.Builder();
- method public android.companion.BluetoothLEDeviceFilter build();
- method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int);
- method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+ public static final class BluetoothLeDeviceFilter.Builder {
+ ctor public BluetoothLeDeviceFilter.Builder();
+ method public android.companion.BluetoothLeDeviceFilter build();
+ method public android.companion.BluetoothLeDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
}
public final class CompanionDeviceManager {
@@ -9893,6 +9878,7 @@
field public static final java.lang.String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST";
field public static final java.lang.String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT";
field public static final java.lang.String ACTION_GET_RESTRICTION_ENTRIES = "android.intent.action.GET_RESTRICTION_ENTRIES";
+ field public static final java.lang.String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
field public static final java.lang.String ACTION_GTALK_SERVICE_CONNECTED = "android.intent.action.GTALK_CONNECTED";
field public static final java.lang.String ACTION_GTALK_SERVICE_DISCONNECTED = "android.intent.action.GTALK_DISCONNECTED";
field public static final java.lang.String ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG";
@@ -15546,18 +15532,16 @@
field public static final int RGBX_8888 = 2; // 0x2
field public static final int RGB_565 = 4; // 0x4
field public static final int RGB_888 = 3; // 0x3
- field public static final long USAGE0_CPU_READ = 2L; // 0x2L
- field public static final long USAGE0_CPU_READ_OFTEN = 6L; // 0x6L
- field public static final long USAGE0_CPU_WRITE = 32L; // 0x20L
- field public static final long USAGE0_CPU_WRITE_OFTEN = 96L; // 0x60L
- field public static final long USAGE0_GPU_COLOR_OUTPUT = 2048L; // 0x800L
- field public static final long USAGE0_GPU_CUBEMAP = 8192L; // 0x2000L
- field public static final long USAGE0_GPU_DATA_BUFFER = 16384L; // 0x4000L
- field public static final long USAGE0_GPU_SAMPLED_IMAGE = 1024L; // 0x400L
- field public static final long USAGE0_GPU_STORAGE_IMAGE = 3072L; // 0xc00L
- field public static final long USAGE0_PROTECTED_CONTENT = 262144L; // 0x40000L
- field public static final long USAGE0_SENSOR_DIRECT_DATA = 536870912L; // 0x20000000L
- field public static final long USAGE0_VIDEO_ENCODE = 2097152L; // 0x200000L
+ field public static final long USAGE_CPU_READ_OFTEN = 3L; // 0x3L
+ field public static final long USAGE_CPU_READ_RARELY = 2L; // 0x2L
+ field public static final long USAGE_CPU_WRITE_OFTEN = 48L; // 0x30L
+ field public static final long USAGE_CPU_WRITE_RARELY = 32L; // 0x20L
+ field public static final long USAGE_GPU_COLOR_OUTPUT = 512L; // 0x200L
+ field public static final long USAGE_GPU_DATA_BUFFER = 16777216L; // 0x1000000L
+ field public static final long USAGE_GPU_SAMPLED_IMAGE = 256L; // 0x100L
+ field public static final long USAGE_PROTECTED_CONTENT = 16384L; // 0x4000L
+ field public static final long USAGE_SENSOR_DIRECT_DATA = 8388608L; // 0x800000L
+ field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L
}
public final class Sensor {
@@ -37428,7 +37412,6 @@
}
public class FontsContract {
- method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
method public static void requestFonts(android.content.Context, android.provider.FontRequest, android.os.Handler, android.os.CancellationSignal, android.provider.FontsContract.FontRequestCallback);
@@ -40988,12 +40971,10 @@
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
method public android.view.SurfaceHolder getSurfaceHolder();
- method public void invalidateColors();
method public boolean isPreview();
method public boolean isVisible();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
- method public android.app.WallpaperColors onComputeWallpaperColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -49193,7 +49174,6 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method protected void onLayout(boolean, int, int, int, int);
method protected void onMeasure(int, int);
- method public void onMovedToDisplay(int, android.content.res.Configuration);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPointerCaptureChange(boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
@@ -52617,7 +52597,6 @@
method public int getRendererRequestedPriority();
method public deprecated float getScale();
method public android.webkit.WebSettings getSettings();
- method public android.view.textclassifier.TextClassifier getTextClassifier();
method public java.lang.String getTitle();
method public java.lang.String getUrl();
method public android.webkit.WebChromeClient getWebChromeClient();
@@ -52665,7 +52644,6 @@
method public void setNetworkAvailable(boolean);
method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
method public void setRendererPriorityPolicy(int, boolean);
- method public void setTextClassifier(android.view.textclassifier.TextClassifier);
method public deprecated void setVerticalScrollbarOverlay(boolean);
method public void setWebChromeClient(android.webkit.WebChromeClient);
method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index f4e2200..a49bc6b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3035,8 +3035,8 @@
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
- field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
- field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android:accounts:key_legacy_not_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android:accounts:key_legacy_visible";
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
@@ -3684,7 +3684,6 @@
method public void onLowMemory();
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
- method public void onMovedToDisplay(int, android.content.res.Configuration);
method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
@@ -3954,7 +3953,7 @@
field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6
- field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82
+ field public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; // 0x82
field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -4041,6 +4040,7 @@
method public static android.app.ActivityOptions makeTaskLaunchBehind();
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public void requestUsageTimeReport(android.app.PendingIntent);
+ method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
method public android.app.ActivityOptions setLaunchDisplayId(int);
method public void setLaunchStackId(int);
@@ -4831,6 +4831,7 @@
method public void onFragmentDetached(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentPaused(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentPreAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context);
+ method public void onFragmentPreCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
method public void onFragmentResumed(android.app.FragmentManager, android.app.Fragment);
method public void onFragmentSaveInstanceState(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
method public void onFragmentStarted(android.app.FragmentManager, android.app.Fragment);
@@ -4863,11 +4864,10 @@
method public abstract android.app.FragmentTransaction hide(android.app.Fragment);
method public abstract boolean isAddToBackStackAllowed();
method public abstract boolean isEmpty();
- method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable);
method public abstract android.app.FragmentTransaction remove(android.app.Fragment);
method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
- method public abstract android.app.FragmentTransaction setAllowOptimization(boolean);
+ method public abstract android.app.FragmentTransaction runOnCommit(java.lang.Runnable);
method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int);
method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence);
method public abstract android.app.FragmentTransaction setBreadCrumbTitle(int);
@@ -4875,6 +4875,7 @@
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
+ method public abstract android.app.FragmentTransaction setReorderingAllowed(boolean);
method public abstract android.app.FragmentTransaction setTransition(int);
method public abstract android.app.FragmentTransaction setTransitionStyle(int);
method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -4968,7 +4969,7 @@
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 android.app.Instrumentation.ActivityResult onStartActivity(android.content.Intent);
method public final android.app.Activity waitForActivity();
method public final android.app.Activity waitForActivityWithTimeout(long);
}
@@ -4988,7 +4989,7 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
- method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
+ method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -4996,6 +4997,7 @@
method public boolean isKeyguardLocked();
method public boolean isKeyguardSecure();
method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
+ method public void requestDismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback);
}
public static abstract class KeyguardManager.KeyguardDismissCallback {
@@ -6133,17 +6135,6 @@
method public void onDetached();
}
- public final class WallpaperColors implements android.os.Parcelable {
- ctor public WallpaperColors(android.os.Parcel);
- ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
- ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
- method public int describeContents();
- method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
- method public boolean supportsDarkText();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
- }
-
public final class WallpaperInfo implements android.os.Parcelable {
ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6166,8 +6157,6 @@
}
public class WallpaperManager {
- method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
- method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
method public void clear() throws java.io.IOException;
method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6182,7 +6171,6 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
- method public android.app.WallpaperColors getWallpaperColors(int);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6191,7 +6179,6 @@
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
- method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6216,16 +6203,12 @@
field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
}
- public static abstract interface WallpaperManager.OnColorsChangedListener {
- method public abstract void onColorsChanged(android.app.WallpaperColors, int);
- }
-
}
package android.app.admin {
public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
- method public java.lang.String getIpAddress();
+ method public java.net.InetAddress getInetAddress();
method public int getPort();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
@@ -6578,8 +6561,8 @@
public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
method public java.lang.String getHostname();
- method public java.lang.String[] getIpAddresses();
- method public int getIpAddressesCount();
+ method public java.net.InetAddress[] getInetAddresses();
+ method public int getTotalResolvedAddressCount();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
}
@@ -8248,8 +8231,10 @@
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
+ field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
+ field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f
}
public final class ScanSettings implements android.os.Parcelable {
@@ -8320,21 +8305,21 @@
method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
}
- public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+ public final class BluetoothLeDeviceFilter implements android.companion.DeviceFilter {
method public int describeContents();
method public static int getRenamePrefixLengthLimit();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothLeDeviceFilter> CREATOR;
}
- public static final class BluetoothLEDeviceFilter.Builder {
- ctor public BluetoothLEDeviceFilter.Builder();
- method public android.companion.BluetoothLEDeviceFilter build();
- method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean);
- method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int);
- method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+ public static final class BluetoothLeDeviceFilter.Builder {
+ ctor public BluetoothLeDeviceFilter.Builder();
+ method public android.companion.BluetoothLeDeviceFilter build();
+ method public android.companion.BluetoothLeDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int);
+ method public android.companion.BluetoothLeDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
}
public final class CompanionDeviceManager {
@@ -14815,18 +14800,16 @@
field public static final int RGBX_8888 = 2; // 0x2
field public static final int RGB_565 = 4; // 0x4
field public static final int RGB_888 = 3; // 0x3
- field public static final long USAGE0_CPU_READ = 2L; // 0x2L
- field public static final long USAGE0_CPU_READ_OFTEN = 6L; // 0x6L
- field public static final long USAGE0_CPU_WRITE = 32L; // 0x20L
- field public static final long USAGE0_CPU_WRITE_OFTEN = 96L; // 0x60L
- field public static final long USAGE0_GPU_COLOR_OUTPUT = 2048L; // 0x800L
- field public static final long USAGE0_GPU_CUBEMAP = 8192L; // 0x2000L
- field public static final long USAGE0_GPU_DATA_BUFFER = 16384L; // 0x4000L
- field public static final long USAGE0_GPU_SAMPLED_IMAGE = 1024L; // 0x400L
- field public static final long USAGE0_GPU_STORAGE_IMAGE = 3072L; // 0xc00L
- field public static final long USAGE0_PROTECTED_CONTENT = 262144L; // 0x40000L
- field public static final long USAGE0_SENSOR_DIRECT_DATA = 536870912L; // 0x20000000L
- field public static final long USAGE0_VIDEO_ENCODE = 2097152L; // 0x200000L
+ field public static final long USAGE_CPU_READ_OFTEN = 3L; // 0x3L
+ field public static final long USAGE_CPU_READ_RARELY = 2L; // 0x2L
+ field public static final long USAGE_CPU_WRITE_OFTEN = 48L; // 0x30L
+ field public static final long USAGE_CPU_WRITE_RARELY = 32L; // 0x20L
+ field public static final long USAGE_GPU_COLOR_OUTPUT = 512L; // 0x200L
+ field public static final long USAGE_GPU_DATA_BUFFER = 16777216L; // 0x1000000L
+ field public static final long USAGE_GPU_SAMPLED_IMAGE = 256L; // 0x100L
+ field public static final long USAGE_PROTECTED_CONTENT = 16384L; // 0x4000L
+ field public static final long USAGE_SENSOR_DIRECT_DATA = 8388608L; // 0x800000L
+ field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L
}
public final class Sensor {
@@ -34574,7 +34557,6 @@
}
public class FontsContract {
- method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
method public static void requestFonts(android.content.Context, android.provider.FontRequest, android.os.Handler, android.os.CancellationSignal, android.provider.FontsContract.FontRequestCallback);
@@ -37925,12 +37907,10 @@
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
method public android.view.SurfaceHolder getSurfaceHolder();
- method public void invalidateColors();
method public boolean isPreview();
method public boolean isVisible();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
- method public android.app.WallpaperColors onComputeWallpaperColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -45977,7 +45957,6 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method protected void onLayout(boolean, int, int, int, int);
method protected void onMeasure(int, int);
- method public void onMovedToDisplay(int, android.content.res.Configuration);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPointerCaptureChange(boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
@@ -49316,7 +49295,6 @@
method public int getRendererRequestedPriority();
method public deprecated float getScale();
method public android.webkit.WebSettings getSettings();
- method public android.view.textclassifier.TextClassifier getTextClassifier();
method public java.lang.String getTitle();
method public java.lang.String getUrl();
method public android.webkit.WebChromeClient getWebChromeClient();
@@ -49363,7 +49341,6 @@
method public void setNetworkAvailable(boolean);
method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
method public void setRendererPriorityPolicy(int, boolean);
- method public void setTextClassifier(android.view.textclassifier.TextClassifier);
method public deprecated void setVerticalScrollbarOverlay(boolean);
method public void setWebChromeClient(android.webkit.WebChromeClient);
method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 06b09c0..a5b37f3 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -376,7 +376,7 @@
* {@link #VISIBILITY_USER_MANAGED_NOT_VISIBLE} is used.
*/
public static final String PACKAGE_NAME_KEY_LEGACY_VISIBLE =
- "android.accounts.key_legacy_visible";
+ "android:accounts:key_legacy_visible";
/**
* Key to set visibility for applications which satisfy one of the following conditions:
@@ -395,7 +395,7 @@
* {@link #VISIBILITY_USER_MANAGED_VISIBLE} is used.
*/
public static final String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE =
- "android.accounts.key_legacy_not_visible";
+ "android:accounts:key_legacy_not_visible";
/**
* @hide
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index cdeca13..ca4b4d5 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -930,12 +930,14 @@
}
/**
- * Gets the current position of the animation in time, which is equal to the current
- * time minus the time that the animation started. An animation that is not yet started will
- * return a value of zero, unless the animation has has its play time set via
- * {@link #setCurrentPlayTime(long)}, in which case it will return the time that was set.
+ * Returns the milliseconds elapsed since the start of the animation.
*
- * @return The current position in time of the animation.
+ * <p>For ongoing animations, this method returns the current progress of the animation in
+ * terms of play time. For an animation that has not yet been started: if the animation has been
+ * seeked to a certain time via {@link #setCurrentPlayTime(long)}, the seeked play time will
+ * be returned; otherwise, this method will return 0.
+ *
+ * @return the current position in time of the animation in milliseconds
*/
public long getCurrentPlayTime() {
if (mSeekState.isActive()) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e621c01..ab4f33d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2172,6 +2172,7 @@
*
* @see #onConfigurationChanged(Configuration)
* @see View#onMovedToDisplay(int, Configuration)
+ * @hide
*/
public void onMovedToDisplay(int displayId, Configuration config) {
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 6e7b750..2230472 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3143,10 +3143,15 @@
* before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK,
* the value of {@link #IMPORTANCE_PERCEPTIBLE} has been fixed.
*
- * @deprecated Use {@link #IMPORTANCE_PERCEPTIBLE} instead.
+ * <p>The system will return this value instead of {@link #IMPORTANCE_PERCEPTIBLE}
+ * on Android versions below {@link Build.VERSION_CODES#O}.
+ *
+ * <p>On Android version {@link Build.VERSION_CODES#O} and later, this value will still be
+ * returned for apps with the target API level below {@link Build.VERSION_CODES#O}.
+ * For apps targeting version {@link Build.VERSION_CODES#O} and later,
+ * the correct value {@link #IMPORTANCE_PERCEPTIBLE} will be returned.
*/
- @Deprecated
- public static final int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130;
+ public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130;
/**
* Constant for {@link #importance}: This process is not something the user
@@ -3160,11 +3165,17 @@
* before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK,
* the value of {@link #IMPORTANCE_CANT_SAVE_STATE} has been fixed.
*
- * @deprecated Use {@link #IMPORTANCE_CANT_SAVE_STATE} instead.
+ * <p>The system will return this value instead of {@link #IMPORTANCE_CANT_SAVE_STATE}
+ * on Android versions below {@link Build.VERSION_CODES#O}.
+ *
+ * <p>On Android version {@link Build.VERSION_CODES#O} after, this value will still be
+ * returned for apps with the target API level below {@link Build.VERSION_CODES#O}.
+ * For apps targeting version {@link Build.VERSION_CODES#O} and later,
+ * the correct value {@link #IMPORTANCE_CANT_SAVE_STATE} will be returned.
+ *
* @hide
*/
- @Deprecated
- public static final int IMPORTANCE_CANT_SAVE_STATE_DEPRECATED = 170;
+ public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170;
/**
* Constant for {@link #importance}: This process is running an
@@ -3244,15 +3255,25 @@
*/
public static @Importance int procStateToImportanceForClient(int procState,
Context clientContext) {
+ return procStateToImportanceForTargetSdk(procState,
+ clientContext.getApplicationInfo().targetSdkVersion);
+ }
+
+ /**
+ * See {@link #procStateToImportanceForClient}.
+ * @hide
+ */
+ public static @Importance int procStateToImportanceForTargetSdk(int procState,
+ int targetSdkVersion) {
final int importance = procStateToImportance(procState);
// For pre O apps, convert to the old, wrong values.
- if (clientContext.getApplicationInfo().targetSdkVersion < VERSION_CODES.O) {
+ if (targetSdkVersion < VERSION_CODES.O) {
switch (importance) {
case IMPORTANCE_PERCEPTIBLE:
- return IMPORTANCE_PERCEPTIBLE_DEPRECATED;
+ return IMPORTANCE_PERCEPTIBLE_PRE_26;
case IMPORTANCE_CANT_SAVE_STATE:
- return IMPORTANCE_CANT_SAVE_STATE_DEPRECATED;
+ return IMPORTANCE_CANT_SAVE_STATE_PRE_26;
}
}
return importance;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 63e8cc6..3eec596 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -211,6 +211,9 @@
private static final String KEY_USAGE_TIME_REPORT = "android:activity.usageTimeReport";
private static final String KEY_ROTATION_ANIMATION_HINT = "android:activity.rotationAnimationHint";
+ private static final String KEY_INSTANT_APP_VERIFICATION_BUNDLE
+ = "android:instantapps.installerbundle";
+
/** @hide */
public static final int ANIM_NONE = 0;
/** @hide */
@@ -264,6 +267,7 @@
private boolean mTaskOverlayCanResume;
private AppTransitionAnimationSpec mAnimSpecs[];
private int mRotationAnimationHint = -1;
+ private Bundle mAppVerificationBundle;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -886,6 +890,7 @@
opts.getBinder(KEY_ANIMATION_FINISHED_LISTENER));
}
mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT);
+ mAppVerificationBundle = opts.getBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE);
}
/**
@@ -1275,6 +1280,9 @@
b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder());
}
b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint);
+ if (mAppVerificationBundle != null) {
+ b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle);
+ }
return b;
}
@@ -1342,6 +1350,30 @@
mRotationAnimationHint = hint;
}
+ /**
+ * Pop the extra verification bundle for the installer.
+ * This removes the bundle from the ActivityOptions to make sure the installer bundle
+ * is only available once.
+ * @hide
+ */
+ public Bundle popAppVerificationBundle() {
+ Bundle out = mAppVerificationBundle;
+ mAppVerificationBundle = null;
+ return out;
+ }
+
+ /**
+ * Set the {@link Bundle} that is provided to the app installer for additional verification
+ * if the call to {@link Context#startActivity} results in an app being installed.
+ *
+ * This Bundle is not provided to any other app besides the installer.
+ */
+ public ActivityOptions setAppVerificationBundle(Bundle bundle) {
+ mAppVerificationBundle = bundle;
+ return this;
+
+ }
+
/** @hide */
@Override
public String toString() {
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index cf274b4..46e6def 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -16,8 +16,6 @@
package android.app;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -45,7 +43,7 @@
final CharSequence mBreadCrumbShortTitleText;
final ArrayList<String> mSharedElementSourceNames;
final ArrayList<String> mSharedElementTargetNames;
- final boolean mAllowOptimization;
+ final boolean mReorderingAllowed;
public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) {
final int numOps = bse.mOps.size();
@@ -75,7 +73,7 @@
mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
mSharedElementSourceNames = bse.mSharedElementSourceNames;
mSharedElementTargetNames = bse.mSharedElementTargetNames;
- mAllowOptimization = bse.mAllowOptimization;
+ mReorderingAllowed = bse.mReorderingAllowed;
}
public BackStackState(Parcel in) {
@@ -90,7 +88,7 @@
mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mSharedElementSourceNames = in.createStringArrayList();
mSharedElementTargetNames = in.createStringArrayList();
- mAllowOptimization = in.readInt() != 0;
+ mReorderingAllowed = in.readInt() != 0;
}
public BackStackRecord instantiate(FragmentManagerImpl fm) {
@@ -133,7 +131,7 @@
bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
bse.mSharedElementSourceNames = mSharedElementSourceNames;
bse.mSharedElementTargetNames = mSharedElementTargetNames;
- bse.mAllowOptimization = mAllowOptimization;
+ bse.mReorderingAllowed = mReorderingAllowed;
bse.bumpBackStackNesting(1);
return bse;
}
@@ -154,7 +152,7 @@
TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
dest.writeStringList(mSharedElementSourceNames);
dest.writeStringList(mSharedElementTargetNames);
- dest.writeInt(mAllowOptimization ? 1 : 0);
+ dest.writeInt(mReorderingAllowed ? 1 : 0);
}
public static final Parcelable.Creator<BackStackState> CREATOR
@@ -218,7 +216,7 @@
String mName;
boolean mCommitted;
int mIndex = -1;
- boolean mAllowOptimization;
+ boolean mReorderingAllowed;
ArrayList<Runnable> mCommitRunnables;
@@ -370,7 +368,7 @@
public BackStackRecord(FragmentManagerImpl manager) {
mManager = manager;
- mAllowOptimization = mManager.getTargetSdk() > Build.VERSION_CODES.N_MR1;
+ mReorderingAllowed = mManager.getTargetSdk() > Build.VERSION_CODES.N_MR1;
}
public int getId() {
@@ -623,7 +621,7 @@
}
@Override
- public FragmentTransaction postOnCommit(Runnable runnable) {
+ public FragmentTransaction runOnCommit(Runnable runnable) {
if (runnable == null) {
throw new IllegalArgumentException("runnable cannot be null");
}
@@ -665,8 +663,8 @@
}
@Override
- public FragmentTransaction setAllowOptimization(boolean allowOptimization) {
- mAllowOptimization = allowOptimization;
+ public FragmentTransaction setReorderingAllowed(boolean reorderingAllowed) {
+ mReorderingAllowed = reorderingAllowed;
return this;
}
@@ -800,11 +798,11 @@
default:
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
- if (!mAllowOptimization && op.cmd != OP_ADD && f != null) {
+ if (!mReorderingAllowed && op.cmd != OP_ADD && f != null) {
mManager.moveFragmentToExpectedState(f);
}
}
- if (!mAllowOptimization) {
+ if (!mReorderingAllowed) {
// Added fragments are added at the end to comply with prior behavior.
mManager.moveToState(mManager.mCurState, true);
}
@@ -859,11 +857,11 @@
default:
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
- if (!mAllowOptimization && op.cmd != OP_REMOVE && f != null) {
+ if (!mReorderingAllowed && op.cmd != OP_REMOVE && f != null) {
mManager.moveFragmentToExpectedState(f);
}
}
- if (!mAllowOptimization && moveToState) {
+ if (!mReorderingAllowed && moveToState) {
mManager.moveToState(mManager.mCurState, true);
}
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 759efdb..c2fd007 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -2417,7 +2417,7 @@
* enabled.
*
* @see Activity#postponeEnterTransition()
- * @see FragmentTransaction#setAllowOptimization(boolean)
+ * @see FragmentTransaction#setReorderingAllowed(boolean)
*/
public void postponeEnterTransition() {
ensureAnimationInfo().mEnterTransitionPostponed = true;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 9e8809a..63c0ef3 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -54,7 +54,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -453,6 +452,18 @@
public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {}
/**
+ * Called right before the fragment's {@link Fragment#onCreate(Bundle)} method is called.
+ * This is a good time to inject any required dependencies or perform other configuration
+ * for the fragment.
+ *
+ * @param fm Host FragmentManager
+ * @param f Fragment changing state
+ * @param savedInstanceState Saved instance bundle from a previous instance
+ */
+ public void onFragmentPreCreated(FragmentManager fm, Fragment f,
+ Bundle savedInstanceState) {}
+
+ /**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onCreate(Bundle)}. This will only happen once for any given
* fragment instance, though the fragment may be attached and detached multiple times.
@@ -682,7 +693,7 @@
String mNoTransactionsBecause;
boolean mHavePendingDeferredStart;
- // Temporary vars for optimizing execution of BackStackRecords:
+ // Temporary vars for removing redundant operations in BackStackRecords:
ArrayList<BackStackRecord> mTmpRecords;
ArrayList<Boolean> mTmpIsPop;
ArrayList<Fragment> mTmpAddedFragments;
@@ -853,7 +864,7 @@
if (executePop) {
mExecutingActions = true;
try {
- optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
+ removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
@@ -1219,6 +1230,7 @@
dispatchOnFragmentAttached(f, mHost.getContext(), false);
if (!f.mRetaining) {
+ dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
f.performCreate(f.mSavedFragmentState);
dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
@@ -2002,7 +2014,7 @@
if (action.generateOps(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
- optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
+ removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
@@ -2032,7 +2044,7 @@
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
- optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
+ removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
@@ -2080,19 +2092,20 @@
}
/**
- * Optimizes BackStackRecord operations. This method merges operations of proximate records
- * that allow optimization. See {@link FragmentTransaction#setAllowOptimization(boolean)}.
+ * Remove redundant BackStackRecord operations and executes them. This method merges operations
+ * of proximate records that allow reordering. See
+ * {@link FragmentTransaction#setReorderingAllowed(boolean)}.
* <p>
* For example, a transaction that adds to the back stack and then another that pops that
- * back stack record will be optimized.
+ * back stack record will be optimized to remove the unnecessary operation.
* <p>
* Likewise, two transactions committed that are executed at the same time will be optimized
- * as well as two pop operations executed together.
+ * to remove the redundant operations as well as two pop operations executed together.
*
* @param records The records pending execution
* @param isRecordPop The direction that these records are being run.
*/
- private void optimizeAndExecuteOps(ArrayList<BackStackRecord> records,
+ private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop) {
if (records == null || records.isEmpty()) {
return;
@@ -2108,24 +2121,25 @@
final int numRecords = records.size();
int startIndex = 0;
for (int recordNum = 0; recordNum < numRecords; recordNum++) {
- final boolean canOptimize = records.get(recordNum).mAllowOptimization;
- if (!canOptimize) {
+ final boolean canReorder = records.get(recordNum).mReorderingAllowed;
+ if (!canReorder) {
// execute all previous transactions
if (startIndex != recordNum) {
executeOpsTogether(records, isRecordPop, startIndex, recordNum);
}
- // execute all unoptimized pop operations together or one add operation
- int optimizeEnd = recordNum + 1;
+ // execute all pop operations that don't allow reordering together or
+ // one add operation
+ int reorderingEnd = recordNum + 1;
if (isRecordPop.get(recordNum)) {
- while (optimizeEnd < numRecords
- && isRecordPop.get(optimizeEnd)
- && !records.get(optimizeEnd).mAllowOptimization) {
- optimizeEnd++;
+ while (reorderingEnd < numRecords
+ && isRecordPop.get(reorderingEnd)
+ && !records.get(reorderingEnd).mReorderingAllowed) {
+ reorderingEnd++;
}
}
- executeOpsTogether(records, isRecordPop, recordNum, optimizeEnd);
- startIndex = optimizeEnd;
- recordNum = optimizeEnd - 1;
+ executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
+ startIndex = reorderingEnd;
+ recordNum = reorderingEnd - 1;
}
}
if (startIndex != numRecords) {
@@ -2134,16 +2148,16 @@
}
/**
- * Optimizes a subset of a list of BackStackRecords, all of which either allow optimization or
- * do not allow optimization.
- * @param records A list of BackStackRecords that are to be optimized
+ * Executes a subset of a list of BackStackRecords, all of which either allow reordering or
+ * do not allow ordering.
+ * @param records A list of BackStackRecords that are to be executed together
* @param isRecordPop The direction that these records are being run.
- * @param startIndex The index of the first record in <code>records</code> to be optimized
- * @param endIndex One more than the final record index in <code>records</code> to optimize.
+ * @param startIndex The index of the first record in <code>records</code> to be executed
+ * @param endIndex One more than the final record index in <code>records</code> to executed.
*/
private void executeOpsTogether(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
- final boolean allowOptimization = records.get(startIndex).mAllowOptimization;
+ final boolean allowReordering = records.get(startIndex).mReorderingAllowed;
boolean addToBackStack = false;
if (mTmpAddedFragments == null) {
mTmpAddedFragments = new ArrayList<>();
@@ -2166,14 +2180,14 @@
}
mTmpAddedFragments.clear();
- if (!allowOptimization) {
+ if (!allowReordering) {
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
false);
}
executeOps(records, isRecordPop, startIndex, endIndex);
int postponeIndex = endIndex;
- if (allowOptimization) {
+ if (allowReordering) {
ArraySet<Fragment> addedFragments = new ArraySet<>();
addAddedFragments(addedFragments);
postponeIndex = postponePostponableTransactions(records, isRecordPop,
@@ -2181,7 +2195,7 @@
makeRemovedFragmentsInvisible(addedFragments);
}
- if (postponeIndex != startIndex && allowOptimization) {
+ if (postponeIndex != startIndex && allowReordering) {
// need to run something now
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex,
postponeIndex, true);
@@ -3273,6 +3287,25 @@
}
}
+ void dispatchOnFragmentPreCreated(Fragment f, Bundle savedInstanceState,
+ boolean onlyRecursive) {
+ if (mParent != null) {
+ FragmentManager parentManager = mParent.getFragmentManager();
+ if (parentManager instanceof FragmentManagerImpl) {
+ ((FragmentManagerImpl) parentManager)
+ .dispatchOnFragmentPreCreated(f, savedInstanceState, true);
+ }
+ }
+ if (mLifecycleCallbacks == null) {
+ return;
+ }
+ for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
+ if (!onlyRecursive || p.second) {
+ p.first.onFragmentPreCreated(this, f, savedInstanceState);
+ }
+ }
+ }
+
void dispatchOnFragmentCreated(Fragment f, Bundle savedInstanceState, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index c938aa6..c910e90 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -6,6 +6,7 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StyleRes;
+import android.os.Bundle;
import android.view.View;
import java.lang.annotation.Retention;
@@ -279,45 +280,57 @@
/**
* Sets whether or not to allow optimizing operations within and across
- * transactions. Optimizing fragment transaction's operations can eliminate
+ * transactions. This will remove redundant operations, eliminating
* operations that cancel. For example, if two transactions are executed
* together, one that adds a fragment A and the next replaces it with fragment B,
* the operations will cancel and only fragment B will be added. That means that
* fragment A may not go through the creation/destruction lifecycle.
* <p>
- * The side effect of optimization is that fragments may have state changes
+ * The side effect of removing redundant operations is that fragments may have state changes
* out of the expected order. For example, one transaction adds fragment A,
- * a second adds fragment B, then a third removes fragment A. Without optimization,
- * fragment B could expect that while it is being created, fragment A will also
+ * a second adds fragment B, then a third removes fragment A. Without removing the redundant
+ * operations, fragment B could expect that while it is being created, fragment A will also
* exist because fragment A will be removed after fragment B was added.
- * With optimization, fragment B cannot expect fragment A to exist when
+ * With removing redundant operations, fragment B cannot expect fragment A to exist when
* it has been created because fragment A's add/remove will be optimized out.
* <p>
+ * It can also reorder the state changes of Fragments to allow for better Transitions.
+ * Added Fragments may have {@link Fragment#onCreate(Bundle)} called before replaced
+ * Fragments have {@link Fragment#onDestroy()} called.
+ * <p>
* The default is {@code false} for applications targeting version
* versions prior to O and {@code true} for applications targeting O and
* later.
*
- * @param allowOptimization {@code true} to enable optimizing operations
- * or {@code false} to disable optimizing
+ * @param reorderingAllowed {@code true} to enable optimizing out redundant operations
+ * or {@code false} to disable optimizing out redundant
* operations on this transaction.
*/
- public abstract FragmentTransaction setAllowOptimization(boolean allowOptimization);
+ public abstract FragmentTransaction setReorderingAllowed(boolean reorderingAllowed);
/**
* Add a Runnable to this transaction that will be run after this transaction has
- * been committed. If fragment transactions are {@link #setAllowOptimization(boolean) optimized}
+ * been committed. If fragment transactions are {@link #setReorderingAllowed(boolean) optimized}
* this may be after other subsequent fragment operations have also taken place, or operations
* in this transaction may have been optimized out due to the presence of a subsequent
* fragment transaction in the batch.
*
- * <p><code>postOnCommit</code> may not be used with transactions
+ *
+ * <p>If a transaction is committed using {@link #commitAllowingStateLoss()} this runnable
+ * may be executed when the FragmentManager is in a state where new transactions may not
+ * be committed without allowing state loss.</p>
+ *
+ * <p><code>runOnCommit</code> may not be used with transactions
* {@link #addToBackStack(String) added to the back stack} as Runnables cannot be persisted
- * with back stack state.</p>
+ * with back stack state. {@link IllegalStateException} will be thrown if
+ * {@link #addToBackStack(String)} has been previously called for this transaction
+ * or if it is called after a call to <code>runOnCommit</code>.</p>
*
* @param runnable Runnable to add
* @return this FragmentTransaction
+ * @throws IllegalStateException if {@link #addToBackStack(String)} has been called
*/
- public abstract FragmentTransaction postOnCommit(Runnable runnable);
+ public abstract FragmentTransaction runOnCommit(Runnable runnable);
/**
* Schedules a commit of this transaction. The commit does
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index b4c6dce..ceb828b 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -34,9 +34,10 @@
import java.util.Map;
/**
- * Contains the Fragment Transition functionality for both optimized and unoptimized
- * Fragment Transactions. With optimized fragment transactions, all Views have been
- * added to the View hierarchy prior to calling startTransitions. With
+ * Contains the Fragment Transition functionality for both ordered and reordered
+ * Fragment Transactions. With reordered fragment transactions, all Views have been
+ * added to the View hierarchy prior to calling startTransitions. With ordered
+ * fragment transactions, Views will be removed and added after calling startTransitions.
*/
class FragmentTransition {
/**
@@ -65,9 +66,9 @@
* {@link Fragment#getSharedElementReturnTransition()} and the entering
* {@link Fragment#getReenterTransition()} will be run.
* <p>
- * With optimized Fragment Transitions, all Views have been added to the
+ * With reordered Fragment Transitions, all Views have been added to the
* View hierarchy prior to calling this method. The incoming Fragment's Views
- * will be INVISIBLE. With unoptimized Fragment Transitions, this method
+ * will be INVISIBLE. With ordered Fragment Transitions, this method
* is called before any change has been made to the hierarchy. That means
* that the added Fragments have not created their Views yet and the hierarchy
* is unknown.
@@ -79,13 +80,13 @@
* part of this transition.
* @param endIndex One past the last index into records and isRecordPop to execute
* as part of this transition.
- * @param isOptimized true if this is an optimized transaction, meaning that the
+ * @param isReordered true if this is a reordered transaction, meaning that the
* Views of incoming fragments have been added. false if the
* transaction has yet to be run and Views haven't been created.
*/
static void startTransitions(FragmentManagerImpl fragmentManager,
ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop,
- int startIndex, int endIndex, boolean isOptimized) {
+ int startIndex, int endIndex, boolean isReordered) {
if (fragmentManager.mCurState < Fragment.CREATED) {
return;
}
@@ -95,9 +96,9 @@
final BackStackRecord record = records.get(i);
final boolean isPop = isRecordPop.get(i);
if (isPop) {
- calculatePopFragments(record, transitioningFragments, isOptimized);
+ calculatePopFragments(record, transitioningFragments, isReordered);
} else {
- calculateFragments(record, transitioningFragments, isOptimized);
+ calculateFragments(record, transitioningFragments, isReordered);
}
}
@@ -111,11 +112,11 @@
FragmentContainerTransition containerTransition = transitioningFragments.valueAt(i);
- if (isOptimized) {
- configureTransitionsOptimized(fragmentManager, containerId,
+ if (isReordered) {
+ configureTransitionsReordered(fragmentManager, containerId,
containerTransition, nonExistentView, nameOverrides);
} else {
- configureTransitionsUnoptimized(fragmentManager, containerId,
+ configureTransitionsOrdered(fragmentManager, containerId,
containerTransition, nonExistentView, nameOverrides);
}
}
@@ -175,7 +176,7 @@
/**
* Configures a transition for a single fragment container for which the transaction was
- * optimized. That means that all Fragment Views have been added and incoming fragment
+ * reordered. That means that all Fragment Views have been added and incoming fragment
* Views are marked invisible.
*
* @param fragmentManager The executing FragmentManagerImpl
@@ -188,7 +189,7 @@
* the final fragment's Views as given in
* {@link FragmentTransaction#addSharedElement(View, String)}.
*/
- private static void configureTransitionsOptimized(FragmentManagerImpl fragmentManager,
+ private static void configureTransitionsReordered(FragmentManagerImpl fragmentManager,
int containerId, FragmentContainerTransition fragments,
View nonExistentView, ArrayMap<String, String> nameOverrides) {
ViewGroup sceneRoot = null;
@@ -208,7 +209,7 @@
Transition enterTransition = getEnterTransition(inFragment, inIsPop);
Transition exitTransition = getExitTransition(outFragment, outIsPop);
- TransitionSet sharedElementTransition = configureSharedElementsOptimized(sceneRoot,
+ TransitionSet sharedElementTransition = configureSharedElementsReordered(sceneRoot,
nonExistentView, nameOverrides, fragments, sharedElementsOut, sharedElementsIn,
enterTransition, exitTransition);
@@ -247,7 +248,7 @@
/**
* Configures a transition for a single fragment container for which the transaction was
- * not optimized. That means that the transaction has not been executed yet, so incoming
+ * ordered. That means that the transaction has not been executed yet, so incoming
* Views are not yet known.
*
* @param fragmentManager The executing FragmentManagerImpl
@@ -260,7 +261,7 @@
* the final fragment's Views as given in
* {@link FragmentTransaction#addSharedElement(View, String)}.
*/
- private static void configureTransitionsUnoptimized(FragmentManagerImpl fragmentManager,
+ private static void configureTransitionsOrdered(FragmentManagerImpl fragmentManager,
int containerId, FragmentContainerTransition fragments,
View nonExistentView, ArrayMap<String, String> nameOverrides) {
ViewGroup sceneRoot = null;
@@ -281,7 +282,7 @@
ArrayList<View> sharedElementsOut = new ArrayList<>();
ArrayList<View> sharedElementsIn = new ArrayList<>();
- TransitionSet sharedElementTransition = configureSharedElementsUnoptimized(sceneRoot,
+ TransitionSet sharedElementTransition = configureSharedElementsOrdered(sceneRoot,
nonExistentView, nameOverrides, fragments, sharedElementsOut, sharedElementsIn,
enterTransition, exitTransition);
@@ -345,7 +346,7 @@
}
/**
- * This method is used for fragment transitions for unoptimized transactions to change the
+ * This method is used for fragment transitions for ordered transactions to change the
* enter and exit transition targets after the call to
* {@link TransitionManager#beginDelayedTransition(ViewGroup, Transition)}. The exit transition
* must ensure that it does not target any Views and the enter transition must start targeting
@@ -448,7 +449,7 @@
}
/**
- * Configures the shared elements of an optimized fragment transaction's transition.
+ * Configures the shared elements of an reordered fragment transaction's transition.
* This retrieves the shared elements of the outgoing and incoming fragments, maps the
* views, and sets up the epicenter on the transitions.
* <p>
@@ -474,7 +475,7 @@
* epicenter
* @return The shared element transition or null if no shared elements exist
*/
- private static TransitionSet configureSharedElementsOptimized(final ViewGroup sceneRoot,
+ private static TransitionSet configureSharedElementsReordered(final ViewGroup sceneRoot,
final View nonExistentView, ArrayMap<String, String> nameOverrides,
final FragmentContainerTransition fragments,
final ArrayList<View> sharedElementsOut,
@@ -576,7 +577,7 @@
}
/**
- * Configures the shared elements of an unoptimized fragment transaction's transition.
+ * Configures the shared elements of an ordered fragment transaction's transition.
* This retrieves the shared elements of the incoming fragments, and schedules capturing
* the incoming fragment's shared elements. It also maps the views, and sets up the epicenter
* on the transitions.
@@ -603,7 +604,7 @@
* epicenter
* @return The shared element transition or null if no shared elements exist
*/
- private static TransitionSet configureSharedElementsUnoptimized(final ViewGroup sceneRoot,
+ private static TransitionSet configureSharedElementsOrdered(final ViewGroup sceneRoot,
final View nonExistentView, ArrayMap<String, String> nameOverrides,
final FragmentContainerTransition fragments,
final ArrayList<View> sharedElementsOut,
@@ -1195,11 +1196,11 @@
*/
public static void calculateFragments(BackStackRecord transaction,
SparseArray<FragmentContainerTransition> transitioningFragments,
- boolean isOptimized) {
+ boolean isReordered) {
final int numOps = transaction.mOps.size();
for (int opNum = 0; opNum < numOps; opNum++) {
final BackStackRecord.Op op = transaction.mOps.get(opNum);
- addToFirstInLastOut(transaction, op, transitioningFragments, false, isOptimized);
+ addToFirstInLastOut(transaction, op, transitioningFragments, false, isReordered);
}
}
@@ -1212,14 +1213,14 @@
* this method.
*/
public static void calculatePopFragments(BackStackRecord transaction,
- SparseArray<FragmentContainerTransition> transitioningFragments, boolean isOptimized) {
+ SparseArray<FragmentContainerTransition> transitioningFragments, boolean isReordered) {
if (!transaction.mManager.mContainer.onHasView()) {
return; // nothing to see, so no transitions
}
final int numOps = transaction.mOps.size();
for (int opNum = numOps - 1; opNum >= 0; opNum--) {
final BackStackRecord.Op op = transaction.mOps.get(opNum);
- addToFirstInLastOut(transaction, op, transitioningFragments, true, isOptimized);
+ addToFirstInLastOut(transaction, op, transitioningFragments, true, isReordered);
}
}
@@ -1232,14 +1233,14 @@
* @param transitioningFragments A structure holding the first in and last out fragments
* for each fragment container.
* @param isPop Is the operation a pop?
- * @param isOptimizedTransaction True if the operations have been partially executed and the
+ * @param isReorderedTransaction True if the operations have been partially executed and the
* added fragments have Views in the hierarchy or false if the
* operations haven't been executed yet.
*/
@SuppressWarnings("ReferenceEquality")
private static void addToFirstInLastOut(BackStackRecord transaction, BackStackRecord.Op op,
SparseArray<FragmentContainerTransition> transitioningFragments, boolean isPop,
- boolean isOptimizedTransaction) {
+ boolean isReorderedTransaction) {
final Fragment fragment = op.fragment;
if (fragment == null) {
return; // no fragment, no transition
@@ -1255,7 +1256,7 @@
boolean wasAdded = false;
switch (command) {
case BackStackRecord.OP_SHOW:
- if (isOptimizedTransaction) {
+ if (isReorderedTransaction) {
setLastIn = fragment.mHiddenChanged && !fragment.mHidden &&
fragment.mAdded;
} else {
@@ -1265,7 +1266,7 @@
break;
case BackStackRecord.OP_ADD:
case BackStackRecord.OP_ATTACH:
- if (isOptimizedTransaction) {
+ if (isReorderedTransaction) {
setLastIn = fragment.mIsNewlyAdded;
} else {
setLastIn = !fragment.mAdded && !fragment.mHidden;
@@ -1273,7 +1274,7 @@
wasAdded = true;
break;
case BackStackRecord.OP_HIDE:
- if (isOptimizedTransaction) {
+ if (isReorderedTransaction) {
setFirstOut = fragment.mHiddenChanged && fragment.mAdded &&
fragment.mHidden;
} else {
@@ -1283,7 +1284,7 @@
break;
case BackStackRecord.OP_REMOVE:
case BackStackRecord.OP_DETACH:
- if (isOptimizedTransaction) {
+ if (isReorderedTransaction) {
setFirstOut = !fragment.mAdded && fragment.mView != null
&& fragment.mView.getVisibility() == View.VISIBLE
&& fragment.mView.getTransitionAlpha() > 0;
@@ -1301,7 +1302,7 @@
containerTransition.lastInIsPop = isPop;
containerTransition.lastInTransaction = transaction;
}
- if (!isOptimizedTransaction && wasAdded) {
+ if (!isReorderedTransaction && wasAdded) {
if (containerTransition != null && containerTransition.firstOut == fragment) {
containerTransition.firstOut = null;
}
@@ -1313,7 +1314,7 @@
FragmentManagerImpl manager = transaction.mManager;
if (fragment.mState < Fragment.CREATED && manager.mCurState >= Fragment.CREATED &&
manager.mHost.getContext().getApplicationInfo().targetSdkVersion >=
- Build.VERSION_CODES.N && !transaction.mAllowOptimization) {
+ Build.VERSION_CODES.N && !transaction.mReorderingAllowed) {
manager.makeActive(fragment);
manager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
}
@@ -1326,7 +1327,7 @@
containerTransition.firstOutTransaction = transaction;
}
- if (!isOptimizedTransaction && wasRemoved &&
+ if (!isReorderedTransaction && wasRemoved &&
(containerTransition != null && containerTransition.lastIn == fragment)) {
containerTransition.lastIn = null;
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 9377d35..69ed439 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -543,10 +543,10 @@
* 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
+ * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on
* instances created using this constructor to see if it is a hit.
*
- * @see #onMatchIntent(Intent)
+ * @see #onStartActivity(Intent)
*/
public ActivityMonitor() {
mWhich = null;
@@ -558,7 +558,7 @@
/**
* @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
+ * into {@link #onStartActivity(Intent)}, false if this monitor is only used
* for specific intents corresponding to the intent filter or activity class
* passed in the constructor.
*/
@@ -665,7 +665,7 @@
* @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) {
+ public ActivityResult onStartActivity(Intent intent) {
return null;
}
@@ -1589,7 +1589,7 @@
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onMatchIntent(intent);
+ result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
@@ -1652,7 +1652,7 @@
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onMatchIntent(intents[0]);
+ result = am.onStartActivity(intents[0]);
}
if (result != null) {
am.mHits++;
@@ -1722,7 +1722,7 @@
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onMatchIntent(intent);
+ result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
@@ -1789,7 +1789,7 @@
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onMatchIntent(intent);
+ result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
@@ -1835,7 +1835,7 @@
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onMatchIntent(intent);
+ result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
@@ -1880,7 +1880,7 @@
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onMatchIntent(intent);
+ result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index b8a5f57..4de6e44 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -381,27 +381,58 @@
* or {@code null} if the caller isn't interested in knowing the result.
* @param handler The handler to invoke the callback on, or {@code null} to use the main
* handler.
+ *
+ * TO BE REMOVED
*/
+ @Deprecated
public void dismissKeyguard(@NonNull Activity activity,
@Nullable KeyguardDismissCallback callback, @Nullable Handler handler) {
+ requestDismissKeyguard(activity, callback);
+ }
+
+ /**
+ * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to
+ * be dismissed.
+ * <p>
+ * If the Keyguard is not secure or the device is currently in a trusted state, calling this
+ * method will immediately dismiss the Keyguard without any user interaction.
+ * <p>
+ * If the Keyguard is secure and the device is not in a trusted state, this will bring up the
+ * UI so the user can enter their credentials.
+ *
+ * @param activity The activity requesting the dismissal. The activity must be either visible
+ * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in
+ * which it would be visible if Keyguard would not be hiding it. If that's not
+ * the case, the request will fail immediately and
+ * {@link KeyguardDismissCallback#onDismissError} will be invoked.
+ * @param callback The callback to be called if the request to dismiss Keyguard was successful
+ * or {@code null} if the caller isn't interested in knowing the result. The
+ * callback will not be invoked if the activity was destroyed before the
+ * callback was received.
+ */
+ public void requestDismissKeyguard(@NonNull Activity activity,
+ @Nullable KeyguardDismissCallback callback) {
try {
- final Handler actualHandler = handler != null
- ? handler
- : new Handler(Looper.getMainLooper());
mAm.dismissKeyguard(activity.getActivityToken(), new IKeyguardDismissCallback.Stub() {
@Override
public void onDismissError() throws RemoteException {
- actualHandler.post(callback::onDismissError);
+ if (callback != null && !activity.isDestroyed()) {
+ activity.mHandler.post(callback::onDismissError);
+ }
}
@Override
public void onDismissSucceeded() throws RemoteException {
- actualHandler.post(callback::onDismissSucceeded);
+ if (callback != null && !activity.isDestroyed()) {
+ activity.mHandler.post(callback::onDismissSucceeded);
+ }
}
@Override
public void onDismissCancelled() throws RemoteException {
- actualHandler.post(callback::onDismissCancelled);
+ if (callback != null && !activity.isDestroyed()) {
+ activity.mHandler.post(callback::onDismissCancelled);
+ }
}
});
} catch (RemoteException e) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 00a8f46..c0ce355 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2681,6 +2681,8 @@
private int mPrimaryTextColor = COLOR_INVALID;
private int mSecondaryTextColor = COLOR_INVALID;
private int mActionBarColor = COLOR_INVALID;
+ private int mBackgroundColor = COLOR_INVALID;
+ private int mForegroundColor = COLOR_INVALID;
/**
* Constructs a new Builder with the defaults:
@@ -3854,10 +3856,62 @@
|| mActionBarColor == COLOR_INVALID
|| mTextColorsAreForBackground != backgroundColor) {
mTextColorsAreForBackground = backgroundColor;
- mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor(
- mContext, backgroundColor);
- mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(
- mContext, backgroundColor);
+ if (mForegroundColor == COLOR_INVALID || !isColorized()) {
+ mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor(mContext,
+ backgroundColor);
+ mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(mContext,
+ backgroundColor);
+ } else {
+ double backLum = NotificationColorUtil.calculateLuminance(backgroundColor);
+ double textLum = NotificationColorUtil.calculateLuminance(mForegroundColor);
+ double contrast = NotificationColorUtil.calculateContrast(mForegroundColor,
+ backgroundColor);
+ boolean textDark = backLum > textLum;
+ if (contrast < 4.5f) {
+ if (textDark) {
+ mSecondaryTextColor = NotificationColorUtil.findContrastColor(
+ mForegroundColor,
+ backgroundColor,
+ true /* findFG */,
+ 4.5f);
+ mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
+ mSecondaryTextColor, -20);
+ } else {
+ mSecondaryTextColor =
+ NotificationColorUtil.findContrastColorAgainstDark(
+ mForegroundColor,
+ backgroundColor,
+ true /* findFG */,
+ 4.5f);
+ mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
+ mSecondaryTextColor, 10);
+ }
+ } else {
+ mPrimaryTextColor = mForegroundColor;
+ mSecondaryTextColor = NotificationColorUtil.changeColorLightness(
+ mPrimaryTextColor, textDark ? 10 : -20);
+ if (NotificationColorUtil.calculateContrast(mSecondaryTextColor,
+ backgroundColor) < 4.5f) {
+ // oh well the secondary is not good enough
+ if (textDark) {
+ mSecondaryTextColor = NotificationColorUtil.findContrastColor(
+ mSecondaryTextColor,
+ backgroundColor,
+ true /* findFG */,
+ 4.5f);
+ } else {
+ mSecondaryTextColor
+ = NotificationColorUtil.findContrastColorAgainstDark(
+ mSecondaryTextColor,
+ backgroundColor,
+ true /* findFG */,
+ 4.5f);
+ }
+ mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
+ mSecondaryTextColor, textDark ? -20 : 10);
+ }
+ }
+ }
mActionBarColor = NotificationColorUtil.resolveActionBarColor(mContext,
backgroundColor);
}
@@ -4845,7 +4899,7 @@
private int getBackgroundColor() {
if (isColorized()) {
- return mN.color;
+ return mBackgroundColor != COLOR_INVALID ? mBackgroundColor : mN.color;
} else {
return COLOR_DEFAULT;
}
@@ -4863,6 +4917,21 @@
return targetSdkVersion > Build.VERSION_CODES.M
&& targetSdkVersion < Build.VERSION_CODES.O;
}
+
+ /**
+ * Set a color palette to be used as the background and textColors
+ *
+ * @param backgroundColor the color to be used as the background
+ * @param foregroundColor the color to be used as the foreground
+ *
+ * @hide
+ */
+ public void setColorPalette(int backgroundColor, int foregroundColor) {
+ mBackgroundColor = backgroundColor;
+ mForegroundColor = foregroundColor;
+ mTextColorsAreForBackground = COLOR_INVALID;
+ ensureColors();
+ }
}
/**
@@ -4899,6 +4968,18 @@
* @hide
*/
public boolean isColorized() {
+ if (isColorizedMedia()) {
+ return true;
+ }
+ return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService();
+ }
+
+ /**
+ * @return true if this notification is colorized and it is a media notification
+ *
+ * @hide
+ */
+ public boolean isColorizedMedia() {
Class<? extends Style> style = getNotificationStyle();
if (MediaStyle.class.equals(style)) {
Boolean colorized = (Boolean) extras.get(EXTRA_COLORIZED);
@@ -4910,7 +4991,23 @@
return true;
}
}
- return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService();
+ return false;
+ }
+
+
+ /**
+ * @return true if this is a media notification
+ *
+ * @hide
+ */
+ public boolean isMediaNotification() {
+ Class<? extends Style> style = getNotificationStyle();
+ if (MediaStyle.class.equals(style)) {
+ return true;
+ } else if (DecoratedMediaCustomViewStyle.class.equals(style)) {
+ return true;
+ }
+ return false;
}
private boolean hasLargeIcon() {
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 875d592..e1df33b 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -238,7 +238,7 @@
*/
public void truncateActions(int size) {
if (hasSetActions()) {
- mUserActions = mUserActions.subList(0, size);
+ mUserActions = mUserActions.subList(0, Math.min(mUserActions.size(), size));
}
}
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
deleted file mode 100644
index 5ed66ca..0000000
--- a/core/java/android/app/WallpaperColors.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.app;
-
-import android.graphics.Color;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import android.util.Pair;
-
-import java.util.List;
-
-/**
- * A class containing information about the colors of a wallpaper.
- */
-public final class WallpaperColors implements Parcelable {
-
- public WallpaperColors(Parcel parcel) {
- }
-
- /**
- * Wallpaper color details containing a list of colors and their weights,
- * as if it were an histogram.
- * This list can be extracted from a bitmap by the Palette API.
- *
- * Dark text support will be calculated internally based on the histogram.
- *
- * @param colors list of pairs where each pair contains a color
- * and number of occurrences/influence.
- */
- public WallpaperColors(List<Pair<Color, Integer>> colors) {
- }
-
- /**
- * Wallpaper color details containing a list of colors and their weights,
- * as if it were an histogram.
- * Explicit dark text support.
- *
- * @param colors list of pairs where each pair contains a color
- * and number of occurrences/influence.
- * @param supportsDarkText can have dark text on top or not
- */
- public WallpaperColors(List<Pair<Color, Integer>> colors, boolean supportsDarkText) {
- }
-
- public static final Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() {
- @Override
- public WallpaperColors createFromParcel(Parcel in) {
- return new WallpaperColors(in);
- }
-
- @Override
- public WallpaperColors[] newArray(int size) {
- return new WallpaperColors[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- /**
- * List of colors with their occurrences. The bigger the int, the more relevant the color.
- * @return list of colors paired with their weights.
- */
- public List<Pair<Color, Integer>> getColors() {
- return null;
- }
-
- /**
- * Whether or not dark text is legible on top of this wallpaper.
- *
- * @return true if dark text is supported
- */
- public boolean supportsDarkText() {
- return false;
- }
-}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 6d87de8..db2f937 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -17,8 +17,6 @@
package android.app;
import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.RawRes;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
@@ -746,43 +744,6 @@
return getWallpaperFile(which, mContext.getUserId());
}
-
- /**
- * Registers a listener to get notified when the wallpaper colors change.
- * Callback might be called from an arbitrary background thread.
- *
- * @param listener A listener to register
- */
- public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
- }
-
- /**
- * Registers a listener to get notified when the wallpaper colors change
- * @param listener A listener to register
- * @param handler Where to call it from. Might be called from a background thread
- * if null.
- */
- public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
- @Nullable Handler handler) {
- }
-
- /**
- * Stop listening to color updates.
- * @param callback A callback to unsubscribe
- */
- public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) {
- }
-
- /**
- * Get the primary colors of a wallpaper
- * @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or
- * {@link #FLAG_LOCK}
- * @return a list of colors ordered by priority
- */
- public @Nullable WallpaperColors getWallpaperColors(int which) {
- return null;
- }
-
/**
* Version of {@link #getWallpaperFile(int)} that can access the wallpaper data
* for a given user. The caller must hold the INTERACT_ACROSS_USERS_FULL
@@ -1774,19 +1735,4 @@
mLatch.countDown();
}
}
-
- /**
- * Interface definition for a callback to be invoked when colors change on a wallpaper.
- */
- public interface OnColorsChangedListener {
- /**
- * Called when colors change.
- * A {@link android.app.WallpaperColors} object containing a simplified
- * color histogram will be given.
- *
- * @param colors Wallpaper color info
- * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM}
- */
- void onColorsChanged(WallpaperColors colors, int which);
- }
}
diff --git a/core/java/android/app/admin/ConnectEvent.java b/core/java/android/app/admin/ConnectEvent.java
index 5111443..423ee52 100644
--- a/core/java/android/app/admin/ConnectEvent.java
+++ b/core/java/android/app/admin/ConnectEvent.java
@@ -19,6 +19,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
/**
* A class that represents a connect library call event.
*/
@@ -44,8 +47,14 @@
this.timestamp = in.readLong();
}
- public String getIpAddress() {
- return ipAddress;
+ public InetAddress getInetAddress() {
+ try {
+ // ipAddress is already an address, not a host name, no DNS resolution will happen.
+ return InetAddress.getByName(ipAddress);
+ } catch (UnknownHostException e) {
+ // Should never happen as we aren't passing a host name.
+ return InetAddress.getLoopbackAddress();
+ }
}
public int getPort() {
diff --git a/core/java/android/app/admin/DnsEvent.java b/core/java/android/app/admin/DnsEvent.java
index a3a3f58..87f86b5 100644
--- a/core/java/android/app/admin/DnsEvent.java
+++ b/core/java/android/app/admin/DnsEvent.java
@@ -19,6 +19,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
/**
* A class that represents a DNS lookup event.
*/
@@ -59,15 +62,27 @@
}
/** Returns (possibly a subset of) the IP addresses returned. */
- public String[] getIpAddresses() {
- return ipAddresses;
+ public InetAddress[] getInetAddresses() {
+ final int length = ipAddresses != null ? ipAddresses.length : 0;
+ final InetAddress[] inetAddresses = new InetAddress[length];
+ for (int i = 0; i < length; i++) {
+ try {
+ // ipAddress is already an address, not a host name, no DNS resolution will happen.
+ inetAddresses[i] = InetAddress.getByName(ipAddresses[i]);
+ } catch (UnknownHostException e) {
+ // Should never happen as we aren't passing a host name.
+ inetAddresses[i] = InetAddress.getLoopbackAddress();
+ }
+ }
+ return inetAddresses;
}
/**
* Returns the number of IP addresses returned from the DNS lookup event. May be different from
- * the length of ipAddresses if there were too many addresses to log.
+ * the length of the array returned by {@link #getInetAddresses()} if there were too many
+ * addresses to log.
*/
- public int getIpAddressesCount() {
+ public int getTotalResolvedAddressCount() {
return ipAddressesCount;
}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index d6b89a1..03ef24a9 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -2023,8 +2023,9 @@
/**
* Returns whether the activity associated with this AssistStructure was the home activity
- * at the time the assist data was acquired.
+ * (Launcher) at the time the assist data was acquired.
* @return Whether the activity was the home activity.
+ * @see android.content.Intent#CATEGORY_HOME
*/
public boolean isHomeActivity() {
return mIsHomeActivity;
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 713dbf4..0f01d62 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -159,8 +159,10 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
- BluetoothProfile.STATE_DISCONNECTED);
+ if (mCallback != null) {
+ mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
+ BluetoothProfile.STATE_DISCONNECTED);
+ }
}
});
@@ -192,7 +194,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
+ if (mCallback != null) {
+ mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
+ }
}
});
}
@@ -212,7 +216,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
+ if (mCallback != null) {
+ mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
+ }
}
});
}
@@ -235,7 +241,10 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
+ if (mCallback != null) {
+ mCallback.onConnectionStateChange(BluetoothGatt.this, status,
+ profileState);
+ }
}
});
@@ -294,7 +303,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onServicesDiscovered(BluetoothGatt.this, status);
+ if (mCallback != null) {
+ mCallback.onServicesDiscovered(BluetoothGatt.this, status);
+ }
}
});
}
@@ -344,7 +355,10 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
+ if (mCallback != null) {
+ mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic,
+ status);
+ }
}
});
}
@@ -390,7 +404,10 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
+ if (mCallback != null) {
+ mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic,
+ status);
+ }
}
});
}
@@ -416,7 +433,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
+ if (mCallback != null) {
+ mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
+ }
}
});
}
@@ -461,7 +480,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
+ if (mCallback != null) {
+ mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
+ }
}
});
}
@@ -505,7 +526,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
+ if (mCallback != null) {
+ mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
+ }
}
});
}
@@ -529,7 +552,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
+ if (mCallback != null) {
+ mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
+ }
}
});
}
@@ -548,7 +573,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
+ if (mCallback != null) {
+ mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
+ }
}
});
}
@@ -568,7 +595,9 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
+ if (mCallback != null) {
+ mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
+ }
}
});
}
@@ -590,8 +619,10 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
- timeout, status);
+ if (mCallback != null) {
+ mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
+ timeout, status);
+ }
}
});
}
@@ -973,6 +1004,41 @@
}
/**
+ * Reads the characteristic using its UUID from the associated remote device.
+ *
+ * <p>This is an asynchronous operation. The result of the read operation
+ * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
+ * callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param uuid UUID of characteristic to read from the remote device
+ * @return true, if the read operation was initiated successfully
+ * @hide
+ */
+ public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) {
+ if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid);
+ if (mService == null || mClientIf == 0) return false;
+
+ synchronized(mDeviceBusy) {
+ if (mDeviceBusy) return false;
+ mDeviceBusy = true;
+ }
+
+ try {
+ mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(),
+ new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ mDeviceBusy = false;
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
* Writes a given characteristic and its values to the associated remote device.
*
* <p>Once the write operation has been completed, the
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 12e9baa..e2d4f5b 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -59,6 +59,7 @@
in IAdvertisingSetCallback callback);
void stopAdvertisingSet(in IAdvertisingSetCallback callback);
+ void getOwnAddress(in int advertiserId);
void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents);
void setAdvertisingData(in int advertiserId, in AdvertiseData data);
void setScanResponseData(in int advertiserId, in AdvertiseData data);
@@ -80,6 +81,8 @@
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
+ void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
+ in int startHandle, in int endHandle, in int authReq);
void writeCharacteristic(in int clientIf, in String address, in int handle,
in int writeType, in int authReq, in byte[] value);
void readDescriptor(in int clientIf, in String address, in int handle, in int authReq);
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index 51571b2..3021be1 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -181,7 +181,23 @@
}
/**
- * Returns advertiserId associated with thsi advertising set.
+ * Returns address associated with this advertising set.
+ * This method is exposed only for Bluetooth PTS tests, no app or system service
+ * should ever use it.
+ *
+ * This method requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission.
+ * @hide
+ */
+ public void getOwnAddress(){
+ try {
+ gatt.getOwnAddress(this.advertiserId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "remote exception - ", e);
+ }
+ }
+
+ /**
+ * Returns advertiserId associated with this advertising set.
*
* @hide
*/
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
index fe3b1cd..2c46e85 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
@@ -143,4 +143,15 @@
*/
public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable,
int status) {}
+
+ /**
+ * Callback triggered in response to {@link AdvertisingSet#getOwnAddress()}
+ * indicating result of the operation.
+ *
+ * @param advertisingSet The advertising set.
+ * @param addressType type of address.
+ * @param address advertising set bluetooth address.
+ * @hide
+ */
+ public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, String address) {}
}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 0c7958d..67d56d5 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -544,6 +544,17 @@
}
@Override
+ public void onOwnAddressRead(int advertiserId, int addressType, String address) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
+ callback.onOwnAddressRead(advertisingSet, addressType, address);
+ }
+ });
+ }
+
+ @Override
public void onAdvertisingSetStopped(int advertiserId) {
handler.post(new Runnable() {
@Override
diff --git a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
index 2c9f4ba..3628c77 100644
--- a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
+++ b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
@@ -21,6 +21,7 @@
*/
oneway interface IAdvertisingSetCallback {
void onAdvertisingSetStarted(in int advertiserId, in int tx_power, in int status);
+ void onOwnAddressRead(in int advertiserId, in int addressType, in String address);
void onAdvertisingSetStopped(in int advertiserId);
void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
void onAdvertisingDataSet(in int advertiserId, in int status);
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index 5b2fa40..e552398 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -52,6 +52,16 @@
public static final int SID_NOT_PRESENT = 0xFF;
/**
+ * TX power is not present in the packet.
+ */
+ public static final int TX_POWER_NOT_PRESENT = 0x7F;
+
+ /**
+ * Periodic advertising interval is not present in the packet.
+ */
+ public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0x00;
+
+ /**
* Mask for checking whether event type represents legacy advertisement.
*/
private static final int ET_LEGACY_MASK = 0x10;
@@ -265,15 +275,16 @@
/**
* Returns the transmit power in dBm.
- * Valid range is [-127, 126]. A value of 127 indicates that the
- * advertisement did not indicate TX power.
+ * Valid range is [-127, 126]. A value of {@link ScanResult#TX_POWER_NOT_PRESENT}
+ * indicates that the TX power is not present.
*/
public int getTxPower() { return mTxPower; }
/**
* Returns the periodic advertising interval in units of 1.25ms.
- * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of 0 means
- * periodic advertising is not used for this scan result.
+ * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of
+ * {@link ScanResult#PERIODIC_INTERVAL_NOT_PRESENT} means periodic
+ * advertising interval is not present.
*/
public int getPeriodicAdvertisingInterval() {
return mPeriodicAdvertisingInterval;
diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
similarity index 95%
rename from core/java/android/companion/BluetoothLEDeviceFilter.java
rename to core/java/android/companion/BluetoothLeDeviceFilter.java
index e5ea4e9..7a9ba1c 100644
--- a/core/java/android/companion/BluetoothLEDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -47,10 +47,10 @@
*
* @see ScanFilter
*/
-public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> {
+public final class BluetoothLeDeviceFilter implements DeviceFilter<ScanResult> {
private static final boolean DEBUG = false;
- private static final String LOG_TAG = "BluetoothLEDeviceFilter";
+ private static final String LOG_TAG = "BluetoothLeDeviceFilter";
private static final int RENAME_PREFIX_LENGTH_LIMIT = 10;
@@ -66,7 +66,7 @@
private final int mRenameNameTo;
private final boolean mRenameBytesReverseOrder;
- private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter,
+ private BluetoothLeDeviceFilter(Pattern namePattern, ScanFilter scanFilter,
byte[] rawDataFilter, byte[] rawDataFilterMask, String renamePrefix,
String renameSuffix, int renameBytesFrom, int renameBytesTo,
int renameNameFrom, int renameNameTo, boolean renameBytesReverseOrder) {
@@ -186,7 +186,7 @@
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- BluetoothLEDeviceFilter that = (BluetoothLEDeviceFilter) o;
+ BluetoothLeDeviceFilter that = (BluetoothLeDeviceFilter) o;
return mRenameBytesFrom == that.mRenameBytesFrom &&
mRenameBytesTo == that.mRenameBytesTo &&
mRenameBytesReverseOrder == that.mRenameBytesReverseOrder &&
@@ -242,10 +242,10 @@
'}';
}
- public static final Creator<BluetoothLEDeviceFilter> CREATOR
- = new Creator<BluetoothLEDeviceFilter>() {
+ public static final Creator<BluetoothLeDeviceFilter> CREATOR
+ = new Creator<BluetoothLeDeviceFilter>() {
@Override
- public BluetoothLEDeviceFilter createFromParcel(Parcel in) {
+ public BluetoothLeDeviceFilter createFromParcel(Parcel in) {
Builder builder = new Builder()
.setNamePattern(patternFromString(in.readString()))
.setScanFilter(in.readParcelable(null));
@@ -273,8 +273,8 @@
}
@Override
- public BluetoothLEDeviceFilter[] newArray(int size) {
- return new BluetoothLEDeviceFilter[size];
+ public BluetoothLeDeviceFilter[] newArray(int size) {
+ return new BluetoothLeDeviceFilter[size];
}
};
@@ -283,9 +283,9 @@
}
/**
- * Builder for {@link BluetoothLEDeviceFilter}
+ * Builder for {@link BluetoothLeDeviceFilter}
*/
- public static final class Builder extends OneTimeUseBuilder<BluetoothLEDeviceFilter> {
+ public static final class Builder extends OneTimeUseBuilder<BluetoothLeDeviceFilter> {
private ScanFilter mScanFilter;
private Pattern mNamePattern;
private byte[] mRawDataFilter;
@@ -418,9 +418,9 @@
/** @inheritDoc */
@Override
@NonNull
- public BluetoothLEDeviceFilter build() {
+ public BluetoothLeDeviceFilter build() {
markUsed();
- return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter,
+ return new BluetoothLeDeviceFilter(mNamePattern, mScanFilter,
mRawDataFilter, mRawDataFilterMask,
mRenamePrefix, mRenameSuffix,
mRenameBytesFrom, mRenameBytesTo,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5f7947f..d746377 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3228,6 +3228,7 @@
* caused the broadcast.
* @hide
*/
+ @SystemApi
public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
/**
@@ -4422,6 +4423,21 @@
public static final String EXTRA_VERSION_CODE = "android.intent.extra.VERSION_CODE";
/**
+ * The app that triggered the ephemeral installation.
+ * @hide
+ */
+ public static final String EXTRA_CALLING_PACKAGE
+ = "android.intent.extra.CALLING_PACKAGE";
+
+ /**
+ * Optional calling app provided bundle containing additional launch information the
+ * installer may use.
+ * @hide
+ */
+ public static final String EXTRA_VERIFICATION_BUNDLE
+ = "android.intent.extra.VERIFICATION_BUNDLE";
+
+ /**
* A Bundle forming a mapping of potential target package names to different extras Bundles
* to add to the default intent extras in {@link #EXTRA_INTENT} when used with
* {@link #ACTION_CHOOSER}. Each key should be a package name. The package need not
diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java
index b45169d..27d2828 100644
--- a/core/java/android/content/pm/InstantAppRequest.java
+++ b/core/java/android/content/pm/InstantAppRequest.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.content.Intent;
+import android.os.Bundle;
/**
* Information needed to make an instant application resolution request.
@@ -33,13 +34,18 @@
public final String callingPackage;
/** ID of the user requesting the instant application */
public final int userId;
+ /**
+ * Optional extra bundle provided by the source application to the installer for additional
+ * verification. */
+ public final Bundle verificationBundle;
public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent,
- String resolvedType, String callingPackage, int userId) {
+ String resolvedType, String callingPackage, int userId, Bundle verificationBundle) {
this.responseObj = responseObj;
this.origIntent = origIntent;
this.resolvedType = resolvedType;
this.callingPackage = callingPackage;
this.userId = userId;
+ this.verificationBundle = verificationBundle;
}
-}
\ No newline at end of file
+}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 7bfde75..426f3cf 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -19,6 +19,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
import android.util.SparseArray;
import java.util.List;
@@ -215,11 +216,13 @@
* @param origIntent The original intent that triggered ephemeral resolution
* @param resolvedType The resolved type of the intent
* @param callingPackage The name of the package requesting the ephemeral application
+ * @param verificationBundle Optional bundle to pass to the installer for additional
+ * verification
* @param userId The ID of the user that triggered ephemeral resolution
*/
public abstract void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
Intent origIntent, String resolvedType, String callingPackage,
- int userId);
+ Bundle verificationBundle, int userId);
/**
* Grants access to the package metadata for an ephemeral application.
@@ -333,4 +336,9 @@
* @param isolatedUid isolated uid that is no longer being used.
*/
public abstract void removeIsolatedUid(int isolatedUid);
+
+ /**
+ * Return the taget SDK version for the app with the given UID.
+ */
+ public abstract int getUidTargetSdkVersion(int uid);
}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index a044804..f0adcd6 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -788,8 +788,8 @@
/**
* Retrieve the resource identifier for the given resource name.
*/
- /*package*/ native final int getResourceIdentifier(String type,
- String name,
+ /*package*/ native final int getResourceIdentifier(String name,
+ String defType,
String defPackage);
/*package*/ native final String getResourceName(int resid);
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index 9d217d3..7049628 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -70,37 +70,34 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {USAGE0_CPU_READ, USAGE0_CPU_READ_OFTEN, USAGE0_CPU_WRITE,
- USAGE0_CPU_WRITE_OFTEN, USAGE0_GPU_SAMPLED_IMAGE, USAGE0_GPU_COLOR_OUTPUT,
- USAGE0_GPU_STORAGE_IMAGE, USAGE0_GPU_CUBEMAP, USAGE0_GPU_DATA_BUFFER,
- USAGE0_PROTECTED_CONTENT, USAGE0_SENSOR_DIRECT_DATA, USAGE0_VIDEO_ENCODE})
- public @interface Usage0 {};
+ @IntDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN,
+ USAGE_CPU_WRITE_RARELY, USAGE_CPU_WRITE_OFTEN, USAGE_GPU_SAMPLED_IMAGE,
+ USAGE_GPU_COLOR_OUTPUT, USAGE_PROTECTED_CONTENT, USAGE_VIDEO_ENCODE,
+ USAGE_GPU_DATA_BUFFER, USAGE_SENSOR_DIRECT_DATA})
+ public @interface Usage {};
- /** Usage0: the buffer will sometimes be read by the CPU */
- public static final long USAGE0_CPU_READ = (1 << 1);
- /** Usage0: the buffer will often be read by the CPU*/
- public static final long USAGE0_CPU_READ_OFTEN = (1 << 2 | USAGE0_CPU_READ);
- /** Usage0: the buffer will sometimes be written to by the CPU */
- public static final long USAGE0_CPU_WRITE = (1 << 5);
- /** Usage0: the buffer will often be written to by the CPU */
- public static final long USAGE0_CPU_WRITE_OFTEN = (1 << 6 | USAGE0_CPU_WRITE);
- /** Usage0: the buffer will be read from by the GPU */
- public static final long USAGE0_GPU_SAMPLED_IMAGE = (1 << 10);
- /** Usage0: the buffer will be written to by the GPU */
- public static final long USAGE0_GPU_COLOR_OUTPUT = (1 << 11);
- /** Usage0: the buffer will be read from and written to by the GPU */
- public static final long USAGE0_GPU_STORAGE_IMAGE = (USAGE0_GPU_SAMPLED_IMAGE |
- USAGE0_GPU_COLOR_OUTPUT);
- /** Usage0: the buffer will be used as a cubemap texture */
- public static final long USAGE0_GPU_CUBEMAP = (1 << 13);
- /** Usage0: the buffer will be used as a shader storage or uniform buffer object*/
- public static final long USAGE0_GPU_DATA_BUFFER = (1 << 14);
- /** Usage0: the buffer must not be used outside of a protected hardware path */
- public static final long USAGE0_PROTECTED_CONTENT = (1 << 18);
- /** Usage0: the buffer will be used for sensor direct data */
- public static final long USAGE0_SENSOR_DIRECT_DATA = (1 << 29);
- /** Usage0: the buffer will be read by a hardware video encoder */
- public static final long USAGE0_VIDEO_ENCODE = (1 << 21);
+ /** Usage: The buffer will sometimes be read by the CPU */
+ public static final long USAGE_CPU_READ_RARELY = 2;
+ /** Usage: The buffer will often be read by the CPU */
+ public static final long USAGE_CPU_READ_OFTEN = 3;
+
+ /** Usage: The buffer will sometimes be written to by the CPU */
+ public static final long USAGE_CPU_WRITE_RARELY = 2 << 4;
+ /** Usage: The buffer will often be written to by the CPU */
+ public static final long USAGE_CPU_WRITE_OFTEN = 3 << 4;
+
+ /** Usage: The buffer will be read from by the GPU */
+ public static final long USAGE_GPU_SAMPLED_IMAGE = 1 << 8;
+ /** Usage: The buffer will be written to by the GPU */
+ public static final long USAGE_GPU_COLOR_OUTPUT = 1 << 9;
+ /** Usage: The buffer must not be used outside of a protected hardware path */
+ public static final long USAGE_PROTECTED_CONTENT = 1 << 14;
+ /** Usage: The buffer will be read by a hardware video encoder */
+ public static final long USAGE_VIDEO_ENCODE = 1 << 16;
+ /** Usage: The buffer will be used for sensor direct data */
+ public static final long USAGE_SENSOR_DIRECT_DATA = 1 << 23;
+ /** Usage: The buffer will be used as a shader storage or uniform buffer object */
+ public static final long USAGE_GPU_DATA_BUFFER = 1 << 24;
// The approximate size of a native AHardwareBuffer object.
private static final long NATIVE_HARDWARE_BUFFER_SIZE = 232;
@@ -116,13 +113,11 @@
* {@link #RGBX_8888}, {@link #RGB_565}, {@link #RGB_888}, {@link #RGBA_1010102}, {@link #BLOB}
* @param layers The number of layers in the buffer
* @param usage Flags describing how the buffer will be used, one of
- * {@link #USAGE0_CPU_READ}, {@link #USAGE0_CPU_READ_OFTEN}, {@link #USAGE0_CPU_WRITE},
- * {@link #USAGE0_CPU_WRITE_OFTEN}, {@link #USAGE0_GPU_SAMPLED_IMAGE},
- * {@link #USAGE0_GPU_COLOR_OUTPUT},{@link #USAGE0_GPU_STORAGE_IMAGE},
- * {@link #USAGE0_GPU_CUBEMAP}, {@link #USAGE0_GPU_DATA_BUFFER},
- * {@link #USAGE0_PROTECTED_CONTENT}, {@link #USAGE0_SENSOR_DIRECT_DATA},
- * {@link #USAGE0_VIDEO_ENCODE}
- *
+ * {@link #USAGE_CPU_READ_RARELY}, {@link #USAGE_CPU_READ_OFTEN},
+ * {@link #USAGE_CPU_WRITE_RARELY}, {@link #USAGE_CPU_WRITE_OFTEN},
+ * {@link #USAGE_GPU_SAMPLED_IMAGE}, {@link #USAGE_GPU_COLOR_OUTPUT},
+ * {@link #USAGE_GPU_DATA_BUFFER}, {@link #USAGE_PROTECTED_CONTENT},
+ * {@link #USAGE_SENSOR_DIRECT_DATA}, {@link #USAGE_VIDEO_ENCODE}
* @return A <code>HardwareBuffer</code> instance if successful, or throws an
* IllegalArgumentException if the dimensions passed are invalid (either zero, negative, or
* too large to allocate), if the format is not supported, if the requested number of layers
@@ -130,7 +125,7 @@
*/
@NonNull
public static HardwareBuffer create(int width, int height, @Format int format, int layers,
- @Usage0 long usage) {
+ @Usage long usage) {
if (!HardwareBuffer.isSupportedFormat(format)) {
throw new IllegalArgumentException("Invalid pixel format " + format);
}
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 80cbde7..0dab5d7 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -589,9 +589,9 @@
"Width if HaradwareBuffer must be greater than "
+ MIN_DIRECT_CHANNEL_BUFFER_SIZE);
}
- if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE0_SENSOR_DIRECT_DATA) == 0) {
+ if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE_SENSOR_DIRECT_DATA) == 0) {
throw new IllegalArgumentException(
- "HardwareBuffer must set usage flag USAGE0_SENSOR_DIRECT_DATA");
+ "HardwareBuffer must set usage flag USAGE_SENSOR_DIRECT_DATA");
}
size = hardwareBuffer.getWidth();
id = nativeCreateDirectChannel(
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 6c038c78..1013b0f 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -607,43 +607,6 @@
}
/**
- * Build a Typeface from an array of {@link FontInfo}. Results that are marked as not ready
- * will be skipped.
- *
- * @param context A {@link Context} that will be used to fetch the font contents.
- * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
- * the operation is canceled, then {@link
- * android.os.OperationCanceledException} will be thrown.
- * @param fonts An array of {@link FontInfo} to be used to create a Typeface.
- * @param weight A weight value to be used for selecting a font from a font family.
- * @param italic {@code true} if this font is of italic style. This will be used for font
- * selection from a font family.
- * @param fallbackFontName A fallback font name used if this method fails to create the
- * Typeface. By passing {@code null}, this method returns {@code null}
- * if typeface creation fails.
- * @return A Typeface object. May return {@code null} if that is the value passed to {@code
- * fallBackFontName}.
- */
- public static Typeface buildTypeface(@NonNull Context context,
- @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts,
- int weight, boolean italic, @Nullable String fallbackFontName) {
- if (context.isRestricted()) {
- // TODO: Should we allow if the peer process is system or myself?
- return null;
- }
- final Map<Uri, ByteBuffer> uriBuffer =
- prepareFontData(context, fonts, cancellationSignal);
- if (uriBuffer.isEmpty()) {
- return null;
- }
- return new Typeface.Builder(fonts, uriBuffer)
- .setFallback(fallbackFontName)
- .setWeight(weight)
- .setItalic(italic)
- .build();
- }
-
- /**
* Build a Typeface from an array of {@link FontInfo}
*
* Results that are marked as not ready will be skipped.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cbd41c3..89c0963 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7065,6 +7065,12 @@
INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR);
INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_TYPEFACE);
INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_FONT_SCALE);
+ INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_WINDOW_COLOR);
+ INSTANT_APP_SETTINGS.add(ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
+ INSTANT_APP_SETTINGS.add(ACCESSIBILITY_DISPLAY_DALTONIZER);
+ INSTANT_APP_SETTINGS.add(ACCESSIBILITY_AUTOCLICK_DELAY);
+ INSTANT_APP_SETTINGS.add(ACCESSIBILITY_AUTOCLICK_ENABLED);
+ INSTANT_APP_SETTINGS.add(ACCESSIBILITY_LARGE_POINTER_ICON);
INSTANT_APP_SETTINGS.add(DEFAULT_INPUT_METHOD);
INSTANT_APP_SETTINGS.add(ENABLED_INPUT_METHODS);
@@ -7717,7 +7723,22 @@
public static final String LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST =
"location_background_throttle_package_whitelist";
- /**
+ /**
+ * The interval in milliseconds at which wifi scan requests will be throttled when they are
+ * coming from the background.
+ * @hide
+ */
+ public static final String WIFI_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS =
+ "wifi_scan_background_throttle_interval_ms";
+
+ /**
+ * Packages that are whitelisted to be exempt for wifi background throttling.
+ * @hide
+ */
+ public static final String WIFI_SCAN_BACKGROUND_THROTTLE_PACKAGE_WHITELIST =
+ "wifi_scan_background_throttle_package_whitelist";
+
+ /**
* Whether TV will switch to MHL port when a mobile device is plugged in.
* (0 = false, 1 = true)
* @hide
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 98780a7..6bbb0ff 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -16,8 +16,6 @@
package android.service.wallpaper;
-import android.annotation.Nullable;
-import android.app.WallpaperColors;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.MergedConfiguration;
@@ -544,24 +542,6 @@
*/
public void onSurfaceDestroyed(SurfaceHolder holder) {
}
-
- /**
- * Notifies the engine that wallpaper colors changed significantly.
- * This will trigger a {@link #onComputeWallpaperColors()} call.
- */
- public void invalidateColors() {
- }
-
- /**
- * Notifies the system about what colors the wallpaper is using.
- * You might return null if no color information is available at the moment. In that case
- * you might want to call {@link #invalidateColors()} in a near future.
- *
- * @return List of wallpaper colors and their weights.
- */
- public @Nullable WallpaperColors onComputeWallpaperColors() {
- return null;
- }
protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
out.print(prefix); out.print("mInitializing="); out.print(mInitializing);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 695efdd..5c9a01f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16577,6 +16577,7 @@
* @param config Configuration of the resources on new display after move.
*
* @see #onConfigurationChanged(Configuration)
+ * @hide
*/
public void onMovedToDisplay(int displayId, Configuration config) {
}
@@ -21084,7 +21085,7 @@
*/
@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
- if (id < 0) {
+ if (id == NO_ID) {
return null;
}
return findViewTraversal(id);
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 9ee0cb1..2c8e43e 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -356,21 +356,7 @@
* @param view view requesting the new autofill context.
*/
public void requestAutofill(@NonNull View view) {
- if (!hasAutofillFeature()) {
- return;
- }
- synchronized (mLock) {
- ensureServiceClientAddedIfNeededLocked();
-
- if (!mEnabled) {
- return;
- }
-
- final AutofillId id = getAutofillId(view);
- final AutofillValue value = view.getAutofillValue();
-
- startSessionLocked(id, view.getWindowToken(), null, value, FLAG_MANUAL_REQUEST);
- }
+ notifyViewEntered(view, FLAG_MANUAL_REQUEST);
}
/**
@@ -385,19 +371,7 @@
* @param bounds child boundaries, relative to the top window.
*/
public void requestAutofill(@NonNull View view, int childId, @NonNull Rect bounds) {
- if (!hasAutofillFeature()) {
- return;
- }
- synchronized (mLock) {
- ensureServiceClientAddedIfNeededLocked();
-
- if (!mEnabled) {
- return;
- }
-
- final AutofillId id = getAutofillId(view, childId);
- startSessionLocked(id, view.getWindowToken(), bounds, null, FLAG_MANUAL_REQUEST);
- }
+ notifyViewEntered(view, childId, bounds, FLAG_MANUAL_REQUEST);
}
/**
@@ -406,6 +380,10 @@
* @param view {@link View} that was entered.
*/
public void notifyViewEntered(@NonNull View view) {
+ notifyViewEntered(view, 0);
+ }
+
+ private void notifyViewEntered(@NonNull View view, int flags) {
if (!hasAutofillFeature()) {
return;
}
@@ -423,7 +401,7 @@
if (mSessionId == NO_SESSION) {
// Starts new session.
- startSessionLocked(id, view.getWindowToken(), null, value, 0);
+ startSessionLocked(id, view.getWindowToken(), null, value, flags);
} else {
// Update focus on existing session.
updateSessionLocked(id, null, value, FLAG_VIEW_ENTERED);
@@ -481,6 +459,10 @@
* @param bounds child boundaries, relative to the top window.
*/
public void notifyViewEntered(@NonNull View view, int childId, @NonNull Rect bounds) {
+ notifyViewEntered(view, childId, bounds, 0);
+ }
+
+ private void notifyViewEntered(View view, int childId, Rect bounds, int flags) {
if (!hasAutofillFeature()) {
return;
}
@@ -497,7 +479,7 @@
if (mSessionId == NO_SESSION) {
// Starts new session.
- startSessionLocked(id, view.getWindowToken(), bounds, null, 0);
+ startSessionLocked(id, view.getWindowToken(), bounds, null, flags);
} else {
// Update focus on existing session.
updateSessionLocked(id, bounds, null, FLAG_VIEW_ENTERED);
diff --git a/core/java/android/view/textclassifier/SmartSelection.java b/core/java/android/view/textclassifier/SmartSelection.java
index f0f39b6..f0e83d1 100644
--- a/core/java/android/view/textclassifier/SmartSelection.java
+++ b/core/java/android/view/textclassifier/SmartSelection.java
@@ -75,6 +75,20 @@
nativeClose(mCtx);
}
+ /**
+ * Returns the language of the model.
+ */
+ public static String getLanguage(int fd) {
+ return nativeGetLanguage(fd);
+ }
+
+ /**
+ * Returns the version of the model.
+ */
+ public static int getVersion(int fd) {
+ return nativeGetVersion(fd);
+ }
+
private static native long nativeNew(int fd);
private static native int[] nativeSuggest(
@@ -85,6 +99,10 @@
private static native void nativeClose(long context);
+ private static native String nativeGetLanguage(int fd);
+
+ private static native int nativeGetVersion(int fd);
+
/** Classification result for classifyText method. */
static final class ClassificationResult {
final String mCollection;
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 246fab3..9c4fc3c 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -44,6 +44,7 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -71,6 +72,8 @@
private static final String LOG_TAG = "TextClassifierImpl";
private static final String MODEL_DIR = "/etc/textclassifier/";
private static final String MODEL_FILE_REGEX = "textclassifier\\.smartselection\\.(.*)\\.model";
+ private static final String UPDATED_MODEL_FILE_PATH =
+ "/data/misc/textclassifier/textclassifier.smartselection.model";
private final Context mContext;
@@ -175,15 +178,12 @@
synchronized (mSmartSelectionLock) {
localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
final Locale locale = findBestSupportedLocaleLocked(localeList);
+ if (locale == null) {
+ throw new FileNotFoundException("No file for null locale");
+ }
if (mSmartSelection == null || !Objects.equals(mLocale, locale)) {
destroySmartSelectionIfExistsLocked();
- mSmartSelection = new SmartSelection(
- ParcelFileDescriptor.open(
- // findBestSupportedLocaleLocked should have initialized
- // mModelFilePaths
- new File(mModelFilePaths.get(locale)),
- ParcelFileDescriptor.MODE_READ_ONLY)
- .getFd());
+ mSmartSelection = new SmartSelection(getFdLocked(locale));
mLocale = locale;
}
return mSmartSelection;
@@ -191,6 +191,68 @@
}
@GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+ private int getFdLocked(Locale locale) throws FileNotFoundException {
+ ParcelFileDescriptor updateFd;
+ try {
+ updateFd = ParcelFileDescriptor.open(
+ new File(UPDATED_MODEL_FILE_PATH), ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ updateFd = null;
+ }
+ ParcelFileDescriptor factoryFd;
+ try {
+ final String factoryModelFilePath = getFactoryModelFilePathsLocked().get(locale);
+ if (factoryModelFilePath != null) {
+ factoryFd = ParcelFileDescriptor.open(
+ new File(factoryModelFilePath), ParcelFileDescriptor.MODE_READ_ONLY);
+ } else {
+ factoryFd = null;
+ }
+ } catch (FileNotFoundException e) {
+ factoryFd = null;
+ }
+
+ if (updateFd == null) {
+ if (factoryFd != null) {
+ return factoryFd.getFd();
+ } else {
+ throw new FileNotFoundException(
+ String.format("No model file found for %s", locale));
+ }
+ }
+
+ final int updateFdInt = updateFd.getFd();
+ final boolean localeMatches = Objects.equals(
+ locale.getLanguage().trim().toLowerCase(),
+ SmartSelection.getLanguage(updateFdInt).trim().toLowerCase());
+ if (factoryFd == null) {
+ if (localeMatches) {
+ return updateFdInt;
+ } else {
+ closeAndLogError(updateFd);
+ throw new FileNotFoundException(
+ String.format("No model file found for %s", locale));
+ }
+ }
+
+ if (!localeMatches) {
+ closeAndLogError(updateFd);
+ return factoryFd.getFd();
+ }
+
+ final int updateVersion = SmartSelection.getVersion(updateFdInt);
+ final int factoryFdInt = factoryFd.getFd();
+ final int factoryVersion = SmartSelection.getVersion(factoryFdInt);
+ if (updateVersion > factoryVersion) {
+ closeAndLogError(factoryFd);
+ return updateFdInt;
+ } else {
+ closeAndLogError(updateFd);
+ return factoryFdInt;
+ }
+ }
+
+ @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
private void destroySmartSelectionIfExistsLocked() {
if (mSmartSelection != null) {
mSmartSelection.close();
@@ -206,11 +268,18 @@
? LocaleList.getDefault().toLanguageTags()
: localeList.toLanguageTags() + "," + LocaleList.getDefault().toLanguageTags();
final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(languages);
- return Locale.lookup(languageRangeList, loadModelFilePathsLocked().keySet());
+
+ final List<Locale> supportedLocales =
+ new ArrayList<>(getFactoryModelFilePathsLocked().keySet());
+ final Locale updatedModelLocale = getUpdatedModelLocale();
+ if (updatedModelLocale != null) {
+ supportedLocales.add(updatedModelLocale);
+ }
+ return Locale.lookup(languageRangeList, supportedLocales);
}
@GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
- private Map<Locale, String> loadModelFilePathsLocked() {
+ private Map<Locale, String> getFactoryModelFilePathsLocked() {
if (mModelFilePaths == null) {
final Map<Locale, String> modelFilePaths = new HashMap<>();
final File modelsDir = new File(MODEL_DIR);
@@ -233,6 +302,20 @@
return mModelFilePaths;
}
+ @Nullable
+ private Locale getUpdatedModelLocale() {
+ try {
+ final ParcelFileDescriptor updateFd = ParcelFileDescriptor.open(
+ new File(UPDATED_MODEL_FILE_PATH), ParcelFileDescriptor.MODE_READ_ONLY);
+ final Locale locale = Locale.forLanguageTag(
+ SmartSelection.getLanguage(updateFd.getFd()));
+ closeAndLogError(updateFd);
+ return locale;
+ } catch (FileNotFoundException e) {
+ return null;
+ }
+ }
+
private TextClassificationResult createClassificationResult(
SmartSelection.ClassificationResult[] classifications, CharSequence text) {
final TextClassificationResult.Builder builder = new TextClassificationResult.Builder()
@@ -319,6 +402,17 @@
}
/**
+ * Closes the ParcelFileDescriptor and logs any errors that occur.
+ */
+ private static void closeAndLogError(ParcelFileDescriptor fd) {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Error closing file.", e);
+ }
+ }
+
+ /**
* @throws IllegalArgumentException if text is null; startIndex is negative;
* endIndex is greater than text.length() or is not greater than startIndex
*/
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6213a63..52c82a7 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2255,6 +2255,7 @@
/**
* Sets the {@link TextClassifier} for this WebView.
+ * @hide
*/
public void setTextClassifier(@Nullable TextClassifier textClassifier) {
mProvider.setTextClassifier(textClassifier);
@@ -2263,6 +2264,7 @@
/**
* Returns the {@link TextClassifier} used by this WebView.
* If no TextClassifier has been set, this WebView uses the default set by the system.
+ * @hide
*/
@NonNull
public TextClassifier getTextClassifier() {
@@ -2506,6 +2508,7 @@
super.onDetachedFromWindowInternal();
}
+ /** @hide */
@Override
public void onMovedToDisplay(int displayId, Configuration config) {
mProvider.getViewDelegate().onMovedToDisplay(displayId, config);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 406386aa..bde1708 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -56,6 +56,7 @@
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.fonts.FontVariationAxis;
+import android.graphics.fonts.FontVariationAxis.InvalidFormatException;
import android.icu.text.DecimalFormatSymbols;
import android.os.AsyncTask;
import android.os.Build.VERSION_CODES;
@@ -125,6 +126,7 @@
import android.view.DragEvent;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
+import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -394,6 +396,14 @@
private TextClassifier mTextClassifier;
+ // A flag to prevent repeated movements from escaping the enclosing text view. The idea here is
+ // that if a user is holding down a movement key to traverse text, we shouldn't also traverse
+ // the view hierarchy. On the other hand, if the user is using the movement key to traverse
+ // views (i.e. the first movement was to traverse out of this view, or this view was traversed
+ // into by the user holding the movement key down) then we shouldn't prevent the focus from
+ // changing.
+ private boolean mPreventDefaultMovement;
+
private TextUtils.TruncateAt mEllipsize;
static class Drawables {
@@ -3886,26 +3896,43 @@
* are invalid. If a specified axis name is not defined in the font, the settings will be
* ignored.
*
+ * <p>
+ * Examples,
+ * <ul>
+ * <li>Set font width to 150.
* <pre>
- * textView.setFontVariationSettings("'wdth' 1.0");
- * textView.setFontVariationSettings("'AX ' 1.8, 'FB ' 2.0");
+ * <code>
+ * TextView textView = (TextView) findViewById(R.id.textView);
+ * textView.setFontVariationSettings("'wdth' 150");
+ * </code>
* </pre>
+ * </li>
+ *
+ * <li>Set the font slant to 20 degrees and ask for italic style.
+ * <pre>
+ * <code>
+ * TextView textView = (TextView) findViewById(R.id.textView);
+ * textView.setFontVariationSettings("'slnt' 20, 'ital' 1");
+ * </code>
+ * </pre>
+ * </p>
+ * </li>
+ * </ul>
*
* @param fontVariationSettings font variation settings. You can pass null or empty string as
* no variation settings.
- *
* @return true if the given settings is effective to at least one font file underlying this
* TextView. This function also returns true for empty settings string. Otherwise
* returns false.
*
- * @throws FontVariationAxis.InvalidFormatException
- * If given string is not a valid font variation settings format.
+ * @throws InvalidFormatException If given string is not a valid font variation settings
+ * format.
*
* @see #getFontVariationSettings()
- * @see Paint#getFontVariationSettings() Paint.getFontVariationSettings()
+ * @see FontVariationAxis
*/
public boolean setFontVariationSettings(@Nullable String fontVariationSettings)
- throws FontVariationAxis.InvalidFormatException {
+ throws InvalidFormatException {
final String existingSettings = mTextPaint.getFontVariationSettings();
if (fontVariationSettings == existingSettings
|| (fontVariationSettings != null
@@ -7137,6 +7164,15 @@
return KEY_EVENT_NOT_HANDLED;
}
+ // If this is the initial keydown, we don't want to prevent a movement away from this view.
+ // While this shouldn't be necessary because any time we're preventing default movement we
+ // should be restricting the focus to remain within this view, thus we'll also receive
+ // the key up event, occasionally key up events will get dropped and we don't want to
+ // prevent the user from traversing out of this on the next key down.
+ if (event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(keyCode)) {
+ mPreventDefaultMovement = false;
+ }
+
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
if (event.hasNoModifiers()) {
@@ -7268,16 +7304,23 @@
}
if (doDown) {
if (mMovement.onKeyDown(this, (Spannable) mText, keyCode, event)) {
+ if (event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(keyCode)) {
+ mPreventDefaultMovement = true;
+ }
return KEY_DOWN_HANDLED_BY_MOVEMENT_METHOD;
}
}
- // Consume arrows to prevent focus leaving the editor.
- if (isDirectionalNavigationKey(keyCode)) {
+ // Consume arrows from keyboard devices to prevent focus leaving the editor.
+ // DPAD/JOY devices (Gamepads, TV remotes) often lack a TAB key so allow those
+ // to move focus with arrows.
+ if (event.getSource() == InputDevice.SOURCE_KEYBOARD
+ && isDirectionalNavigationKey(keyCode)) {
return KEY_EVENT_HANDLED;
}
}
- return KEY_EVENT_NOT_HANDLED;
+ return mPreventDefaultMovement && !KeyEvent.isModifierKey(keyCode)
+ ? KEY_EVENT_HANDLED : KEY_EVENT_NOT_HANDLED;
}
/**
@@ -7310,6 +7353,10 @@
return super.onKeyUp(keyCode, event);
}
+ if (!KeyEvent.isModifierKey(keyCode)) {
+ mPreventDefaultMovement = false;
+ }
+
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
if (event.hasNoModifiers()) {
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index c6b6a7fb..d2e9789 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -65,6 +65,7 @@
int mChangeType;
int mChangeUserId = UserHandle.USER_NULL;
boolean mSomePackagesChanged;
+ String[] mModifiedComponents;
String[] mTempArray = new String[1];
@@ -269,6 +270,18 @@
}
return false;
}
+
+ public boolean isComponentModified(String className) {
+ if (className == null || mModifiedComponents == null) {
+ return false;
+ }
+ for (int i = mModifiedComponents.length - 1; i >= 0; i--) {
+ if (className.equals(mModifiedComponents[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
public void onSomePackagesChanged() {
}
@@ -301,6 +314,7 @@
mDisappearingPackages = mAppearingPackages = null;
mSomePackagesChanged = false;
+ mModifiedComponents = null;
String action = intent.getAction();
if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
@@ -358,13 +372,13 @@
} else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
String pkg = getPackageName(intent);
int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
- String[] components = intent.getStringArrayExtra(
+ mModifiedComponents = intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
if (pkg != null) {
mModifiedPackages = mTempArray;
mTempArray[0] = pkg;
mChangeType = PACKAGE_PERMANENT_CHANGE;
- if (onPackageChanged(pkg, uid, components)) {
+ if (onPackageChanged(pkg, uid, mModifiedComponents)) {
mSomePackagesChanged = true;
}
onPackageModified(pkg);
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 5cb66e5..2c97f8b 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -257,7 +257,7 @@
* @return a color with the same hue as {@param color}, potentially darkened to meet the
* contrast ratio.
*/
- private static int findContrastColor(int color, int other, boolean findFg, double minRatio) {
+ public static int findContrastColor(int color, int other, boolean findFg, double minRatio) {
int fg = findFg ? color : other;
int bg = findFg ? other : color;
if (ColorUtilsFromCompat.calculateContrast(fg, bg) >= minRatio) {
@@ -402,16 +402,17 @@
}
/**
- * Lighten a color by a specified value
+ * Change a color by a specified value
* @param baseColor the base color to lighten
* @param amount the amount to lighten the color from 0 to 100. This corresponds to the L
- * increase in the LAB color space.
- * @return the lightened color
+ * increase in the LAB color space. A negative value will darken the color and
+ * a positive will lighten it.
+ * @return the changed color
*/
- public static int lightenColor(int baseColor, int amount) {
+ public static int changeColorLightness(int baseColor, int amount) {
final double[] result = ColorUtilsFromCompat.getTempDouble3Array();
ColorUtilsFromCompat.colorToLAB(baseColor, result);
- result[0] = Math.min(100, result[0] + amount);
+ result[0] = Math.max(Math.min(100, result[0] + amount), 0);
return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]);
}
@@ -491,6 +492,15 @@
return useDark;
}
+ public static double calculateLuminance(int backgroundColor) {
+ return ColorUtilsFromCompat.calculateLuminance(backgroundColor);
+ }
+
+
+ public static double calculateContrast(int foregroundColor, int backgroundColor) {
+ return ColorUtilsFromCompat.calculateContrast(foregroundColor, backgroundColor);
+ }
+
/**
* Framework copy of functions needed from android.support.v4.graphics.ColorUtils.
*/
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index afb2a5e..bbebcc2 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -23,7 +23,6 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.RelativeLayout;
import android.widget.RemoteViews;
/**
@@ -34,8 +33,7 @@
@RemoteViews.RemoteView
public class MediaNotificationView extends FrameLayout {
- private final int mMaxImageSize;
- private final int mImageMinTopMargin;
+ private final int mSmallImageSize;
private final int mNotificationContentMarginEnd;
private final int mNotificationContentImageMarginEnd;
private ImageView mRightIcon;
@@ -57,72 +55,68 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int mode = MeasureSpec.getMode(widthMeasureSpec);
boolean hasIcon = mRightIcon.getVisibility() != GONE;
+ if (!hasIcon) {
+ resetHeaderIndention();
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int mode = MeasureSpec.getMode(widthMeasureSpec);
+ boolean reMeasure = false;
if (hasIcon && mode != MeasureSpec.UNSPECIFIED) {
- measureChild(mActions, widthMeasureSpec, heightMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
size = size - mActions.getMeasuredWidth();
ViewGroup.MarginLayoutParams layoutParams =
(MarginLayoutParams) mRightIcon.getLayoutParams();
int imageEndMargin = layoutParams.getMarginEnd();
size -= imageEndMargin;
- size = Math.min(size, mMaxImageSize);
- size = Math.max(size, mRightIcon.getMinimumWidth());
- layoutParams.width = size;
- layoutParams.height = size;
- mRightIcon.setLayoutParams(layoutParams);
-
- // lets ensure that the main column doesn't run into the image
- ViewGroup.MarginLayoutParams mainParams
- = (MarginLayoutParams) mMainColumn.getLayoutParams();
- int marginEnd = size + imageEndMargin + mNotificationContentMarginEnd;
- if (marginEnd != mainParams.getMarginEnd()) {
- mainParams.setMarginEnd(marginEnd);
- mMainColumn.setLayoutParams(mainParams);
+ int fullHeight = getMeasuredHeight();
+ if (size < fullHeight) {
+ size = mSmallImageSize;
+ } else {
+ size = fullHeight;
}
-
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- ViewGroup.MarginLayoutParams iconParams =
- (MarginLayoutParams) mRightIcon.getLayoutParams();
- int topMargin = getMeasuredHeight() - mRightIcon.getMeasuredHeight()
- - iconParams.bottomMargin;
- // If the topMargin is high enough we can also remove the header constraint!
- boolean reMeasure = false;
- if (!hasIcon || topMargin >= mImageMinTopMargin) {
- reMeasure = resetHeaderIndention();
- } else {
- int paddingEnd = mNotificationContentImageMarginEnd;
- ViewGroup.MarginLayoutParams headerParams =
- (MarginLayoutParams) mHeader.getLayoutParams();
- int newMarginEnd = mRightIcon.getMeasuredWidth() + iconParams.getMarginEnd();
- if (headerParams.getMarginEnd() != newMarginEnd) {
- headerParams.setMarginEnd(newMarginEnd);
- mHeader.setLayoutParams(headerParams);
+ if (layoutParams.width != size || layoutParams.height != size) {
+ layoutParams.width = size;
+ layoutParams.height = size;
+ mRightIcon.setLayoutParams(layoutParams);
reMeasure = true;
}
- if (mHeader.getPaddingEnd() != paddingEnd) {
+
+ // lets ensure that the main column doesn't run into the image
+ ViewGroup.MarginLayoutParams params
+ = (MarginLayoutParams) mMainColumn.getLayoutParams();
+ int marginEnd = size + imageEndMargin + mNotificationContentMarginEnd;
+ if (marginEnd != params.getMarginEnd()) {
+ params.setMarginEnd(marginEnd);
+ mMainColumn.setLayoutParams(params);
+ reMeasure = true;
+ }
+ int headerMarginEnd = size + imageEndMargin;
+ params = (MarginLayoutParams) mHeader.getLayoutParams();
+ if (params.getMarginEnd() != headerMarginEnd) {
+ params.setMarginEnd(headerMarginEnd);
+ mHeader.setLayoutParams(params);
+ reMeasure = true;
+ }
+ if (mHeader.getPaddingEnd() != mNotificationContentImageMarginEnd) {
mHeader.setPaddingRelative(mHeader.getPaddingStart(),
mHeader.getPaddingTop(),
- paddingEnd,
+ mNotificationContentImageMarginEnd,
mHeader.getPaddingBottom());
reMeasure = true;
}
}
if (reMeasure) {
- measureChildWithMargins(mHeader, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
- private boolean resetHeaderIndention() {
- boolean remeasure = false;
+ private void resetHeaderIndention() {
if (mHeader.getPaddingEnd() != mNotificationContentMarginEnd) {
mHeader.setPaddingRelative(mHeader.getPaddingStart(),
mHeader.getPaddingTop(),
mNotificationContentMarginEnd,
mHeader.getPaddingBottom());
- remeasure = true;
}
ViewGroup.MarginLayoutParams headerParams =
(MarginLayoutParams) mHeader.getLayoutParams();
@@ -130,19 +124,14 @@
if (headerParams.getMarginEnd() != 0) {
headerParams.setMarginEnd(0);
mHeader.setLayoutParams(headerParams);
- remeasure = true;
}
- return remeasure;
}
public MediaNotificationView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mMaxImageSize = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.media_notification_expanded_image_max_size);
- mImageMinTopMargin = (int) (context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_top)
- + getResources().getDisplayMetrics().density * 2);
+ mSmallImageSize = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.media_notification_expanded_image_small_size);
mNotificationContentMarginEnd = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_end);
mNotificationContentImageMarginEnd = context.getResources().getDimensionPixelSize(
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index 4b31c91..ba23450 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -80,14 +80,10 @@
}
return NULL;
}
- uint64_t producerUsage = 0;
- uint64_t consumerUsage = 0;
- android_hardware_HardwareBuffer_convertToGrallocUsageBits(
- &producerUsage, &consumerUsage, usage, 0);
+ uint64_t grallocUsage = AHardwareBuffer_convertToGrallocUsageBits(usage);
sp<GraphicBuffer> buffer = new GraphicBuffer(width, height, pixelFormat, layers,
- android_convertGralloc1To0Usage(producerUsage, consumerUsage),
- std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]");
+ grallocUsage, std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]");
status_t error = buffer->initCheck();
if (error < 0) {
if (kDebugGraphicBuffer) {
@@ -145,11 +141,7 @@
static jlong android_hardware_HardwareBuffer_getUsage(JNIEnv* env,
jobject clazz, jlong nativeObject) {
GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
- uint64_t usage0 = 0;
- uint64_t usage1 = 0;
- android_hardware_HardwareBuffer_convertFromGrallocUsageBits(&usage0, &usage1,
- buffer->getUsage(), buffer->getUsage());
- return usage0;
+ return AHardwareBuffer_convertFromGrallocUsageBits(buffer->getUsage());
}
// ----------------------------------------------------------------------------
@@ -221,14 +213,8 @@
return AHardwareBuffer_convertToPixelFormat(format);
}
-void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t* outProducerUsage,
- uint64_t* outConsumerUsage, uint64_t usage0, uint64_t usage1) {
- AHardwareBuffer_convertToGrallocUsageBits(outProducerUsage, outConsumerUsage, usage0, usage1);
-}
-
-void android_hardware_HardwareBuffer_convertFromGrallocUsageBits(uint64_t* outUsage0,
- uint64_t* outUsage1, uint64_t producerUsage, uint64_t consumerUsage) {
- AHardwareBuffer_convertFromGrallocUsageBits(outUsage0, outUsage1, producerUsage, consumerUsage);
+uint64_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage) {
+ return AHardwareBuffer_convertToGrallocUsageBits(usage);
}
} // namespace android
diff --git a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
index 3545c56..c452b74 100644
--- a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
+++ b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
@@ -32,22 +32,19 @@
JNIEnv* env, AHardwareBuffer* hardwareBuffer);
/* Convert from HAL_PIXEL_FORMAT values to AHARDWAREBUFFER_FORMAT values. */
-extern uint32_t android_hardware_HardwareBuffer_convertFromPixelFormat(
- uint32_t format);
+extern uint32_t android_hardware_HardwareBuffer_convertFromPixelFormat(uint32_t format);
/* Convert from AHARDWAREBUFFER_FORMAT values to HAL_PIXEL_FORMAT values. */
-extern uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(
- uint32_t format);
+extern uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(uint32_t format);
/* Convert from AHARDWAREBUFFER_USAGE* flags to to gralloc usage flags. */
-extern void android_hardware_HardwareBuffer_convertToGrallocUsageBits(
- uint64_t* outProducerUsage, uint64_t* outConsumerUsage, uint64_t usage0,
- uint64_t usage1);
+extern uint64_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage);
-/* Convert from gralloc usage flags to to AHARDWAREBUFFER_USAGE0* flags. */
-extern void android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
- uint64_t* outUsage0, uint64_t* outUsage1, uint64_t producerUsage,
- uint64_t consumerUsage);
+inline void android_hardware_HardwareBuffer_convertToGrallocUsageBits(
+ uint64_t* outProducerUsage, uint64_t* outConsumerUsage, uint64_t usage, uint64_t) {
+ outProducerUsage[0] = outConsumerUsage[0] =
+ android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage);
+}
} // namespace android
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index 04ea12d..532f28e 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -23,6 +23,13 @@
android:background="#00000000"
android:tag="bigMediaNarrow"
>
+ <!-- The size will actually be determined at runtime -->
+ <ImageView android:id="@+id/right_icon"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_gravity="top|end"
+ android:scaleType="centerCrop"
+ />
<include layout="@layout/notification_template_header"
android:layout_width="match_parent"
android:layout_height="53dp"
@@ -60,14 +67,4 @@
<!-- media buttons will be added here -->
</LinearLayout>
</LinearLayout>
-
- <ImageView android:id="@+id/right_icon"
- android:layout_width="@dimen/media_notification_expanded_image_max_size"
- android:layout_height="@dimen/media_notification_expanded_image_max_size"
- android:minWidth="40dp"
- android:layout_marginEnd="16dp"
- android:layout_marginBottom="20dp"
- android:layout_gravity="bottom|end"
- android:scaleType="centerCrop"
- />
</com.android.internal.widget.MediaNotificationView>
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 4c64207..4be53e0 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -23,6 +23,13 @@
android:background="#00000000"
android:tag="media"
>
+ <ImageView android:id="@+id/right_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="true"
+ android:layout_gravity="top|end"
+ android:scaleType="centerCrop"
+ />
<include layout="@layout/notification_template_header"
android:layout_width="fill_parent"
android:layout_height="53dp" />
@@ -61,5 +68,4 @@
<!-- media buttons will be added here -->
</LinearLayout>
</LinearLayout>
- <include layout="@layout/notification_template_right_icon" />
</FrameLayout>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c5316c6..ef6c21f 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -208,8 +208,8 @@
<!-- The minimum height of the content if there are at least two lines or a picture-->
<dimen name="notification_min_content_height">41dp</dimen>
- <!-- The maximum size of the image in the expanded media notification -->
- <dimen name="media_notification_expanded_image_max_size">94dp</dimen>
+ <!-- The small size of the image if the height drawing doesn't work anymore -->
+ <dimen name="media_notification_expanded_image_small_size">72dp</dimen>
<!-- The maximum size of the image in the expanded media notification -->
<dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 63a5cfd7..0ea9b39 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -598,11 +598,9 @@
<java-symbol type="string" name="badPin" />
<java-symbol type="string" name="badPuk" />
<java-symbol type="string" name="byteShort" />
- <java-symbol type="string" name="capability_desc_canRequestEnhancedWebAccessibility" />
<java-symbol type="string" name="capability_title_canRequestFilterKeyEvents" />
<java-symbol type="string" name="capability_desc_canRequestTouchExploration" />
<java-symbol type="string" name="capability_desc_canRetrieveWindowContent" />
- <java-symbol type="string" name="capability_title_canRequestEnhancedWebAccessibility" />
<java-symbol type="string" name="capability_desc_canRequestFilterKeyEvents" />
<java-symbol type="string" name="capability_title_canRequestTouchExploration" />
<java-symbol type="string" name="capability_title_canRetrieveWindowContent" />
@@ -2616,7 +2614,7 @@
<java-symbol type="string" name="new_sms_notification_title" />
<java-symbol type="string" name="new_sms_notification_content" />
- <java-symbol type="dimen" name="media_notification_expanded_image_max_size" />
+ <java-symbol type="dimen" name="media_notification_expanded_image_small_size" />
<java-symbol type="dimen" name="media_notification_expanded_image_margin_bottom" />
<java-symbol type="dimen" name="notification_content_image_margin_end" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ad4afae..ba24eec 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -37,8 +37,7 @@
/** Tests that ensure appropriate settings are backed up. */
@RunWith(AndroidJUnit4.class)
-// TODO(b/37684646): Can re-enable pre-submit once test is fixed.
-//@Presubmit
+@Presubmit
@SmallTest
public class SettingsBackupTest {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 828729a..81bd6ad 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -21,6 +21,7 @@
import android.annotation.Size;
import android.graphics.FontListParser;
import android.graphics.fonts.FontVariationAxis;
+import android.graphics.fonts.FontVariationAxis.InvalidFormatException;
import android.os.LocaleList;
import android.text.FontConfig;
import android.text.GraphicsOperations;
@@ -1539,25 +1540,49 @@
}
/**
- * Set font variation settings.
+ * 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.
*
- * This function does nothing if none of the settings is applicable to underlying font files.
+ * Examples,
+ * <ul>
+ * <li>Set font width to 150.
+ * <pre>
+ * <code>
+ * Paint paint = new Paint();
+ * paint.setFontVariationSettings("'wdth' 150");
+ * </code>
+ * </pre>
+ * </li>
*
- * @param settings font variation settings, e.g. "'wdth' 300, 'wght' 1.8"
+ * <li>Set the font slant to 20 degrees and ask for italic style.
+ * <pre>
+ * <code>
+ * Paint paint = new Paint();
+ * paint.setFontVariationSettings("'slnt' 20, 'ital' 1");
+ * </code>
+ * </pre>
+ * </li>
+ * </ul>
*
- * @see #getFontVariationSettings()
+ * @param fontVariationSettings font variation settings. You can pass null or empty string as
+ * no variation settings.
*
- * @param settings the font variation settings. You can pass null or empty string as no
- * variation settings.
* @return true if the given settings is effective to at least one font file underlying this
* typeface. This function also returns true for empty settings string. Otherwise
* returns false
- * @throws FontVariationAxis.InvalidFormatException
- * If given string is not a valid font variation settings format.
+ *
+ * @throws InvalidFormatException If given string is not a valid font variation settings format.
+ *
+ * @see #getFontVariationSettings()
+ * @see FontVariationAxis
*/
- public boolean setFontVariationSettings(String settings)
- throws FontVariationAxis.InvalidFormatException {
- settings = TextUtils.nullIfEmpty(settings);
+ public boolean setFontVariationSettings(String fontVariationSettings)
+ throws InvalidFormatException {
+ final String settings = TextUtils.nullIfEmpty(fontVariationSettings);
if (settings == mFontVariationSettings
|| (settings != null && settings.equals(mFontVariationSettings))) {
return true;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 09840a5..f661f29b 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -6664,6 +6664,10 @@
return NO_ERROR;
}
+void DynamicRefTable::addMapping(uint8_t buildPackageId, uint8_t runtimePackageId) {
+ mLookupTable[buildPackageId] = runtimePackageId;
+}
+
status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const {
uint32_t res = *resId;
size_t packageId = Res_GETPACKAGE(res) + 1;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 306ff9a..7a6e37d 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1610,6 +1610,8 @@
// the given package.
status_t addMapping(const String16& packageName, uint8_t packageId);
+ void addMapping(uint8_t buildPackageId, uint8_t runtimePackageId);
+
// Performs the actual conversion of build-time resource ID to run-time
// resource ID.
status_t lookupResourceId(uint32_t* resId) const;
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 0c7bb60..dd45786 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -88,7 +88,8 @@
}; \
INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \
INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); \
+ /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
+ /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread)
/**
@@ -111,7 +112,8 @@
static void doTheThing(renderthread::RenderThread& renderThread); \
}; \
INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); \
+ /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
+ /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread)
/**
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 06555c1..ccdf5ae 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -728,15 +728,15 @@
if (format == ImageFormat.PRIVATE) {
// Usage need to be either USAGE0_GPU_SAMPLED_IMAGE or USAGE0_VIDEO_ENCODE or combined.
- boolean isAllowed = (usage == HardwareBuffer.USAGE0_GPU_SAMPLED_IMAGE);
- isAllowed = isAllowed || (usage == HardwareBuffer.USAGE0_VIDEO_ENCODE);
+ boolean isAllowed = (usage == HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
+ isAllowed = isAllowed || (usage == HardwareBuffer.USAGE_VIDEO_ENCODE);
isAllowed = isAllowed || (usage ==
- (HardwareBuffer.USAGE0_VIDEO_ENCODE | HardwareBuffer.USAGE0_GPU_SAMPLED_IMAGE));
+ (HardwareBuffer.USAGE_VIDEO_ENCODE | HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE));
return isAllowed;
} else {
// Usage need to make the buffer CPU readable for explicit format.
- return ((usage == HardwareBuffer.USAGE0_CPU_READ) ||
- (usage == HardwareBuffer.USAGE0_CPU_READ_OFTEN));
+ return ((usage == HardwareBuffer.USAGE_CPU_READ_RARELY) ||
+ (usage == HardwareBuffer.USAGE_CPU_READ_OFTEN));
}
}
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index e450283..2ef1cf5 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -33,6 +33,7 @@
<receiver android:name="com.android.carrierdefaultapp.CarrierDefaultBroadcastReceiver">
<intent-filter>
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
+ <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
</intent-filter>
</receiver>
<service android:name="com.android.carrierdefaultapp.ProvisionObserver"
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
index e1125d9..d5d0b79 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
@@ -91,6 +91,10 @@
arg1 = intent.getStringExtra(TelephonyIntents.EXTRA_APN_TYPE_KEY);
arg2 = intent.getStringExtra(TelephonyIntents.EXTRA_ERROR_CODE_KEY);
break;
+ case TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET:
+ configs = b.getStringArray(CarrierConfigManager
+ .KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET);
+ break;
default:
Rlog.e(TAG, "load carrier config failure with un-configured key: " +
intent.getAction());
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index 11c858f..2a4ab0f 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -35,7 +35,7 @@
import android.bluetooth.le.ScanSettings;
import android.companion.AssociationRequest;
import android.companion.BluetoothDeviceFilter;
-import android.companion.BluetoothLEDeviceFilter;
+import android.companion.BluetoothLeDeviceFilter;
import android.companion.DeviceFilter;
import android.companion.ICompanionDeviceDiscoveryService;
import android.companion.ICompanionDeviceDiscoveryServiceCallback;
@@ -79,7 +79,7 @@
private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build();
private List<DeviceFilter<?>> mFilters;
- private List<BluetoothLEDeviceFilter> mBLEFilters;
+ private List<BluetoothLeDeviceFilter> mBLEFilters;
private List<BluetoothDeviceFilter> mBluetoothFilters;
private List<WifiDeviceFilter> mWifiFilters;
private List<ScanFilter> mBLEScanFilters;
@@ -144,8 +144,8 @@
mFilters = request.getDeviceFilters();
mWifiFilters = CollectionUtils.filter(mFilters, WifiDeviceFilter.class);
mBluetoothFilters = CollectionUtils.filter(mFilters, BluetoothDeviceFilter.class);
- mBLEFilters = CollectionUtils.filter(mFilters, BluetoothLEDeviceFilter.class);
- mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLEDeviceFilter::getScanFilter);
+ mBLEFilters = CollectionUtils.filter(mFilters, BluetoothLeDeviceFilter.class);
+ mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter);
reset();
} else if (DEBUG) Log.i(LOG_TAG, "startDiscovery: duplicate request: " + request);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 49fc2ea..32e6389 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -35,8 +35,8 @@
import android.os.UserManager;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
-import android.text.Spanned;
import android.text.SpannableStringBuilder;
+import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.view.MenuItem;
@@ -75,41 +75,52 @@
*/
public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
String userRestriction, int userId) {
- DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (dpm == null) {
return null;
}
- UserManager um = UserManager.get(context);
- int restrictionSource = um.getUserRestrictionSource(userRestriction,
- UserHandle.of(userId));
- // If the restriction is not enforced or enforced only by system then return null
- if (restrictionSource == UserManager.RESTRICTION_NOT_SET
- || restrictionSource == UserManager.RESTRICTION_SOURCE_SYSTEM) {
+ final UserManager um = UserManager.get(context);
+ final List<UserManager.EnforcingUser> enforcingUsers =
+ um.getUserRestrictionSources(userRestriction, UserHandle.of(userId));
+
+ if (enforcingUsers.isEmpty()) {
+ // Restriction is not enforced.
return null;
+ } else if (enforcingUsers.size() > 1) {
+ return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
- final boolean enforcedByProfileOwner =
- (restrictionSource & UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) != 0;
- final boolean enforcedByDeviceOwner =
- (restrictionSource & UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) != 0;
- if (enforcedByProfileOwner) {
- return getProfileOwner(context, userId);
- } else if (enforcedByDeviceOwner) {
+ final int restrictionSource = enforcingUsers.get(0).getUserRestrictionSource();
+ final int adminUserId = enforcingUsers.get(0).getUserHandle().getIdentifier();
+
+ if (restrictionSource == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) {
+ // Check if it is a profile owner of the user under consideration.
+ if (adminUserId == userId) {
+ return getProfileOwner(context, adminUserId);
+ } else {
+ // Check if it is a profile owner of a managed profile of the current user.
+ // Otherwise it is in a separate user and we return a default EnforcedAdmin.
+ final UserInfo parentUser = um.getProfileParent(adminUserId);
+ return (parentUser != null && parentUser.id == userId)
+ ? getProfileOwner(context, adminUserId)
+ : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+ }
+ } else if (restrictionSource == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) {
// When the restriction is enforced by device owner, return the device owner admin only
// if the admin is for the {@param userId} otherwise return a default EnforcedAdmin.
- final EnforcedAdmin deviceOwner = getDeviceOwner(context);
- return deviceOwner.userId == userId
- ? deviceOwner
- : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+ return adminUserId == userId
+ ? getDeviceOwner(context) : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
+
+ // If the restriction is enforced by system then return null.
return null;
}
public static boolean hasBaseUserRestriction(Context context,
String userRestriction, int userId) {
- UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
return um.hasBaseUserRestriction(userRestriction, UserHandle.of(userId));
}
@@ -424,7 +435,6 @@
if (dpm == null) {
return null;
}
- LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
EnforcedAdmin enforcedAdmin = null;
final int userId = UserHandle.myUserId();
final UserManager um = UserManager.get(context);
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 2f52227..1efa3a8 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -102,6 +102,9 @@
<string name="keyguard_widget_12_hours_format" translatable="false">h\uee01mm</string>
<!-- Time format strings for fall-back clock widget -->
<string name="keyguard_widget_24_hours_format" translatable="false">kk\uee01mm</string>
+ <!-- The character used in keyguard_widget_12_hours_format and keyguard_widget_24_hours_format
+ to represent a ":". -->
+ <string name="keyguard_fancy_colon" translatable="false">\uee01</string>
<!-- Accessibility description of the PIN password view. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_pin_area">PIN area</string>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
index be9a7e2..d7463a4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="17dp"
- android:height="17dp"
- android:viewportWidth="12.0"
- android:viewportHeight="12.0">
+ android:width="8.5dp"
+ android:height="17dp"
+ android:viewportWidth="12.0"
+ android:viewportHeight="24.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/stat_sys_data_fully_connected_3g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
index fd7a658..6309b6d 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="17dp"
+ android:width="9.208dp"
android:height="17dp"
android:viewportWidth="13.0"
- android:viewportHeight="13.0">
+ android:viewportHeight="24.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/stat_sys_data_fully_connected_4g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
index 02c4ab6..4067ae5 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="17dp"
+ android:width="8.5dp"
android:height="17dp"
android:viewportWidth="12.0"
- android:viewportHeight="12.0">
+ android:viewportHeight="24.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/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
index daf4061..3cdd3e1 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="25.5dp"
+ android:width="17.0dp"
android:height="17.0dp"
- android:viewportWidth="18.0"
- android:viewportHeight="12.0">
+ android:viewportWidth="24.0"
+ 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/stat_sys_data_fully_connected_e.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
index cd0cc65..acaa9b1 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="7.083dp"
+ android:width="3.541dp"
android:height="17dp"
android:viewportWidth="5.0"
- android:viewportHeight="12.0">
+ android:viewportHeight="24.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/stat_sys_data_fully_connected_g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
index 92ed49c..7985237 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="9.154dp"
+ android:width="4.958dp"
android:height="17dp"
android:viewportWidth="7.0"
- android:viewportHeight="13">
+ android:viewportHeight="24.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/stat_sys_data_fully_connected_h.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
index ca61b6f..fda8761 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="9.5dp"
+ android:width="4.25dp"
android:height="17dp"
android:viewportWidth="6.0"
- android:viewportHeight="12.0">
+ android:viewportHeight="24.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/stat_sys_data_fully_connected_lte.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
index add96b4..c08ff20 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18.417dp"
+ android:width="9.208dp"
android:height="17dp"
- android:viewportWidth="13"
- android:viewportHeight="12.0">
+ android:viewportWidth="13.0"
+ android:viewportHeight="24.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/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
index 8811d2f..db18fad 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="25.0dp"
+ android:width="17.0dp"
android:height="17.0dp"
- android:viewportWidth="18.0"
- android:viewportHeight="12.0">
+ android:viewportWidth="24.0"
+ 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/stat_sys_roaming.xml b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
index 363e231..4baa472 100644
--- a/packages/SystemUI/res/drawable/stat_sys_roaming.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="4.25dp"
+ android:width="8.5dp"
android:height="17dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="12.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/stat_sys_wifi_signal_disconnected.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml
deleted file mode 100644
index 8e626e9..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml
+++ /dev/null
@@ -1,41 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18.41dp"
- android:height="17dp"
- android:viewportWidth="26.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="?attr/backgroundColor"
- android:pathData="M21.0,8.5
- c0.85,0.0 1.6,0.23 2.3,0.62l2.24,-2.79
- C25.1,5.96 20.26,2.0 13.0,2.0
- S0.9,5.9 0.42,6.32
- l12.57,15.6 4.21,-5.17
- c-0.76,-0.87 -1.22,-2.0 -1.22,-3.25
- c0.0,-2.76 2.24,-5.0 5.0,-5.0z"/>
- <path
- android:fillColor="?attr/backgroundColor"
- android:pathData="M21.0,10.0
- c-1.93,0.0 -3.5,1.57 -3.5,3.5l1.75,0.0
- c0.0,-0.9 0.78,-1.75 1.75,-1.75s1.7,0.78 1.75,1.75
- c0.0,0.48 -0.2,0.92 -0.51,1.24l-1.09,1.1
- c-0.6,0.63 -1.02,1.51 -1.02,2.47l0.0,0.44l1.75,0.0
- c0.0,-1.3 0.39,-1.84 1.03,-2.47l0.78,-0.8
- c0.5,-0.5 0.82,-1.2 0.82,-1.97
- C24.5,11.57 22.93,10.0 21.0,10.0z
- m-0.95,11.95l1.9,0.0l0.0,-1.9l-1.9,0.0l0.0,1.9z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
index c1856fa..5169de4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
@@ -20,8 +20,5 @@
android:viewportHeight="24.0">
<path
android:fillColor="?attr/backgroundColor"
- 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="?attr/backgroundColor"
- 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"/>
+ 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/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 6d4365c..33effba 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -63,21 +63,20 @@
systemui:hasOverlappingRendering="false"
/>
<ImageView
- android:id="@+id/mobile_roaming"
+ android:id="@+id/mobile_type"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:src="@drawable/stat_sys_roaming"
- android:contentDescription="@string/accessibility_data_connection_roaming"
- android:visibility="gone"
/>
<ImageView
- android:id="@+id/mobile_type"
+ android:id="@+id/mobile_roaming"
android:layout_width="wrap_content"
android:layout_height="17dp"
- android:paddingStart="19dp"
+ android:paddingStart="22dp"
android:paddingTop="1.5dp"
android:paddingBottom="3dp"
android:scaleType="fitCenter"
+ android:src="@drawable/stat_sys_roaming"
+ android:contentDescription="@string/accessibility_data_connection_roaming"
android:visibility="gone" />
</FrameLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 5df50cd..9a97d60 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -53,54 +53,9 @@
android:alpha="0.0"
/>
</FrameLayout>
- <ViewStub
- android:id="@+id/connected_device_signals_stub"
- android:layout="@layout/connected_device_signal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <LinearLayout
- android:id="@+id/mobile_signal_group"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- >
- </LinearLayout>
- <View
- android:id="@+id/wifi_signal_spacer"
- android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
- android:layout_height="4dp"
- android:visibility="gone"
- />
- <FrameLayout
- android:id="@+id/no_sims_combo"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:contentDescription="@string/accessibility_no_sims">
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:theme="@style/DualToneLightTheme"
- android:id="@+id/no_sims"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:src="@drawable/stat_sys_no_sims"
- />
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:theme="@style/DualToneDarkTheme"
- android:id="@+id/no_sims_dark"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:src="@drawable/stat_sys_no_sims"
- android:alpha="0.0"
- />
- </FrameLayout>
- <View
- android:id="@+id/wifi_airplane_spacer"
- android:layout_width="@dimen/status_bar_airplane_spacer_width"
- android:layout_height="4dp"
- android:visibility="gone"
- />
<FrameLayout
android:layout_height="17dp"
- android:layout_width="wrap_content"
- android:paddingStart="2dp">
+ android:layout_width="wrap_content">
<ImageView
android:id="@+id/wifi_in"
android:layout_height="wrap_content"
@@ -142,6 +97,50 @@
android:layout_width="wrap_content"
/>
</FrameLayout>
+ <View
+ android:id="@+id/wifi_signal_spacer"
+ android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
+ android:layout_height="4dp"
+ android:visibility="gone"
+ />
+ <ViewStub
+ android:id="@+id/connected_device_signals_stub"
+ android:layout="@layout/connected_device_signal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <LinearLayout
+ android:id="@+id/mobile_signal_group"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ >
+ </LinearLayout>
+ <FrameLayout
+ android:id="@+id/no_sims_combo"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:contentDescription="@string/accessibility_no_sims">
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:theme="@style/DualToneLightTheme"
+ android:id="@+id/no_sims"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/stat_sys_no_sims"
+ />
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:theme="@style/DualToneDarkTheme"
+ android:id="@+id/no_sims_dark"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/stat_sys_no_sims"
+ android:alpha="0.0"
+ />
+ </FrameLayout>
+ <View
+ android:id="@+id/wifi_airplane_spacer"
+ android:layout_width="@dimen/status_bar_airplane_spacer_width"
+ android:layout_height="4dp"
+ android:visibility="gone"
+ />
<ImageView
android:id="@+id/airplane"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java
new file mode 100644
index 0000000..80509a6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java
@@ -0,0 +1,67 @@
+/*
+ * 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.keyguard;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.TextView;
+
+/**
+ * Replaces fancy colons with regular colons. Only works on TextViews.
+ */
+class KeyguardClockAccessibilityDelegate extends View.AccessibilityDelegate {
+ private final String mFancyColon;
+
+ public KeyguardClockAccessibilityDelegate(Context context) {
+ mFancyColon = context.getString(R.string.keyguard_fancy_colon);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(host, event);
+ CharSequence text = event.getContentDescription();
+ if (!TextUtils.isEmpty(text)) {
+ event.setContentDescription(replaceFancyColon(text));
+ }
+ }
+
+ @Override
+ public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+ CharSequence text = ((TextView) host).getText();
+ if (!TextUtils.isEmpty(text)) {
+ event.getText().add(replaceFancyColon(text));
+ }
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ if (!TextUtils.isEmpty(info.getText())) {
+ info.setText(replaceFancyColon(info.getText()));
+ }
+ if (!TextUtils.isEmpty(info.getContentDescription())) {
+ info.setContentDescription(replaceFancyColon(info.getContentDescription()));
+ }
+ }
+
+ private CharSequence replaceFancyColon(CharSequence text) {
+ return text.toString().replace(mFancyColon, ":");
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 162faa5..d4d69ff 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -38,7 +38,6 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.ChargingView;
-import java.util.Arrays;
import java.util.Locale;
public class KeyguardStatusView extends GridLayout {
@@ -121,6 +120,7 @@
mClockView = findViewById(R.id.clock_view);
mDateView.setShowCurrentUserTime(true);
mClockView.setShowCurrentUserTime(true);
+ mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
mOwnerInfo = findViewById(R.id.owner_info);
mBatteryDoze = findViewById(R.id.battery_doze);
mVisibleInDoze = new View[]{mBatteryDoze, mClockView};
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 8c4159a..9c03ea6 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -51,7 +51,7 @@
public static final int X = 0;
public static final int Y = 1;
- private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
+ private float SWIPE_ESCAPE_VELOCITY = 500f; // dp/sec
private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
private int MAX_DISMISS_VELOCITY = 4000; // dp/sec
@@ -59,6 +59,9 @@
static final float SWIPE_PROGRESS_FADE_END = 0.5f; // fraction of thumbnail width
// beyond which swipe progress->0
+ public static final float SWIPED_FAR_ENOUGH_SIZE_FRACTION = 0.6f;
+ static final float MAX_SCROLL_SIZE_FRACTION = 0.3f;
+
private float mMinSwipeProgress = 0f;
private float mMaxSwipeProgress = 1f;
@@ -363,9 +366,8 @@
// if the language is rtl we prefer swiping to the left
boolean animateLeftForRtl = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
&& isLayoutRtl;
- boolean animateLeft = velocity < 0
- || (velocity == 0 && getTranslation(animView) < 0 && !isDismissAll);
-
+ boolean animateLeft = (Math.abs(velocity) > getEscapeVelocity() && velocity < 0) ||
+ (getTranslation(animView) < 0 && !isDismissAll);
if (animateLeft || animateLeftForRtl || animateUpForMenu) {
newPos = -getSize(animView);
} else {
@@ -584,7 +586,7 @@
// maxScrollDistance
if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
float size = getSize(mCurrView);
- float maxScrollDistance = 0.25f * size;
+ float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
if (absDelta >= size) {
delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
} else {
@@ -646,7 +648,8 @@
protected boolean swipedFarEnough() {
float translation = getTranslation(mCurrView);
- return DISMISS_IF_SWIPED_FAR_ENOUGH && Math.abs(translation) > 0.4 * getSize(mCurrView);
+ return DISMISS_IF_SWIPED_FAR_ENOUGH
+ && Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(mCurrView);
}
public boolean isDismissGesture(MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index e457d72..7518527a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -77,9 +77,6 @@
BatteryMeterView battery = findViewById(R.id.battery);
battery.setForceShowPercent(true);
- // Don't show the Wi-Fi indicator here, because it is shown just below in the tile.
- SignalClusterView signalCluster = findViewById(R.id.signal_cluster);
- signalCluster.setForceBlockWifi();
mActivityStarter = Dependency.get(ActivityStarter.class);
}
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 d74e3ac..92ff17a1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -128,7 +128,7 @@
state.value = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
state.icon = ResourceIcon.get(R.drawable.ic_data_unavailable);
- state.state = cb.airplaneModeEnabled || !cb.enabled || cb.noSim ? Tile.STATE_UNAVAILABLE
+ state.state = cb.airplaneModeEnabled || !cb.enabled ? Tile.STATE_UNAVAILABLE
: state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
if (state.state == Tile.STATE_ACTIVE) {
state.icon = ResourceIcon.get(R.drawable.ic_data_on);
@@ -161,27 +161,44 @@
private static final class CallbackInfo {
boolean enabled;
+ boolean wifiEnabled;
boolean airplaneModeEnabled;
+ String signalContentDescription;
+ int dataTypeIconId;
+ String dataContentDescription;
boolean activityIn;
boolean activityOut;
+ String enabledDesc;
boolean noSim;
+ boolean isDataTypeIconWide;
boolean roaming;
}
private final class CellSignalCallback implements SignalCallback {
private final CallbackInfo mInfo = new CallbackInfo();
+ @Override
+ public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {
+ mInfo.wifiEnabled = enabled;
+ refreshState(mInfo);
+ }
@Override
- public void setMobileDataIndicators(IconState statusIcon, int statusType,
- boolean activityIn, boolean activityOut, String typeContentDescription,
- int subId, boolean roaming, boolean isEmergency) {
- if (statusIcon == null) {
+ public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
+ int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
+ String description, boolean isWide, int subId, boolean roaming) {
+ if (qsIcon == null) {
// Not data sim, don't display.
return;
}
- mInfo.enabled = statusIcon.visible;
+ mInfo.enabled = qsIcon.visible;
+ mInfo.signalContentDescription = qsIcon.contentDescription;
+ mInfo.dataTypeIconId = qsType;
+ mInfo.dataContentDescription = typeContentDescription;
mInfo.activityIn = activityIn;
mInfo.activityOut = activityOut;
+ mInfo.enabledDesc = description;
+ mInfo.isDataTypeIconWide = qsType != 0 && isWide;
mInfo.roaming = roaming;
refreshState(mInfo);
}
@@ -189,6 +206,15 @@
@Override
public void setNoSims(boolean show) {
mInfo.noSim = show;
+ if (mInfo.noSim) {
+ // Make sure signal gets cleared out when no sims.
+ mInfo.dataTypeIconId = 0;
+ // Show a No SIMs description to avoid emergency calls message.
+ mInfo.enabled = true;
+ mInfo.enabledDesc = mContext.getString(
+ R.string.keyguard_missing_sim_message_short);
+ mInfo.signalContentDescription = mInfo.enabledDesc;
+ }
refreshState(mInfo);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 469f3ad..d7eab97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -172,6 +172,11 @@
private int mOverrideTint;
private float mOverrideAmount;
private boolean mShadowHidden;
+ private boolean mWasActivatedOnDown;
+ /**
+ * Similar to mDimmed but is also true if it's not dimmable but should be
+ */
+ private boolean mNeedsDimming;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -223,7 +228,7 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mDimmed && !mActivated && ev.getActionMasked() == MotionEvent.ACTION_DOWN
+ if (mNeedsDimming && !mActivated && ev.getActionMasked() == MotionEvent.ACTION_DOWN
&& disallowSingleClick(ev) && !isTouchExplorationEnabled()) {
return true;
}
@@ -245,7 +250,10 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result;
- if (mDimmed && !isTouchExplorationEnabled() && isInteractive()) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ mWasActivatedOnDown = mActivated;
+ }
+ if ((mNeedsDimming && !mActivated) && !isTouchExplorationEnabled() && isInteractive()) {
boolean wasActivated = mActivated;
result = handleTouchEventDimmed(event);
if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
@@ -282,9 +290,21 @@
}
private boolean handleTouchEventDimmed(MotionEvent event) {
+ if (mNeedsDimming && !mDimmed) {
+ // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple
+ super.onTouchEvent(event);
+ }
return mDoubleTapHelper.onTouchEvent(event, getActualHeight());
}
+ @Override
+ public boolean performClick() {
+ if (mWasActivatedOnDown || !mNeedsDimming) {
+ return super.performClick();
+ }
+ return false;
+ }
+
private void makeActive() {
mFalsingManager.onNotificationActive();
startActivateAnimation(false /* reverse */);
@@ -298,6 +318,9 @@
if (!isAttachedToWindow()) {
return;
}
+ if (!isDimmable()) {
+ return;
+ }
int widthHalf = mBackgroundNormal.getWidth()/2;
int heightHalf = mBackgroundNormal.getActualHeight()/2;
float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf);
@@ -371,6 +394,8 @@
}
public void setDimmed(boolean dimmed, boolean fade) {
+ mNeedsDimming = dimmed;
+ dimmed &= isDimmable();
if (mDimmed != dimmed) {
mDimmed = dimmed;
resetBackgroundAlpha();
@@ -382,6 +407,10 @@
}
}
+ public boolean isDimmable() {
+ return true;
+ }
+
public void setDark(boolean dark, boolean fade, long delay) {
super.setDark(dark, fade, delay);
if (mDark == dark) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index dff09bd..8c1b334 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar;
-import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler;
+import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -47,6 +47,7 @@
import android.widget.ImageView;
import android.widget.RemoteViews;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.NotificationColorUtil;
@@ -61,7 +62,6 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.statusbar.NotificationGuts.GutsContent;
import com.android.systemui.statusbar.notification.HybridNotificationView;
-import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationInflater;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
@@ -314,14 +314,13 @@
}
}
- public void updateNotification(NotificationData.Entry entry) throws InflationException {
+ public void updateNotification(NotificationData.Entry entry) {
mEntry = entry;
mStatusBarNotification = entry.notification;
mNotificationInflater.inflateNotificationViews();
- onNotificationUpdated();
}
- private void onNotificationUpdated() {
+ public void onNotificationUpdated() {
for (NotificationContentView l : mLayouts) {
l.onNotificationUpdated(mEntry);
}
@@ -361,6 +360,14 @@
expandedIcon.setStaticDrawableColor(color);
}
+ @Override
+ public boolean isDimmable() {
+ if (!getShowingLayout().isDimmable()) {
+ return false;
+ }
+ return super.isDimmable();
+ }
+
private void updateLimits() {
for (NotificationContentView l : mLayouts) {
updateLimitsForView(l);
@@ -482,9 +489,7 @@
boolean childInGroup = StatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
mNotificationParent = childInGroup ? parent : null;
mPrivateLayout.setIsChildInGroup(childInGroup);
- if (mNotificationInflater.setIsChildInGroup(childInGroup)) {
- onNotificationUpdated();
- }
+ mNotificationInflater.setIsChildInGroup(childInGroup);
resetBackgroundAlpha();
updateBackgroundForGroupState();
updateClickAndFocus();
@@ -1111,14 +1116,19 @@
mNotificationInflater.setRemoteViewClickHandler(remoteViewClickHandler);
}
- public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) {
- mNotificationInflater.setInflateExceptionHandler(inflateExceptionHandler);
+ public void setInflationCallback(InflationCallback callback) {
+ mNotificationInflater.setInflationCallback(callback);
}
public void setNeedsRedaction(boolean needsRedaction) {
mNotificationInflater.setRedactAmbient(needsRedaction);
}
+ @VisibleForTesting
+ public NotificationInflater getNotificationInflater() {
+ return mNotificationInflater;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 6098565..e7bf983 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -1363,4 +1363,11 @@
public void setIsLowPriority(boolean isLowPriority) {
mIsLowPriority = isLowPriority;
}
+
+ public boolean isDimmable() {
+ if (!mContractedWrapper.isDimmable()) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 90e908b..b5f7ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager;
import android.content.Context;
import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
@@ -32,6 +33,7 @@
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews;
@@ -41,6 +43,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.NotificationInflater;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -83,6 +86,7 @@
public List<SnoozeCriterion> snoozeCriteria;
private int mCachedContrastColor = COLOR_INVALID;
private int mCachedContrastColorIsFor = COLOR_INVALID;
+ private ArraySet<AsyncTask> mRunningTasks = new ArraySet();
public Entry(StatusBarNotification n) {
this.key = n.getKey();
@@ -210,6 +214,19 @@
mCachedContrastColor = contrasted;
return mCachedContrastColor;
}
+
+ /**
+ * Abort all existing inflation tasks
+ */
+ public void abortInflation() {
+ for (AsyncTask task : mRunningTasks) {
+ task.cancel(true /* mayInterruptIfRunning */);
+ }
+ }
+
+ public void addInflationTask(AsyncTask asyncInflationTask) {
+ mRunningTasks.add(asyncInflationTask);
+ }
}
private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
@@ -302,12 +319,12 @@
return mEntries.get(key);
}
- public void add(Entry entry, RankingMap ranking) {
+ public void add(Entry entry) {
synchronized (mEntries) {
mEntries.put(entry.notification.getKey(), entry);
}
mGroupManager.onEntryAdded(entry);
- updateRankingAndSort(ranking);
+ filterAndSort();
}
public Entry remove(String key, RankingMap ranking) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 7563fd1..4305bdef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -16,13 +16,13 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
+
import java.util.ArrayList;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.NotificationGuts.GutsContent;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -46,10 +46,21 @@
public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "swipe";
+
private static final int ICON_ALPHA_ANIM_DURATION = 200;
private static final long SHOW_MENU_DELAY = 60;
private static final long SWIPE_MENU_TIMING = 200;
+ // Notification must be swiped at least this fraction of a single menu item to show menu
+ private static final float SWIPED_FAR_ENOUGH_MENU_FRACTION = 0.25f;
+ private static final float SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION = 0.15f;
+
+ // When the menu is displayed, the notification must be swiped within this fraction of a single
+ // menu item to snap back to menu (else it will cover the menu or it'll be dismissed)
+ private static final float SWIPED_BACK_ENOUGH_TO_COVER_FRACTION = 0.2f;
+
private ExpandableNotificationRow mParent;
private Context mContext;
@@ -78,6 +89,7 @@
private int mIconPadding;
private float mAlpha = 0f;
+ private float mPrevX;
private CheckForDrag mCheckForDrag;
private Handler mHandler;
@@ -203,14 +215,14 @@
}
mHandler.removeCallbacks(mCheckForDrag);
mCheckForDrag = null;
+ mPrevX = ev.getRawX();
break;
case MotionEvent.ACTION_MOVE:
mSnapping = false;
- // If the menu is visible and the movement is towards it it's not a location change.
- boolean locationChange = isTowardsMenu(mTranslation)
- ? false : isMenuLocationChange();
- if (locationChange) {
+ float diffX = ev.getRawX() - mPrevX;
+ mPrevX = ev.getRawX();
+ if (!isTowardsMenu(diffX) && isMenuLocationChange()) {
// Don't consider it "snapped" if location has changed.
mMenuSnappedTo = false;
@@ -262,36 +274,53 @@
final double timeForGesture = ev.getEventTime() - ev.getDownTime();
final boolean showMenuForSlowOnGoing = !mParent.canViewBeDismissed()
&& timeForGesture >= SWIPE_MENU_TIMING;
+ final float menuSnapTarget = mOnLeft ? getSpaceForMenu() : -getSpaceForMenu();
- final float targetLeft = mOnLeft ? getSpaceForMenu() : -getSpaceForMenu();
- if (mMenuSnappedTo && isMenuVisible()) {
- if (mMenuSnappedOnLeft == mOnLeft) {
- boolean coveringMenu = Math.abs(mTranslation) <= getSpaceForMenu() * 0.6f;
- if (gestureTowardsMenu || coveringMenu) {
- // Gesture is towards or covering the menu or a dismiss
- snapBack(animView, 0);
- } else if (mSwipeHelper.isDismissGesture(ev)) {
- dismiss(animView, velocity);
- } else {
- // Didn't move enough to dismiss or cover, snap to the menu
- showMenu(animView, targetLeft, velocity);
- }
- } else if ((!gestureFastEnough && swipedEnoughToShowMenu())
- || (gestureTowardsMenu && !gestureFarEnough)) {
- // The menu has been snapped to previously, however, the menu is now on the
- // other side. If gesture is towards menu and not too far snap to the menu.
- showMenu(animView, targetLeft, velocity);
- } else if (mSwipeHelper.isDismissGesture(ev)) {
+ if (DEBUG) {
+ Log.d(TAG, "mTranslation= " + mTranslation
+ + " mAlpha= " + mAlpha
+ + " velocity= " + velocity
+ + " mMenuSnappedTo= " + mMenuSnappedTo
+ + " mMenuSnappedOnLeft= " + mMenuSnappedOnLeft
+ + " mOnLeft= " + mOnLeft
+ + " minDismissVel= " + mSwipeHelper.getMinDismissVelocity()
+ + " isDismissGesture= " + mSwipeHelper.isDismissGesture(ev)
+ + " gestureTowardsMenu= " + gestureTowardsMenu
+ + " gestureFastEnough= " + gestureFastEnough
+ + " gestureFarEnough= " + gestureFarEnough);
+ }
+
+ if (mMenuSnappedTo && isMenuVisible() && mMenuSnappedOnLeft == mOnLeft) {
+ // Menu was snapped to previously and we're on the same side, figure out if
+ // we should stick to the menu, snap back into place, or dismiss
+ final float maximumSwipeDistance = mHorizSpaceForIcon
+ * SWIPED_BACK_ENOUGH_TO_COVER_FRACTION;
+ final float targetLeft = getSpaceForMenu() - maximumSwipeDistance;
+ final float targetRight = mParent.getWidth() * SWIPED_FAR_ENOUGH_SIZE_FRACTION;
+ boolean withinSnapMenuThreshold = mOnLeft
+ ? mTranslation > targetLeft && mTranslation < targetRight
+ : mTranslation < -targetLeft && mTranslation > -targetRight;
+ boolean shouldSnapTo = mOnLeft ? mTranslation < targetLeft : mTranslation > -targetLeft;
+ if (DEBUG) {
+ Log.d(TAG, " withinSnapMenuThreshold= " + withinSnapMenuThreshold
+ + " shouldSnapTo= " + shouldSnapTo
+ + " targetLeft= " + targetLeft
+ + " targetRight= " + targetRight);
+ }
+ if (withinSnapMenuThreshold && !mSwipeHelper.isDismissGesture(ev)) {
+ // Haven't moved enough to unsnap from the menu
+ showMenu(animView, menuSnapTarget, velocity);
+ } else if (mSwipeHelper.isDismissGesture(ev) && !shouldSnapTo) {
+ // Only dismiss if we're not moving towards the menu
dismiss(animView, velocity);
} else {
snapBack(animView, velocity);
}
- } else if (((!gestureFastEnough || showMenuForSlowOnGoing)
- && swipedEnoughToShowMenu())
- || gestureTowardsMenu) {
+ } else if ((swipedEnoughToShowMenu() && (!gestureFastEnough || showMenuForSlowOnGoing))
+ || (gestureTowardsMenu && !mSwipeHelper.isDismissGesture(ev))) {
// Menu has not been snapped to previously and this is menu revealing gesture
- showMenu(animView, targetLeft, velocity);
- } else if (mSwipeHelper.isDismissGesture(ev)) {
+ showMenu(animView, menuSnapTarget, velocity);
+ } else if (mSwipeHelper.isDismissGesture(ev) && !gestureTowardsMenu) {
dismiss(animView, velocity);
} else {
snapBack(animView, velocity);
@@ -326,14 +355,18 @@
mSwipeHelper.dismiss(animView, velocity);
}
+ /**
+ * @return whether the notification has been translated enough to show the menu and not enough
+ * to be dismissed.
+ */
private boolean swipedEnoughToShowMenu() {
- // If the notification can't be dismissed then how far it can move is
- // restricted -- reduce the distance it needs to move in this case.
- final float multiplier = mParent.canViewBeDismissed() ? 0.4f : 0.2f;
- final float snapBackThreshold = getSpaceForMenu() * multiplier;
- return !mSwipeHelper.swipedFarEnough(0, 0) && isMenuVisible() && (mOnLeft
- ? mTranslation > snapBackThreshold
- : mTranslation < -snapBackThreshold);
+ final float multiplier = mParent.canViewBeDismissed()
+ ? SWIPED_FAR_ENOUGH_MENU_FRACTION
+ : SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION;
+ final float minimumSwipeDistance = mHorizSpaceForIcon * multiplier;
+ return !mSwipeHelper.swipedFarEnough(0, 0) && isMenuVisible()
+ && (mOnLeft ? mTranslation > minimumSwipeDistance
+ : mTranslation < -minimumSwipeDistance);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index b01d9cc..dc254f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -24,6 +24,8 @@
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.telephony.SubscriptionInfo;
@@ -118,7 +120,6 @@
private boolean mBlockWifi;
private boolean mBlockEthernet;
private boolean mActivityEnabled;
- private boolean mForceBlockWifi;
public SignalClusterView(Context context) {
this(context, null);
@@ -150,16 +151,6 @@
updateActivityEnabled();
}
- public void setForceBlockWifi() {
- mForceBlockWifi = true;
- mBlockWifi = true;
- if (isAttachedToWindow()) {
- // Re-register to get new callbacks.
- mNetworkController.removeCallback(this);
- mNetworkController.addCallback(this);
- }
- }
-
@Override
public void onTuningChanged(String key, String newValue) {
if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
@@ -176,7 +167,7 @@
mBlockAirplane = blockAirplane;
mBlockMobile = blockMobile;
mBlockEthernet = blockEthernet;
- mBlockWifi = blockWifi || mForceBlockWifi;
+ mBlockWifi = blockWifi;
// Re-register to get new callbacks.
mNetworkController.removeCallback(this);
mNetworkController.addCallback(this);
@@ -297,9 +288,9 @@
}
@Override
- public void setMobileDataIndicators(IconState statusIcon, int statusType,
- boolean activityIn, boolean activityOut, String typeContentDescription,
- int subId, boolean roaming, boolean isEmergency) {
+ public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
+ int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
+ String description, boolean isWide, int subId, boolean roaming) {
PhoneState state = getState(subId);
if (state == null) {
return;
@@ -309,6 +300,7 @@
state.mMobileTypeId = statusType;
state.mMobileDescription = statusIcon.contentDescription;
state.mMobileTypeDescription = typeContentDescription;
+ state.mIsMobileTypeIconWide = statusType != 0 && isWide;
state.mRoaming = roaming;
state.mActivityIn = activityIn && mActivityEnabled;
state.mActivityOut = activityOut && mActivityEnabled;
@@ -533,7 +525,7 @@
mWifiAirplaneSpacer.setVisibility(View.GONE);
}
- if (((anyMobileVisible && firstMobileTypeId == 0) || mNoSimsVisible) && mWifiVisible) {
+ if (((anyMobileVisible && firstMobileTypeId != 0) || mNoSimsVisible) && mWifiVisible) {
mWifiSignalSpacer.setVisibility(View.VISIBLE);
} else {
mWifiSignalSpacer.setVisibility(View.GONE);
@@ -644,6 +636,7 @@
private int mMobileStrengthId = 0, mMobileTypeId = 0;
private int mLastMobileStrengthId = -1;
private int mLastMobileTypeId = -1;
+ private boolean mIsMobileTypeIconWide;
private String mMobileDescription, mMobileTypeDescription;
private ViewGroup mMobileGroup;
@@ -699,8 +692,12 @@
// When this isn't next to wifi, give it some extra padding between the signals.
mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0,
0, 0, 0);
- mMobile.setPaddingRelative(mMobileDataIconStartPadding, 0, 0, 0);
- mMobileDark.setPaddingRelative(mMobileDataIconStartPadding, 0, 0, 0);
+ mMobile.setPaddingRelative(
+ mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
+ 0, 0, 0);
+ mMobileDark.setPaddingRelative(
+ mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
+ 0, 0, 0);
if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
(mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
new file mode 100644
index 0000000..82910b8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Shader;
+import android.graphics.Xfermode;
+import android.graphics.drawable.Drawable;
+
+/**
+ * A utility class to colorize bitmaps with a color gradient and a special blending mode
+ */
+public class ImageGradientColorizer {
+ public Bitmap colorize(Drawable drawable, int backgroundColor) {
+ int width = drawable.getIntrinsicWidth();
+ int height = drawable.getIntrinsicHeight();
+ int size = Math.min(width, height);
+ int widthInset = (width - size) / 2;
+ int heightInset = (height - size) / 2;
+ drawable = drawable.mutate();
+ drawable.setBounds(- widthInset, - heightInset, width - widthInset, height - heightInset);
+ Bitmap newBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(newBitmap);
+
+ // Values to calculate the luminance of a color
+ float lr = 0.2126f;
+ float lg = 0.7152f;
+ float lb = 0.0722f;
+
+ // Extract the red, green, blue components of the color extraction color in
+ // float and int form
+ int tri = Color.red(backgroundColor);
+ int tgi = Color.green(backgroundColor);
+ int tbi = Color.blue(backgroundColor);
+
+ float tr = tri / 255f;
+ float tg = tgi / 255f;
+ float tb = tbi / 255f;
+
+ // Calculate the luminance of the color extraction color
+ float cLum = (tr * lr + tg * lg + tb * lb) * 255;
+
+ ColorMatrix m = new ColorMatrix(new float[] {
+ lr, lg, lb, 0, tri - cLum,
+ lr, lg, lb, 0, tgi - cLum,
+ lr, lg, lb, 0, tbi - cLum,
+ 0, 0, 0, 1, 0,
+ });
+
+ drawable.setColorFilter(new ColorMatrixColorFilter(m));
+ drawable.draw(canvas);
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ LinearGradient linearGradient = new LinearGradient(0, 0, size, 0,
+ new int[] {0, Color.argb(0.5f, 1, 1, 1), Color.BLACK},
+ new float[] {0.0f, 0.4f, 1.0f}, Shader.TileMode.CLAMP);
+ paint.setShader(linearGradient);
+ Bitmap fadeIn = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas fadeInCanvas = new Canvas(fadeIn);
+ drawable.clearColorFilter();
+ drawable.draw(fadeInCanvas);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
+ fadeInCanvas.drawPaint(paint);
+ canvas.drawBitmap(fadeIn, 0, 0, null);
+
+ linearGradient = new LinearGradient(0, 0, size, 0,
+ new int[] {backgroundColor, Color.argb(0.5f, tr, tg, tb), 0},
+ new float[] {0.0f, 0.6f, 1.0f}, Shader.TileMode.CLAMP);
+ paint.setShader(linearGradient);
+ paint.setXfermode(null);
+ canvas.drawPaint(paint);
+ return newBitmap;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
new file mode 100644
index 0000000..cef225b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.support.v4.graphics.ColorUtils;
+import android.support.v7.graphics.Palette;
+
+import com.android.systemui.R;
+
+import java.util.List;
+
+/**
+ * A class the processes media notifications and extracts the right text and background colors.
+ */
+public class MediaNotificationProcessor {
+
+ /**
+ * The fraction below which we select the vibrant instead of the light/dark vibrant color
+ */
+ private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 0.75f;
+ private static final float POPULATION_FRACTION_FOR_WHITE_OR_BLACK = 2.5f;
+ private static final float BLACK_MAX_LIGHTNESS = 0.08f;
+ private static final float WHITE_MIN_LIGHTNESS = 0.92f;
+ private static final int RESIZE_BITMAP_AREA = 150 * 150;
+ private final ImageGradientColorizer mColorizer;
+ private final Context mContext;
+ private float[] mFilteredBackgroundHsl = null;
+ private Palette.Filter mBlackWhiteFilter = (rgb, hsl) -> !isWhiteOrBlack(hsl);
+
+ /**
+ * The context of the notification. This is the app context of the package posting the
+ * notification.
+ */
+ private final Context mPackageContext;
+ private boolean mIsLowPriority;
+
+ public MediaNotificationProcessor(Context context, Context packageContext) {
+ mContext = context;
+ mPackageContext = packageContext;
+ mColorizer = new ImageGradientColorizer();
+ }
+
+ /**
+ * Processes a builder of a media notification and calculates the appropriate colors that should
+ * be used.
+ *
+ * @param notification the notification that is being processed
+ * @param builder the recovered builder for the notification. this will be modified
+ */
+ public void processNotification(Notification notification, Notification.Builder builder) {
+ Icon largeIcon = notification.getLargeIcon();
+ Bitmap bitmap = null;
+ Drawable drawable = null;
+ if (largeIcon != null) {
+ drawable = largeIcon.loadDrawable(mPackageContext);
+ int backgroundColor = 0;
+ if (notification.isColorizedMedia()) {
+ int width = drawable.getIntrinsicWidth();
+ int height = drawable.getIntrinsicHeight();
+ int area = width * height;
+ if (area > RESIZE_BITMAP_AREA) {
+ double factor = Math.sqrt((float) RESIZE_BITMAP_AREA / area);
+ width = (int) (factor * width);
+ height = (int) (factor * height);
+ }
+ bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, width, height);
+ drawable.draw(canvas);
+
+ // for the background we only take the left side of the image to ensure
+ // a smooth transition
+ Palette.Builder paletteBuilder = Palette.from(bitmap)
+ .setRegion(0, 0, bitmap.getWidth() / 2, bitmap.getHeight())
+ .clearFilters() // we want all colors, red / white / black ones too!
+ .resizeBitmapArea(RESIZE_BITMAP_AREA);
+ Palette palette = paletteBuilder.generate();
+ backgroundColor = findBackgroundColorAndFilter(palette);
+ // we want the full region again
+ paletteBuilder.setRegion(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ if (mFilteredBackgroundHsl != null) {
+ paletteBuilder.addFilter((rgb, hsl) -> {
+ // at least 10 degrees hue difference
+ float diff = Math.abs(hsl[0] - mFilteredBackgroundHsl[0]);
+ return diff > 10 && diff < 350;
+ });
+ }
+ paletteBuilder.addFilter(mBlackWhiteFilter);
+ palette = paletteBuilder.generate();
+ int foregroundColor;
+ if (ColorUtils.calculateLuminance(backgroundColor) > 0.5) {
+ Palette.Swatch first = palette.getDarkVibrantSwatch();
+ Palette.Swatch second = palette.getVibrantSwatch();
+ if (first != null && second != null) {
+ int firstPopulation = first.getPopulation();
+ int secondPopulation = second.getPopulation();
+ if (firstPopulation / secondPopulation
+ < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
+ foregroundColor = second.getRgb();
+ } else {
+ foregroundColor = first.getRgb();
+ }
+ } else if (first != null) {
+ foregroundColor = first.getRgb();
+ } else if (second != null) {
+ foregroundColor = second.getRgb();
+ } else {
+ first = palette.getMutedSwatch();
+ second = palette.getDarkMutedSwatch();
+ if (first != null && second != null) {
+ float firstSaturation = first.getHsl()[1];
+ float secondSaturation = second.getHsl()[1];
+ if (firstSaturation > secondSaturation) {
+ foregroundColor = first.getRgb();
+ } else {
+ foregroundColor = second.getRgb();
+ }
+ } else if (first != null) {
+ foregroundColor = first.getRgb();
+ } else if (second != null) {
+ foregroundColor = second.getRgb();
+ } else {
+ foregroundColor = Color.BLACK;
+ }
+ }
+ } else {
+ Palette.Swatch first = palette.getLightVibrantSwatch();
+ Palette.Swatch second = palette.getVibrantSwatch();
+ if (first != null && second != null) {
+ int firstPopulation = first.getPopulation();
+ int secondPopulation = second.getPopulation();
+ if (firstPopulation / secondPopulation
+ < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
+ foregroundColor = second.getRgb();
+ } else {
+ foregroundColor = first.getRgb();
+ }
+ } else if (first != null) {
+ foregroundColor = first.getRgb();
+ } else if (second != null) {
+ foregroundColor = second.getRgb();
+ } else {
+ first = palette.getMutedSwatch();
+ second = palette.getLightMutedSwatch();
+ if (first != null && second != null) {
+ float firstSaturation = first.getHsl()[1];
+ float secondSaturation = second.getHsl()[1];
+ if (firstSaturation > secondSaturation) {
+ foregroundColor = first.getRgb();
+ } else {
+ foregroundColor = second.getRgb();
+ }
+ } else if (first != null) {
+ foregroundColor = first.getRgb();
+ } else if (second != null) {
+ foregroundColor = second.getRgb();
+ } else {
+ foregroundColor = Color.WHITE;
+ }
+ }
+ }
+ builder.setColorPalette(backgroundColor, foregroundColor);
+ } else {
+ int id = mIsLowPriority
+ ? R.color.notification_material_background_low_priority_color
+ : R.color.notification_material_background_color;
+ backgroundColor = mContext.getColor(id);
+ }
+ Bitmap colorized = mColorizer.colorize(drawable, backgroundColor);
+ builder.setLargeIcon(Icon.createWithBitmap(colorized));
+ }
+ }
+
+ private int findBackgroundColorAndFilter(Palette palette) {
+ // by default we use the dominant palette
+ Palette.Swatch dominantSwatch = palette.getDominantSwatch();
+ if (dominantSwatch == null) {
+ // We're not filtering on white or black
+ mFilteredBackgroundHsl = null;
+ return Color.WHITE;
+ }
+
+ if (!isWhiteOrBlack(dominantSwatch.getHsl())) {
+ mFilteredBackgroundHsl = dominantSwatch.getHsl();
+ return dominantSwatch.getRgb();
+ }
+ // Oh well, we selected black or white. Lets look at the second color!
+ List<Palette.Swatch> swatches = palette.getSwatches();
+ float highestNonWhitePopulation = -1;
+ Palette.Swatch second = null;
+ for (Palette.Swatch swatch: swatches) {
+ if (swatch != dominantSwatch
+ && swatch.getPopulation() > highestNonWhitePopulation
+ && !isWhiteOrBlack(swatch.getHsl())) {
+ second = swatch;
+ highestNonWhitePopulation = swatch.getPopulation();
+ }
+ }
+ if (second == null) {
+ // We're not filtering on white or black
+ mFilteredBackgroundHsl = null;
+ return dominantSwatch.getRgb();
+ }
+ if (dominantSwatch.getPopulation() / highestNonWhitePopulation
+ > POPULATION_FRACTION_FOR_WHITE_OR_BLACK) {
+ // The dominant swatch is very dominant, lets take it!
+ // We're not filtering on white or black
+ mFilteredBackgroundHsl = null;
+ return dominantSwatch.getRgb();
+ } else {
+ mFilteredBackgroundHsl = second.getHsl();
+ return second.getRgb();
+ }
+ }
+
+ private boolean isWhiteOrBlack(float[] hsl) {
+ return isBlack(hsl) || isWhite(hsl);
+ }
+
+
+ /**
+ * @return true if the color represents a color which is close to black.
+ */
+ private boolean isBlack(float[] hslColor) {
+ return hslColor[2] <= BLACK_MAX_LIGHTNESS;
+ }
+
+ /**
+ * @return true if the color represents a color which is close to white.
+ */
+ private boolean isWhite(float[] hslColor) {
+ return hslColor[2] >= WHITE_MIN_LIGHTNESS;
+ }
+
+ public void setIsLowPriority(boolean isLowPriority) {
+ mIsLowPriority = isLowPriority;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
index 2e34f24..6c6dfa4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
@@ -18,11 +18,10 @@
import android.app.Notification;
import android.content.Context;
+import android.os.AsyncTask;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
import android.widget.RemoteViews;
import com.android.internal.annotations.VisibleForTesting;
@@ -39,7 +38,8 @@
@VisibleForTesting
static final int FLAG_REINFLATE_ALL = ~0;
private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
- private static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
+ @VisibleForTesting
+ static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3;
private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4;
@@ -50,7 +50,7 @@
private boolean mUsesIncreasedHeadsUpHeight;
private RemoteViews.OnClickHandler mRemoteViewClickHandler;
private boolean mIsChildInGroup;
- private InflationExceptionHandler mInflateExceptionHandler;
+ private InflationCallback mCallback;
private boolean mRedactAmbient;
public NotificationInflater(ExpandableNotificationRow row) {
@@ -66,21 +66,14 @@
*
* @return whether the view was re-inflated
*/
- public boolean setIsChildInGroup(boolean childInGroup) {
+ public void setIsChildInGroup(boolean childInGroup) {
if (childInGroup != mIsChildInGroup) {
mIsChildInGroup = childInGroup;
if (mIsLowPriority) {
- try {
- int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
- inflateNotificationViews(flags);
- } catch (InflationException e) {
- mInflateExceptionHandler.handleInflationException(
- mRow.getStatusBarNotification(), e);
- }
+ int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
+ inflateNotificationViews(flags);
}
- return true;
- }
- return false;
+ } ;
}
public void setUsesIncreasedHeight(boolean usesIncreasedHeight) {
@@ -101,39 +94,29 @@
if (mRow.getEntry() == null) {
return;
}
- try {
- inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
- } catch (InflationException e) {
- mInflateExceptionHandler.handleInflationException(
- mRow.getStatusBarNotification(), e);
- }
+ inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
}
}
- public void inflateNotificationViews() throws InflationException {
+ /**
+ * Inflate all views of this notification on a background thread. This is asynchronous and will
+ * notify the callback once it's finished.
+ */
+ public void inflateNotificationViews() {
inflateNotificationViews(FLAG_REINFLATE_ALL);
}
/**
- * reinflate all views for the specified flags
+ * Reinflate all views for the specified flags on a background thread. This is asynchronous and
+ * will notify the callback once it's finished.
+ *
* @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL}
* to reinflate all of views.
- * @throws InflationException
*/
- private void inflateNotificationViews(int reInflateFlags)
- throws InflationException {
+ @VisibleForTesting
+ void inflateNotificationViews(int reInflateFlags) {
StatusBarNotification sbn = mRow.getEntry().notification;
- try {
- final Notification.Builder recoveredBuilder
- = Notification.Builder.recoverBuilder(mRow.getContext(), sbn.getNotification());
- Context packageContext = sbn.getPackageContext(mRow.getContext());
- inflateNotificationViews(reInflateFlags, recoveredBuilder, packageContext);
-
- } catch (RuntimeException e) {
- final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
- Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
- throw new InflationException("Couldn't inflate contentViews");
- }
+ new AsyncInflationTask(mRow.getContext(), sbn, reInflateFlags).execute();
}
@VisibleForTesting
@@ -284,12 +267,13 @@
&& a.getLayoutId() == b.getLayoutId());
}
- public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) {
- mInflateExceptionHandler = inflateExceptionHandler;
+ public void setInflationCallback(InflationCallback callback) {
+ mCallback = callback;
}
- public interface InflationExceptionHandler {
+ public interface InflationCallback {
void handleInflationException(StatusBarNotification notification, InflationException e);
+ void onAsyncInflationFinished(NotificationData.Entry entry);
}
public void onDensityOrFontScaleChanged() {
@@ -299,12 +283,74 @@
entry.cachedContentView = null;
entry.cachedHeadsUpContentView = null;
entry.cachedPublicContentView = null;
- try {
- inflateNotificationViews();
- } catch (InflationException e) {
- mInflateExceptionHandler.handleInflationException(
- mRow.getStatusBarNotification(), e);
+ inflateNotificationViews();
+ }
+
+ private class AsyncInflationTask extends AsyncTask<Void, Void, Notification.Builder> {
+
+ private final StatusBarNotification mSbn;
+ private final Context mContext;
+ private final int mReInflateFlags;
+ private Context mPackageContext = null;
+ private Exception mError;
+
+ private AsyncInflationTask(Context context, StatusBarNotification notification,
+ int reInflateFlags) {
+ mSbn = notification;
+ mContext = context;
+ mReInflateFlags = reInflateFlags;
+ mRow.getEntry().addInflationTask(this);
+ }
+
+ @Override
+ protected Notification.Builder doInBackground(Void... params) {
+ try {
+ final Notification.Builder recoveredBuilder
+ = Notification.Builder.recoverBuilder(mContext,
+ mSbn.getNotification());
+ mPackageContext = mSbn.getPackageContext(mContext);
+ Notification notification = mSbn.getNotification();
+ if (notification.isMediaNotification()) {
+ MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext,
+ mPackageContext);
+ processor.setIsLowPriority(mIsLowPriority);
+ processor.processNotification(notification, recoveredBuilder);
+ }
+ return recoveredBuilder;
+ } catch (Exception e) {
+ mError = e;
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Notification.Builder builder) {
+ if (mError == null) {
+ finishInflation(mReInflateFlags, builder, mPackageContext);
+ } else {
+ handleError(mError);
+ }
}
}
+ private void finishInflation(int reinflationFlags, Notification.Builder builder,
+ Context context) {
+ try {
+ inflateNotificationViews(reinflationFlags, builder, context);
+ } catch (RuntimeException e){
+ handleError(e);
+ return;
+ }
+ mRow.onNotificationUpdated();
+ mCallback.onAsyncInflationFinished(mRow.getEntry());
+ }
+
+ private void handleError(Exception e) {
+ StatusBarNotification sbn = mRow.getStatusBarNotification();
+ final String ident = sbn.getPackageName() + "/0x"
+ + Integer.toHexString(sbn.getId());
+ Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
+ mCallback.handleInflationException(sbn,
+ new InflationException("Couldn't inflate contentViews" + e));
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
index ef5a25c..8596cb3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -56,4 +56,9 @@
mActions);
}
}
+
+ @Override
+ public boolean isDimmable() {
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index f4db9a1..5cc39cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -178,4 +178,8 @@
public void setIsChildInGroup(boolean isChildInGroup) {
}
+
+ public boolean isDimmable() {
+ return true;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
index 6361eb6..a9eb20b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
@@ -57,12 +57,12 @@
private static final int LEVEL_MASK = 0xff;
private static final int NUM_LEVEL_SHIFT = 8;
private static final int NUM_LEVEL_MASK = 0xff << NUM_LEVEL_SHIFT;
- public static final int STATE_SHIFT = 16;
- public static final int STATE_MASK = 0xff << STATE_SHIFT;
- public static final int STATE_NONE = 0;
- public static final int STATE_EMPTY = 1;
- public static final int STATE_CUT = 2;
- public static final int STATE_CARRIER_CHANGE = 3;
+ private static final int STATE_SHIFT = 16;
+ private static final int STATE_MASK = 0xff << STATE_SHIFT;
+ private static final int STATE_NONE = 0;
+ private static final int STATE_EMPTY = 1;
+ private static final int STATE_CUT = 2;
+ private static final int STATE_CARRIER_CHANGE = 3;
private static final long DOT_DELAY = 1000;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 46d6415..c1859fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -22,7 +22,7 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
-import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler;
+import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -257,7 +257,7 @@
OnHeadsUpChangedListener, VisualStabilityManager.Callback, CommandQueue.Callbacks,
ActivatableNotificationView.OnActivatedListener,
ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
- ExpandableNotificationRow.OnExpandClickListener {
+ ExpandableNotificationRow.OnExpandClickListener, InflationCallback {
public static final boolean MULTIUSER_DEBUG = false;
public static final boolean ENABLE_REMOTE_INPUT =
@@ -713,8 +713,8 @@
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private NotificationIconAreaController mNotificationIconAreaController;
private ConfigurationListener mConfigurationListener;
- private InflationExceptionHandler mInflationExceptionHandler = this::handleInflationException;
private boolean mReinflateNotificationsOnUserSwitched;
+ private HashMap<String, Entry> mPendingNotifications = new HashMap<>();
private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
final int N = array.size();
@@ -1544,29 +1544,24 @@
return new UserHandle(mCurrentUserId);
}
- public void addNotification(StatusBarNotification notification, RankingMap ranking,
- Entry oldEntry) throws InflationException {
- if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
+ public void addNotification(StatusBarNotification notification, RankingMap ranking)
+ throws InflationException {
+ String key = notification.getKey();
+ if (DEBUG) Log.d(TAG, "addNotification key=" + key);
mNotificationData.updateRanking(ranking);
Entry shadeEntry = createNotificationViews(notification);
boolean isHeadsUped = shouldPeek(shadeEntry);
- if (isHeadsUped) {
- mHeadsUpManager.showNotification(shadeEntry);
- // Mark as seen immediately
- setNotificationShown(notification);
- }
-
if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
- if (shouldSuppressFullScreenIntent(notification.getKey())) {
+ if (shouldSuppressFullScreenIntent(key)) {
if (DEBUG) {
- Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
+ Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key);
}
- } else if (mNotificationData.getImportance(notification.getKey())
+ } else if (mNotificationData.getImportance(key)
< NotificationManager.IMPORTANCE_HIGH) {
if (DEBUG) {
Log.d(TAG, "No Fullscreen intent: not important enough: "
- + notification.getKey());
+ + key);
}
} else {
// Stop screensaver if the notification has a full-screen intent.
@@ -1578,7 +1573,7 @@
Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
try {
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
- notification.getKey());
+ key);
notification.getNotification().fullScreenIntent.send();
shadeEntry.notifyFullScreenIntentLaunched();
mMetricsLogger.count("note_fullscreen", 1);
@@ -1586,15 +1581,47 @@
}
}
}
- addNotificationViews(shadeEntry, ranking);
+ abortExistingInflation(key);
+ mPendingNotifications.put(key, shadeEntry);
+ }
+
+ private void abortExistingInflation(String key) {
+ if (mPendingNotifications.containsKey(key)) {
+ Entry entry = mPendingNotifications.get(key);
+ entry.abortInflation();
+ mPendingNotifications.remove(key);
+ }
+ Entry addedEntry = mNotificationData.get(key);
+ if (addedEntry != null) {
+ addedEntry.abortInflation();
+ }
+ }
+
+ private void addEntry(Entry shadeEntry) {
+ boolean isHeadsUped = shouldPeek(shadeEntry);
+ if (isHeadsUped) {
+ mHeadsUpManager.showNotification(shadeEntry);
+ // Mark as seen immediately
+ setNotificationShown(shadeEntry.notification);
+ }
+ addNotificationViews(shadeEntry);
// Recalculate the position of the sliding windows and the titles.
setAreThereNotifications();
}
+ @Override
public void handleInflationException(StatusBarNotification notification, InflationException e) {
handleNotificationError(notification, e.getMessage());
}
+ @Override
+ public void onAsyncInflationFinished(Entry entry) {
+ mPendingNotifications.remove(entry.key);
+ if (mNotificationData.get(entry.key) == null) {
+ addEntry(entry);
+ }
+ }
+
private boolean shouldSuppressFullScreenIntent(String key) {
if (isDeviceInVrMode()) {
return true;
@@ -1614,6 +1641,7 @@
public void removeNotification(String key, RankingMap ranking) {
boolean deferRemoval = false;
+ abortExistingInflation(key);
if (mHeadsUpManager.isHeadsUp(key)) {
// A cancel() in repsonse to a remote input shouldn't be delayed, as it makes the
// sending look longer than it takes.
@@ -3295,6 +3323,14 @@
+ " scroll " + mStackScroller.getScrollX()
+ "," + mStackScroller.getScrollY());
}
+ pw.print(" mPendingNotifications=");
+ if (mPendingNotifications.size() == 0) {
+ pw.println("null");
+ } else {
+ for (Entry entry : mPendingNotifications.values()) {
+ pw.println(entry.notification);
+ }
+ }
pw.print(" mInteractingWindows="); pw.println(mInteractingWindows);
pw.print(" mStatusBarWindowState=");
@@ -5531,7 +5567,7 @@
public void run() {
for (StatusBarNotification sbn : notifications) {
try {
- addNotification(sbn, currentRanking, null /* oldEntry */);
+ addNotification(sbn, currentRanking);
} catch (InflationException e) {
handleInflationException(sbn, e);
}
@@ -5574,7 +5610,7 @@
if (isUpdate) {
updateNotification(sbn, rankingMap);
} else {
- addNotification(sbn, rankingMap, null /* oldEntry */);
+ addNotification(sbn, rankingMap);
}
} catch (InflationException e) {
handleInflationException(sbn, e);
@@ -6132,8 +6168,7 @@
}
}
- protected void inflateViews(Entry entry, ViewGroup parent) throws
- InflationException {
+ protected void inflateViews(Entry entry, ViewGroup parent) {
PackageManager pmUser = getPackageManagerForUser(mContext,
entry.notification.getUser().getIdentifier());
@@ -6154,7 +6189,7 @@
row.setRemoteInputController(mRemoteInputController);
row.setOnExpandClickListener(this);
row.setRemoteViewClickHandler(mOnClickHandler);
- row.setInflateExceptionHandler(mInflationExceptionHandler);
+ row.setInflationCallback(this);
// Get the app name.
// Note that Notification.Builder#bindHeaderAppName has similar logic
@@ -6552,12 +6587,12 @@
return entry;
}
- protected void addNotificationViews(Entry entry, RankingMap ranking) {
+ protected void addNotificationViews(Entry entry) {
if (entry == null) {
return;
}
// Add the expanded view and icon.
- mNotificationData.add(entry, ranking);
+ mNotificationData.add(entry);
updateNotifications();
}
@@ -6675,6 +6710,7 @@
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
final String key = notification.getKey();
+ abortExistingInflation(key);
Entry entry = mNotificationData.get(key);
if (entry == null) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index e98dc98..a456786 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -110,24 +110,30 @@
public void setWifiIndicators(final boolean enabled, final IconState statusIcon,
final IconState qsIcon, final boolean activityIn, final boolean activityOut,
final String description, boolean isTransient) {
- post(() -> {
- for (SignalCallback callback : mSignalCallbacks) {
- callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
- description, isTransient);
+ post(new Runnable() {
+ @Override
+ public void run() {
+ for (SignalCallback callback : mSignalCallbacks) {
+ callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
+ description, isTransient);
+ }
}
});
}
@Override
- public void setMobileDataIndicators(final IconState statusIcon,
- final int statusType, final boolean activityIn,
+ public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon,
+ final int statusType, final int qsType,final boolean activityIn,
final boolean activityOut, final String typeContentDescription,
- final int subId, boolean roaming, boolean isEmergency) {
- post(() -> {
- for (SignalCallback signalCluster : mSignalCallbacks) {
- signalCluster.setMobileDataIndicators(statusIcon, statusType,
- activityIn, activityOut, typeContentDescription,
- subId, roaming, isEmergency);
+ final String description, final boolean isWide, final int subId, boolean roaming) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ for (SignalCallback signalCluster : mSignalCallbacks) {
+ signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType,
+ activityIn, activityOut, typeContentDescription, description, isWide,
+ subId, roaming);
+ }
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 4421a6a..67b5596 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -244,8 +244,7 @@
return SignalDrawable.getCarrierChangeState(getNumLevels());
} else if (mCurrentState.connected) {
return SignalDrawable.getState(mCurrentState.level, getNumLevels(),
- mCurrentState.inetCondition == 0 ||
- (mCurrentState.dataDisabled && mCurrentState.userSetup));
+ mCurrentState.inetCondition == 0);
} else if (mCurrentState.enabled) {
return SignalDrawable.getEmptyState(getNumLevels());
} else {
@@ -264,14 +263,24 @@
String contentDescription = getStringIfExists(getContentDescription());
String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
- final boolean dataDisabled = mCurrentState.dataDisabled
+ final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
&& mCurrentState.userSetup;
// Show icon in QS when we are connected or data is disabled.
- boolean showDataIcon = mCurrentState.dataConnected;
+ boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
getCurrentIconId(), contentDescription);
+ int qsTypeIcon = 0;
+ IconState qsIcon = null;
+ String description = null;
+ // Only send data sim callbacks to QS.
+ if (mCurrentState.dataSim) {
+ qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
+ qsIcon = new IconState(mCurrentState.enabled
+ && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
+ description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
+ }
boolean activityIn = mCurrentState.dataConnected
&& !mCurrentState.carrierNetworkChangeMode
&& mCurrentState.activityIn;
@@ -280,10 +289,9 @@
&& mCurrentState.activityOut;
showDataIcon &= mCurrentState.isDefault || dataDisabled;
int typeIcon = showDataIcon ? icons.mDataType : 0;
- callback.setMobileDataIndicators(statusIcon, typeIcon,
- activityIn, activityOut, dataContentDescription,
- mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming,
- mCurrentState.isEmergency);
+ callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+ activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
+ mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
}
@Override
@@ -430,14 +438,14 @@
} else {
mCurrentState.iconGroup = mDefaultIcons;
}
- mCurrentState.dataDisabled = isDataDisabled();
mCurrentState.dataConnected = mCurrentState.connected
- && mDataState == TelephonyManager.DATA_CONNECTED
- && !mCurrentState.dataDisabled;
+ && mDataState == TelephonyManager.DATA_CONNECTED;
mCurrentState.roaming = isRoaming();
if (isCarrierNetworkChangeActive()) {
mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
+ } else if (isDataDisabled()) {
+ mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
}
if (isEmergencyOnly() != mCurrentState.isEmergency) {
mCurrentState.isEmergency = isEmergencyOnly();
@@ -569,7 +577,6 @@
boolean isDefault;
boolean userSetup;
boolean roaming;
- boolean dataDisabled;
@Override
public void copyFrom(State s) {
@@ -585,7 +592,6 @@
carrierNetworkChangeMode = state.carrierNetworkChangeMode;
userSetup = state.userSetup;
roaming = state.roaming;
- dataDisabled = state.dataDisabled;
}
@Override
@@ -603,7 +609,6 @@
builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
.append(',');
builder.append("userSetup=").append(userSetup);
- builder.append("dataDisabled=").append(dataDisabled);
}
@Override
@@ -618,7 +623,6 @@
&& ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
&& ((MobileState) o).userSetup == userSetup
&& ((MobileState) o).isDefault == isDefault
- && ((MobileState) o).dataDisabled == dataDisabled
&& ((MobileState) o).roaming == roaming;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index ab4a8f2..c02ce0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -48,9 +48,9 @@
default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient) {}
- default void setMobileDataIndicators(IconState statusIcon, int statusType,
- boolean activityIn, boolean activityOut, String typeContentDescription,
- int subId, boolean roaming, boolean isEmergency) {}
+ default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
+ int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
+ String description, boolean isWide, int subId, boolean roaming) {}
default void setSubs(List<SubscriptionInfo> subs) {}
default void setNoSims(boolean show) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 60f4ab8..c21f444 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -867,6 +867,7 @@
datatype.equals("h") ? TelephonyIcons.H :
datatype.equals("lte") ? TelephonyIcons.LTE :
datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
+ datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
TelephonyIcons.UNKNOWN;
}
if (args.containsKey("roam")) {
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 ec7e557..aaa0568 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -44,6 +44,10 @@
static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
+ static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
+
+ static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
+
static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
"CARRIER_NETWORK_CHANGE",
null,
@@ -217,5 +221,20 @@
true,
TelephonyIcons.QS_DATA_LTE_PLUS
);
+
+ static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
+ "DataDisabled",
+ null,
+ null,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ 0,
+ 0,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_cell_data_off,
+ TelephonyIcons.ICON_DATA_DISABLED,
+ false,
+ TelephonyIcons.QS_ICON_DATA_DISABLED
+ );
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index dfc3591..374408d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -47,7 +47,6 @@
static final int QS_WIFI_NO_NETWORK = R.drawable.ic_qs_wifi_no_network;
static final int WIFI_NO_NETWORK = R.drawable.stat_sys_wifi_signal_null;
- static final int WIFI_DISCONNECTED = R.drawable.stat_sys_wifi_signal_disconnected;
static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index a773acf..2104cb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -80,7 +80,7 @@
AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
- WifiIcons.WIFI_DISCONNECTED,
+ WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
AccessibilityContentDescriptions.WIFI_NO_CONNECTION
);
@@ -133,7 +133,8 @@
@Override
public void notifyListeners(SignalCallback callback) {
// only show wifi in the cluster if connected or if wifi-only
- boolean wifiVisible = true;
+ boolean wifiVisible = mCurrentState.enabled
+ && (mCurrentState.connected || !mHasMobileData);
String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
String contentDescription = getStringIfExists(getContentDescription());
diff --git a/packages/SystemUI/src/com/android/systemui/util/Assert.java b/packages/SystemUI/src/com/android/systemui/util/Assert.java
index af447f3..0f7c9a4 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Assert.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Assert.java
@@ -28,4 +28,10 @@
throw new IllegalStateException("should be called from the main thread.");
}
}
+
+ public static void isNotMainThread() {
+ if (Looper.getMainLooper().isCurrentThread()) {
+ throw new IllegalStateException("should not be called from the main thread.");
+ }
+ }
}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 8eedf31..5e8b3f9 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -42,6 +42,7 @@
android-support-v7-preference \
android-support-v7-appcompat \
android-support-v7-mediarouter \
+ android-support-v7-palette \
android-support-v14-preference \
android-support-v17-leanback
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
new file mode 100644
index 0000000..1c9f813
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.keyguard;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.TextView;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+public class KeyguardClockAccessibilityDelegateTest {
+
+ private Context mContext;
+ private TextView mView;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+ mView = new TextView(mContext);
+ mView.setText(R.string.keyguard_widget_12_hours_format);
+ mView.setContentDescription(mContext.getString(R.string.keyguard_widget_12_hours_format));
+ mView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
+ }
+
+ @Test
+ public void onInitializeAccessibilityEvent_producesNonEmptyAsciiContentDesc() throws Exception {
+ AccessibilityEvent ev = AccessibilityEvent.obtain();
+ mView.onInitializeAccessibilityEvent(ev);
+
+ assertFalse(TextUtils.isEmpty(ev.getContentDescription()));
+ assertTrue(isAscii(ev.getContentDescription()));
+ }
+
+ @Test
+ public void onPopulateAccessibilityEvent_producesNonEmptyAsciiText() throws Exception {
+ AccessibilityEvent ev = AccessibilityEvent.obtain();
+ mView.onPopulateAccessibilityEvent(ev);
+
+ assertFalse(isEmpty(ev.getText()));
+ assertTrue(isAscii(ev.getText()));
+ }
+
+ @Test
+ public void onInitializeAccessibilityNodeInfo_producesNonEmptyAsciiText() throws Exception {
+ AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+ // Usually done in View.onInitializeAccessibilityNodeInfoInternal, but only when attached.
+ info.setContentDescription(mView.getContentDescription());
+ mView.onInitializeAccessibilityNodeInfo(info);
+
+ assertFalse(TextUtils.isEmpty(info.getText()));
+ assertTrue(isAscii(info.getText()));
+
+ assertFalse(TextUtils.isEmpty(info.getContentDescription()));
+ assertTrue(isAscii(info.getContentDescription()));
+ }
+
+ private boolean isAscii(CharSequence text) {
+ return text.chars().allMatch((i) -> i < 128);
+ }
+
+ private boolean isAscii(List<CharSequence> texts) {
+ return texts.stream().allMatch(this::isAscii);
+ }
+
+ private boolean isEmpty(List<CharSequence> texts) {
+ return texts.stream().allMatch(TextUtils::isEmpty);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
index 1b5d4a4..aa840989 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
@@ -43,12 +43,13 @@
private ExpandHelper.Callback mCallback;
@Before
- @UiThreadTest
- public void setUp() {
+ public void setUp() throws Exception {
Context context = getContext();
mRow = new NotificationTestHelper(context).createRow();
mCallback = mock(ExpandHelper.Callback.class);
- mExpandHelper = new ExpandHelper(context, mCallback, 10, 100);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ () -> mExpandHelper = new ExpandHelper(context, mCallback, 10, 100));
+
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
index 048936b..bbe324d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
@@ -47,9 +47,8 @@
return;
}
- mContext.getSettingsProvider().acquireOverridesBuilder()
- .addSetting("secure", Settings.Secure.DOZE_ALWAYS_ON, null)
- .build();
+ Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.DOZE_ALWAYS_ON,
+ null);
assertFalse(mDozeConfig.alwaysOnEnabled(UserHandle.USER_CURRENT));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index 3db2440..5cd092b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -39,8 +39,7 @@
private NotificationTestHelper mNotificationTestHelper;
@Before
- @UiThreadTest
- public void setUp() {
+ public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
mNotificationTestHelper = new NotificationTestHelper(mContext);
mGroup = mNotificationTestHelper.createGroup();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index c91b269..cb238dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -17,15 +17,18 @@
package com.android.systemui.statusbar;
import android.app.ActivityManager;
+import android.app.Instrumentation;
import android.app.Notification;
import android.content.Context;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
import android.view.LayoutInflater;
import android.widget.RemoteViews;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.NotificationInflaterTest;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
/**
@@ -34,14 +37,18 @@
public class NotificationTestHelper {
private final Context mContext;
+ private final Instrumentation mInstrumentation;
private int mId;
private final NotificationGroupManager mGroupManager = new NotificationGroupManager();
+ private ExpandableNotificationRow mRow;
+ private InflationException mException;
public NotificationTestHelper(Context context) {
mContext = context;
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
}
- public ExpandableNotificationRow createRow() {
+ public ExpandableNotificationRow createRow() throws Exception {
Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
R.drawable.ic_person)
.setCustomContentView(new RemoteViews(mContext.getPackageName(),
@@ -56,12 +63,15 @@
return createRow(notification);
}
- public ExpandableNotificationRow createRow(Notification notification) {
+ public ExpandableNotificationRow createRow(Notification notification) throws Exception {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
mContext.LAYOUT_INFLATER_SERVICE);
- ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
- R.layout.status_bar_notification_row,
- null, false);
+ mInstrumentation.runOnMainSync(() -> {
+ mRow = (ExpandableNotificationRow) inflater.inflate(
+ R.layout.status_bar_notification_row,
+ null, false);
+ });
+ ExpandableNotificationRow row = mRow;
row.setGroupManager(mGroupManager);
UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
StatusBarNotification sbn = new StatusBarNotification("com.android.systemui",
@@ -69,16 +79,13 @@
2000, notification, mUser, null, System.currentTimeMillis());
NotificationData.Entry entry = new NotificationData.Entry(sbn);
entry.row = row;
- try {
- entry.createIcons(mContext, sbn);
- row.updateNotification(entry);
- } catch (InflationException e) {
- throw new RuntimeException(e.getMessage());
- }
+ entry.createIcons(mContext, sbn);
+ NotificationInflaterTest.runThenWaitForInflation(() -> row.updateNotification(entry),
+ row.getNotificationInflater());
return row;
}
- public ExpandableNotificationRow createGroup() {
+ public ExpandableNotificationRow createGroup() throws Exception {
ExpandableNotificationRow row = createRow();
row.addChildNotification(createRow());
row.addChildNotification(createRow());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
new file mode 100644
index 0000000..65e0568
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static com.android.systemui.statusbar.notification.NotificationInflater.FLAG_REINFLATE_ALL;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Notification;
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Function;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationInflaterTest {
+
+ private Context mContext;
+ private NotificationInflater mNotificationInflater;
+ private Notification.Builder mBuilder;
+ private ExpandableNotificationRow mRow;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mBuilder = new Notification.Builder(mContext).setSmallIcon(
+ R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text")
+ .setStyle(new Notification.BigTextStyle().bigText("big text"));
+ ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
+ mBuilder.build());
+ mRow = spy(row);
+ mNotificationInflater = new NotificationInflater(mRow);
+ mNotificationInflater.setInflationCallback(new NotificationInflater.InflationCallback() {
+ @Override
+ public void handleInflationException(StatusBarNotification notification,
+ InflationException e) {
+ }
+
+ @Override
+ public void onAsyncInflationFinished(NotificationData.Entry entry) {
+ }
+ });
+ }
+
+ @Test
+ public void testIncreasedHeadsUpBeingUsed() {
+ mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
+ Notification.Builder builder = spy(mBuilder);
+ mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
+ verify(builder).createHeadsUpContentView(true);
+ }
+
+ @Test
+ public void testIncreasedHeightBeingUsed() {
+ mNotificationInflater.setUsesIncreasedHeight(true);
+ Notification.Builder builder = spy(mBuilder);
+ mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
+ verify(builder).createContentView(true);
+ }
+
+ @Test
+ public void testInflationCallsUpdated() throws Exception {
+ runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
+ mNotificationInflater);
+ verify(mRow).onNotificationUpdated();
+ }
+
+ @Test
+ public void testInflationCallsOnlyRightMethod() throws Exception {
+ mRow.getPrivateLayout().removeAllViews();
+ mRow.getEntry().cachedBigContentView = null;
+ runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(
+ NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater);
+ Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 1);
+ Assert.assertTrue(mRow.getPrivateLayout().getChildAt(0)
+ == mRow.getPrivateLayout().getExpandedChild());
+ verify(mRow).onNotificationUpdated();
+ }
+
+ @Test
+ public void testInflationThrowsErrorDoesntCallUpdated() throws Exception {
+ mRow.getPrivateLayout().removeAllViews();
+ mRow.getStatusBarNotification().getNotification().contentView
+ = new RemoteViews(mContext.getPackageName(), R.layout.status_bar);;
+ runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
+ true /* expectingException */, mNotificationInflater);
+ Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 0);
+ verify(mRow, times(0)).onNotificationUpdated();
+ }
+
+ public static void runThenWaitForInflation(Runnable block,
+ NotificationInflater inflater) throws Exception {
+ runThenWaitForInflation(block, false /* expectingException */, inflater);
+ }
+
+ private static void runThenWaitForInflation(Runnable block, boolean expectingException,
+ NotificationInflater inflater) throws Exception {
+ com.android.systemui.util.Assert.isNotMainThread();
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ final ExceptionHolder exceptionHolder = new ExceptionHolder();
+ inflater.setInflationCallback(new NotificationInflater.InflationCallback() {
+ @Override
+ public void handleInflationException(StatusBarNotification notification,
+ InflationException e) {
+ if (!expectingException) {
+ exceptionHolder.setException(e);
+ }
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void onAsyncInflationFinished(NotificationData.Entry entry) {
+ if (expectingException) {
+ exceptionHolder.setException(new RuntimeException(
+ "Inflation finished even though there should be an error"));
+ }
+ countDownLatch.countDown();
+ }
+ });
+ block.run();
+ countDownLatch.await(5, java.util.concurrent.TimeUnit.SECONDS);
+ if (exceptionHolder.mException != null) {
+ throw exceptionHolder.mException;
+ }
+ }
+
+ private static class ExceptionHolder {
+ private Exception mException;
+
+ public void setException(Exception exception) {
+ mException = exception;
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationinflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationinflaterTest.java
deleted file mode 100644
index 0ec9c10..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationinflaterTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import static com.android.systemui.statusbar.notification.NotificationInflater.FLAG_REINFLATE_ALL;
-
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.app.Notification;
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationTestHelper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class NotificationinflaterTest {
-
- private Context mContext;
- private NotificationInflater mNotificationInflater;
- private Notification.Builder mBuilder;
-
- @Before
- @UiThreadTest
- public void setUp() {
- mContext = InstrumentationRegistry.getTargetContext();
- mBuilder = new Notification.Builder(mContext).setSmallIcon(
- R.drawable.ic_person)
- .setContentTitle("Title")
- .setContentText("Text");
- ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
- mBuilder.build());
- mNotificationInflater = new NotificationInflater(row);
- }
-
- @Test
- public void testIncreasedHeadsUpBeingUsed() {
- mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
- Notification.Builder builder = spy(mBuilder);
- mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
- verify(builder).createHeadsUpContentView(true);
- }
-
- @Test
- public void testIncreasedHeightBeingUsed() {
- mNotificationInflater.setUsesIncreasedHeight(true);
- Notification.Builder builder = spy(mBuilder);
- mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
- verify(builder).createContentView(true);
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index f6c75a8..3ed1681 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -114,26 +114,33 @@
boolean wide = true;
int subId = 5;
boolean roaming = true;
- boolean isEmergency = true;
- mHandler.setMobileDataIndicators(status, type, in, out, typeDescription,
- subId, roaming, isEmergency);
+ mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription,
+ description, wide, subId, roaming);
waitForCallbacks();
ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class);
+ ArgumentCaptor<IconState> qsArg = ArgumentCaptor.forClass(IconState.class);
ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<String> typeContentArg = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<Boolean> wideArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<Integer> subIdArg = ArgumentCaptor.forClass(Integer.class);
Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(),
- typeIconArg.capture(), inArg.capture(),
- outArg.capture(), typeContentArg.capture(),
- subIdArg.capture(), eq(roaming), eq(isEmergency));
+ qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(),
+ outArg.capture(), typeContentArg.capture(), descArg.capture(), wideArg.capture(),
+ subIdArg.capture(), eq(roaming));
assertEquals(status, statusArg.getValue());
+ assertEquals(qs, qsArg.getValue());
assertEquals(type, (int) typeIconArg.getValue());
+ assertEquals(qsType, (int) qsTypeIconArg.getValue());
assertEquals(in, (boolean) inArg.getValue());
assertEquals(out, (boolean) outArg.getValue());
assertEquals(typeDescription, typeContentArg.getValue());
+ assertEquals(description, descArg.getValue());
+ assertEquals(wide, (boolean) wideArg.getValue());
assertEquals(subId, (int) subIdArg.getValue());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index b39171e..505e1d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -29,7 +29,6 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
-
import com.android.internal.telephony.cdma.EriInfo;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.statusbar.phone.SignalDrawable;
@@ -46,6 +45,8 @@
import org.junit.runner.Description;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -69,7 +70,7 @@
protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL;
protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL;
protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G;
- protected static final int DEFAULT_QS_ICON = DEFAULT_ICON;
+ protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_DATA_3G;
protected NetworkControllerImpl mNetworkController;
protected MobileSignalController mMobileSignalController;
@@ -116,7 +117,7 @@
when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true);
when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn(
- new NetworkCapabilities[]{mNetCapabilities});
+ new NetworkCapabilities[] { mNetCapabilities });
mSignalStrength = mock(SignalStrength.class);
mServiceState = mock(ServiceState.class);
@@ -174,17 +175,17 @@
}
protected NetworkControllerImpl setUpNoMobileData() {
- when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
- NetworkControllerImpl networkControllerNoMobile
- = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager, mMockTm,
- mMockWm, mMockSm, mConfig, mContext.getMainLooper(), mCallbackHandler,
- mock(AccessPointControllerImpl.class),
- mock(DataUsageController.class), mMockSubDefaults,
- mock(DeviceProvisionedController.class));
+ when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
+ NetworkControllerImpl networkControllerNoMobile
+ = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager, mMockTm,
+ mMockWm, mMockSm, mConfig, mContext.getMainLooper(), mCallbackHandler,
+ mock(AccessPointControllerImpl.class),
+ mock(DataUsageController.class), mMockSubDefaults,
+ mock(DeviceProvisionedController.class));
- setupNetworkController();
+ setupNetworkController();
- return networkControllerNoMobile;
+ return networkControllerNoMobile;
}
@@ -307,10 +308,11 @@
ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class);
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
- iconArg.capture(),
- typeIconArg.capture(),
- dataInArg.capture(), dataOutArg.capture(),
- anyString(), anyInt(), anyBoolean(), anyBoolean());
+ any(),
+ iconArg.capture(),
+ anyInt(),
+ typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(),
+ anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
IconState iconState = iconArg.getValue();
int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
false);
@@ -333,16 +335,17 @@
}
protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
- boolean roaming, boolean inet) {
+ boolean roaming, boolean inet) {
ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
// TODO: Verify all fields.
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
iconArg.capture(),
+ any(),
typeIconArg.capture(),
- anyBoolean(), anyBoolean(), anyString(),
- anyInt(), eq(roaming), anyBoolean());
+ anyInt(), anyBoolean(), anyBoolean(), anyString(), anyString(), anyBoolean(),
+ anyInt(), eq(roaming));
IconState iconState = iconArg.getValue();
int state = icon == -1 ? 0
@@ -353,18 +356,22 @@
}
protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
- boolean qsVisible, boolean dataIn, boolean dataOut) {
+ boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut) {
ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class);
+ ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class);
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
iconArg.capture(),
+ qsIconArg.capture(),
typeIconArg.capture(),
+ qsTypeIconArg.capture(),
dataInArg.capture(),
dataOutArg.capture(),
- anyString(), anyInt(), anyBoolean(), anyBoolean());
+ anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
IconState iconState = iconArg.getValue();
@@ -374,15 +381,17 @@
assertEquals("Signal icon in status bar", state, iconState.icon);
assertEquals("Visibility in status bar", visible, iconState.visible);
+ iconState = qsIconArg.getValue();
assertEquals("Visibility in quick settings", qsVisible, iconState.visible);
assertEquals("Signal icon in quick settings", state, iconState.icon);
+ assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue());
assertEquals("Data direction in in quick settings", dataIn,
(boolean) dataInArg.getValue());
assertEquals("Data direction out in quick settings", dataOut,
(boolean) dataOutArg.getValue());
}
- protected void assertNetworkNameEquals(String expected) {
- assertEquals("Network name", expected, mMobileSignalController.getState().networkName);
- }
+ protected void assertNetworkNameEquals(String expected) {
+ assertEquals("Network name", expected, mMobileSignalController.getState().networkName);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 6470c11..dfe00f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -1,9 +1,5 @@
package com.android.systemui.statusbar.policy;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -15,14 +11,10 @@
import android.test.suitebuilder.annotation.SmallTest;
import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.statusbar.phone.SignalDrawable;
-import com.android.systemui.statusbar.policy.NetworkController.IconState;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -124,11 +116,8 @@
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
- ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
- Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
- iconArg.capture(), anyInt(), anyBoolean(), anyBoolean(), any(), anyInt(),
- anyBoolean(), anyBoolean());
- assertEquals(SignalDrawable.STATE_CUT, SignalDrawable.getState(iconArg.getValue().icon));
+ verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED,
+ TelephonyIcons.QS_ICON_DATA_DISABLED);
}
@Test
@@ -140,14 +129,9 @@
setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false);
mUserCallback.onUserSetupChanged();
- waitForIdleSync();
// Don't show the X until the device is setup.
- ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
- Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
- iconArg.capture(), anyInt(), anyBoolean(), anyBoolean(), any(), anyInt(),
- anyBoolean(), anyBoolean());
- assertNotEquals(SignalDrawable.STATE_CUT, SignalDrawable.getState(iconArg.getValue().icon));
+ verifyDataIndicators(0, 0);
}
@Test
@@ -197,12 +181,12 @@
updateDataActivity(direction);
verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, DEFAULT_ICON, true,
- in, out);
+ DEFAULT_QS_SIGNAL_STRENGTH, DEFAULT_QS_ICON, in, out);
}
private void verifyDataIndicators(int dataIcon, int qsDataIcon) {
verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, dataIcon,
- true, false,
+ true, DEFAULT_QS_SIGNAL_STRENGTH, qsDataIcon, false,
false);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index e542c37..1627925 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -214,7 +214,7 @@
verifyLastQsMobileDataIndicators(true,
testStrength,
- TelephonyIcons.ICON_1X, false, false);
+ TelephonyIcons.QS_DATA_1X, false, false);
}
}
@@ -434,7 +434,7 @@
verifyLastQsMobileDataIndicators(true /* visible */,
DEFAULT_LEVEL /* icon */,
- DEFAULT_ICON /* typeIcon */,
+ DEFAULT_QS_ICON /* typeIcon */,
false /* dataIn */,
true /* dataOut */);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index edfa326..dbaa2c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -18,7 +18,6 @@
import com.android.settingslib.Utils;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import android.testing.TestableSettings.SettingOverrider;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -62,7 +61,7 @@
public void testWifiIcon() {
String testSsid = "Test SSID";
setWifiEnabled(true);
- verifyLastWifiIcon(true, WifiIcons.WIFI_DISCONNECTED);
+ verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
setWifiState(true, testSsid);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
@@ -92,11 +91,10 @@
attr);
// Must set the Settings value before instantiating the NetworkControllerImpl due to bugs in
- // TestableSettings.
- SettingOverrider settingsOverrider =
- mContext.getSettingsProvider().acquireOverridesBuilder()
- .addSetting("global", Settings.Global.NETWORK_SCORING_UI_ENABLED, "1")
- .build();
+ // TestableSettingsProvider.
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.NETWORK_SCORING_UI_ENABLED,
+ "1");
super.setUp(); // re-instantiate NetworkControllImpl now that setting has been updated
setupNetworkScoreManager();
@@ -131,8 +129,6 @@
assertEquals("SD Badge is set",
Utils.getWifiBadgeResource(NetworkBadging.BADGING_SD),
iconState.iconOverlay);
-
- settingsOverrider.release();
}
private void setupNetworkScoreManager() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
index dbe0de4..f051f30 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
@@ -42,8 +42,7 @@
private NotificationTestHelper mNotificationTestHelper;
@Before
- @UiThreadTest
- public void setUp() {
+ public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
mNotificationTestHelper = new NotificationTestHelper(mContext);
mGroup = mNotificationTestHelper.createGroup();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 93a5557..dc082e1 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3938,6 +3938,16 @@
// OS: O
ENTERPRISE_PRIVACY_DEFAULT_APPS = 940;
+ // OPEN: Settings > Notifications > An app > A channel > Importance
+ // CATEGORY: SETTINGS
+ // OS: O
+ NOTIFICATION_CHANNEL_IMPORTANCE = 941;
+
+ // OPEN: Settings > Notifications > An app > A channel > On the lock screen
+ // CATEGORY: SETTINGS
+ // OS: O
+ NOTIFICATION_CHANNEL_LOCK_SCREEN_VIS = 942;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index f61edc5..8a20c85 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -390,7 +390,7 @@
* Updates a cached service for a given user.
*/
private void updateCachedServiceLocked(int userId, boolean disabled) {
- AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
if (service != null) {
service.updateLocked(disabled);
if (!service.isEnabled()) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0687f6d..79311b0 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -563,7 +563,6 @@
// AutoFillUiCallback
@Override
public void fill(int requestId, Dataset dataset) {
- mHandlerCaller.getHandler().post(() -> autoFill(requestId, dataset));
synchronized (mLock) {
if (mDestroyed) {
Slog.w(TAG, "Call to Session#fill() rejected - session: "
diff --git a/services/core/java/com/android/server/SyntheticPasswordManager.java b/services/core/java/com/android/server/SyntheticPasswordManager.java
index d23584f..6ec74e1 100644
--- a/services/core/java/com/android/server/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/SyntheticPasswordManager.java
@@ -82,7 +82,7 @@
// 256-bit synthetic password
private static final byte SYNTHETIC_PASSWORD_LENGTH = 256 / 8;
- private static final int PASSWORD_SCRYPT_N = 13;
+ private static final int PASSWORD_SCRYPT_N = 11;
private static final int PASSWORD_SCRYPT_R = 3;
private static final int PASSWORD_SCRYPT_P = 1;
private static final int PASSWORD_SALT_LENGTH = 16;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 018e41b..03da5b2 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -576,6 +576,22 @@
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
+ if (AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE.equals(packageName)) {
+ int visibility = getAccountVisibilityFromCache(account, packageName, accounts);
+ if (AccountManager.VISIBILITY_UNDEFINED != visibility) {
+ return visibility;
+ } else {
+ return AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
+ }
+ }
+ if (AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE.equals(packageName)) {
+ int visibility = getAccountVisibilityFromCache(account, packageName, accounts);
+ if (AccountManager.VISIBILITY_UNDEFINED != visibility) {
+ return visibility;
+ } else {
+ return AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE;
+ }
+ }
return resolveAccountVisibility(account, packageName, accounts);
} finally {
restoreCallingIdentity(identityToken);
@@ -641,11 +657,6 @@
return AccountManager.VISIBILITY_VISIBLE; // Authenticator can always see the account
}
- if (isSpecialPackageKey(packageName)) {
- Log.d(TAG, "Package name is forbidden: " + packageName);
- return AccountManager.VISIBILITY_NOT_VISIBLE;
- }
-
// Return stored value if it was set.
int visibility = getAccountVisibilityFromCache(account, packageName, accounts);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8d1435b..01a66b4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14644,8 +14644,10 @@
}
static int procStateToImportance(int procState, int memAdj,
- ActivityManager.RunningAppProcessInfo currApp) {
- int imp = ActivityManager.RunningAppProcessInfo.procStateToImportance(procState);
+ ActivityManager.RunningAppProcessInfo currApp,
+ int clientTargetSdk) {
+ int imp = ActivityManager.RunningAppProcessInfo.procStateToImportanceForTargetSdk(
+ procState, clientTargetSdk);
if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
currApp.lru = memAdj;
} else {
@@ -14655,7 +14657,8 @@
}
private void fillInProcMemInfo(ProcessRecord app,
- ActivityManager.RunningAppProcessInfo outInfo) {
+ ActivityManager.RunningAppProcessInfo outInfo,
+ int clientTargetSdk) {
outInfo.pid = app.pid;
outInfo.uid = app.info.uid;
if (mHeavyWeightProcess == app) {
@@ -14670,7 +14673,7 @@
outInfo.lastTrimLevel = app.trimMemoryLevel;
int adj = app.curAdj;
int procState = app.curProcState;
- outInfo.importance = procStateToImportance(procState, adj, outInfo);
+ outInfo.importance = procStateToImportance(procState, adj, outInfo, clientTargetSdk);
outInfo.importanceReasonCode = app.adjTypeCode;
outInfo.processState = app.curProcState;
}
@@ -14680,6 +14683,7 @@
enforceNotIsolatedCaller("getRunningAppProcesses");
final int callingUid = Binder.getCallingUid();
+ final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid);
// Lazy instantiation of list
List<ActivityManager.RunningAppProcessInfo> runList = null;
@@ -14702,7 +14706,7 @@
ActivityManager.RunningAppProcessInfo currApp =
new ActivityManager.RunningAppProcessInfo(app.processName,
app.pid, app.getPackageList());
- fillInProcMemInfo(app, currApp);
+ fillInProcMemInfo(app, currApp, clientTargetSdk);
if (app.adjSource instanceof ProcessRecord) {
currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
currApp.importanceReasonImportance =
@@ -14758,12 +14762,16 @@
@Override
public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) {
enforceNotIsolatedCaller("getMyMemoryState");
+
+ final int callingUid = Binder.getCallingUid();
+ final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid);
+
synchronized (this) {
ProcessRecord proc;
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(Binder.getCallingPid());
}
- fillInProcMemInfo(proc, outInfo);
+ fillInProcMemInfo(proc, outInfo, clientTargetSdk);
}
}
@@ -21722,9 +21730,11 @@
}
}
} catch (Exception e) {
- Slog.w(TAG, "Failed setting process group of " + app.pid
- + " to " + app.curSchedGroup);
- e.printStackTrace();
+ if (false) {
+ Slog.w(TAG, "Failed setting process group of " + app.pid
+ + " to " + app.curSchedGroup);
+ Slog.w(TAG, "at location", e);
+ }
} finally {
Binder.restoreCallingIdentity(oldId);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 728a3b9..82e2a3d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3301,13 +3301,21 @@
final ActivityRecord next = topRunningActivityLocked();
final String myReason = reason + " adjustFocus";
+
if (next != r) {
if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) {
// For freeform, docked, and pinned stacks we always keep the focus within the
// stack as long as there is a running activity.
return;
} else {
+ // Task is not guaranteed to be non-null. For example, destroying the
+ // {@link ActivityRecord} will disassociate the task from the activity.
final TaskRecord task = r.getTask();
+
+ if (task == null) {
+ throw new IllegalStateException("activity no longer associated with task:" + r);
+ }
+
final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() ||
task.isOverAssistantStack();
if (r.frontOfTask && isATopFinishingTask(task)
@@ -3373,8 +3381,8 @@
if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r);
if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"stop-no-history", false)) {
- // Activity was finished, no need to continue trying to schedule stop.
- adjustFocusedActivityStackLocked(r, "stopActivityFinished");
+ // If {@link requestFinishActivityLocked} returns {@code true},
+ // {@link adjustFocusedActivityStackLocked} would have been already called.
r.resumeKeyDispatchingLocked();
return;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index bff3ce3..dfeff52 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -110,7 +110,6 @@
import android.app.ActivityOptions;
import android.app.AppOpsManager;
import android.app.IActivityContainerCallback;
-import android.app.ITaskStackListener;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.StatusBarManager;
@@ -157,7 +156,6 @@
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.voice.IVoiceInteractionSession;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
@@ -1129,7 +1127,7 @@
mActivitiesWaitingForVisibleActivity.remove(r);
for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
- if (mWaitingForActivityVisible.get(i).matches(r)) {
+ if (mWaitingForActivityVisible.get(i).matches(r.realActivity)) {
mWaitingForActivityVisible.remove(i);
}
}
@@ -1143,7 +1141,7 @@
boolean changed = false;
for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
final WaitInfo w = mWaitingForActivityVisible.get(i);
- if (w.matches(r)) {
+ if (w.matches(r.realActivity)) {
final WaitResult result = w.getResult();
changed = true;
result.timeout = false;
@@ -3944,10 +3942,11 @@
}
private StackInfo getStackInfoLocked(ActivityStack stack) {
- final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
+ final int displayId = stack.mDisplayId;
+ final ActivityDisplay display = mActivityDisplays.get(displayId);
StackInfo info = new StackInfo();
stack.getWindowContainerBounds(info.bounds);
- info.displayId = DEFAULT_DISPLAY;
+ info.displayId = displayId;
info.stackId = stack.mStackId;
info.userId = stack.mCurrentUser;
info.visible = stack.shouldBeVisible(null) == STACK_VISIBLE;
@@ -5140,10 +5139,8 @@
this.mResult = result;
}
- public boolean matches(ActivityRecord record) {
- return mTargetComponent == null ||
- (TextUtils.equals(mTargetComponent.getPackageName(), record.info.packageName)
- && TextUtils.equals(mTargetComponent.getClassName(), record.info.name));
+ public boolean matches(ComponentName targetComponent) {
+ return mTargetComponent == null || mTargetComponent.equals(targetComponent);
}
public WaitResult getResult() {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 1f4b21b1..ca842d55 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -245,6 +245,9 @@
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
+ // Pull the optional Ephemeral Installer-only bundle out of the options early.
+ final Bundle verificationBundle
+ = options != null ? options.popAppVerificationBundle() : null;
ProcessRecord callerApp = null;
if (caller != null) {
@@ -466,7 +469,7 @@
// app [on install success].
if (rInfo != null && rInfo.auxiliaryInfo != null) {
intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
- callingPackage, resolvedType, userId);
+ callingPackage, verificationBundle, resolvedType, userId);
resolvedType = null;
callingUid = realCallingUid;
callingPid = realCallingPid;
@@ -522,14 +525,16 @@
* Creates a launch intent for the given auxiliary resolution data.
*/
private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
- Intent originalIntent, String callingPackage, String resolvedType, int userId) {
+ Intent originalIntent, String callingPackage, Bundle verificationBundle,
+ String resolvedType, int userId) {
if (auxiliaryResponse.needsPhaseTwo) {
// request phase two resolution
mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
- auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
+ auxiliaryResponse, originalIntent, resolvedType, callingPackage,
+ verificationBundle, userId);
}
return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent,
- callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
+ callingPackage, verificationBundle, resolvedType, userId, auxiliaryResponse.packageName,
auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 42c405f..027dc08 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -495,8 +495,9 @@
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
runningIntent.setData(Uri.fromParts("package",
appInfo.packageName, null));
- PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
- runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pi = PendingIntent.getActivityAsUser(ams.mContext, 0,
+ runningIntent, PendingIntent.FLAG_UPDATE_CURRENT, null,
+ UserHandle.of(userId));
notiBuilder.setColor(ams.mContext.getColor(
com.android.internal
.R.color.system_notification_accent_color));
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 313abab..dbccc07 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -353,6 +353,7 @@
&& mCurrentDreamIsTest == isTest
&& mCurrentDreamCanDoze == canDoze
&& mCurrentDreamUserId == userId) {
+ Slog.i(TAG, "Already in target dream.");
return;
}
@@ -388,6 +389,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
+ Slog.i(TAG, "Performing gentle wake from dream.");
mController.stopDream(immediate);
}
});
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
index 848704e..1c31c3e 100644
--- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -109,44 +109,49 @@
final String pkgName = getNextArgRequired();
final int jobId = Integer.parseInt(getNextArgRequired());
- int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
- switch (ret) {
- case CMD_ERR_NO_PACKAGE:
- pw.print("Package not found: ");
- pw.print(pkgName);
- pw.print(" / user ");
- pw.println(userId);
- break;
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
+ switch (ret) {
+ case CMD_ERR_NO_PACKAGE:
+ pw.print("Package not found: ");
+ pw.print(pkgName);
+ pw.print(" / user ");
+ pw.println(userId);
+ break;
- case CMD_ERR_NO_JOB:
- pw.print("Could not find job ");
- pw.print(jobId);
- pw.print(" in package ");
- pw.print(pkgName);
- pw.print(" / user ");
- pw.println(userId);
- break;
+ case CMD_ERR_NO_JOB:
+ pw.print("Could not find job ");
+ pw.print(jobId);
+ pw.print(" in package ");
+ pw.print(pkgName);
+ pw.print(" / user ");
+ pw.println(userId);
+ break;
- case CMD_ERR_CONSTRAINTS:
- pw.print("Job ");
- pw.print(jobId);
- pw.print(" in package ");
- pw.print(pkgName);
- pw.print(" / user ");
- pw.print(userId);
- pw.println(" has functional constraints but --force not specified");
- break;
+ case CMD_ERR_CONSTRAINTS:
+ pw.print("Job ");
+ pw.print(jobId);
+ pw.print(" in package ");
+ pw.print(pkgName);
+ pw.print(" / user ");
+ pw.print(userId);
+ pw.println(" has functional constraints but --force not specified");
+ break;
- default:
- // success!
- pw.print("Running job");
- if (force) {
- pw.print(" [FORCED]");
- }
- pw.println();
- break;
+ default:
+ // success!
+ pw.print("Running job");
+ if (force) {
+ pw.print(" [FORCED]");
+ }
+ pw.println();
+ break;
+ }
+ return ret;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- return ret;
}
private int runMonitorBattery(PrintWriter pw) throws Exception {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 51cc391..b8ca2bb 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -56,6 +56,7 @@
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -980,6 +981,14 @@
void addNotification(NotificationRecord r) {
mNotificationList.add(r);
mNotificationsByKey.put(r.sbn.getKey(), r);
+ if (r.sbn.isGroup()) {
+ mSummaryByGroupKey.put(r.getGroupKey(), r);
+ }
+ }
+
+ @VisibleForTesting
+ void addEnqueuedNotification(NotificationRecord r) {
+ mEnqueuedNotifications.add(r);
}
@VisibleForTesting
@@ -1016,7 +1025,7 @@
@VisibleForTesting
void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
LightsManager lightsManager, NotificationListeners notificationListeners,
- ICompanionDeviceManager companionManager) {
+ ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper) {
Resources resources = getContext().getResources();
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1071,21 +1080,7 @@
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
}
});
- mSnoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {
- @Override
- public void repost(int userId, NotificationRecord r) {
- try {
- if (DBG) {
- Slog.d(TAG, "Reposting " + r.getKey());
- }
- enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),
- r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),
- r.sbn.getNotification(), userId);
- } catch (Exception e) {
- Slog.e(TAG, "Cannot un-snooze notification", e);
- }
- }
- }, mUserProfiles);
+ mSnoozeHelper = snoozeHelper;
mGroupHelper = new GroupHelper(new GroupHelper.Callback() {
@Override
public void addAutoGroup(String key) {
@@ -1204,9 +1199,25 @@
@Override
public void onStart() {
+ SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {
+ @Override
+ public void repost(int userId, NotificationRecord r) {
+ try {
+ if (DBG) {
+ Slog.d(TAG, "Reposting " + r.getKey());
+ }
+ enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),
+ r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),
+ r.sbn.getNotification(), userId);
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot un-snooze notification", e);
+ }
+ }
+ }, mUserProfiles);
+
init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
getLocalService(LightsManager.class), new NotificationListeners(),
- null);
+ null, snoozeHelper);
publishBinderService(Context.NOTIFICATION_SERVICE, mService);
publishLocalService(NotificationManagerInternal.class, mInternalService);
}
@@ -3304,7 +3315,7 @@
return false;
}
} else if (isCallerInstantApp(pkg)) {
- // Ephemeral apps have some special contraints for notifications.
+ // Ephemeral apps have some special constraints for notifications.
// They are not allowed to create new notifications however they are allowed to
// update notifications created by the system (e.g. a foreground service
// notification).
@@ -3378,6 +3389,76 @@
return isBlocked;
}
+ protected class SnoozeNotificationRunnable implements Runnable {
+ private final String mKey;
+ private final long mDuration;
+ private final String mSnoozeCriterionId;
+
+ SnoozeNotificationRunnable(String key, long duration, String snoozeCriterionId) {
+ mKey = key;
+ mDuration = duration;
+ mSnoozeCriterionId = snoozeCriterionId;
+ }
+
+ @Override
+ public void run() {
+ synchronized (mNotificationLock) {
+ final NotificationRecord r = findNotificationByKeyLocked(mKey);
+ if (r != null) {
+ snoozeLocked(r);
+ }
+ }
+ }
+
+ void snoozeLocked(NotificationRecord r) {
+ if (r.sbn.isGroup()) {
+ final List<NotificationRecord> groupNotifications = findGroupNotificationsLocked(
+ r.sbn.getPackageName(), r.sbn.getGroupKey(), r.sbn.getUserId());
+ if (r.getNotification().isGroupSummary()) {
+ // snooze summary and all children
+ for (int i = 0; i < groupNotifications.size(); i++) {
+ snoozeNotificationLocked(groupNotifications.get(i));
+ }
+ } else {
+ // if there is a valid summary for this group, and we are snoozing the only
+ // child, also snooze the summary
+ if (mSummaryByGroupKey.containsKey(r.sbn.getGroupKey())) {
+ if (groupNotifications.size() != 2) {
+ snoozeNotificationLocked(r);
+ } else {
+ // snooze summary and the one child
+ for (int i = 0; i < groupNotifications.size(); i++) {
+ snoozeNotificationLocked(groupNotifications.get(i));
+ }
+ }
+ } else {
+ snoozeNotificationLocked(r);
+ }
+ }
+ } else {
+ // just snooze the one notification
+ snoozeNotificationLocked(r);
+ }
+ }
+
+ void snoozeNotificationLocked(NotificationRecord r) {
+ MetricsLogger.action(r.getLogMaker()
+ .setCategory(MetricsEvent.NOTIFICATION_SNOOZED)
+ .setType(MetricsEvent.TYPE_CLOSE)
+ .addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA,
+ mSnoozeCriterionId == null ? 0 : 1));
+ cancelNotificationLocked(r, false, REASON_SNOOZED);
+ updateLightsLocked();
+ if (mSnoozeCriterionId != null) {
+ mNotificationAssistants.notifyAssistantSnoozedLocked(r.sbn, mSnoozeCriterionId);
+ mSnoozeHelper.snooze(r);
+ } else {
+ mSnoozeHelper.snooze(r, mDuration);
+ }
+ savePolicyFile();
+ }
+ }
+
protected class EnqueueNotificationRunnable implements Runnable {
private final NotificationRecord r;
private final int userId;
@@ -3412,6 +3493,11 @@
// can to avoid extracting signals.
handleGroupedNotificationLocked(r, old, callingUid, callingPid);
+ // if this is a group child, unsnooze parent summary
+ if (n.isGroup() && notification.isGroupChild()) {
+ mSnoozeHelper.repostGroupSummary(pkg, r.getUserId(), n.getGroupKey());
+ }
+
// This conditional is a dirty hack to limit the logging done on
// behalf of the download manager without affecting other apps.
if (!pkg.equals("com.android.providers.downloads")
@@ -4394,31 +4480,7 @@
snoozeCriterionId, listenerName));
}
// Needs to post so that it can cancel notifications not yet enqueued.
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- synchronized (mNotificationLock) {
- final NotificationRecord r = findNotificationByKeyLocked(key);
- if (r != null) {
- MetricsLogger.action(r.getLogMaker()
- .setCategory(MetricsEvent.NOTIFICATION_SNOOZED)
- .setType(MetricsEvent.TYPE_CLOSE)
- .addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA,
- snoozeCriterionId == null ? 0 : 1));
- cancelNotificationLocked(r, false, REASON_SNOOZED);
- updateLightsLocked();
- if (snoozeCriterionId != null) {
- mNotificationAssistants.notifyAssistantSnoozedLocked(r.sbn,
- snoozeCriterionId);
- mSnoozeHelper.snooze(r);
- } else {
- mSnoozeHelper.snooze(r, duration);
- }
- savePolicyFile();
- }
- }
- }
- });
+ mHandler.post(new SnoozeNotificationRunnable(key, duration, snoozeCriterionId));
}
void unsnoozeNotificationInt(String key, ManagedServiceInfo listener) {
@@ -4531,6 +4593,30 @@
}
}
+ @NonNull List<NotificationRecord> findGroupNotificationsLocked(String pkg,
+ String groupKey, int userId) {
+ List<NotificationRecord> records = new ArrayList<>();
+ records.addAll(findGroupNotificationByListLocked(mNotificationList, pkg, groupKey, userId));
+ records.addAll(
+ findGroupNotificationByListLocked(mEnqueuedNotifications, pkg, groupKey, userId));
+ return records;
+ }
+
+
+ private @NonNull List<NotificationRecord> findGroupNotificationByListLocked(
+ ArrayList<NotificationRecord> list, String pkg, String groupKey, int userId) {
+ List<NotificationRecord> records = new ArrayList<>();
+ final int len = list.size();
+ for (int i = 0; i < len; i++) {
+ NotificationRecord r = list.get(i);
+ if (notificationMatchesUserId(r, userId) && r.getGroupKey().equals(groupKey)
+ && r.sbn.getPackageName().equals(pkg)) {
+ records.add(r);
+ }
+ }
+ return records;
+ }
+
// Searches both enqueued and posted notifications by key.
// TODO: need to combine a bunch of these getters with slightly different behavior.
// TODO: Should enqueuing just add to mNotificationsByKey instead?
@@ -4545,7 +4631,7 @@
return null;
}
- private NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) {
+ NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) {
NotificationRecord r;
if ((r = findNotificationByListLocked(mNotificationList, pkg, tag, id, userId)) != null) {
return r;
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 913f636..42b4f57 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -25,6 +25,7 @@
import android.annotation.NonNull;
import android.app.AlarmManager;
+import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -61,7 +62,6 @@
private static final String REPOST_ACTION = SnoozeHelper.class.getSimpleName() + ".EVALUATE";
private static final int REQUEST_CODE_REPOST = 1;
private static final String REPOST_SCHEME = "repost";
- private static final String EXTRA_PKG = "pkg";
private static final String EXTRA_KEY = "key";
private static final String EXTRA_USER_ID = "userId";
@@ -98,7 +98,7 @@
protected Collection<NotificationRecord> getSnoozed(int userId, String pkg) {
if (mSnoozedNotifications.containsKey(userId)
&& mSnoozedNotifications.get(userId).containsKey(pkg)) {
- mSnoozedNotifications.get(userId).get(pkg).values();
+ return mSnoozedNotifications.get(userId).get(pkg).values();
}
return Collections.EMPTY_LIST;
}
@@ -106,16 +106,18 @@
protected @NonNull List<NotificationRecord> getSnoozed() {
List<NotificationRecord> snoozedForUser = new ArrayList<>();
int[] userIds = mUserProfiles.getCurrentProfileIds();
- final int N = userIds.length;
- for (int i = 0; i < N; i++) {
- final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs =
- mSnoozedNotifications.get(userIds[i]);
- if (snoozedPkgs != null) {
- final int M = snoozedPkgs.size();
- for (int j = 0; j < M; j++) {
- final ArrayMap<String, NotificationRecord> records = snoozedPkgs.valueAt(j);
- if (records != null) {
- snoozedForUser.addAll(records.values());
+ if (userIds != null) {
+ final int N = userIds.length;
+ for (int i = 0; i < N; i++) {
+ final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs =
+ mSnoozedNotifications.get(userIds[i]);
+ if (snoozedPkgs != null) {
+ final int M = snoozedPkgs.size();
+ for (int j = 0; j < M; j++) {
+ final ArrayMap<String, NotificationRecord> records = snoozedPkgs.valueAt(j);
+ if (records != null) {
+ snoozedForUser.addAll(records.values());
+ }
}
}
}
@@ -281,6 +283,42 @@
}
}
+ protected void repostGroupSummary(String pkg, int userId, String groupKey) {
+ if (mSnoozedNotifications.containsKey(userId)) {
+ ArrayMap<String, ArrayMap<String, NotificationRecord>> keysByPackage
+ = mSnoozedNotifications.get(userId);
+
+ if (keysByPackage != null && keysByPackage.containsKey(pkg)) {
+ ArrayMap<String, NotificationRecord> recordsByKey = keysByPackage.get(pkg);
+
+ if (recordsByKey != null) {
+ String groupSummaryKey = null;
+ int N = recordsByKey.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord potentialGroupSummary = recordsByKey.valueAt(i);
+ if (potentialGroupSummary.sbn.isGroup()
+ && potentialGroupSummary.getNotification().isGroupSummary()
+ && groupKey.equals(potentialGroupSummary.getGroupKey())) {
+ groupSummaryKey = potentialGroupSummary.getKey();
+ break;
+ }
+ }
+
+ if (groupSummaryKey != null) {
+ NotificationRecord record = recordsByKey.remove(groupSummaryKey);
+ mPackages.remove(groupSummaryKey);
+ mUsers.remove(groupSummaryKey);
+
+ MetricsLogger.action(record.getLogMaker()
+ .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
+ .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
+ mCallback.repost(userId, record);
+ }
+ }
+ }
+ }
+ }
+
private PendingIntent createPendingIntent(String pkg, String key, int userId) {
return PendingIntent.getBroadcast(mContext,
REQUEST_CODE_REPOST,
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index b56db04..624d8c9 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -41,6 +41,7 @@
import android.metrics.LogMaker;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
@@ -147,6 +148,7 @@
final Intent installerIntent = buildEphemeralInstallerIntent(
requestObj.origIntent,
requestObj.callingPackage,
+ requestObj.verificationBundle,
requestObj.resolvedType,
requestObj.userId,
packageName,
@@ -172,6 +174,7 @@
*/
public static Intent buildEphemeralInstallerIntent(@NonNull Intent origIntent,
@NonNull String callingPackage,
+ @Nullable Bundle verificationBundle,
@NonNull String resolvedType,
int userId,
@NonNull String instantAppPackageName,
@@ -234,6 +237,10 @@
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, instantAppPackageName);
intent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName);
intent.putExtra(Intent.EXTRA_VERSION_CODE, versionCode);
+ intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage);
+ if (verificationBundle != null) {
+ intent.putExtra(Intent.EXTRA_VERIFICATION_BUNDLE, verificationBundle);
+ }
}
return intent;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7bbb1fe..a14c273 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5820,10 +5820,10 @@
private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
Intent origIntent, String resolvedType, String callingPackage,
- int userId) {
+ Bundle verificationBundle, int userId) {
final Message msg = mHandler.obtainMessage(INSTANT_APP_RESOLUTION_PHASE_TWO,
new InstantAppRequest(responseObj, origIntent, resolvedType,
- callingPackage, userId));
+ callingPackage, userId, verificationBundle));
mHandler.sendMessage(msg);
}
@@ -6372,7 +6372,7 @@
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
final InstantAppRequest requestObject = new InstantAppRequest(
null /*responseObj*/, intent /*origIntent*/, resolvedType,
- null /*callingPackage*/, userId);
+ null /*callingPackage*/, userId, null /*verificationBundle*/);
final AuxiliaryResolveInfo auxiliaryResponse =
InstantAppResolver.doInstantAppResolutionPhaseOne(
mContext, mInstantAppResolverConnection, requestObject);
@@ -20570,6 +20570,7 @@
public static final int DUMP_DEXOPT = 1 << 20;
public static final int DUMP_COMPILER_STATS = 1 << 21;
public static final int DUMP_ENABLED_OVERLAYS = 1 << 22;
+ public static final int DUMP_CHANGES = 1 << 23;
public static final int OPTION_SHOW_FILTERS = 1 << 0;
@@ -20815,6 +20816,8 @@
dumpState.setDump(DumpState.DUMP_COMPILER_STATS);
} else if ("enabled-overlays".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_ENABLED_OVERLAYS);
+ } else if ("changes".equals(cmd)) {
+ dumpState.setDump(DumpState.DUMP_CHANGES);
} else if ("write".equals(cmd)) {
synchronized (mPackages) {
mSettings.writeLPr();
@@ -21145,6 +21148,31 @@
mSettings.dumpSharedUsersLPr(pw, packageName, permissionNames, dumpState, checkin);
}
+ if (dumpState.isDumping(DumpState.DUMP_CHANGES)) {
+ if (dumpState.onTitlePrinted()) pw.println();
+ pw.println("Package Changes:");
+ pw.print(" Sequence number="); pw.println(mChangedPackagesSequenceNumber);
+ final int K = mChangedPackages.size();
+ for (int i = 0; i < K; i++) {
+ final SparseArray<String> changes = mChangedPackages.valueAt(i);
+ pw.print(" User "); pw.print(mChangedPackages.keyAt(i)); pw.println(":");
+ final int N = changes.size();
+ if (N == 0) {
+ pw.print(" "); pw.println("No packages changed");
+ } else {
+ for (int j = 0; j < N; j++) {
+ final String pkgName = changes.valueAt(j);
+ final int sequenceNumber = changes.keyAt(j);
+ pw.print(" ");
+ pw.print("seq=");
+ pw.print(sequenceNumber);
+ pw.print(", package=");
+ pw.println(pkgName);
+ }
+ }
+ }
+ }
+
if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS) && packageName == null) {
mSettings.dumpRestoredPermissionGrantsLPr(pw, dumpState);
}
@@ -23423,9 +23451,11 @@
@Override
public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
- Intent origIntent, String resolvedType, String callingPackage, int userId) {
+ Intent origIntent, String resolvedType, String callingPackage,
+ Bundle verificationBundle, int userId) {
PackageManagerService.this.requestInstantAppResolutionPhaseTwo(
- responseObj, origIntent, resolvedType, callingPackage, userId);
+ responseObj, origIntent, resolvedType, callingPackage, verificationBundle,
+ userId);
}
@Override
@@ -23570,6 +23600,13 @@
mIsolatedOwners.delete(isolatedUid);
}
}
+
+ @Override
+ public int getUidTargetSdkVersion(int uid) {
+ synchronized (mPackages) {
+ return getUidTargetSdkVersionLockedLPr(uid);
+ }
+ }
}
@Override
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index d402d10..f41a99f 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -24,6 +24,7 @@
import static junit.framework.Assert.fail;
import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
@@ -96,6 +97,7 @@
private NotificationManagerService.NotificationListeners mNotificationListeners;
private ManagedServices.ManagedServiceInfo mListener;
@Mock private ICompanionDeviceManager mCompanionMgr;
+ @Mock SnoozeHelper mSnoozeHelper;
// Use a Testable subclass so we can simulate calls from the system without failing.
private static class TestableNotificationManagerService extends NotificationManagerService {
@@ -133,7 +135,8 @@
null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
- mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr);
+ mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr,
+ mSnoozeHelper);
// Tests call directly into the Binder.
mBinderService = mNotificationManagerService.getBinderService();
@@ -147,6 +150,18 @@
mTestableLooper.processAllMessages();
}
+ private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
+ String groupKey, boolean isSummary) {
+ Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
+ .setContentTitle("foo")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setGroup(groupKey)
+ .setGroupSummary(isSummary);
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", uid, 0,
+ nb.build(), new UserHandle(uid), null, 0);
+ return new NotificationRecord(mContext, sbn, channel);
+ }
private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
return generateNotificationRecord(channel, null);
}
@@ -396,6 +411,46 @@
}
@Test
+ public void testFindGroupNotificationsLocked() throws Exception {
+ // make sure the same notification can be found in both lists and returned
+ final NotificationRecord group1 = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group1", true);
+ mNotificationManagerService.addEnqueuedNotification(group1);
+ mNotificationManagerService.addNotification(group1);
+
+ // should not be returned
+ final NotificationRecord group2 = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group2", true);
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+ group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
+ waitForIdle();
+
+ // should not be returned
+ final NotificationRecord nonGroup = generateNotificationRecord(
+ mTestNotificationChannel, 3, null, false);
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+ nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
+ waitForIdle();
+
+ // same group, child, should be returned
+ final NotificationRecord group1Child = generateNotificationRecord(
+ mTestNotificationChannel, 4, "group1", false);
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, group1Child.sbn.getId(),
+ group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
+ waitForIdle();
+
+ List<NotificationRecord> inGroup1 =
+ mNotificationManagerService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
+ group1.sbn.getUserId());
+ assertEquals(3, inGroup1.size());
+ for (NotificationRecord record : inGroup1) {
+ assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
+ assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
+ }
+ }
+
+
+ @Test
public void testTvExtenderChannelOverride_onTv() throws Exception {
mNotificationManagerService.setIsTelevision(true);
mNotificationManagerService.setRankingHelper(mRankingHelper);
@@ -701,4 +756,134 @@
assertFalse(mNotificationManagerService.hasCompanionDevice(mListener));
}
+ @Test
+ public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
+ final NotificationRecord nonGrouped = generateNotificationRecord(
+ mTestNotificationChannel, 1, null, false);
+ final NotificationRecord grouped = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group", false);
+ mNotificationManagerService.addNotification(grouped);
+ mNotificationManagerService.addNotification(nonGrouped);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mNotificationManagerService.new SnoozeNotificationRunnable(
+ nonGrouped.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ // only snooze the one notification
+ verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
+ }
+
+ @Test
+ public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
+ final NotificationRecord parent = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", true);
+ final NotificationRecord child = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group", false);
+ final NotificationRecord child2 = generateNotificationRecord(
+ mTestNotificationChannel, 3, "group", false);
+ mNotificationManagerService.addNotification(parent);
+ mNotificationManagerService.addNotification(child);
+ mNotificationManagerService.addNotification(child2);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mNotificationManagerService.new SnoozeNotificationRunnable(
+ parent.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ // snooze parent and children
+ verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
+ }
+
+ @Test
+ public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
+ final NotificationRecord parent = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", true);
+ final NotificationRecord child = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group", false);
+ final NotificationRecord child2 = generateNotificationRecord(
+ mTestNotificationChannel, 3, "group", false);
+ mNotificationManagerService.addNotification(parent);
+ mNotificationManagerService.addNotification(child);
+ mNotificationManagerService.addNotification(child2);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mNotificationManagerService.new SnoozeNotificationRunnable(
+ child2.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ // only snooze the one child
+ verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
+ }
+
+ @Test
+ public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
+ final NotificationRecord parent = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", true);
+ assertTrue(parent.sbn.getNotification().isGroupSummary());
+ final NotificationRecord child = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group", false);
+ mNotificationManagerService.addNotification(parent);
+ mNotificationManagerService.addNotification(child);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mNotificationManagerService.new SnoozeNotificationRunnable(
+ child.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ // snooze child and summary
+ verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
+ }
+
+ @Test
+ public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
+ final NotificationRecord child = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group", false);
+ mNotificationManagerService.addNotification(child);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mNotificationManagerService.new SnoozeNotificationRunnable(
+ child.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ // snooze child only
+ verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
+ }
+
+ @Test
+ public void testPostGroupChild_unsnoozeParent() throws Exception {
+ final NotificationRecord child = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group", false);
+
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+ child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
+ waitForIdle();
+
+ verify(mSnoozeHelper, times(1)).repostGroupSummary(
+ anyString(), anyInt(), eq(child.getGroupKey()));
+ }
+
+ @Test
+ public void testPostNonGroup_noUnsnoozing() throws Exception {
+ final NotificationRecord record = generateNotificationRecord(
+ mTestNotificationChannel, 2, null, false);
+
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+ record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
+ waitForIdle();
+
+ verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
+ }
+
+ @Test
+ public void testPostGroupSummary_noUnsnoozing() throws Exception {
+ final NotificationRecord parent = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group", true);
+
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+ parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
+ waitForIdle();
+
+ verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
+ }
}
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index 9575d32..51ec05c 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -34,6 +34,7 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Slog;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -232,13 +233,50 @@
assertEquals(4, mSnoozeHelper.getSnoozed().size());
}
+ @Test
+ public void repostGroupSummary_onlyFellowGroupChildren() throws Exception {
+ NotificationRecord r = getNotificationRecord(
+ "pkg", 1, "one", UserHandle.SYSTEM, "group1", false);
+ NotificationRecord r2 = getNotificationRecord(
+ "pkg", 2, "two", UserHandle.SYSTEM, "group1", false);
+ mSnoozeHelper.snooze(r, 1000);
+ mSnoozeHelper.snooze(r2, 1000);
+ mSnoozeHelper.repostGroupSummary("pkg", UserHandle.USER_SYSTEM, "group1");
+
+ verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r);
+ }
+
+ @Test
+ public void repostGroupSummary_repostsSummary() throws Exception {
+ when(mUserProfiles.getCurrentProfileIds()).thenReturn(
+ new int[] {UserHandle.USER_SYSTEM});
+ NotificationRecord r = getNotificationRecord(
+ "pkg", 1, "one", UserHandle.SYSTEM, "group1", true);
+ NotificationRecord r2 = getNotificationRecord(
+ "pkg", 2, "two", UserHandle.SYSTEM, "group1", false);
+ mSnoozeHelper.snooze(r, 1000);
+ mSnoozeHelper.snooze(r2, 1000);
+ assertEquals(2, mSnoozeHelper.getSnoozed().size());
+ assertEquals(2, mSnoozeHelper.getSnoozed(UserHandle.USER_SYSTEM, "pkg").size());
+
+ mSnoozeHelper.repostGroupSummary("pkg", UserHandle.USER_SYSTEM, r.getGroupKey());
+
+ verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
+ verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r2);
+
+ assertEquals(1, mSnoozeHelper.getSnoozed().size());
+ assertEquals(1, mSnoozeHelper.getSnoozed(UserHandle.USER_SYSTEM, "pkg").size());
+ }
+
private NotificationRecord getNotificationRecord(String pkg, int id, String tag,
- UserHandle user) {
+ UserHandle user, String groupKey, boolean groupSummary) {
Notification n = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("A")
.setGroup("G")
.setSortKey("A")
.setWhen(1205)
+ .setGroup(groupKey)
+ .setGroupSummary(groupSummary)
.build();
final NotificationChannel notificationChannel = new NotificationChannel(
TEST_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_LOW);
@@ -246,4 +284,9 @@
pkg, pkg, id, tag, 0, 0, n, user, null,
System.currentTimeMillis()), notificationChannel);
}
+
+ private NotificationRecord getNotificationRecord(String pkg, int id, String tag,
+ UserHandle user) {
+ return getNotificationRecord(pkg, id, tag, user, null, false);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 58166b6..c87eaed 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertTrue;
import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -84,4 +85,16 @@
// Make sure the resumed activity is untouched.
assertEquals(testStack.mResumedActivity, activityRecord);
}
+
+ @Test
+ public void testStopActivityWhenActivityDestroyed() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
+ final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
+ activityRecord.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
+ final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID);
+ service.mStackSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", testStack);
+
+ testStack.stopActivityLocked(activityRecord);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 0827084..3fc2c12 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -161,6 +161,11 @@
void moveHomeStackToFront(String reason) {
}
+ @Override
+ boolean moveHomeStackTaskToTop(String reason) {
+ return true;
+ }
+
// Invoked during {@link ActivityStack} creation.
@Override
void updateUIDsPresentOnDisplay() {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
index 315d37c..caa26e1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
@@ -35,7 +35,7 @@
p.setDataPosition(0);
ConnectEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
p.recycle();
- assertEquals(event.getIpAddress(), unparceledEvent.getIpAddress());
+ assertEquals(event.getInetAddress(), unparceledEvent.getInetAddress());
assertEquals(event.getPort(), unparceledEvent.getPort());
assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
@@ -53,9 +53,9 @@
DnsEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
p.recycle();
assertEquals(event.getHostname(), unparceledEvent.getHostname());
- assertEquals(event.getIpAddresses()[0], unparceledEvent.getIpAddresses()[0]);
- assertEquals(event.getIpAddresses()[1], unparceledEvent.getIpAddresses()[1]);
- assertEquals(event.getIpAddressesCount(), unparceledEvent.getIpAddressesCount());
+ assertEquals(event.getInetAddresses()[0], unparceledEvent.getInetAddresses()[0]);
+ assertEquals(event.getInetAddresses()[1], unparceledEvent.getInetAddresses()[1]);
+ assertEquals(event.getTotalResolvedAddressCount(), unparceledEvent.getTotalResolvedAddressCount());
assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 6c4ced4..4ffacfd 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1203,6 +1203,50 @@
}
@Override
+ public void onPackageModified(String pkgName) {
+ // If the package modified is not in the current user, then don't bother making
+ // any changes as we are going to do any initialization needed when we switch users.
+ if (mCurUser != getChangingUserId()) {
+ return;
+ }
+ // Package getting updated will be handled by {@link #onSomePackagesChanged}.
+ if (isPackageAppearing(pkgName) != PACKAGE_UNCHANGED) {
+ return;
+ }
+ final ComponentName curInteractor = getCurInteractor(mCurUser);
+ if (curInteractor == null) {
+ final VoiceInteractionServiceInfo availInteractorInfo
+ = findAvailInteractor(mCurUser, pkgName);
+ if (availInteractorInfo != null) {
+ final ComponentName availInteractor = new ComponentName(
+ availInteractorInfo.getServiceInfo().packageName,
+ availInteractorInfo.getServiceInfo().name);
+ setCurInteractor(availInteractor, mCurUser);
+ if (getCurRecognizer(mCurUser) == null &&
+ availInteractorInfo.getRecognitionService() != null) {
+ setCurRecognizer(new ComponentName(
+ availInteractorInfo.getServiceInfo().packageName,
+ availInteractorInfo.getRecognitionService()), mCurUser);
+ }
+ }
+ } else {
+ if (didSomePackagesChange()) {
+ // Package is changed
+ if (curInteractor != null && pkgName.equals(
+ curInteractor.getPackageName())) {
+ switchImplementationIfNeeded(true);
+ }
+ } else {
+ // Only some components are changed
+ if (curInteractor != null
+ && isComponentModified(curInteractor.getClassName())) {
+ switchImplementationIfNeeded(true);
+ }
+ }
+ }
+ }
+
+ @Override
public void onSomePackagesChanged() {
int userHandle = getChangingUserId();
if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0b4a3e8..7174a70 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -993,6 +993,20 @@
"carrier_default_actions_on_dcfailure_string_array";
/**
+ * Defines carrier-specific actions which act upon
+ * com.android.internal.telephony.CARRIER_SIGNAL_RESET, used for customization of the
+ * default carrier app
+ * Format: "CARRIER_ACTION_IDX, ..."
+ * Where {@code CARRIER_ACTION_IDX} is an integer defined in
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * Example:
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils
+ * #CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS clear all notifications on reset}
+ * @hide
+ */
+ public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET =
+ "carrier_default_actions_on_reset_string_array";
+ /**
* Defines a list of acceptable redirection url for default carrier app
* @hides
*/
@@ -1594,7 +1608,8 @@
sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
new String[]{
"com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" +
- "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED"
+ "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED," +
+ "com.android.internal.telephony.CARRIER_SIGNAL_RESET"
});
sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
@@ -1606,6 +1621,9 @@
//4: CARRIER_ACTION_DISABLE_METERED_APNS
//1: CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
});
+ sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET, new String[]{
+ "6" //6: CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
+ });
sDefaults.putStringArray(KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY, null);
sDefaults.putInt(KEY_MONTHLY_DATA_CYCLE_DAY_INT, DATA_CYCLE_USE_PLATFORM_DEFAULT);
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index f9875c5..ec9ca1d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -402,7 +402,7 @@
* <ul>
* <li>apnType</li><dd>A string with the apn type.</dd>
* <li>redirectionUrl</li><dd>redirection url string</dd>
- * <li>subId</dt><li>Sub Id which associated the data connection failure.</dd>
+ * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd>
* </ul>
* <p class="note">This is a protected intent that can only be sent by the system.</p>
*/
@@ -415,7 +415,7 @@
* <ul>
* <li>apnType</li><dd>A string with the apn type.</dd>
* <li>errorCode</li><dd>A integer with dataFailCause.</dd>
- * <li>subId</dt><li>Sub Id which associated the data connection failure.</dd>
+ * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd>
* </ul>
* <p class="note">This is a protected intent that can only be sent by the system. </p>
*/
@@ -432,13 +432,25 @@
* IPV4V6)</dd>
* <li>pcoId</li><dd>An integer indicating the pco id for the data.</dd>
* <li>pcoValue</li><dd>A byte array of pco data read from modem.</dd>
- * <li>subId</dt><li>Sub Id which associated the data connection.</dd>
+ * <li>subId</li><dd>Sub Id which associated the data connection.</dd>
* </ul>
* <p class="note">This is a protected intent that can only be sent by the system. </p>
*/
public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE =
"com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE";
+ /**
+ * <p>Broadcast Action: when framework reset all carrier actions on sim load or absent.
+ * intended for carrier apps clean up (clear UI e.g.) and only sent to the specified carrier app
+ * The intent will have the following extra values:</p>
+ * <ul>
+ * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd>
+ * </ul>
+ * <p class="note">This is a protected intent that can only be sent by the system.</p>
+ */
+ public static final String ACTION_CARRIER_SIGNAL_RESET =
+ "com.android.internal.telephony.CARRIER_SIGNAL_RESET";
+
// CARRIER_SIGNAL_ACTION extra keys
public static final String EXTRA_REDIRECTION_URL_KEY = "redirectionUrl";
public static final String EXTRA_ERROR_CODE_KEY = "errorCode";
diff --git a/tests/FeatureSplit/feature1/AndroidManifest.xml b/tests/FeatureSplit/feature1/AndroidManifest.xml
index 42619b6..b87361f 100644
--- a/tests/FeatureSplit/feature1/AndroidManifest.xml
+++ b/tests/FeatureSplit/feature1/AndroidManifest.xml
@@ -16,7 +16,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.split.feature"
- featureName="feature1">
+ featureSplit="feature1">
<uses-sdk android:minSdkVersion="21" />
diff --git a/tests/FeatureSplit/feature1/res/layout/included.xml b/tests/FeatureSplit/feature1/res/layout/included.xml
new file mode 100644
index 0000000..c64bdb7
--- /dev/null
+++ b/tests/FeatureSplit/feature1/res/layout/included.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
diff --git a/tests/FeatureSplit/feature1/res/layout/main.xml b/tests/FeatureSplit/feature1/res/layout/main.xml
new file mode 100644
index 0000000..dbea42a
--- /dev/null
+++ b/tests/FeatureSplit/feature1/res/layout/main.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <include layout="@layout/included"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</FrameLayout>
diff --git a/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java b/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java
index def1339..61ac9df 100644
--- a/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java
+++ b/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java
@@ -15,17 +15,16 @@
*/
package com.android.test.split.feature.one;
-import com.android.test.split.feature.ActivityMain;
-
+import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
-public class One extends ActivityMain {
+public class One extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ((TextView) findViewById(com.android.test.split.feature.R.id.text))
- .setText(R.string.feature_string);
+ setContentView(R.layout.main);
+ ((TextView) findViewById(R.id.text)).setText(R.string.feature_string);
}
}
diff --git a/tests/FeatureSplit/feature2/AndroidManifest.xml b/tests/FeatureSplit/feature2/AndroidManifest.xml
index b50044a..abd0b5e 100644
--- a/tests/FeatureSplit/feature2/AndroidManifest.xml
+++ b/tests/FeatureSplit/feature2/AndroidManifest.xml
@@ -16,7 +16,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.split.feature"
- featureName="feature2">
+ featureSplit="feature2">
<uses-sdk android:minSdkVersion="21" />
diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java
index cb5d4cb..630a287 100644
--- a/tests/testables/src/android/testing/TestableContext.java
+++ b/tests/testables/src/android/testing/TestableContext.java
@@ -43,7 +43,7 @@
* <ul>
* <li>System services can be mocked out with {@link #addMockSystemService}</li>
* <li>Service binding can be mocked out with {@link #addMockService}</li>
- * <li>Settings support {@link TestableSettings}</li>
+ * <li>Settings support {@link TestableSettingsProvider}</li>
* <li>Has support for {@link LeakCheck} for services and receivers</li>
* </ul>
*
@@ -59,7 +59,7 @@
public class TestableContext extends ContextWrapper implements TestRule {
private final TestableContentResolver mTestableContentResolver;
- private final TestableSettings mSettingsProvider;
+ private final TestableSettingsProvider mSettingsProvider;
private ArrayMap<String, Object> mMockSystemServices;
private ArrayMap<ComponentName, IBinder> mMockServices;
@@ -79,9 +79,8 @@
mTestableContentResolver = new TestableContentResolver(base);
ContentProviderClient settings = base.getContentResolver()
.acquireContentProviderClient(Settings.AUTHORITY);
- mSettingsProvider = TestableSettings.getFakeSettingsProvider(settings,
- mTestableContentResolver);
- mTestableContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider.getProvider());
+ mSettingsProvider = TestableSettingsProvider.getFakeSettingsProvider(settings);
+ mTestableContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
mReceiver = check != null ? check.getTracker("receiver") : null;
mService = check != null ? check.getTracker("service") : null;
mComponent = check != null ? check.getTracker("component") : null;
@@ -129,7 +128,7 @@
return super.getSystemService(name);
}
- public TestableSettings getSettingsProvider() {
+ TestableSettingsProvider getSettingsProvider() {
return mSettingsProvider;
}
@@ -236,12 +235,12 @@
return new TestWatcher() {
@Override
protected void succeeded(Description description) {
- mSettingsProvider.clearOverrides();
+ mSettingsProvider.clearValuesAndCheck(TestableContext.this);
}
@Override
protected void failed(Throwable e, Description description) {
- mSettingsProvider.clearOverrides();
+ mSettingsProvider.clearValuesAndCheck(TestableContext.this);
}
}.apply(base, description);
}
diff --git a/tests/testables/src/android/testing/TestableSettings.java b/tests/testables/src/android/testing/TestableSettings.java
deleted file mode 100644
index d19f1ef..0000000
--- a/tests/testables/src/android/testing/TestableSettings.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package android.testing;
-
-import android.content.ContentProvider;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.support.annotation.VisibleForTesting;
-import android.test.mock.MockContentProvider;
-import android.testing.TestableSettings.SettingOverrider.Builder;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Allows calls to android.provider.Settings to be tested easier. A SettingOverride
- * can be acquired and a set of specific settings can be set to a value (and not changed
- * in the system when set), so that they can be tested without breaking the test device.
- * <p>
- * To use, in the before method acquire the override add all settings that will affect if
- * your test passes or not.
- *
- * <pre class="prettyprint">
- * {@literal
- * mSettingOverride = mTestableContext.getSettingsProvider().acquireOverridesBuilder()
- * .addSetting("secure", Secure.USER_SETUP_COMPLETE, "0")
- * .build();
- * }
- * </pre>
- *
- * Then in the after free up the settings.
- *
- * <pre class="prettyprint">
- * {@literal
- * mSettingOverride.release();
- * }
- * </pre>
- */
-public class TestableSettings {
-
- private static final String TAG = "TestableSettings";
- private static final boolean DEBUG = false;
-
- // Number of times to try to acquire a setting if in use.
- private static final int MAX_TRIES = 10;
- // Time to wait for each setting. WAIT_TIMEOUT * MAX_TRIES will be the maximum wait time
- // for a setting.
- private static final long WAIT_TIMEOUT = 1000;
-
- private static TestableSettingsProvider sInstance;
-
- private final TestableSettingsProvider mProvider;
-
- private TestableSettings(TestableSettingsProvider provider) {
- mProvider = provider;
- }
-
- public Builder acquireOverridesBuilder() {
- return new Builder(this);
- }
-
- public void clearOverrides() {
- List<SettingOverrider> overrides = mProvider.mOwners.remove(this);
- if (overrides != null) {
- overrides.forEach(override -> override.ensureReleased());
- }
- }
-
- private void acquireSettings(SettingOverrider overridder, Set<String> keys)
- throws AcquireTimeoutException {
- mProvider.acquireSettings(overridder, keys, this);
- }
-
- ContentProvider getProvider() {
- return mProvider;
- }
-
- @VisibleForTesting
- Object getLock() {
- return mProvider.mOverrideMap;
- }
-
- public static class SettingOverrider {
- private final Set<String> mValidKeys;
- private final Map<String, String> mValueMap = new ArrayMap<>();
- private final TestableSettings mSettings;
- private boolean mReleased;
- public Throwable mObtain;
-
- private SettingOverrider(Set<String> keys, TestableSettings provider) {
- mValidKeys = new ArraySet<>(keys);
- mSettings = provider;
- }
-
- private void ensureReleased() {
- if (!mReleased) {
- release();
- }
- }
-
- public void release() {
- mSettings.mProvider.releaseSettings(mValidKeys);
- mReleased = true;
- }
-
- private void putDirect(String key, String value) {
- mValueMap.put(key, value);
- }
-
- public void put(String table, String key, String value) {
- if (!mValidKeys.contains(key(table, key))) {
- throw new IllegalArgumentException("Key " + table + " " + key
- + " not acquired for this overrider");
- }
- mValueMap.put(key(table, key), value);
- }
-
- public void remove(String table, String key) {
- if (!mValidKeys.contains(key(table, key))) {
- throw new IllegalArgumentException("Key " + table + " " + key
- + " not acquired for this overrider");
- }
- mValueMap.remove(key(table, key));
- }
-
- public String get(String table, String key) {
- if (!mValidKeys.contains(key(table, key))) {
- throw new IllegalArgumentException("Key " + table + " " + key
- + " not acquired for this overrider");
- }
- Log.d(TAG, "Get " + table + " " + key + " " + mValueMap.get(key(table, key)));
- return mValueMap.get(key(table, key));
- }
-
- public static class Builder {
- private final TestableSettings mProvider;
- private Set<String> mKeys = new ArraySet<>();
- private Map<String, String> mValues = new ArrayMap<>();
-
- private Builder(TestableSettings provider) {
- mProvider = provider;
- }
-
- public Builder addSetting(String table, String key) {
- mKeys.add(key(table, key));
- return this;
- }
-
- public Builder addSetting(String table, String key, String value) {
- addSetting(table, key);
- mValues.put(key(table, key), value);
- return this;
- }
-
- public SettingOverrider build() throws AcquireTimeoutException {
- SettingOverrider overrider = new SettingOverrider(mKeys, mProvider);
- mProvider.acquireSettings(overrider, mKeys);
- mValues.forEach((key, value) -> overrider.putDirect(key, value));
- return overrider;
- }
- }
- }
-
- private static class TestableSettingsProvider extends MockContentProvider {
-
- private final Map<String, SettingOverrider> mOverrideMap = new ArrayMap<>();
- private final Map<Object, List<SettingOverrider>> mOwners = new ArrayMap<>();
-
- private final ContentProviderClient mSettings;
- private final ContentResolver mResolver;
-
- public TestableSettingsProvider(ContentProviderClient settings, ContentResolver resolver) {
- mSettings = settings;
- mResolver = resolver;
- }
-
- private void releaseSettings(Set<String> keys) {
- synchronized (mOverrideMap) {
- for (String key : keys) {
- if (DEBUG) Log.d(TAG, "Releasing " + key);
- mOverrideMap.remove(key);
- }
- if (DEBUG) Log.d(TAG, "Notifying");
- mOverrideMap.notify();
- }
- }
-
- private boolean checkKeysLocked(Set<String> keys, boolean shouldThrow)
- throws AcquireTimeoutException {
- for (String key : keys) {
- if (mOverrideMap.containsKey(key)) {
- if (shouldThrow) {
- if (DEBUG) Log.e(TAG, "Lock obtained at",
- mOverrideMap.get(key).mObtain);
- throw new AcquireTimeoutException("Could not acquire " + key,
- mOverrideMap.get(key).mObtain);
- }
- return false;
- }
- }
- return true;
- }
-
- private void acquireSettings(SettingOverrider overridder, Set<String> keys,
- Object owner) throws AcquireTimeoutException {
- synchronized (mOwners) {
- List<SettingOverrider> list = mOwners.get(owner);
- if (list == null) {
- list = new ArrayList<>();
- mOwners.put(owner, list);
- }
- list.add(overridder);
- }
- synchronized (mOverrideMap) {
- for (int i = 0; i < MAX_TRIES; i++) {
- if (checkKeysLocked(keys, false)) break;
- try {
- if (DEBUG) Log.d(TAG, "Waiting for contention to finish");
- mOverrideMap.wait(WAIT_TIMEOUT);
- } catch (InterruptedException e) {
- }
- }
- overridder.mObtain = new Throwable();
- checkKeysLocked(keys, true);
- for (String key : keys) {
- if (DEBUG) Log.d(TAG, "Acquiring " + key);
- mOverrideMap.put(key, overridder);
- }
- }
- }
-
- public Bundle call(String method, String arg, Bundle extras) {
- // Methods are "GET_system", "GET_global", "PUT_secure", etc.
- final String[] commands = method.split("_", 2);
- final String op = commands[0];
- final String table = commands[1];
-
- synchronized (mOverrideMap) {
- SettingOverrider overrider = mOverrideMap.get(key(table, arg));
- if (overrider == null) {
- // Fall through to real settings.
- try {
- if (DEBUG) Log.d(TAG, "Falling through to real settings " + method);
- // TODO: Add our own version of caching to handle this.
- Bundle call = mSettings.call(method, arg, extras);
- call.remove(Settings.CALL_METHOD_TRACK_GENERATION_KEY);
- return call;
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- String value;
- Bundle out = new Bundle();
- switch (op) {
- case "GET":
- value = overrider.get(table, arg);
- if (value != null) {
- out.putString(Settings.NameValueTable.VALUE, value);
- }
- break;
- case "PUT":
- value = extras.getString(Settings.NameValueTable.VALUE, null);
- if (value != null) {
- overrider.put(table, arg, value);
- } else {
- overrider.remove(table, arg);
- }
- break;
- default:
- throw new UnsupportedOperationException("Unknown command " + method);
- }
- return out;
- }
- }
- }
-
- public static class AcquireTimeoutException extends Exception {
- public AcquireTimeoutException(String str, Throwable cause) {
- super(str, cause);
- }
- }
-
- private static String key(String table, String key) {
- return table + "_" + key;
- }
-
- /**
- * Since the settings provider is cached inside android.provider.Settings, this must
- * be gotten statically to ensure there is only one instance referenced.
- */
- public static TestableSettings getFakeSettingsProvider(ContentProviderClient settings,
- ContentResolver resolver) {
- if (sInstance == null) {
- sInstance = new TestableSettingsProvider(settings, resolver);
- }
- return new TestableSettings(sInstance);
- }
-}
diff --git a/tests/testables/src/android/testing/TestableSettingsProvider.java b/tests/testables/src/android/testing/TestableSettingsProvider.java
new file mode 100644
index 0000000..13056cf
--- /dev/null
+++ b/tests/testables/src/android/testing/TestableSettingsProvider.java
@@ -0,0 +1,120 @@
+/*
+ * 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.testing;
+
+import android.content.ContentProviderClient;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.test.mock.MockContentProvider;
+import android.util.Log;
+
+import java.util.HashMap;
+
+import static org.junit.Assert.*;
+
+/**
+ * Allows calls to android.provider.Settings to be tested easier.
+ *
+ * This provides a simple copy-on-write implementation of settings that gets cleared
+ * at the end of each test.
+ */
+public class TestableSettingsProvider extends MockContentProvider {
+
+ private static final String TAG = "TestableSettingsProvider";
+ private static final boolean DEBUG = false;
+ private static final String MY_UNIQUE_KEY = "Key_" + TestableSettingsProvider.class.getName();
+ private static TestableSettingsProvider sInstance;
+
+ private final ContentProviderClient mSettings;
+
+ private final HashMap<String, String> mValues = new HashMap<>();
+
+ private TestableSettingsProvider(ContentProviderClient settings) {
+ mSettings = settings;
+ }
+
+ void clearValuesAndCheck(Context context) {
+ mValues.put(key("global", MY_UNIQUE_KEY), MY_UNIQUE_KEY);
+ mValues.put(key("secure", MY_UNIQUE_KEY), MY_UNIQUE_KEY);
+ mValues.put(key("system", MY_UNIQUE_KEY), MY_UNIQUE_KEY);
+
+ // Verify that if any test is using TestableContext, they all have the correct settings
+ // provider.
+ assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY,
+ Settings.Global.getString(context.getContentResolver(), MY_UNIQUE_KEY));
+ assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY,
+ Settings.Secure.getString(context.getContentResolver(), MY_UNIQUE_KEY));
+ assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY,
+ Settings.System.getString(context.getContentResolver(), MY_UNIQUE_KEY));
+
+ mValues.clear();
+ }
+
+ public Bundle call(String method, String arg, Bundle extras) {
+ // Methods are "GET_system", "GET_global", "PUT_secure", etc.
+ final String[] commands = method.split("_", 2);
+ final String op = commands[0];
+ final String table = commands[1];
+
+ String k = key(table, arg);
+ String value;
+ Bundle out = new Bundle();
+ switch (op) {
+ case "GET":
+ if (mValues.containsKey(k)) {
+ value = mValues.get(k);
+ if (value != null) {
+ out.putString(Settings.NameValueTable.VALUE, value);
+ }
+ } else {
+ // Fall through to real settings.
+ try {
+ if (DEBUG) Log.d(TAG, "Falling through to real settings " + method);
+ // TODO: Add our own version of caching to handle this.
+ Bundle call = mSettings.call(method, arg, extras);
+ call.remove(Settings.CALL_METHOD_TRACK_GENERATION_KEY);
+ return call;
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ break;
+ case "PUT":
+ value = extras.getString(Settings.NameValueTable.VALUE, null);
+ mValues.put(k, value);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unknown command " + method);
+ }
+ return out;
+ }
+
+ private static String key(String table, String key) {
+ return table + "_" + key;
+ }
+
+ /**
+ * Since the settings provider is cached inside android.provider.Settings, this must
+ * be gotten statically to ensure there is only one instance referenced.
+ */
+ static TestableSettingsProvider getFakeSettingsProvider(ContentProviderClient settings) {
+ if (sInstance == null) {
+ sInstance = new TestableSettingsProvider(settings);
+ }
+ return sInstance;
+ }
+}
diff --git a/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java b/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java
new file mode 100644
index 0000000..1f71867
--- /dev/null
+++ b/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.testing;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.provider.Settings.Secure;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@RunWith(AndroidJUnit4.class)
+public class TestableSettingsProviderTest {
+
+ public static final String NONEXISTENT_SETTING = "nonexistent_setting";
+ private static final String TAG = "TestableSettingsProviderTest";
+ private ContentResolver mContentResolver;
+ @Rule
+ public final TestableContext mContext =
+ new TestableContext(InstrumentationRegistry.getContext());
+
+ @Before
+ public void setup() {
+ mContentResolver = mContext.getContentResolver();
+ Settings.Secure.putString(mContentResolver, NONEXISTENT_SETTING, null);
+ Settings.Global.putString(mContentResolver, NONEXISTENT_SETTING, "initial value");
+ Settings.Global.putString(mContentResolver, Global.DEVICE_PROVISIONED, null);
+ }
+
+ @Test
+ public void testInitialValueSecure() {
+ String value = Secure.getString(mContentResolver, NONEXISTENT_SETTING);
+ assertNull(value);
+ }
+
+ @Test
+ public void testInitialValueGlobal() {
+ String value = Global.getString(mContentResolver, NONEXISTENT_SETTING);
+ assertEquals("initial value", value);
+ }
+
+ @Test
+ public void testSeparateTables() {
+ Secure.putString(mContentResolver, NONEXISTENT_SETTING, "something");
+ Global.putString(mContentResolver, NONEXISTENT_SETTING, "else");
+ assertEquals("something", Secure.getString(mContentResolver, NONEXISTENT_SETTING));
+ assertEquals("else", Global.getString(mContentResolver, NONEXISTENT_SETTING));
+ }
+
+ @Test
+ public void testPassThrough() {
+ // Grab the value of a setting that is not overridden.
+ assertTrue(Secure.getInt(mContentResolver, Secure.USER_SETUP_COMPLETE, 0) != 0);
+ }
+
+ @Test
+ public void testOverrideExisting() {
+ // Grab the value of a setting that is overridden and will be different than the actual
+ // value.
+ assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED));
+ }
+
+ @Test
+ public void testRelease() {
+ // Verify different value.
+ assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED));
+ mContext.getSettingsProvider().clearValuesAndCheck(mContext);
+ // Verify actual value after release.
+ assertEquals("1", Global.getString(mContentResolver, Global.DEVICE_PROVISIONED));
+ }
+}
diff --git a/tests/testables/tests/src/android/testing/TestableSettingsTest.java b/tests/testables/tests/src/android/testing/TestableSettingsTest.java
deleted file mode 100644
index 1b01542..0000000
--- a/tests/testables/tests/src/android/testing/TestableSettingsTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package android.testing;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import android.content.ContentResolver;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.provider.Settings;
-import android.provider.Settings.Global;
-import android.provider.Settings.Secure;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.testing.TestableSettings.AcquireTimeoutException;
-import android.testing.TestableSettings.SettingOverrider;
-import android.util.Log;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class TestableSettingsTest {
-
- public static final String NONEXISTENT_SETTING = "nonexistent_setting";
- private static final String TAG = "TestableSettingsTest";
- private SettingOverrider mOverrider;
- private ContentResolver mContentResolver;
- @Rule
- public final TestableContext mContext =
- new TestableContext(InstrumentationRegistry.getContext());
-
- @Before
- public void setup() throws AcquireTimeoutException {
- mOverrider = mContext.getSettingsProvider().acquireOverridesBuilder()
- .addSetting("secure", NONEXISTENT_SETTING)
- .addSetting("global", NONEXISTENT_SETTING, "initial value")
- .addSetting("global", Global.DEVICE_PROVISIONED)
- .build();
- mContentResolver = mContext.getContentResolver();
- }
-
- @Test
- public void testInitialValueSecure() {
- String value = Secure.getString(mContentResolver, NONEXISTENT_SETTING);
- assertNull(value);
- }
-
- @Test
- public void testInitialValueGlobal() {
- String value = Global.getString(mContentResolver, NONEXISTENT_SETTING);
- assertEquals("initial value", value);
- }
-
- @Test
- public void testSeparateTables() {
- Secure.putString(mContentResolver, NONEXISTENT_SETTING, "something");
- Global.putString(mContentResolver, NONEXISTENT_SETTING, "else");
- assertEquals("something", Secure.getString(mContentResolver, NONEXISTENT_SETTING));
- assertEquals("something", mOverrider.get("secure", NONEXISTENT_SETTING));
- assertEquals("else", Global.getString(mContentResolver, NONEXISTENT_SETTING));
- assertEquals("else", mOverrider.get("global", NONEXISTENT_SETTING));
- }
-
- @Test
- public void testPassThrough() {
- // Grab the value of a setting that is not overridden.
- assertTrue(Secure.getInt(mContentResolver, Secure.USER_SETUP_COMPLETE, 0) != 0);
- }
-
- @Test
- public void testOverrideExisting() {
- // Grab the value of a setting that is overridden and will be different than the actual
- // value.
- assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED));
- }
-
- @Test
- public void testRelease() {
- // Verify different value.
- assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED));
- mOverrider.release();
- mOverrider = null;
- // Verify actual value after release.
- assertEquals("1", Global.getString(mContentResolver, Global.DEVICE_PROVISIONED));
- }
-
- @Test
- public void testAutoRelease() throws Exception {
- mOverrider.release();
- mOverrider = null;
- mContext.getSettingsProvider().acquireOverridesBuilder()
- .addSetting("global", Global.DEVICE_PROVISIONED)
- .build();
- }
-
- @Test
- public void testContention() throws AcquireTimeoutException, InterruptedException {
- SettingOverrider[] overriders = new SettingOverrider[2];
- Object lock = new Object();
- String secure = "secure";
- String key = "something shared";
- String[] result = new String[1];
- overriders[0] = mContext.getSettingsProvider().acquireOverridesBuilder()
- .addSetting(secure, key, "Some craziness")
- .build();
- synchronized (lock) {
- HandlerThread t = runOnHandler(() -> {
- try {
- // Grab the lock that will be used for the settings ownership to ensure
- // we have some contention going on.
- synchronized (mContext.getSettingsProvider().getLock()) {
- synchronized (lock) {
- // Let the other thread know to release the settings, but it won't
- // be able to until this thread waits in the build() method.
- lock.notify();
- }
- overriders[1] = mContext.getSettingsProvider()
- .acquireOverridesBuilder()
- .addSetting(secure, key, "default value")
- .build();
- // Ensure that the default is the one we set, and not left over from
- // the other setting override.
- result[0] = Settings.Secure.getString(mContentResolver, key);
- synchronized (lock) {
- // Let the main thread know we are done.
- lock.notify();
- }
- }
- } catch (AcquireTimeoutException e) {
- Log.e(TAG, "Couldn't acquire setting", e);
- }
- });
- // Wait for the thread to hold the acquire lock, then release the settings.
- lock.wait();
- overriders[0].release();
- // Wait for the thread to be done getting the value.
- lock.wait();
- // Quit and cleanup.
- t.quitSafely();
- assertNotNull(overriders[1]);
- overriders[1].release();
- }
- // Verify the value was the expected one from the thread's SettingOverride.
- assertEquals("default value", result[0]);
- }
-
- private HandlerThread runOnHandler(Runnable r) {
- HandlerThread t = new HandlerThread("Test Thread");
- t.start();
- new Handler(t.getLooper()).post(r);
- return t;
- }
-}
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 60b01e3..b872ebb 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -274,7 +274,13 @@
if (!attr.namespace_uri.empty()) {
std::cerr << attr.namespace_uri << ":";
}
- std::cerr << attr.name << "=" << attr.value << "\n";
+ std::cerr << attr.name;
+
+ if (attr.compiled_attribute) {
+ std::cerr << "(" << attr.compiled_attribute.value().id.value_or_default(ResourceId(0x0))
+ << ")";
+ }
+ std::cerr << "=" << attr.value << "\n";
}
const size_t previous_size = prefix_.size();
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index d44b3e0..f4d0226 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -573,10 +573,17 @@
// Write the ResTable header.
ChunkWriter table_writer(buffer_);
- ResTable_header* table_header =
- table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE);
+ ResTable_header* table_header = table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE);
table_header->packageCount = util::HostToDevice32(table->packages.size());
+ // Write a self mapping entry for this package if the ID is non-standard (0x7f).
+ if (context->GetPackageType() == PackageType::kApp) {
+ const uint8_t package_id = context->GetPackageId();
+ if (package_id != kFrameworkPackageId && package_id != kAppPackageId) {
+ table->included_packages_[package_id] = context->GetCompilationPackage();
+ }
+ }
+
// Flatten the values string pool.
StringPool::FlattenUtf8(table_writer.buffer(), table->string_pool);
diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp
index 8dff3a2..6d1350d 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -400,7 +400,7 @@
const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1);
ASSERT_NE(nullptr, dynamic_ref_table);
- const KeyedVector<String16, uint8_t> entries = dynamic_ref_table->entries();
+ const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries();
ssize_t idx = entries.indexOfKey(android::String16("lib_one"));
ASSERT_GE(idx, 0);
@@ -411,6 +411,26 @@
EXPECT_EQ(0x03u, entries.valueAt(idx));
}
+TEST_F(TableFlattenerTest, PackageWithNonStandardIdHasDynamicRefTable) {
+ std::unique_ptr<IAaptContext> context =
+ test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x80).Build();
+ std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
+ .SetPackageId("app", 0x80)
+ .AddSimple("app:id/foo", ResourceId(0x80010000))
+ .Build();
+
+ ResTable result;
+ ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result));
+
+ const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1);
+ ASSERT_NE(nullptr, dynamic_ref_table);
+
+ const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries();
+ ssize_t idx = entries.indexOfKey(android::String16("app"));
+ ASSERT_GE(idx, 0);
+ EXPECT_EQ(0x80u, entries.valueAt(idx));
+}
+
TEST_F(TableFlattenerTest, LongPackageNameIsTruncated) {
std::string kPackageName(256, 'F');
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 494d9d2..f0613e7 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -35,13 +35,16 @@
.SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
.AddSymbolSource(
test::StaticSymbolSourceBuilder()
- .AddSymbol("android:attr/id", ResourceId(0x010100d0),
- test::AttributeBuilder().Build())
+ .AddPublicSymbol("android:attr/id", ResourceId(0x010100d0),
+ test::AttributeBuilder().Build())
.AddSymbol("com.app.test:id/id", ResourceId(0x7f020000))
.AddPublicSymbol("android:attr/paddingStart", ResourceId(0x010103b3),
test::AttributeBuilder().Build())
.AddPublicSymbol("android:attr/colorAccent", ResourceId(0x01010435),
test::AttributeBuilder().Build())
+ .AddSymbol("com.app.test.feature:id/foo", ResourceId(0x80020000))
+ .AddSymbol("com.app.test.feature:attr/foo", ResourceId(0x80010000),
+ test::AttributeBuilder().Build())
.Build())
.Build();
}
@@ -65,7 +68,7 @@
}
protected:
- std::unique_ptr<IAaptContext> context_;
+ std::unique_ptr<test::Context> context_;
};
TEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
@@ -218,14 +221,10 @@
EXPECT_EQ(tree.indexOfStyle(), 1);
}
-/*
- * The device ResXMLParser in libandroidfw differentiates between empty
- * namespace and null
- * namespace.
- */
+// The device ResXMLParser in libandroidfw differentiates between empty namespace and null
+// namespace.
TEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
- std::unique_ptr<xml::XmlResource> doc =
- test::BuildXmlDom("<View package=\"android\"/>");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom("<View package=\"android\"/>");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
@@ -261,4 +260,44 @@
EXPECT_NE(nullptr, tree.getAttributeStringValue(idx, &len));
}
+TEST_F(XmlFlattenerTest, FlattenNonStandardPackageId) {
+ context_->SetCompilationPackage("com.app.test.feature");
+ context_->SetPackageId(0x80);
+ context_->SetNameManglerPolicy({"com.app.test.feature"});
+
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+ <View xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@id/foo"
+ app:foo="@id/foo" />)EOF");
+
+ XmlReferenceLinker linker;
+ ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
+
+ // The tree needs a custom DynamicRefTable since it is not using a standard app ID (0x7f).
+ android::DynamicRefTable dynamic_ref_table;
+ dynamic_ref_table.addMapping(0x80, 0x80);
+
+ android::ResXMLTree tree(&dynamic_ref_table);
+ ASSERT_TRUE(Flatten(doc.get(), &tree));
+
+ while (tree.next() != android::ResXMLTree::START_TAG) {
+ ASSERT_NE(android::ResXMLTree::BAD_DOCUMENT, tree.getEventType());
+ ASSERT_NE(android::ResXMLTree::END_DOCUMENT, tree.getEventType());
+ }
+
+ ssize_t idx;
+
+ idx = tree.indexOfAttribute(xml::kSchemaAndroid, "id");
+ ASSERT_GE(idx, 0);
+ EXPECT_EQ(idx, tree.indexOfID());
+ EXPECT_EQ(ResourceId(0x010100d0), ResourceId(tree.getAttributeNameResID(idx)));
+
+ idx = tree.indexOfAttribute(xml::kSchemaAuto, "foo");
+ ASSERT_GE(idx, 0);
+ EXPECT_EQ(ResourceId(0x80010000), ResourceId(tree.getAttributeNameResID(idx)));
+ EXPECT_EQ(android::Res_value::TYPE_REFERENCE, tree.getAttributeDataType(idx));
+ EXPECT_EQ(ResourceId(0x80020000), tree.getAttributeData(idx));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index 29d1838..0564db0 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -52,15 +52,27 @@
return compilation_package_.value();
}
+ void SetCompilationPackage(const android::StringPiece& package) {
+ compilation_package_ = package.to_string();
+ }
+
uint8_t GetPackageId() override {
CHECK(bool(package_id_)) << "package ID not set";
return package_id_.value();
}
+ void SetPackageId(uint8_t package_id) {
+ package_id_ = package_id;
+ }
+
NameMangler* GetNameMangler() override {
return &name_mangler_;
}
+ void SetNameManglerPolicy(const NameManglerPolicy& policy) {
+ name_mangler_ = NameMangler(policy);
+ }
+
bool IsVerbose() override {
return false;
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 229aa97..a7b4544 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -81,7 +81,7 @@
boolean disableNetwork(int netId);
- void startScan(in ScanSettings requested, in WorkSource ws);
+ void startScan(in ScanSettings requested, in WorkSource ws, in String packageName);
List<ScanResult> getScanResults(String callingPackage);
@@ -125,6 +125,8 @@
void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
+ void updateInterfaceIpState(String ifaceName, int mode);
+
boolean startSoftAp(in WifiConfiguration wifiConfig);
boolean stopSoftAp();
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 7defa7c..e31a74b 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -228,9 +228,9 @@
*/
public int networkId;
+ // Fixme We need remove this field to use only Quality network selection status only
/**
* The current status of this network configuration entry.
- * Fixme We need remove this field to use only Quality network selection status only
* @see Status
*/
public int status;
@@ -238,8 +238,8 @@
/**
* The network's SSID. Can either be an ASCII string,
* which must be enclosed in double quotation marks
- * (e.g., {@code "MyNetwork"}, or a string of
- * hex digits,which are not enclosed in quotes
+ * (e.g., {@code "MyNetwork"}), or a string of
+ * hex digits, which are not enclosed in quotes
* (e.g., {@code 01a243f405}).
*/
public String SSID;
@@ -290,9 +290,10 @@
* string otherwise.
*/
public String preSharedKey;
+
/**
* Up to four WEP keys. Either an ASCII string enclosed in double
- * quotation marks (e.g., {@code "abcdef"} or a string
+ * quotation marks (e.g., {@code "abcdef"}) or a string
* of hex digits (e.g., {@code 0102030405}).
* <p/>
* When the value of one of these keys is read, the actual key is
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ed54c3b..ab069f2 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -20,7 +20,6 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
@@ -46,9 +45,9 @@
import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
-import java.util.Collections;
/**
* This class provides the primary API for managing all aspects of Wi-Fi
@@ -446,6 +445,35 @@
* @hide
*/
public static final int SAP_START_FAILURE_NO_CHANNEL = 1;
+
+ /**
+ * Interface IP mode for configuration error.
+ *
+ * @see updateInterfaceIpState(String, int)
+ *
+ * @hide
+ */
+ public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0;
+
+ /**
+ * Interface IP mode for tethering.
+ *
+ * @see updateInterfaceIpState(String, int)
+ *
+ * @hide
+ */
+ public static final int IFACE_IP_MODE_TETHERED = 1;
+
+ /**
+ * Interface IP mode for Local Only Hotspot.
+ *
+ * @see updateInterfaceIpState(String, int)
+ *
+ * @hide
+ */
+ public static final int IFACE_IP_MODE_LOCAL_ONLY = 2;
+
+
/**
* Broadcast intent action indicating that a connection to the supplicant has
* been established (and it is now possible
@@ -1429,19 +1457,15 @@
* @return {@code true} if the operation succeeded, i.e., the scan was initiated
*/
public boolean startScan() {
- try {
- mService.startScan(null, null);
- return true;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return startScan(null);
}
/** @hide */
@SystemApi
public boolean startScan(WorkSource workSource) {
try {
- mService.startScan(null, workSource);
+ String packageName = mContext.getOpPackageName();
+ mService.startScan(null, workSource, packageName);
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1732,6 +1756,26 @@
}
/**
+ * Call allowing ConnectivityService to update WifiService with interface mode changes.
+ *
+ * The possible modes include: {@link IFACE_IP_MODE_TETHERED},
+ * {@link IFACE_IP_MODE_LOCAL_ONLY},
+ * {@link IFACE_IP_MODE_CONFIGURATION_ERROR}
+ *
+ * @param ifaceName String name of the updated interface
+ * @param mode int representing the new mode
+ *
+ * @hide
+ */
+ public void updateInterfaceIpState(String ifaceName, int mode) {
+ try {
+ mService.updateInterfaceIpState(ifaceName, mode);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Start SoftAp mode with the specified configuration.
* Note that starting in access point mode disables station
* mode operation