Merge "[QS] Disable hotspot when data saver is enabled" into pi-dev
diff --git a/api/current.txt b/api/current.txt
index 4416532..94c1d32 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13601,11 +13601,19 @@
method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source) throws java.io.IOException;
method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source) throws java.io.IOException;
+ method public int getAllocator();
+ method public boolean getConserveMemory();
+ method public android.graphics.Rect getCrop();
+ method public boolean getDecodeAsAlphaMask();
+ method public boolean getMutable();
+ method public android.graphics.ImageDecoder.OnPartialImageListener getOnPartialImageListener();
+ method public android.graphics.PostProcessor getPostProcessor();
+ method public boolean getRequireUnpremultiplied();
method public android.util.Size getSampledSize(int);
method public android.graphics.ImageDecoder setAllocator(int);
- method public android.graphics.ImageDecoder setAsAlphaMask(boolean);
method public android.graphics.ImageDecoder setConserveMemory(boolean);
method public android.graphics.ImageDecoder setCrop(android.graphics.Rect);
+ method public android.graphics.ImageDecoder setDecodeAsAlphaMask(boolean);
method public android.graphics.ImageDecoder setMutable(boolean);
method public android.graphics.ImageDecoder setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener);
method public android.graphics.ImageDecoder setPostProcessor(android.graphics.PostProcessor);
@@ -37136,6 +37144,7 @@
field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
field public static final java.lang.String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
+ field public static final java.lang.String ACTION_DATA_USAGE_SETTINGS = "android.settings.DATA_USAGE_SETTINGS";
field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
@@ -41371,10 +41380,10 @@
method public void onStateChanged(android.telecom.Call, int);
method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
- field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
- field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
- field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
- field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5; // 0x5
+ field public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; // 0x2
+ field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4; // 0x4
+ field public static final int HANDOVER_FAILURE_UNKNOWN = 5; // 0x5
+ field public static final int HANDOVER_FAILURE_USER_REJECTED = 3; // 0x3
}
public static class Call.Details {
diff --git a/api/removed.txt b/api/removed.txt
index b8e2b98..a5370f4 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -152,6 +152,11 @@
method public deprecated boolean clipRegion(android.graphics.Region);
}
+ public final class ImageDecoder implements java.lang.AutoCloseable {
+ method public deprecated boolean getAsAlphaMask();
+ method public deprecated android.graphics.ImageDecoder setAsAlphaMask(boolean);
+ }
+
public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
ctor public LayerRasterizer();
method public void addLayer(android.graphics.Paint, float, float);
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index af43032..64a5181 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -65,8 +65,8 @@
* <pre class="prettyprint">
* {@literal
* <provider
- * android:name="com.android.mypkg.MySliceProvider"
- * android:authorities="com.android.mypkg" />}
+ * android:name="com.example.mypkg.MySliceProvider"
+ * android:authorities="com.example.mypkg" />}
* </pre>
* <p>
* Slices can be identified by a Uri or by an Intent. To link an Intent with a slice, the provider
@@ -77,10 +77,10 @@
* <pre class="prettyprint">
* {@literal
* <provider
- * android:name="com.android.mypkg.MySliceProvider"
- * android:authorities="com.android.mypkg">
+ * android:name="com.example.mypkg.MySliceProvider"
+ * android:authorities="com.example.mypkg">
* <intent-filter>
- * <action android:name="android.intent.action.MY_SLICE_INTENT" />
+ * <action android:name="com.example.mypkg.intent.action.MY_SLICE_INTENT" />
* </intent-filter>
* </provider>}
* </pre>
diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java
index 0294a29..2a878eb 100644
--- a/core/java/android/hardware/radio/ProgramSelector.java
+++ b/core/java/android/hardware/radio/ProgramSelector.java
@@ -441,6 +441,15 @@
*/
public static @NonNull ProgramSelector createAmFmSelector(
@RadioManager.Band int band, int frequencyKhz, int subChannel) {
+ if (band == RadioManager.BAND_INVALID) {
+ // 50MHz is a rough boundary between AM (<30MHz) and FM (>60MHz).
+ if (frequencyKhz < 50000) {
+ band = (subChannel <= 0) ? RadioManager.BAND_AM : RadioManager.BAND_AM_HD;
+ } else {
+ band = (subChannel <= 0) ? RadioManager.BAND_FM : RadioManager.BAND_FM_HD;
+ }
+ }
+
boolean isAm = (band == RadioManager.BAND_AM || band == RadioManager.BAND_AM_HD);
boolean isDigital = (band == RadioManager.BAND_AM_HD || band == RadioManager.BAND_FM_HD);
if (!isAm && !isDigital && band != RadioManager.BAND_FM) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bd29d2d..c717dd9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -430,6 +430,20 @@
"android.settings.WIFI_IP_SETTINGS";
/**
+ * Activity Action: Show settings to allow configuration of data and view data usage.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_DATA_USAGE_SETTINGS =
+ "android.settings.DATA_USAGE_SETTINGS";
+
+ /**
* Activity Action: Show settings to allow configuration of Bluetooth.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 75940e8..77a74e2 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -416,4 +416,10 @@
* Returns true if window trace is enabled.
*/
boolean isWindowTraceEnabled();
+
+ /**
+ * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
+ * on the next user activity.
+ */
+ void requestUserActivityNotification();
}
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index a6f36bb..23dc9da 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -51,6 +51,12 @@
int NAV_BAR_BOTTOM = 1 << 2;
/**
+ * Broadcast sent when a user activity is detected.
+ */
+ String ACTION_USER_ACTIVITY_NOTIFICATION =
+ "android.intent.action.USER_ACTIVITY_NOTIFICATION";
+
+ /**
* Sticky broadcast of the current HDMI plugged state.
*/
String ACTION_HDMI_PLUGGED = "android.intent.action.HDMI_PLUGGED";
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 344c772..246a50f 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -38,11 +38,6 @@
*/
public class PowerProfile {
- /**
- * No power consumption, or accounted for elsewhere.
- */
- public static final String POWER_NONE = "none";
-
/*
* POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode.
* POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index ed032c7..c7ad2a4 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -51,6 +51,18 @@
std::vector<minikin::FontVariation> axes;
};
+static inline NativeFamilyBuilder* toNativeBuilder(jlong ptr) {
+ return reinterpret_cast<NativeFamilyBuilder*>(ptr);
+}
+
+static inline FontFamilyWrapper* toFamily(jlong ptr) {
+ return reinterpret_cast<FontFamilyWrapper*>(ptr);
+}
+
+template<typename Ptr> static inline jlong toJLong(Ptr ptr) {
+ return reinterpret_cast<jlong>(ptr);
+}
+
static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring langs, jint variant) {
NativeFamilyBuilder* builder;
if (langs != nullptr) {
@@ -59,15 +71,14 @@
} else {
builder = new NativeFamilyBuilder(minikin::registerLocaleList(""), variant);
}
- return reinterpret_cast<jlong>(builder);
+ return toJLong(builder);
}
static jlong FontFamily_create(jlong builderPtr) {
if (builderPtr == 0) {
return 0;
}
- std::unique_ptr<NativeFamilyBuilder> builder(
- reinterpret_cast<NativeFamilyBuilder*>(builderPtr));
+ NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
if (builder->fonts.empty()) {
return 0;
}
@@ -76,17 +87,23 @@
if (family->getCoverage().length() == 0) {
return 0;
}
- return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
+ return toJLong(new FontFamilyWrapper(std::move(family)));
}
-static void FontFamily_abort(jlong builderPtr) {
- NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
- delete builder;
+static void releaseBuilder(jlong builderPtr) {
+ delete toNativeBuilder(builderPtr);
}
-static void FontFamily_unref(jlong familyPtr) {
- FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(familyPtr);
- delete family;
+static jlong FontFamily_getBuilderReleaseFunc() {
+ return toJLong(&releaseBuilder);
+}
+
+static void releaseFamily(jlong familyPtr) {
+ delete toFamily(familyPtr);
+}
+
+static jlong FontFamily_getFamilyReleaseFunc() {
+ return toJLong(&releaseFamily);
}
static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex,
@@ -175,7 +192,7 @@
static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong builderPtr,
jobject font, jint ttcIndex, jint weight, jint isItalic) {
NPE_CHECK_RETURN_ZERO(env, font);
- NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
+ NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
const void* fontPtr = env->GetDirectBufferAddress(font);
if (fontPtr == NULL) {
ALOGE("addFont failed to create font, buffer invalid");
@@ -204,8 +221,7 @@
NPE_CHECK_RETURN_ZERO(env, jassetMgr);
NPE_CHECK_RETURN_ZERO(env, jpath);
- NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-
+ NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
if (NULL == mgr) {
builder->axes.clear();
@@ -249,19 +265,19 @@
}
static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) {
- NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
+ NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
builder->axes.push_back({static_cast<minikin::AxisTag>(tag), value});
}
///////////////////////////////////////////////////////////////////////////////
static const JNINativeMethod gFontFamilyMethods[] = {
- { "nInitBuilder", "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
- { "nCreateFamily", "(J)J", (void*)FontFamily_create },
- { "nAbort", "(J)V", (void*)FontFamily_abort },
- { "nUnrefFamily", "(J)V", (void*)FontFamily_unref },
- { "nAddFont", "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
- { "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;III)Z",
+ { "nInitBuilder", "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
+ { "nCreateFamily", "(J)J", (void*)FontFamily_create },
+ { "nGetBuilderReleaseFunc", "()J", (void*)FontFamily_getBuilderReleaseFunc },
+ { "nGetFamilyReleaseFunc", "()J", (void*)FontFamily_getFamilyReleaseFunc },
+ { "nAddFont", "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
+ { "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;III)Z",
(void*)FontFamily_addFontWeightStyle },
{ "nAddFontFromAssetManager", "(JLandroid/content/res/AssetManager;Ljava/lang/String;IZIII)Z",
(void*)FontFamily_addFontFromAssetManager },
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index d67c0b0..34ec365 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -28,8 +28,16 @@
using namespace android;
+static inline Typeface* toTypeface(jlong ptr) {
+ return reinterpret_cast<Typeface*>(ptr);
+}
+
+template<typename Ptr> static inline jlong toJLong(Ptr ptr) {
+ return reinterpret_cast<jlong>(ptr);
+}
+
static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandle, jint style) {
- Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
+ Typeface* family = toTypeface(familyHandle);
Typeface* face = Typeface::createRelative(family, (Typeface::Style)style);
// TODO: the following logic shouldn't be necessary, the above should always succeed.
// Try to find the closest matching font, using the standard heuristic
@@ -39,13 +47,12 @@
for (int i = 0; NULL == face && i < 4; i++) {
face = Typeface::createRelative(family, (Typeface::Style)i);
}
- return reinterpret_cast<jlong>(face);
+ return toJLong(face);
}
static jlong Typeface_createFromTypefaceWithExactStyle(JNIEnv* env, jobject, jlong nativeInstance,
jint weight, jboolean italic) {
- Typeface* baseTypeface = reinterpret_cast<Typeface*>(nativeInstance);
- return reinterpret_cast<jlong>(Typeface::createAbsolute(baseTypeface, weight, italic));
+ return toJLong(Typeface::createAbsolute(toTypeface(nativeInstance), weight, italic));
}
static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
@@ -60,30 +67,30 @@
AxisHelper axis(env, axisObject);
variations.push_back(minikin::FontVariation(axis.getTag(), axis.getStyleValue()));
}
- Typeface* baseTypeface = reinterpret_cast<Typeface*>(familyHandle);
- Typeface* result = Typeface::createFromTypefaceWithVariation(baseTypeface, variations);
- return reinterpret_cast<jlong>(result);
+ return toJLong(Typeface::createFromTypefaceWithVariation(toTypeface(familyHandle), variations));
}
static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
- Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
- Typeface* face = Typeface::createWithDifferentBaseWeight(family, weight);
- return reinterpret_cast<jlong>(face);
+ return toJLong(Typeface::createWithDifferentBaseWeight(toTypeface(familyHandle), weight));
}
-static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
- Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
- delete face;
+static void releaseFunc(jlong ptr) {
+ delete toTypeface(ptr);
}
-static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
- Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
- return face->fAPIStyle;
+// CriticalNative
+static jlong Typeface_getReleaseFunc() {
+ return toJLong(&releaseFunc);
}
-static jint Typeface_getWeight(JNIEnv* env, jobject obj, jlong faceHandle) {
- Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
- return face->fStyle.weight();
+// CriticalNative
+static jint Typeface_getStyle(jlong faceHandle) {
+ return toTypeface(faceHandle)->fAPIStyle;
+}
+
+// CriticalNative
+static jint Typeface_getWeight(jlong faceHandle) {
+ return toTypeface(faceHandle)->fStyle.weight();
}
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
@@ -95,17 +102,16 @@
FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
familyVec.emplace_back(family->family);
}
- return reinterpret_cast<jlong>(
- Typeface::createFromFamilies(std::move(familyVec), weight, italic));
+ return toJLong(Typeface::createFromFamilies(std::move(familyVec), weight, italic));
}
-static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
- Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
- Typeface::setDefault(face);
+// CriticalNative
+static void Typeface_setDefault(jlong faceHandle) {
+ Typeface::setDefault(toTypeface(faceHandle));
}
static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) {
- Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+ Typeface* face = toTypeface(faceHandle);
const std::unordered_set<minikin::AxisTag>& tagSet = face->fFontCollection->getSupportedTags();
const size_t length = tagSet.size();
if (length == 0) {
@@ -131,7 +137,7 @@
{ "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
(void*)Typeface_createFromTypefaceWithVariation },
{ "nativeCreateWeightAlias", "(JI)J", (void*)Typeface_createWeightAlias },
- { "nativeUnref", "(J)V", (void*)Typeface_unref },
+ { "nativeGetReleaseFunc", "()J", (void*)Typeface_getReleaseFunc },
{ "nativeGetStyle", "(J)I", (void*)Typeface_getStyle },
{ "nativeGetWeight", "(J)I", (void*)Typeface_getWeight },
{ "nativeCreateFromArray", "([JII)J",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ef206f9..7aec812 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -87,6 +87,7 @@
<protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
<protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
<protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index eff7c55..899d630 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -27,7 +27,6 @@
are totally dependent on the platform and can vary
significantly, so should be measured on the shipping platform
with a power meter. -->
- <item name="none">0</item>
<item name="ambient.on">0.1</item> <!-- ~100mA -->
<item name="screen.on">0.1</item> <!-- ~100mA -->
<item name="screen.full">0.1</item> <!-- ~100mA -->
diff --git a/core/res/res/xml/power_profile_test.xml b/core/res/res/xml/power_profile_test.xml
index 6dc5c7e..001cc68 100644
--- a/core/res/res/xml/power_profile_test.xml
+++ b/core/res/res/xml/power_profile_test.xml
@@ -24,9 +24,6 @@
sample values, not meant to reflect any real device.
-->
- <!-- Nothing -->
- <item name="none">0</item>
-
<!-- This is the battery capacity in mAh -->
<item name="battery.capacity">3000</item>
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index e7cfcfd..c69eb32 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -24,6 +24,8 @@
import dalvik.annotation.optimization.CriticalNative;
+import libcore.util.NativeAllocationRegistry;
+
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -38,6 +40,14 @@
private static String TAG = "FontFamily";
+ private static final NativeAllocationRegistry sBuilderRegistry = new NativeAllocationRegistry(
+ FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc(), 64);
+
+ private @Nullable Runnable mNativeBuilderCleaner;
+
+ private static final NativeAllocationRegistry sFamilyRegistry = new NativeAllocationRegistry(
+ FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc(), 64);
+
/**
* @hide
*/
@@ -48,6 +58,7 @@
public FontFamily() {
mBuilderPtr = nInitBuilder(null, 0);
+ mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
}
public FontFamily(@Nullable String[] langs, int variant) {
@@ -60,6 +71,7 @@
langsString = TextUtils.join(",", langs);
}
mBuilderPtr = nInitBuilder(langsString, variant);
+ mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
}
/**
@@ -73,7 +85,11 @@
throw new IllegalStateException("This FontFamily is already frozen");
}
mNativePtr = nCreateFamily(mBuilderPtr);
+ mNativeBuilderCleaner.run();
mBuilderPtr = 0;
+ if (mNativePtr != 0) {
+ sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
+ }
return mNativePtr != 0;
}
@@ -81,24 +97,10 @@
if (mBuilderPtr == 0) {
throw new IllegalStateException("This FontFamily is already frozen or abandoned");
}
- nAbort(mBuilderPtr);
+ mNativeBuilderCleaner.run();
mBuilderPtr = 0;
}
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mNativePtr != 0) {
- nUnrefFamily(mNativePtr);
- }
- if (mBuilderPtr != 0) {
- nAbort(mBuilderPtr);
- }
- } finally {
- super.finalize();
- }
- }
-
public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
int italic) {
if (mBuilderPtr == 0) {
@@ -171,10 +173,10 @@
private static native long nCreateFamily(long mBuilderPtr);
@CriticalNative
- private static native void nAbort(long mBuilderPtr);
+ private static native long nGetBuilderReleaseFunc();
@CriticalNative
- private static native void nUnrefFamily(long nativePtr);
+ private static native long nGetFamilyReleaseFunc();
// By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
// By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 5602a3e..88701fa 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -493,7 +493,7 @@
private boolean mRequireUnpremultiplied = false;
private boolean mMutable = false;
private boolean mConserveMemory = false;
- private boolean mAsAlphaMask = false;
+ private boolean mDecodeAsAlphaMask = false;
private Rect mCropRect;
private Rect mOutPaddingRect;
private Source mSource;
@@ -730,7 +730,7 @@
* Will typically result in a {@link Bitmap.Config#HARDWARE}
* allocation, but may be software for small images. In addition, this will
* switch to software when HARDWARE is incompatible, e.g.
- * {@link #setMutable}, {@link #setAsAlphaMask}.
+ * {@link #setMutable}, {@link #setDecodeAsAlphaMask}.
*/
public static final int ALLOCATOR_DEFAULT = 0;
@@ -753,7 +753,7 @@
* Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}.
*
* When this is combined with incompatible options, like
- * {@link #setMutable} or {@link #setAsAlphaMask}, {@link #decodeDrawable}
+ * {@link #setMutable} or {@link #setDecodeAsAlphaMask}, {@link #decodeDrawable}
* / {@link #decodeBitmap} will throw an
* {@link java.lang.IllegalStateException}.
*/
@@ -783,6 +783,14 @@
}
/**
+ * Return the allocator for the pixel memory.
+ */
+ @Allocator
+ public int getAllocator() {
+ return mAllocator;
+ }
+
+ /**
* Specify whether the {@link Bitmap} should have unpremultiplied pixels.
*
* <p>By default, ImageDecoder will create a {@link Bitmap} with
@@ -803,6 +811,13 @@
}
/**
+ * Return whether the {@link Bitmap} will have unpremultiplied pixels.
+ */
+ public boolean getRequireUnpremultiplied() {
+ return mRequireUnpremultiplied;
+ }
+
+ /**
* Modify the image after decoding and scaling.
*
* <p>This allows adding effects prior to returning a {@link Drawable} or
@@ -823,6 +838,14 @@
}
/**
+ * Return the {@link PostProcessor} currently set.
+ */
+ @Nullable
+ public PostProcessor getPostProcessor() {
+ return mPostProcessor;
+ }
+
+ /**
* Set (replace) the {@link OnPartialImageListener} on this object.
*
* <p>Will be called if there is an error in the input. Without one, an
@@ -836,6 +859,14 @@
}
/**
+ * Return the {@link OnPartialImageListener} currently set.
+ */
+ @Nullable
+ public OnPartialImageListener getOnPartialImageListener() {
+ return mOnPartialImageListener;
+ }
+
+ /**
* Crop the output to {@code subset} of the (possibly) scaled image.
*
* <p>{@code subset} must be contained within the size set by
@@ -855,6 +886,14 @@
}
/**
+ * Return the cropping rectangle, if set.
+ */
+ @Nullable
+ public Rect getCrop() {
+ return mCropRect;
+ }
+
+ /**
* Set a Rect for retrieving nine patch padding.
*
* If the image is a nine patch, this Rect will be set to the padding
@@ -893,6 +932,13 @@
}
/**
+ * Return whether the {@link Bitmap} will be mutable.
+ */
+ public boolean getMutable() {
+ return mMutable;
+ }
+
+ /**
* Specify whether to potentially save RAM at the expense of quality.
*
* <p>Setting this to {@code true} may result in a {@link Bitmap} with a
@@ -912,24 +958,62 @@
}
/**
+ * Return whether this object will try to save RAM at the expense of quality.
+ *
+ * <p>This returns whether {@link #setConserveMemory} was set to {@code true}.
+ * It may still return {@code true} even if the {@code ImageDecoder} does not
+ * have a way to save RAM at the expense of quality for this image.</p>
+ */
+ public boolean getConserveMemory() {
+ return mConserveMemory;
+ }
+
+ /**
* Specify whether to potentially treat the output as an alpha mask.
*
* <p>If this is set to {@code true} and the image is encoded in a format
* with only one channel, treat that channel as alpha. Otherwise this call has
* no effect.</p>
*
- * <p>setAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
+ * <p>setDecodeAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
* combine them will result in {@link #decodeDrawable}/
* {@link #decodeBitmap} throwing an
* {@link java.lang.IllegalStateException}.</p>
*
* @return this object for chaining.
*/
- public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
- mAsAlphaMask = asAlphaMask;
+ public ImageDecoder setDecodeAsAlphaMask(boolean decodeAsAlphaMask) {
+ mDecodeAsAlphaMask = decodeAsAlphaMask;
return this;
}
+ /** @removed
+ * @deprecated Call {@link #setDecodeAsAlphaMask} instead.
+ */
+ @java.lang.Deprecated
+ public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
+ return this.setDecodeAsAlphaMask(asAlphaMask);
+ }
+
+ /**
+ * Return whether to treat single channel input as alpha.
+ *
+ * <p>This returns whether {@link #setDecodeAsAlphaMask} was set to {@code true}.
+ * It may still return {@code true} even if the image has more than one
+ * channel and therefore will not be treated as an alpha mask.</p>
+ */
+ public boolean getDecodeAsAlphaMask() {
+ return mDecodeAsAlphaMask;
+ }
+
+ /** @removed
+ * @deprecated Call {@link #getDecodeAsAlphaMask} instead.
+ */
+ @java.lang.Deprecated
+ public boolean getAsAlphaMask() {
+ return this.getDecodeAsAlphaMask();
+ }
+
@Override
public void close() {
mCloseGuard.close();
@@ -960,7 +1044,7 @@
if (mMutable) {
throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!");
}
- if (mAsAlphaMask) {
+ if (mDecodeAsAlphaMask) {
throw new IllegalStateException("Cannot make HARDWARE Alpha mask Bitmap!");
}
}
@@ -992,7 +1076,7 @@
return nDecodeBitmap(mNativePtr, partialImagePtr,
postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
mMutable, mAllocator, mRequireUnpremultiplied,
- mConserveMemory, mAsAlphaMask);
+ mConserveMemory, mDecodeAsAlphaMask);
}
private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -1224,7 +1308,7 @@
int width, int height,
@Nullable Rect cropRect, boolean mutable,
int allocator, boolean requireUnpremul,
- boolean conserveMemory, boolean asAlphaMask)
+ boolean conserveMemory, boolean decodeAsAlphaMask)
throws IOException;
private static native Size nGetSampledSize(long nativePtr,
int sampleSize);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 38beebd..f27c11d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -42,6 +42,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
@@ -71,6 +75,9 @@
private static String TAG = "Typeface";
+ private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+ Typeface.class.getClassLoader(), nativeGetReleaseFunc(), 64);
+
/** The default NORMAL typeface object */
public static final Typeface DEFAULT;
/**
@@ -911,6 +918,7 @@
}
native_instance = ni;
+ sRegistry.registerNativeAllocation(this, native_instance);
mStyle = nativeGetStyle(ni);
mWeight = nativeGetWeight(ni);
}
@@ -1120,16 +1128,6 @@
}
@Override
- protected void finalize() throws Throwable {
- try {
- nativeUnref(native_instance);
- native_instance = 0; // Other finalizers can still call us.
- } finally {
- super.finalize();
- }
- }
-
- @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -1173,10 +1171,18 @@
private static native long nativeCreateFromTypefaceWithVariation(
long native_instance, List<FontVariationAxis> axes);
private static native long nativeCreateWeightAlias(long native_instance, int weight);
- private static native void nativeUnref(long native_instance);
- private static native int nativeGetStyle(long native_instance);
- private static native int nativeGetWeight(long native_instance);
private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
- private static native void nativeSetDefault(long native_instance);
private static native int[] nativeGetSupportedAxes(long native_instance);
+
+ @CriticalNative
+ private static native void nativeSetDefault(long nativePtr);
+
+ @CriticalNative
+ private static native int nativeGetStyle(long nativePtr);
+
+ @CriticalNative
+ private static native int nativeGetWeight(long nativePtr);
+
+ @CriticalNative
+ private static native long nativeGetReleaseFunc();
}
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
deleted file mode 100644
index 8908975..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
+++ /dev/null
@@ -1,25 +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="12dp"
- android:height="24.0dp"
- android:viewportWidth="20.0"
- android:viewportHeight="40.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
deleted file mode 100644
index ea794d4..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
+++ /dev/null
@@ -1,25 +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:autoMirrored="true"
- android:width="17.0dp"
- android:height="17.0dp"
- android:viewportWidth="40.0"
- android:viewportHeight="40.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 89d6e99..7ec437c 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -29,7 +29,7 @@
android:alpha="0"
android:text="@string/quick_settings_header_onboarding_text"
android:textAppearance="@style/TextAppearance.QS.TileLabel"
- android:textColor="?android:attr/colorAccent"
+ android:textColor="?android:attr/textColorSecondary"
android:visibility="invisible" />
<LinearLayout
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 2151436..ec4d1a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -65,7 +65,7 @@
private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
private static final int FADE_ANIMATION_DURATION_MS = 300;
private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
- public static final int MAX_TOOLTIP_SHOWN_COUNT = 3;
+ public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
private final Handler mHandler = new Handler();
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 0ce3e6a..8922094 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.view.LayoutInflater;
import android.view.View;
@@ -52,16 +53,6 @@
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTileImpl<SignalState> {
- private static final ComponentName CELLULAR_SETTING_COMPONENT = new ComponentName(
- "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity");
- private static final ComponentName DATA_PLAN_CELLULAR_COMPONENT = new ComponentName(
- "com.android.settings", "com.android.settings.Settings$DataPlanUsageSummaryActivity");
-
- private static final Intent CELLULAR_SETTINGS =
- new Intent().setComponent(CELLULAR_SETTING_COMPONENT);
- private static final Intent DATA_PLAN_CELLULAR_SETTINGS =
- new Intent().setComponent(DATA_PLAN_CELLULAR_COMPONENT);
-
private static final String ENABLE_SETTINGS_DATA_PLAN = "enable.settings.data.plan";
private final NetworkController mController;
@@ -107,7 +98,7 @@
@Override
public Intent getLongClickIntent() {
- return getCellularSettingIntent(mContext);
+ return getCellularSettingIntent();
}
@Override
@@ -148,8 +139,7 @@
showDetail(true);
} else {
mActivityStarter
- .postStartActivityDismissingKeyguard(getCellularSettingIntent(mContext),
- 0 /* delay */);
+ .postStartActivityDismissingKeyguard(getCellularSettingIntent(),0 /* delay */);
}
}
@@ -293,25 +283,8 @@
}
}
- static Intent getCellularSettingIntent(Context context) {
- // TODO(b/62349208): We should replace feature flag check below with data plans
- // availability check. If the data plans are available we display the data plans usage
- // summary otherwise we display data usage summary without data plans.
- boolean isDataPlanFeatureEnabled =
- SystemProperties.getBoolean(ENABLE_SETTINGS_DATA_PLAN, false /* default */);
- context.getPackageManager()
- .setComponentEnabledSetting(
- DATA_PLAN_CELLULAR_COMPONENT,
- isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- context.getPackageManager()
- .setComponentEnabledSetting(
- CELLULAR_SETTING_COMPONENT,
- isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP);
- return isDataPlanFeatureEnabled ? DATA_PLAN_CELLULAR_SETTINGS : CELLULAR_SETTINGS;
+ static Intent getCellularSettingIntent() {
+ return new Intent(Settings.ACTION_DATA_USAGE_SETTINGS);
}
private final class CellularDetailAdapter implements DetailAdapter {
@@ -330,7 +303,7 @@
@Override
public Intent getSettingsIntent() {
- return getCellularSettingIntent(mContext);
+ return getCellularSettingIntent();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index a102696..ace361b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -55,7 +55,7 @@
@Override
public Intent getLongClickIntent() {
- return CellularTile.getCellularSettingIntent(mContext);
+ return CellularTile.getCellularSettingIntent();
}
@Override
protected void handleClick() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bc14203..859dc39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -58,6 +58,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.NumberFormat;
+import java.util.IllegalFormatConversionException;
/**
* Controls the indications and error messages shown on the Keyguard
@@ -414,11 +415,24 @@
String percentage = NumberFormat.getPercentInstance()
.format(mBatteryLevel / 100f);
if (hasChargingTime) {
+ // We now have battery percentage in these strings and it's expected that all
+ // locales will also have it in the future. For now, we still have to support the old
+ // format until all languages get the new translations.
String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, chargingTimeRemaining);
- return mContext.getResources().getString(chargingId, chargingTimeFormatted, percentage);
+ try {
+ return mContext.getResources().getString(chargingId, chargingTimeFormatted,
+ percentage);
+ } catch (IllegalFormatConversionException e) {
+ return mContext.getResources().getString(chargingId, chargingTimeFormatted);
+ }
} else {
- return mContext.getResources().getString(chargingId, percentage);
+ // Same as above
+ try {
+ return mContext.getResources().getString(chargingId, percentage);
+ } catch (IllegalFormatConversionException e) {
+ return mContext.getResources().getString(chargingId);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 948f524..defb46c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
import android.app.ActivityManager;
@@ -108,6 +110,7 @@
mLp.setTitle("StatusBar");
mLp.accessibilityTitle = mContext.getString(R.string.status_bar);
mLp.packageName = mContext.getPackageName();
+ mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
mStatusBarView = statusBarView;
mBarHeight = barHeight;
mWindowManager.addView(mStatusBarView, mLp);
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 f0854ed..d3f74ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -251,8 +251,11 @@
if (mConfig.inflateSignalStrengths) {
level++;
}
- return SignalDrawable.getState(level, getNumLevels(),
- mCurrentState.inetCondition == 0);
+ boolean dataDisabled = mCurrentState.userSetup
+ && mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
+ boolean noInternet = mCurrentState.inetCondition == 0;
+ boolean cutOut = dataDisabled || noInternet;
+ return SignalDrawable.getState(level, getNumLevels(), cutOut);
} else if (mCurrentState.enabled) {
return SignalDrawable.getEmptyState(getNumLevels());
} else {
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 aaa0568..09a1e44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -44,10 +44,6 @@
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,
@@ -232,9 +228,9 @@
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.accessibility_cell_data_off,
- TelephonyIcons.ICON_DATA_DISABLED,
+ 0,
false,
- TelephonyIcons.QS_ICON_DATA_DISABLED
+ 0
);
}
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 8aab837..27cd9a0 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
@@ -353,6 +353,13 @@
protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut) {
+ verifyLastMobileDataIndicators(
+ visible, icon, typeIcon, qsVisible, qsIcon, qsTypeIcon, dataIn, dataOut, false);
+ }
+
+ protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
+ boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut,
+ boolean cutOut) {
ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class);
@@ -372,7 +379,7 @@
IconState iconState = iconArg.getValue();
int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
- false);
+ cutOut);
assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
assertEquals("Signal icon in status bar", state, iconState.icon);
assertEquals("Visibility in status bar", visible, iconState.visible);
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 3b796ca..cf3620d 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
@@ -111,6 +111,20 @@
}
@Test
+ public void testNoInternetIcon() {
+ setupNetworkController();
+ when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
+ setupDefaultSignal();
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0);
+ setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
+
+ // Verify that a SignalDrawable with a cut out is used to display data disabled.
+ verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+ true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
+ false, true);
+ }
+
+ @Test
public void testDataDisabledIcon() {
setupNetworkController();
when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
@@ -118,8 +132,10 @@
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
- verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED,
- TelephonyIcons.QS_ICON_DATA_DISABLED);
+ // Verify that a SignalDrawable with a cut out is used to display data disabled.
+ verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+ true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
+ false, true);
}
@Test
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bf25928..62d91a8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3364,7 +3364,8 @@
/**
* Update AMS states when an activity is resumed. This should only be called by
- * {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
+ * {@link ActivityStack#onActivityStateChanged(ActivityRecord, ActivityState, String)} when an
+ * activity is resumed.
*/
@GuardedBy("this")
void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e6d6fdf..59f027a 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1636,7 +1636,11 @@
mRecentTransitions.add(new StateTransition(prev, state, reason));
- mState = state;
+ final TaskRecord parent = getTask();
+
+ if (parent != null) {
+ parent.onActivityStateChanged(this, state, reason);
+ }
if (isState(DESTROYING, DESTROYED)) {
makeFinishingLocked();
@@ -2111,7 +2115,7 @@
if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) {
final ActivityStack stack = mStackSupervisor.getFocusedStack();
// Try to use the one which is closest to top.
- ActivityRecord r = stack.mResumedActivity;
+ ActivityRecord r = stack.getResumedActivity();
if (r == null) {
r = stack.mPausingActivity;
}
@@ -2208,7 +2212,7 @@
return false;
}
final ActivityStack stack = getStack();
- if (stack == null || this == stack.mResumedActivity || this == stack.mPausingActivity
+ if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity
|| !haveState || !stopped) {
// We're not ready for this kind of thing.
return false;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 666f3a2..7749bd7 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -475,6 +475,28 @@
return mWindowContainerController;
}
+ /**
+ * This should be called when an activity in a child task changes state. This should only
+ * be called from
+ * {@link TaskRecord#onActivityStateChanged(ActivityRecord, ActivityState, String)}.
+ * @param record The {@link ActivityRecord} whose state has changed.
+ * @param state The new state.
+ * @param reason The reason for the change.
+ */
+ void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
+ if (record == mResumedActivity && state != RESUMED) {
+ clearResumedActivity(reason + " - onActivityStateChanged");
+ }
+
+ if (state == RESUMED) {
+ if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
+ + reason);
+ mResumedActivity = record;
+ mService.setResumedActivityUncheckLocked(record, reason);
+ mStackSupervisor.mRecentTasks.add(record.getTask());
+ }
+ }
+
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
final int prevWindowingMode = getWindowingMode();
@@ -1229,7 +1251,7 @@
void minimalResumeActivityLocked(ActivityRecord r) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
+ " callers=" + Debug.getCallers(5));
- setResumedActivityLocked(r, "minimalResumeActivityLocked");
+ r.setState(RESUMED, "minimalResumeActivityLocked");
r.completeResumeLocked();
setLaunchTime(r);
if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
@@ -1454,7 +1476,6 @@
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
- mResumedActivity = null;
mPausingActivity = prev;
mLastPausedActivity = prev;
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
@@ -2282,13 +2303,21 @@
return result;
}
- void setResumedActivityLocked(ActivityRecord r, String reason) {
- // TODO: move mResumedActivity to stack supervisor,
- // there should only be 1 global copy of resumed activity.
- mResumedActivity = r;
- r.setState(RESUMED, "setResumedActivityLocked");
- mService.setResumedActivityUncheckLocked(r, reason);
- mStackSupervisor.mRecentTasks.add(r.getTask());
+ /**
+ * Returns the currently resumed activity.
+ */
+ protected ActivityRecord getResumedActivity() {
+ return mResumedActivity;
+ }
+
+ /**
+ * Clears reference to currently resumed activity.
+ */
+ private void clearResumedActivity(String reason) {
+ if (DEBUG_STACK) Slog.d(TAG_STACK, "clearResumedActivity: " + mResumedActivity + " reason:"
+ + reason);
+
+ mResumedActivity = null;
}
@GuardedBy("mService")
@@ -2577,7 +2606,7 @@
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
+ " (in existing)");
- setResumedActivityLocked(next, "resumeTopActivityInnerLocked");
+ next.setState(RESUMED, "resumeTopActivityInnerLocked");
mService.updateLruProcessLocked(next.app, true, null);
updateLRUListLocked(next);
@@ -2679,7 +2708,7 @@
+ lastState + ": " + next);
next.setState(lastState, "resumeTopActivityInnerLocked");
if (lastStack != null) {
- lastStack.mResumedActivity = lastResumedActivity;
+ lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
}
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
@@ -3779,9 +3808,6 @@
mStackSupervisor.mStoppingActivities.remove(r);
mStackSupervisor.mGoingToSleepActivities.remove(r);
mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
- if (mResumedActivity == r) {
- mResumedActivity = null;
- }
final ActivityState prevState = r.getState();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
@@ -3994,7 +4020,7 @@
*/
void onActivityRemovedFromStack(ActivityRecord r) {
if (mResumedActivity == r) {
- mResumedActivity = null;
+ clearResumedActivity("onActivityRemovedFromStack");
}
if (mPausingActivity == r) {
mPausingActivity = null;
@@ -5186,7 +5212,7 @@
+ " other stack to this stack mResumedActivity=" + mResumedActivity
+ " other mResumedActivity=" + topRunningActivity);
}
- mResumedActivity = topRunningActivity;
+ topRunningActivity.setState(RESUMED, "positionChildAt");
}
// The task might have already been running and its visibility needs to be synchronized with
@@ -5231,7 +5257,7 @@
// so that we don't resume the same activity again in the new stack.
// Apps may depend on onResume()/onPause() being called in pairs.
if (setResume) {
- mResumedActivity = r;
+ r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded");
updateLRUListLocked(r);
}
// If the activity was previously pausing, then ensure we transfer that as well
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index d372bd8..0216439 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -930,7 +930,7 @@
if (stack == null) {
return null;
}
- ActivityRecord resumedActivity = stack.mResumedActivity;
+ ActivityRecord resumedActivity = stack.getResumedActivity();
if (resumedActivity == null || resumedActivity.app == null) {
resumedActivity = stack.mPausingActivity;
if (resumedActivity == null || resumedActivity.app == null) {
@@ -985,7 +985,7 @@
if (!isFocusedStack(stack) || stack.numActivities() == 0) {
continue;
}
- final ActivityRecord resumedActivity = stack.mResumedActivity;
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
if (resumedActivity == null || !resumedActivity.idle) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+ stack.mStackId + " " + resumedActivity + " not idle");
@@ -1004,7 +1004,7 @@
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
if (isFocusedStack(stack)) {
- final ActivityRecord r = stack.mResumedActivity;
+ final ActivityRecord r = stack.getResumedActivity();
if (r != null && !r.isState(RESUMED)) {
return false;
}
@@ -1025,7 +1025,7 @@
final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord r = stack.mResumedActivity;
+ final ActivityRecord r = stack.getResumedActivity();
if (r != null) {
if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) {
return false;
@@ -1051,9 +1051,9 @@
final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
- if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
+ if (!isFocusedStack(stack) && stack.getResumedActivity() != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
- " mResumedActivity=" + stack.mResumedActivity);
+ " mResumedActivity=" + stack.getResumedActivity());
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
}
@@ -2063,8 +2063,9 @@
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
if (isFocusedStack(stack)) {
- if (stack.mResumedActivity != null) {
- fgApp = stack.mResumedActivity.app;
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity != null) {
+ fgApp = resumedActivity.app;
} else if (stack.mPausingActivity != null) {
fgApp = stack.mPausingActivity.app;
}
@@ -3734,7 +3735,7 @@
+ " state=" + state);
}
} else {
- final ActivityRecord resumed = stack.mResumedActivity;
+ final ActivityRecord resumed = stack.getResumedActivity();
if (resumed != null && resumed == r) Slog.e(TAG,
"validateTop...: back stack has resumed activity r=" + r
+ " state=" + state);
@@ -3884,7 +3885,7 @@
printed = true;
needSep = false;
}
- pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+ pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep,
" mResumedActivity: ");
if (pr) {
printed = true;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index fcdf3d2..bd53eac 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -820,8 +820,8 @@
// If we are starting an activity that is not from the same uid as the currently resumed
// one, check whether app switches are allowed.
- if (voiceSession == null && (stack.mResumedActivity == null
- || stack.mResumedActivity.info.applicationInfo.uid != realCallingUid)) {
+ if (voiceSession == null && (stack.getResumedActivity() == null
+ || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 8174f40..7280f57 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -650,7 +650,7 @@
final ActivityRecord r = topRunningActivityLocked();
final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
&& (topRunningActivityLocked() == r);
- final boolean wasResumed = r != null && sourceStack.mResumedActivity == r;
+ final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
// In some cases the focused stack isn't the front stack. E.g. pinned stack.
@@ -1754,6 +1754,22 @@
return !mTmpConfig.equals(newConfig);
}
+ /**
+ * This should be called when an child activity changes state. This should only
+ * be called from
+ * {@link ActivityRecord#setState(ActivityState, String)} .
+ * @param record The {@link ActivityRecord} whose state has changed.
+ * @param state The new state.
+ * @param reason The reason for the change.
+ */
+ void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
+ final ActivityStack parent = getStack();
+
+ if (parent != null) {
+ parent.onActivityStateChanged(record, state, reason);
+ }
+ }
+
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
final boolean wasInMultiWindowMode = inMultiWindowMode();
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
index 2a9d3860..ff1e29b 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
@@ -120,6 +120,12 @@
}
}
+ private boolean checkConfiguredLocked() {
+ if (mTunerCallback.isInitialConfigurationDone()) return true;
+ Slog.w(TAG, "Initial configuration is still pending, skipping the operation");
+ return false;
+ }
+
@Override
public void setConfiguration(RadioManager.BandConfig config) {
if (config == null) {
@@ -170,6 +176,7 @@
public void step(boolean directionDown, boolean skipSubChannel) {
synchronized (mLock) {
checkNotClosedLocked();
+ if (!checkConfiguredLocked()) return;
nativeStep(mNativeContext, directionDown, skipSubChannel);
}
}
@@ -178,6 +185,7 @@
public void scan(boolean directionDown, boolean skipSubChannel) {
synchronized (mLock) {
checkNotClosedLocked();
+ if (!checkConfiguredLocked()) return;
nativeScan(mNativeContext, directionDown, skipSubChannel);
}
}
@@ -190,6 +198,7 @@
Slog.i(TAG, "Tuning to " + selector);
synchronized (mLock) {
checkNotClosedLocked();
+ if (!checkConfiguredLocked()) return;
nativeTune(mNativeContext, selector);
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
index 7ad73c3..32b1d1a 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
@@ -47,6 +47,7 @@
@NonNull private final ITunerCallback mClientCallback;
private final AtomicReference<ProgramList.Filter> mProgramListFilter = new AtomicReference<>();
+ private boolean mInitialConfigurationDone = false;
TunerCallback(@NonNull Tuner tuner, @NonNull ITunerCallback clientCallback, int halRev) {
mTuner = tuner;
@@ -95,6 +96,10 @@
mProgramListFilter.set(null);
}
+ boolean isInitialConfigurationDone() {
+ return mInitialConfigurationDone;
+ }
+
@Override
public void onError(int status) {
dispatch(() -> mClientCallback.onError(status));
@@ -107,6 +112,7 @@
@Override
public void onConfigurationChanged(RadioManager.BandConfig config) {
+ mInitialConfigurationDone = true;
dispatch(() -> mClientCallback.onConfigurationChanged(config));
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8bc9830..a0e4f4f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -427,6 +427,8 @@
KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
}
+ private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
+
/** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
@@ -674,6 +676,7 @@
private boolean mPendingKeyguardOccluded;
private boolean mKeyguardOccludedChanged;
+ private boolean mNotifyUserActivity;
boolean mShowingDream;
private boolean mLastShowingDream;
@@ -721,6 +724,9 @@
// Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
int mShowRotationSuggestions;
+ // Whether system navigation keys are enabled
+ boolean mSystemNavigationKeysEnabled;
+
Display mDisplay;
int mLandscapeRotation = 0; // default landscape rotation
@@ -828,6 +834,7 @@
private static final int MSG_LAUNCH_ASSIST = 26;
private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 27;
private static final int MSG_POWER_VERY_LONG_PRESS = 28;
+ private static final int MSG_NOTIFY_USER_ACTIVITY = 29;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -929,6 +936,13 @@
case MSG_HANDLE_ALL_APPS:
launchAllAppsAction();
break;
+ case MSG_NOTIFY_USER_ACTIVITY:
+ removeMessages(MSG_NOTIFY_USER_ACTIVITY);
+ Intent intent = new Intent(ACTION_USER_ACTIVITY_NOTIFICATION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.USER_ACTIVITY);
+ break;
}
}
}
@@ -984,6 +998,9 @@
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.POLICY_CONTROL), false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED), false, this,
+ UserHandle.USER_ALL);
updateSettings();
}
@@ -2359,6 +2376,9 @@
Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
UserHandle.USER_CURRENT);
+ mSystemNavigationKeysEnabled = Settings.Secure.getIntForUser(resolver,
+ Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
+ 0, UserHandle.USER_CURRENT) == 1;
// Configure rotation suggestions.
int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
@@ -6224,7 +6244,7 @@
if (event.getAction() == KeyEvent.ACTION_UP) {
if (!mAccessibilityManager.isEnabled()
|| !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
- if (areSystemNavigationKeysEnabled()) {
+ if (mSystemNavigationKeysEnabled) {
sendSystemKeyToStatusBarAsync(event.getKeyCode());
}
}
@@ -7486,6 +7506,13 @@
mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
}
+ @Override
+ public void requestUserActivityNotification() {
+ if (!mNotifyUserActivity && !mHandler.hasMessages(MSG_NOTIFY_USER_ACTIVITY)) {
+ mNotifyUserActivity = true;
+ }
+ }
+
/** {@inheritDoc} */
@Override
public void userActivity() {
@@ -7507,6 +7534,12 @@
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
}
}
+
+ if (mAwake && mNotifyUserActivity) {
+ mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
+ USER_ACTIVITY_NOTIFICATION_DELAY);
+ mNotifyUserActivity = false;
+ }
}
class ScreenLockTimeout implements Runnable {
@@ -7803,11 +7836,6 @@
Settings.Global.THEATER_MODE_ON, 0) == 1;
}
- private boolean areSystemNavigationKeysEnabled() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
- }
-
@Override
public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
if (!mVibrator.hasVibrator()) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index d5c12f7..cd6ff30 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1718,4 +1718,10 @@
return Integer.toString(mode);
}
}
+
+ /**
+ * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
+ * on the next user activity.
+ */
+ public void requestUserActivityNotification();
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2041c6f..b44d8a9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6989,6 +6989,15 @@
mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
}
+ @Override
+ public void requestUserActivityNotification() {
+ if (!checkCallingPermission(android.Manifest.permission.USER_ACTIVITY,
+ "requestUserActivityNotification()")) {
+ throw new SecurityException("Requires USER_ACTIVITY permission");
+ }
+ mPolicy.requestUserActivityNotification();
+ }
+
void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
if (seamlesslyRotated == w.mSeamlesslyRotated) {
return;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f36b692..c4185fa 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2284,13 +2284,14 @@
// interactive, the value may persist until the next animation, which could potentially
// be occurring while turning off the screen. This would lead to the screen incorrectly
// turning back on.
- if (hasTurnScreenOnFlag && allowTheaterMode && canTurnScreenOn
- && !mPowerManagerWrapper.isInteractive()) {
- if (DEBUG_VISIBILITY || DEBUG_POWER) {
- Slog.v(TAG, "Relayout window turning screen on: " + this);
+ if (hasTurnScreenOnFlag) {
+ if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) {
+ if (DEBUG_VISIBILITY || DEBUG_POWER) {
+ Slog.v(TAG, "Relayout window turning screen on: " + this);
+ }
+ mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
+ "android.server.wm:TURN_ON");
}
- mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
- "android.server.wm:TURN_ON");
if (mAppToken != null) {
mAppToken.setCanTurnScreenOn(false);
diff --git a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
index 14e3578..ecf1a33 100644
--- a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
+++ b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
@@ -72,6 +72,7 @@
struct Module {
sp<V1_0::IBroadcastRadio> radioModule;
HalRevision halRev;
+ std::vector<hardware::broadcastradio::V1_0::BandConfig> bands;
};
struct ServiceContext {
@@ -169,7 +170,8 @@
if (module10 == nullptr) continue;
auto idx = ctx.mModules.size();
- ctx.mModules.push_back({module10, halRev});
+ ctx.mModules.push_back({module10, halRev, {}});
+ auto& nModule = ctx.mModules[idx];
ALOGI("loaded broadcast radio module %zu: %s:%s (HAL 1.%d)",
idx, serviceName.c_str(), V1_0::toString(clazz).c_str(), halMinor);
@@ -178,6 +180,7 @@
Return<void> hidlResult;
if (module11 != nullptr) {
hidlResult = module11->getProperties_1_1([&](const V1_1::Properties& properties) {
+ nModule.bands = properties.base.bands;
jModule = convert::ModulePropertiesFromHal(env, properties, idx, serviceName);
});
} else {
@@ -185,6 +188,7 @@
const V1_0::Properties& properties) {
halResult = result;
if (result != Result::OK) return;
+ nModule.bands = properties.bands;
jModule = convert::ModulePropertiesFromHal(env, properties, idx, serviceName);
});
}
@@ -217,7 +221,21 @@
auto module = ctx.mModules[moduleId];
Region region;
- BandConfig bandConfigHal = convert::BandConfigToHal(env, bandConfig, region);
+ BandConfig bandConfigHal;
+ if (bandConfig != nullptr) {
+ bandConfigHal = convert::BandConfigToHal(env, bandConfig, region);
+ } else {
+ region = Region::INVALID;
+ if (module.bands.size() == 0) {
+ ALOGE("No bands defined");
+ return nullptr;
+ }
+ bandConfigHal = module.bands[0];
+ if (bandConfigHal.spacings.size() > 1) {
+ bandConfigHal.spacings = hidl_vec<uint32_t>({ *std::min_element(
+ bandConfigHal.spacings.begin(), bandConfigHal.spacings.end()) });
+ }
+ }
auto tuner = make_javaref(env, env->NewObject(gjni.Tuner.clazz, gjni.Tuner.cstor,
callback, module.halRev, region, withAudio, bandConfigHal.type));
diff --git a/services/core/jni/BroadcastRadio/types.h b/services/core/jni/BroadcastRadio/types.h
index 64a4f63..910bb7c 100644
--- a/services/core/jni/BroadcastRadio/types.h
+++ b/services/core/jni/BroadcastRadio/types.h
@@ -41,6 +41,7 @@
// Keep in sync with REGION_* constants from RadioManager.java.
enum class Region : jint {
+ INVALID = -1,
ITU_1 = 0,
ITU_2 = 1,
OIRT = 2,
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 d60623d..bda68d1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -26,6 +26,8 @@
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static org.junit.Assert.assertEquals;
@@ -99,7 +101,7 @@
// Simulate the a resumed activity set during
// {@link ActivityStack#resumeTopActivityUncheckedLocked}.
mSupervisor.inResumeTopActivity = true;
- mStack.mResumedActivity = r;
+ r.setState(RESUMED, "testNoPauseDuringResumeTopActivity");
final boolean waiting = mStack.goToSleepIfPossible(false);
@@ -107,7 +109,18 @@
assertFalse(waiting);
// Make sure the resumed activity is untouched.
- assertEquals(mStack.mResumedActivity, r);
+ assertEquals(mStack.getResumedActivity(), r);
+ }
+
+ @Test
+ public void testResumedActivity() throws Exception {
+ final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
+ assertEquals(mStack.getResumedActivity(), null);
+ r.setState(RESUMED, "testResumedActivity");
+ assertEquals(mStack.getResumedActivity(), r);
+ r.setState(PAUSING, "testResumedActivity");
+ assertEquals(mStack.getResumedActivity(), null);
+
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
index 091d9bd..f740654 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -42,7 +42,11 @@
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
+import java.time.Instant;
import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -257,7 +261,7 @@
@Test
public void testInstallationOptionWithoutFreeze() {
// Also duplicated at com.google.android.gts.deviceowner.SystemUpdatePolicyTest
- final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800);
+ final long millis_2018_01_01 = toMillis(2018, 1, 1);
SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy();
assertInstallationOption(SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, Long.MAX_VALUE,
@@ -294,11 +298,11 @@
@Test
public void testInstallationOptionWithFreeze() throws Exception {
- final long millis_2016_02_29 = TimeUnit.SECONDS.toMillis(1456704000);
- final long millis_2017_01_31 = TimeUnit.SECONDS.toMillis(1485820800);
- final long millis_2017_02_28 = TimeUnit.SECONDS.toMillis(1488240000);
- final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800);
- final long millis_2018_08_01 = TimeUnit.SECONDS.toMillis(1533081600);
+ final long millis_2016_02_29 = toMillis(2016, 2, 29);
+ final long millis_2017_01_31 = toMillis(2017, 1, 31);
+ final long millis_2017_02_28 = toMillis(2017, 2, 28);
+ final long millis_2018_01_01 = toMillis(2018, 1, 1);
+ final long millis_2018_08_01 = toMillis(2018, 8, 1);
SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy();
setFreezePeriods(p, "01-01", "01-31");
@@ -313,12 +317,12 @@
// Freeze period contains leap day Feb 29
p = SystemUpdatePolicy.createPostponeInstallPolicy();
- setFreezePeriods(p, "02-01", "03-15");
- // Freezed until 3/31, note 2016 is a leap year
- assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+ setFreezePeriods(p, "02-01", "03-05");
+ // Freezed until 3/5, note 2016 is a leap year
+ assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
millis_2016_02_29, p);
- // Freezed until 3/31, note 2017 is not a leap year
- assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+ // Freezed until 3/5, note 2017 is not a leap year
+ assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
millis_2017_02_28, p);
// Next freeze is 2018/2/1
assertInstallationOption(SystemUpdatePolicy.TYPE_POSTPONE, TimeUnit.DAYS.toMillis(31),
@@ -333,12 +337,12 @@
assertInstallationOption(
SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(1),
millis_2017_02_28, p);
- setFreezePeriods(p, "02-28", "03-15");
+ setFreezePeriods(p, "02-28", "03-05");
assertInstallationOption(
- SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+ SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
millis_2016_02_29, p);
assertInstallationOption(
- SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+ SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
millis_2017_02_28, p);
// Freeze period end on or right after leap day
@@ -382,10 +386,10 @@
// Two freeze periods
p = SystemUpdatePolicy.createAutomaticInstallPolicy();
- setFreezePeriods(p, "05-01", "06-01", "12-01", "01-31");
- // automatic policy for August, September, November and December
+ setFreezePeriods(p, "05-01", "06-01", "11-01", "01-29");
+ // automatic policy for July, August, September and October
assertInstallationOption(
- SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(122),
+ SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(92),
millis_2018_08_01, p);
}
@@ -510,4 +514,9 @@
return result;
}
}
+
+ private long toMillis(int year, int month, int day) {
+ return LocalDateTime.of(year, month, day, 0, 0, 0).atZone(ZoneId.systemDefault())
+ .toInstant().toEpochMilli();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 34c5db3..6784e30 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -652,4 +652,8 @@
@Override
public void onScreenMagnificationStateChanged(boolean active) {
}
+
+ @Override
+ public void requestUserActivityNotification() {
+ }
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a79f2c9..73243d2 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -879,42 +879,76 @@
/**
* @hide
*/
- @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
- HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED,
- HANDOVER_FAILURE_ONGOING_EMERG_CALL})
+ @IntDef(prefix = { "HANDOVER_" },
+ value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
+ HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERG_CALL,
+ HANDOVER_FAILURE_UNKNOWN})
@Retention(RetentionPolicy.SOURCE)
public @interface HandoverFailureErrors {}
/**
* Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
- * to handover the call rejects handover.
+ * to handover the call to rejects the handover request.
+ * <p>
+ * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
+ * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
+ * {@code null} {@link Connection} from
+ * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+ * ConnectionRequest)}.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
/**
- * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there is
- * an error associated with unsupported handover.
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+ * is initiated but the source or destination app does not support handover.
+ * <p>
+ * Will be returned when a handover is requested via
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
+ * {@link PhoneAccountHandle} does not declare
+ * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
+ * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
+ * {@link Details#getAccountHandle()}) does not declare
+ * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
- public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2;
+ public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
/**
- * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
- * are some permission errors associated with APIs doing handover.
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
+ * user rejects the handover request.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
- public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3;
-
- /**
- * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when user
- * rejects handover.
- */
- public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
+ public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
/**
* Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
* is ongoing emergency call.
+ * <p>
+ * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
+ * called on an emergency call, or if any other call is an emergency call.
+ * <p>
+ * Handovers are not permitted while there are ongoing emergency calls.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
- public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5;
+ public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4;
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+ * fails for an unknown reason.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
+ */
+ public static final int HANDOVER_FAILURE_UNKNOWN = 5;
/**
* Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
@@ -1055,6 +1089,10 @@
/**
* Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
* has completed successfully.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ *
* @param call The call which had initiated handover.
*/
public void onHandoverComplete(Call call) {}
@@ -1062,8 +1100,12 @@
/**
* Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
* has failed.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ *
* @param call The call which had initiated handover.
- * @param failureReason Error reason for failure
+ * @param failureReason Error reason for failure.
*/
public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
}
@@ -1260,7 +1302,7 @@
* Instructs this {@link #STATE_RINGING} {@code Call} to answer.
* @param videoState The video state in which to answer the call.
*/
- public void answer(int videoState) {
+ public void answer(@VideoProfile.VideoState int videoState) {
mInCallAdapter.answerCall(mTelecomCallId, videoState);
}
@@ -1474,16 +1516,65 @@
* by {@code toHandle}. The videoState specified indicates the desired video state after the
* handover.
* <p>
- * A handover request is initiated by the user from one app to indicate a desire
- * to handover a call to another.
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the device this method is called on is considered the
+ * <em>initiating</em> device (since the user initiates the handover from this device), and the
+ * other device is considered the <em>receiving</em> device.
+ * <p>
+ * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
+ * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
+ * and invoke
+ * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+ * ConnectionRequest)} to inform the destination app that a request has been made to handover a
+ * call to it. The app returns an instance of {@link Connection} to represent the handover call
+ * At this point the app should display UI to indicate to the user that a call
+ * handover is in process.
+ * <p>
+ * The destination app is responsible for communicating the handover request from the
+ * <em>initiating</em> device to the <em>receiving</em> device.
+ * <p>
+ * When the app on the <em>receiving</em> device receives the handover request, it calls
+ * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
+ * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
+ * the destination app on the <em>receiving</em> device should show UI to allow the user to
+ * choose whether they want to continue their call in the destination app.
+ * <p>
+ * When the destination app on the <em>receiving</em> device calls
+ * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
+ * {@link ConnectionService} and call
+ * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
+ * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
+ * {@link Connection} to represent the handover call.
+ * <p>
+ * If the user of the <em>receiving</em> device accepts the handover, the app calls
+ * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
+ * original call. If the user rejects the handover, the app calls
+ * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
+ * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
+ * <p>
+ * Telecom will only allow handovers from {@link PhoneAccount}s which declare
+ * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
+ * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
+ * <p>
+ * Errors in the handover process are reported to the {@link InCallService} via
+ * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
+ * the involved {@link ConnectionService}s via
+ * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
*
* @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
* this call to.
- * @param videoState Indicates the video state desired after the handover.
+ * @param videoState Indicates the video state desired after the handover (see the
+ * {@code STATE_*} constants defined in {@link VideoProfile}).
* @param extras Bundle containing extra information to be passed to the
* {@link ConnectionService}
*/
- public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
+ public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
+ Bundle extras) {
mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index ffa0c94..fc32b17 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2219,12 +2219,50 @@
}
/**
- * Called by Telecom on the initiating side of the handover to create an instance of a
- * handover connection.
+ * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+ * outgoing handover {@link Connection}.
+ * <p>
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+ * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+ * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+ * device.
+ * <p>
+ * This method is called on the destination {@link ConnectionService} on <em>initiating</em>
+ * device when the user initiates a handover request from one app to another. The user request
+ * originates in the {@link InCallService} via
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * Implementations of this method should return an instance of {@link Connection} which
+ * represents the handover. If your app does not wish to accept a handover to it at this time,
+ * you can return {@code null}. The code below shows an example of how this is done.
+ * <pre>
+ * {@code
+ * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+ * fromPhoneAccountHandle, ConnectionRequest request) {
+ * if (!isHandoverAvailable()) {
+ * return null;
+ * }
+ * MyConnection connection = new MyConnection();
+ * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+ * connection.setVideoState(request.getVideoState());
+ * return connection;
+ * }
+ * }
+ * </pre>
+ *
* @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
* ConnectionService which needs to handover the call.
- * @param request Details about the call which needs to be handover.
- * @return Connection object corresponding to the handover call.
+ * @param request Details about the call to handover.
+ * @return {@link Connection} instance corresponding to the handover call.
*/
public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
ConnectionRequest request) {
@@ -2232,12 +2270,46 @@
}
/**
- * Called by Telecom on the receiving side of the handover to request the
- * {@link ConnectionService} to create an instance of a handover connection.
+ * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+ * incoming handover {@link Connection}.
+ * <p>
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+ * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+ * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+ * device.
+ * <p>
+ * This method is called on the destination app on the <em>receiving</em> device when the
+ * destination app calls {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to
+ * accept an incoming handover from the <em>initiating</em> device.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * Implementations of this method should return an instance of {@link Connection} which
+ * represents the handover. The code below shows an example of how this is done.
+ * <pre>
+ * {@code
+ * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+ * fromPhoneAccountHandle, ConnectionRequest request) {
+ * // Given that your app requested to accept the handover, you should not return null here.
+ * MyConnection connection = new MyConnection();
+ * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+ * connection.setVideoState(request.getVideoState());
+ * return connection;
+ * }
+ * }
+ * </pre>
+ *
* @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
* ConnectionService which needs to handover the call.
* @param request Details about the call which needs to be handover.
- * @return {@link Connection} object corresponding to the handover call.
+ * @return {@link Connection} instance corresponding to the handover call.
*/
public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
ConnectionRequest request) {
@@ -2247,11 +2319,15 @@
/**
* Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
* invocation which failed.
- * @param request Details about the call which needs to be handover.
- * @param error Reason for handover failure as defined in
- * {@link android.telecom.Call.Callback#HANDOVER_FAILURE_DEST_INVALID_PERM}
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}
+ *
+ * @param request Details about the call which failed to handover.
+ * @param error Reason for handover failure. Will be one of the
*/
- public void onHandoverFailed(ConnectionRequest request, int error) {
+ public void onHandoverFailed(ConnectionRequest request,
+ @Call.Callback.HandoverFailureErrors int error) {
return;
}
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 59ce590..bb4b483 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -93,6 +93,10 @@
// failure on the providing end, so immediately mark it destroyed
connection.setDestroyed();
}
+ connection.setStatusHints(parcel.getStatusHints());
+ connection.setIsVoipAudioMode(parcel.getIsVoipAudioMode());
+ connection.setRingbackRequested(parcel.isRingbackRequested());
+ connection.putExtras(parcel.getExtras());
}
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e456830..72c67d3 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1794,8 +1794,25 @@
}
/**
- * Called from the recipient side of a handover to indicate a desire to accept the handover
- * of an ongoing call to another {@link ConnectionService} identified by
+ * Called by an app to indicate that it wishes to accept the handover of an ongoing call to a
+ * {@link PhoneAccountHandle} it defines.
+ * <p>
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+ * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+ * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+ * device.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * This method is called from the <em>receiving</em> side of a handover to indicate a desire to
+ * accept the handover of an ongoing call to another {@link ConnectionService} identified by
* {@link PhoneAccountHandle} destAcct. For managed {@link ConnectionService}s, the specified
* {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
* the user must have enabled the corresponding {@link PhoneAccount}. This can be checked using
@@ -1819,7 +1836,8 @@
* @param videoState Video state after the handover.
* @param destAcct The {@link PhoneAccountHandle} registered to the calling package.
*/
- public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+ public void acceptHandover(Uri srcAddr, @VideoProfile.VideoState int videoState,
+ PhoneAccountHandle destAcct) {
try {
if (isServiceConnected()) {
getTelecomService().acceptHandover(srcAddr, videoState, destAcct);
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index e0e3a08..90ed36f 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -62,6 +62,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef(
flag = true,
+ prefix = { "STATE_" },
value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL,
STATE_PAUSED})
public @interface VideoState {}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index ea2b0ae..4e56396 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -161,6 +161,7 @@
mTdScdmaRscp = INVALID;
mWcdmaSignalStrength = 99;
mWcdmaRscp = INVALID;
+ mWcdmaRscpAsu = 255;
mLteRsrpBoost = 0;
mIsGsm = gsmFlag;
mUseOnlyRsrpForLteLevel = false;
@@ -383,7 +384,7 @@
// but are reported in ASU which is 0 through 96, so we do the conversion here
mWcdmaRscpAsu =
((mWcdmaRscpAsu - 120 >= MIN_WCDMA_RSCP) && (mWcdmaRscpAsu - 120 <= MAX_WCDMA_RSCP))
- ? mWcdmaRscpAsu : INVALID;
+ ? mWcdmaRscpAsu : 255;
mWcdmaRscp = ((mWcdmaRscp >= MIN_WCDMA_RSCP) && (mWcdmaRscp <= MAX_WCDMA_RSCP))
? mWcdmaRscp : INVALID;