Merge "Update Hvac to remove the self register or ui components with their controller"
diff --git a/api/current.txt b/api/current.txt
index 897a8d9..c38d837 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -47620,6 +47620,7 @@
method public void forceLayout();
method public static int generateViewId();
method public java.lang.CharSequence getAccessibilityClassName();
+ method public android.view.View.AccessibilityDelegate getAccessibilityDelegate();
method public int getAccessibilityLiveRegion();
method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
method public java.lang.CharSequence getAccessibilityPaneTitle();
diff --git a/api/system-current.txt b/api/system-current.txt
index 6a00815..cb7f7bb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6042,12 +6042,16 @@
ctor public ImsSsInfo(int, java.lang.String);
method public int describeContents();
method public java.lang.String getIcbNum();
+ method public int getProvisionStatus();
method public int getStatus();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
field public static final int DISABLED = 0; // 0x0
field public static final int ENABLED = 1; // 0x1
field public static final int NOT_REGISTERED = -1; // 0xffffffff
+ field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
+ field public static final int SERVICE_PROVISIONED = 1; // 0x1
+ field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
}
public final class ImsStreamMediaProfile implements android.os.Parcelable {
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index 5cc4fc4..b3e287b 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -42,7 +42,6 @@
namespace uhid {
static const char* UHID_PATH = "/dev/uhid";
-static const size_t UHID_MAX_NAME_LENGTH = 128;
static struct {
jmethodID onDeviceOpen;
@@ -90,8 +89,13 @@
}
Device* Device::open(int32_t id, const char* name, int32_t vid, int32_t pid,
- std::unique_ptr<uint8_t[]> descriptor, size_t descriptorSize,
- std::unique_ptr<DeviceCallback> callback) {
+ std::vector<uint8_t> descriptor, std::unique_ptr<DeviceCallback> callback) {
+
+ size_t size = descriptor.size();
+ if (size > HID_MAX_DESCRIPTOR_SIZE) {
+ LOGE("Received invalid hid report with descriptor size %zu, skipping", size);
+ return nullptr;
+ }
int fd = ::open(UHID_PATH, O_RDWR | O_CLOEXEC);
if (fd < 0) {
@@ -102,10 +106,10 @@
struct uhid_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = UHID_CREATE2;
- strncpy((char*)ev.u.create2.name, name, UHID_MAX_NAME_LENGTH);
- memcpy(&ev.u.create2.rd_data, descriptor.get(),
- descriptorSize * sizeof(ev.u.create2.rd_data[0]));
- ev.u.create2.rd_size = descriptorSize;
+ strlcpy(reinterpret_cast<char*>(ev.u.create2.name), name, sizeof(ev.u.create2.name));
+ memcpy(&ev.u.create2.rd_data, descriptor.data(),
+ size * sizeof(ev.u.create2.rd_data[0]));
+ ev.u.create2.rd_size = size;
ev.u.create2.bus = BUS_BLUETOOTH;
ev.u.create2.vendor = vid;
ev.u.create2.product = pid;
@@ -156,12 +160,17 @@
mFd = -1;
}
-void Device::sendReport(uint8_t* report, size_t reportSize) {
+void Device::sendReport(const std::vector<uint8_t>& report) const {
+ if (report.size() > UHID_DATA_MAX) {
+ LOGE("Received invalid report of size %zu, skipping", report.size());
+ return;
+ }
+
struct uhid_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = UHID_INPUT2;
- ev.u.input2.size = reportSize;
- memcpy(&ev.u.input2.data, report, reportSize);
+ ev.u.input2.size = report.size();
+ memcpy(&ev.u.input2.data, report.data(), report.size() * sizeof(ev.u.input2.data[0]));
ssize_t ret = TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
if (ret < 0 || ret != sizeof(ev)) {
LOGE("Failed to send hid event: %s", strerror(errno));
@@ -191,12 +200,13 @@
} // namespace uhid
-std::unique_ptr<uint8_t[]> getData(JNIEnv* env, jbyteArray javaArray, size_t& outSize) {
+std::vector<uint8_t> getData(JNIEnv* env, jbyteArray javaArray) {
ScopedByteArrayRO scopedArray(env, javaArray);
- outSize = scopedArray.size();
- std::unique_ptr<uint8_t[]> data(new uint8_t[outSize]);
- for (size_t i = 0; i < outSize; i++) {
- data[i] = static_cast<uint8_t>(scopedArray[i]);
+ size_t size = scopedArray.size();
+ std::vector<uint8_t> data;
+ data.reserve(size);
+ for (size_t i = 0; i < size; i++) {
+ data.push_back(static_cast<uint8_t>(scopedArray[i]));
}
return data;
}
@@ -208,23 +218,20 @@
return 0;
}
- size_t size;
- std::unique_ptr<uint8_t[]> desc = getData(env, rawDescriptor, size);
+ std::vector<uint8_t> desc = getData(env, rawDescriptor);
std::unique_ptr<uhid::DeviceCallback> cb(new uhid::DeviceCallback(env, callback));
uhid::Device* d = uhid::Device::open(
- id, reinterpret_cast<const char*>(name.c_str()), vid, pid,
- std::move(desc), size, std::move(cb));
+ id, reinterpret_cast<const char*>(name.c_str()), vid, pid, desc, std::move(cb));
return reinterpret_cast<jlong>(d);
}
static void sendReport(JNIEnv* env, jclass /* clazz */, jlong ptr, jbyteArray rawReport) {
- size_t size;
- std::unique_ptr<uint8_t[]> report = getData(env, rawReport, size);
+ std::vector<uint8_t> report = getData(env, rawReport);
uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
if (d) {
- d->sendReport(report.get(), size);
+ d->sendReport(report);
} else {
LOGE("Could not send report, Device* is null!");
}
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index 149456d..61a1f76 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -15,6 +15,7 @@
*/
#include <memory>
+#include <vector>
#include <jni.h>
@@ -38,13 +39,12 @@
class Device {
public:
static Device* open(int32_t id, const char* name, int32_t vid, int32_t pid,
- std::unique_ptr<uint8_t[]> descriptor, size_t descriptorSize,
- std::unique_ptr<DeviceCallback> callback);
+ std::vector<uint8_t> descriptor, std::unique_ptr<DeviceCallback> callback);
Device(int32_t id, int fd, std::unique_ptr<DeviceCallback> callback);
~Device();
- void sendReport(uint8_t* report, size_t reportSize);
+ void sendReport(const std::vector<uint8_t>& report) const;
void close();
int handleEvents(int events);
diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp
index 691356b..35e03e4 100644
--- a/cmds/statsd/src/condition/condition_util.cpp
+++ b/cmds/statsd/src/condition/condition_util.cpp
@@ -76,9 +76,9 @@
break;
}
case LogicalOperation::NOT:
- newCondition = (conditionCache[children[0]] == ConditionState::kFalse)
- ? ConditionState::kTrue
- : ConditionState::kFalse;
+ newCondition = children.empty() ? ConditionState::kUnknown :
+ ((conditionCache[children[0]] == ConditionState::kFalse) ?
+ ConditionState::kTrue : ConditionState::kFalse);
break;
case LogicalOperation::NAND:
newCondition = hasFalse ? ConditionState::kTrue : ConditionState::kFalse;
diff --git a/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp b/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp
index 23d6926..6529d65 100644
--- a/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp
@@ -40,6 +40,7 @@
EXPECT_EQ(evaluateCombinationCondition(children, operation, conditionResults),
ConditionState::kUnknown);
}
+
TEST(ConditionTrackerTest, TestAndCondition) {
// Set up the matcher
LogicalOperation operation = LogicalOperation::AND;
@@ -103,6 +104,11 @@
conditionResults.clear();
conditionResults.push_back(ConditionState::kFalse);
EXPECT_TRUE(evaluateCombinationCondition(children, operation, conditionResults));
+
+ children.clear();
+ conditionResults.clear();
+ EXPECT_EQ(evaluateCombinationCondition(children, operation, conditionResults),
+ ConditionState::kUnknown);
}
TEST(ConditionTrackerTest, TestNandCondition) {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 4f60b0c..bc4ed15 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -964,22 +964,6 @@
Landroid/app/WallpaperManager;->setBitmap(Landroid/graphics/Bitmap;Landroid/graphics/Rect;ZII)I
Landroid/app/WallpaperManager;->setWallpaperComponent(Landroid/content/ComponentName;I)Z
Landroid/app/WallpaperManager;->sGlobals:Landroid/app/WallpaperManager$Globals;
-Landroid/appwidget/AppWidgetHost;-><init>(Landroid/content/Context;ILandroid/widget/RemoteViews$OnClickHandler;Landroid/os/Looper;)V
-Landroid/appwidget/AppWidgetHost;->HANDLE_VIEW_DATA_CHANGED:I
-Landroid/appwidget/AppWidgetHost;->mHandler:Landroid/os/Handler;
-Landroid/appwidget/AppWidgetHost;->sService:Lcom/android/internal/appwidget/IAppWidgetService;
-Landroid/appwidget/AppWidgetHostView;->getDefaultPaddingForWidget(Landroid/content/Context;Landroid/content/pm/ApplicationInfo;Landroid/graphics/Rect;)Landroid/graphics/Rect;
-Landroid/appwidget/AppWidgetHostView;->mAppWidgetId:I
-Landroid/appwidget/AppWidgetHostView;->mInfo:Landroid/appwidget/AppWidgetProviderInfo;
-Landroid/appwidget/AppWidgetHostView;->updateAppWidgetSize(Landroid/os/Bundle;IIIIZ)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;Landroid/os/Bundle;)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetIdIfAllowed(IILandroid/content/ComponentName;Landroid/os/Bundle;)Z
-Landroid/appwidget/AppWidgetManager;->bindRemoteViewsService(Landroid/content/Context;ILandroid/content/Intent;Landroid/app/IServiceConnection;I)Z
-Landroid/appwidget/AppWidgetManager;->getInstalledProviders(I)Ljava/util/List;
-Landroid/appwidget/AppWidgetManager;->getInstalledProvidersForProfile(ILandroid/os/UserHandle;Ljava/lang/String;)Ljava/util/List;
-Landroid/appwidget/AppWidgetManager;->mService:Lcom/android/internal/appwidget/IAppWidgetService;
-Landroid/appwidget/AppWidgetProviderInfo;->providerInfo:Landroid/content/pm/ActivityInfo;
Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
Landroid/bluetooth/IBluetooth$Stub;-><init>()V
@@ -1849,18 +1833,6 @@
Landroid/icu/util/UResourceBundle;->getType()I
Landroid/icu/util/UResourceBundleIterator;->hasNext()Z
Landroid/icu/util/UResourceBundleIterator;->next()Landroid/icu/util/UResourceBundle;
-Landroid/location/Country;-><init>(Ljava/lang/String;I)V
-Landroid/location/Country;->getCountryIso()Ljava/lang/String;
-Landroid/location/Country;->getSource()I
-Landroid/location/CountryDetector;-><init>(Landroid/location/ICountryDetector;)V
-Landroid/location/CountryDetector;->addCountryListener(Landroid/location/CountryListener;Landroid/os/Looper;)V
-Landroid/location/CountryDetector;->detectCountry()Landroid/location/Country;
-Landroid/location/CountryDetector;->removeCountryListener(Landroid/location/CountryListener;)V
-Landroid/location/CountryListener;->onCountryDetected(Landroid/location/Country;)V
-Landroid/location/GeocoderParams;->getClientPackage()Ljava/lang/String;
-Landroid/location/GeocoderParams;->getLocale()Ljava/util/Locale;
-Landroid/location/Geofence;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/location/GpsStatus;->setTimeToFirstFix(I)V
Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
Landroid/location/ICountryListener$Stub;-><init>()V
Landroid/location/IGeocodeProvider$Stub;-><init>()V
@@ -1879,25 +1851,6 @@
Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List;
-Landroid/location/Location;->mElapsedRealtimeNanos:J
-Landroid/location/Location;->mProvider:Ljava/lang/String;
-Landroid/location/LocationManager;->mService:Landroid/location/ILocationManager;
-Landroid/location/LocationManager;->requestLocationUpdates(Landroid/location/LocationRequest;Landroid/location/LocationListener;Landroid/os/Looper;Landroid/app/PendingIntent;)V
-Landroid/location/LocationManager;->sendNiResponse(II)Z
-Landroid/location/LocationRequest;->checkDisplacement(F)V
-Landroid/location/LocationRequest;->checkInterval(J)V
-Landroid/location/LocationRequest;->checkProvider(Ljava/lang/String;)V
-Landroid/location/LocationRequest;->checkQuality(I)V
-Landroid/location/LocationRequest;->mExpireAt:J
-Landroid/location/LocationRequest;->mExplicitFastestInterval:Z
-Landroid/location/LocationRequest;->mFastestInterval:J
-Landroid/location/LocationRequest;->mHideFromAppOps:Z
-Landroid/location/LocationRequest;->mInterval:J
-Landroid/location/LocationRequest;->mNumUpdates:I
-Landroid/location/LocationRequest;->mProvider:Ljava/lang/String;
-Landroid/location/LocationRequest;->mQuality:I
-Landroid/location/LocationRequest;->mSmallestDisplacement:F
-Landroid/location/LocationRequest;->mWorkSource:Landroid/os/WorkSource;
Landroid/media/AmrInputStream;-><init>(Ljava/io/InputStream;)V
Landroid/media/AsyncPlayer;->setUsesWakeLock(Landroid/content/Context;)V
Landroid/media/AudioAttributes$Builder;->addTag(Ljava/lang/String;)Landroid/media/AudioAttributes$Builder;
@@ -2366,10 +2319,6 @@
Landroid/media/VolumeShaper$State;->mVolume:F
Landroid/media/VolumeShaper$State;->mXOffset:F
Landroid/media/WebVttRenderer;-><init>(Landroid/content/Context;)V
-Landroid/mtp/MtpPropertyList;->append(IIIJ)V
-Landroid/mtp/MtpPropertyList;->append(IILjava/lang/String;)V
-Landroid/mtp/MtpStorage;->getPath()Ljava/lang/String;
-Landroid/mtp/MtpStorage;->getStorageId()I
Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;
Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String;
Landroid/net/ConnectivityManager;->EXTRA_AVAILABLE_TETHER:Ljava/lang/String;
@@ -2847,13 +2796,6 @@
Landroid/nfc/INfcAdapterExtras;->open(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
Landroid/nfc/INfcAdapterExtras;->setCardEmulationRoute(Ljava/lang/String;I)V
Landroid/nfc/INfcAdapterExtras;->transceive(Ljava/lang/String;[B)Landroid/os/Bundle;
-Landroid/opengl/EGL14;->eglGetDisplay(J)Landroid/opengl/EGLDisplay;
-Landroid/opengl/GLES20;->glGetActiveAttrib(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V
-Landroid/opengl/GLES20;->glGetActiveUniform(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V
-Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext;
-Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper;
-Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread;
-Landroid/opengl/GLSurfaceView;->mRenderer:Landroid/opengl/GLSurfaceView$Renderer;
Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;)Landroid/os/AsyncResult;
Landroid/os/AsyncTask;->mFuture:Ljava/util/concurrent/FutureTask;
Landroid/os/AsyncTask;->mStatus:Landroid/os/AsyncTask$Status;
@@ -5233,7 +5175,6 @@
Landroid/view/View;->findViewByAccessibilityId(I)Landroid/view/View;
Landroid/view/View;->fitsSystemWindows()Z
Landroid/view/View;->gatherTransparentRegion(Landroid/graphics/Region;)Z
-Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate;
Landroid/view/View;->getAccessibilityViewId()I
Landroid/view/View;->getBoundsOnScreen(Landroid/graphics/Rect;)V
Landroid/view/View;->getBoundsOnScreen(Landroid/graphics/Rect;Z)V
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 4b4250d..2808166 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -55,15 +55,6 @@
Landroid/app/TaskStackListener;->onTaskStackChanged()V
Landroid/app/WallpaperColors;-><init>(Landroid/graphics/Color;Landroid/graphics/Color;Landroid/graphics/Color;I)V
Landroid/bluetooth/IBluetooth;->sendConnectionStateChange(Landroid/bluetooth/BluetoothDevice;III)V
-Landroid/companion/AssociationRequest;->getDeviceFilters()Ljava/util/List;
-Landroid/companion/AssociationRequest;->isSingleDevice()Z
-Landroid/companion/BluetoothDeviceFilter;->getAddress()Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/net/wifi/ScanResult;)Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceMacAddress(Landroid/os/Parcelable;)Ljava/lang/String;
-Landroid/companion/BluetoothLeDeviceFilter;->getScanFilter()Landroid/bluetooth/le/ScanFilter;
-Landroid/companion/DeviceFilter;->getDeviceDisplayName(Landroid/os/Parcelable;)Ljava/lang/String;
-Landroid/companion/DeviceFilter;->matches(Landroid/os/Parcelable;)Z
Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V
Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V
Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V
@@ -99,7 +90,6 @@
Landroid/location/ILocationManager;->reportLocation(Landroid/location/Location;Z)V
Landroid/location/INetInitiatedListener$Stub;-><init>()V
Landroid/location/INetInitiatedListener;->sendNiResponse(II)Z
-Landroid/location/Location;->setExtraLocation(Ljava/lang/String;Landroid/location/Location;)V
Landroid/media/AudioManager;->registerAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V
Landroid/media/AudioManager;->unregisterAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V
Landroid/media/AudioSystem;->checkAudioFlinger()I
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 49cc498..f003d4b 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -53,14 +54,17 @@
static final int HANDLE_UPDATE = 1;
static final int HANDLE_PROVIDER_CHANGED = 2;
static final int HANDLE_PROVIDERS_CHANGED = 3;
+ @UnsupportedAppUsage
static final int HANDLE_VIEW_DATA_CHANGED = 4;
final static Object sServiceLock = new Object();
+ @UnsupportedAppUsage
static IAppWidgetService sService;
static boolean sServiceInitialized = false;
private DisplayMetrics mDisplayMetrics;
private String mContextOpPackageName;
+ @UnsupportedAppUsage
private final Handler mHandler;
private final int mHostId;
private final Callbacks mCallbacks;
@@ -156,6 +160,7 @@
/**
* @hide
*/
+ @UnsupportedAppUsage
public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) {
mContextOpPackageName = context.getOpPackageName();
mHostId = hostId;
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ab0eb92..a9187b6 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -16,6 +16,7 @@
package android.appwidget;
+import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -70,7 +71,9 @@
Context mContext;
Context mRemoteContext;
+ @UnsupportedAppUsage
int mAppWidgetId;
+ @UnsupportedAppUsage
AppWidgetProviderInfo mInfo;
View mView;
int mViewMode = VIEW_MODE_NOINIT;
@@ -174,6 +177,7 @@
return getDefaultPaddingForWidget(context, appInfo, padding);
}
+ @UnsupportedAppUsage
private static Rect getDefaultPaddingForWidget(Context context, ApplicationInfo appInfo,
Rect padding) {
if (padding == null) {
@@ -284,6 +288,7 @@
/**
* @hide
*/
+ @UnsupportedAppUsage
public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
int maxHeight, boolean ignorePadding) {
if (newOptions == null) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 20248b9..dbc1c19 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,6 +23,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
import android.app.IServiceConnection;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -463,6 +464,7 @@
private final Context mContext;
private final String mPackageName;
+ @UnsupportedAppUsage
private final IAppWidgetService mService;
private final DisplayMetrics mDisplayMetrics;
@@ -816,6 +818,7 @@
*
* @hide
*/
+ @UnsupportedAppUsage
public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
if (mService == null) {
return Collections.emptyList();
@@ -842,6 +845,7 @@
*
* @hide
*/
+ @UnsupportedAppUsage
public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
@Nullable UserHandle profile, @Nullable String packageName) {
if (mService == null) {
@@ -902,6 +906,7 @@
* provider for this AppWidget.
* @hide
*/
+ @UnsupportedAppUsage
public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
if (mService == null) {
return;
@@ -924,6 +929,7 @@
*
* @hide
*/
+ @UnsupportedAppUsage
public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
if (mService == null) {
return;
@@ -1094,6 +1100,7 @@
* @see Context#getServiceDispatcher(ServiceConnection, Handler, int)
* @hide
*/
+ @UnsupportedAppUsage
public boolean bindRemoteViewsService(Context context, int appWidgetId, Intent intent,
IServiceConnection connection, @Context.BindServiceFlags int flags) {
if (mService == null) {
@@ -1139,6 +1146,7 @@
}
}
+ @UnsupportedAppUsage
private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId,
ComponentName provider, Bundle options) {
if (mService == null) {
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 6dd85ca..53315cc 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -270,6 +271,7 @@
public int widgetFeatures;
/** @hide */
+ @UnsupportedAppUsage
public ActivityInfo providerInfo;
public AppWidgetProviderInfo() {
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index 922224a..db54f08 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.OneTimeUseBuilder;
@@ -59,12 +60,14 @@
}
/** @hide */
+ @UnsupportedAppUsage
public boolean isSingleDevice() {
return mSingleDevice;
}
/** @hide */
@NonNull
+ @UnsupportedAppUsage
public List<DeviceFilter<?>> getDeviceFilters() {
return mDeviceFilters;
}
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index 84e1536..7507e17 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -25,6 +25,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.ParcelUuid;
@@ -99,6 +100,7 @@
/** @hide */
@Nullable
+ @UnsupportedAppUsage
public String getAddress() {
return mAddress;
}
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 4ee38fe..bd507a6 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
import android.net.wifi.ScanResult;
@@ -124,14 +125,17 @@
Log.i(LOG_TAG, getDeviceDisplayNameInternal(device) + (result ? " ~ " : " !~ ") + criteria);
}
+ @UnsupportedAppUsage
public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) {
return firstNotEmpty(device.getAliasName(), device.getAddress());
}
+ @UnsupportedAppUsage
public static String getDeviceDisplayNameInternal(@NonNull ScanResult device) {
return firstNotEmpty(device.SSID, device.BSSID);
}
+ @UnsupportedAppUsage
public static String getDeviceMacAddress(@NonNull Parcelable device) {
if (device instanceof BluetoothDevice) {
return ((BluetoothDevice) device).getAddress();
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index 7fb768c..1de931e 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -25,6 +25,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
@@ -92,6 +93,7 @@
/** @hide */
@NonNull
+ @UnsupportedAppUsage
public ScanFilter getScanFilter() {
return mScanFilter;
}
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
index 10135a4..dc7cf82 100644
--- a/core/java/android/companion/DeviceFilter.java
+++ b/core/java/android/companion/DeviceFilter.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcelable;
import java.lang.annotation.Retention;
@@ -44,9 +45,11 @@
*
* @hide
*/
+ @UnsupportedAppUsage
boolean matches(D device);
/** @hide */
+ @UnsupportedAppUsage
String getDeviceDisplayName(D device);
/** @hide */
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index 93fa403..b06dd7a 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -21,9 +21,12 @@
import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.util.Preconditions;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -55,6 +58,7 @@
* @param size the initial size of the set of values
*/
public ContentValues(int size) {
+ Preconditions.checkArgumentNonnegative(size);
mMap = new ArrayMap<>(size);
}
@@ -64,6 +68,7 @@
* @param from the values to copy
*/
public ContentValues(ContentValues from) {
+ Objects.requireNonNull(from);
mMap = new ArrayMap<>(from.mMap);
}
diff --git a/core/java/android/database/RedactingCursor.java b/core/java/android/database/RedactingCursor.java
new file mode 100644
index 0000000..6322d56
--- /dev/null
+++ b/core/java/android/database/RedactingCursor.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database;
+
+import android.annotation.NonNull;
+import android.util.SparseArray;
+
+import java.util.Map;
+
+/**
+ * Cursor that offers to redact values of requested columns.
+ *
+ * @hide
+ */
+public class RedactingCursor extends CrossProcessCursorWrapper {
+ private final SparseArray<Object> mRedactions;
+
+ private RedactingCursor(@NonNull Cursor cursor, SparseArray<Object> redactions) {
+ super(cursor);
+ mRedactions = redactions;
+ }
+
+ /**
+ * Create a wrapped instance of the given {@link Cursor} which redacts the
+ * requested columns so they always return specific values when accessed.
+ * <p>
+ * If a redacted column appears multiple times in the underlying cursor, all
+ * instances will be redacted. If none of the redacted columns appear in the
+ * given cursor, the given cursor will be returned untouched to improve
+ * performance.
+ */
+ public static Cursor create(@NonNull Cursor cursor, @NonNull Map<String, Object> redactions) {
+ final SparseArray<Object> internalRedactions = new SparseArray<>();
+
+ final String[] columns = cursor.getColumnNames();
+ for (int i = 0; i < columns.length; i++) {
+ if (redactions.containsKey(columns[i])) {
+ internalRedactions.put(i, redactions.get(columns[i]));
+ }
+ }
+
+ if (internalRedactions.size() == 0) {
+ return cursor;
+ } else {
+ return new RedactingCursor(cursor, internalRedactions);
+ }
+ }
+
+ @Override
+ public void fillWindow(int position, CursorWindow window) {
+ // Fill window directly to ensure data is redacted
+ DatabaseUtils.cursorFillWindow(this, position, window);
+ }
+
+ @Override
+ public CursorWindow getWindow() {
+ // Returning underlying window risks leaking redacted data
+ return null;
+ }
+
+ @Override
+ public Cursor getWrappedCursor() {
+ throw new UnsupportedOperationException(
+ "Returning underlying cursor risks leaking redacted data");
+ }
+
+ @Override
+ public double getDouble(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return (double) mRedactions.valueAt(i);
+ } else {
+ return super.getDouble(columnIndex);
+ }
+ }
+
+ @Override
+ public float getFloat(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return (float) mRedactions.valueAt(i);
+ } else {
+ return super.getFloat(columnIndex);
+ }
+ }
+
+ @Override
+ public int getInt(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return (int) mRedactions.valueAt(i);
+ } else {
+ return super.getInt(columnIndex);
+ }
+ }
+
+ @Override
+ public long getLong(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return (long) mRedactions.valueAt(i);
+ } else {
+ return super.getLong(columnIndex);
+ }
+ }
+
+ @Override
+ public short getShort(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return (short) mRedactions.valueAt(i);
+ } else {
+ return super.getShort(columnIndex);
+ }
+ }
+
+ @Override
+ public String getString(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return (String) mRedactions.valueAt(i);
+ } else {
+ return super.getString(columnIndex);
+ }
+ }
+
+ @Override
+ public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ buffer.data = ((String) mRedactions.valueAt(i)).toCharArray();
+ buffer.sizeCopied = buffer.data.length;
+ } else {
+ super.copyStringToBuffer(columnIndex, buffer);
+ }
+ }
+
+ @Override
+ public byte[] getBlob(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return (byte[]) mRedactions.valueAt(i);
+ } else {
+ return super.getBlob(columnIndex);
+ }
+ }
+
+ @Override
+ public int getType(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return DatabaseUtils.getTypeOfObject(mRedactions.valueAt(i));
+ } else {
+ return super.getType(columnIndex);
+ }
+ }
+
+ @Override
+ public boolean isNull(int columnIndex) {
+ final int i = mRedactions.indexOfKey(columnIndex);
+ if (i >= 0) {
+ return mRedactions.valueAt(i) == null;
+ } else {
+ return super.isNull(columnIndex);
+ }
+ }
+}
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index d6d9764..e6b6acf 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -39,11 +39,18 @@
public final class SQLiteGlobal {
private static final String TAG = "SQLiteGlobal";
+ /** @hide */
+ public static final String SYNC_MODE_FULL = "FULL";
+
private static final Object sLock = new Object();
+
private static int sDefaultPageSize;
private static native int nativeReleaseMemory();
+ /** @hide */
+ public static volatile String sDefaultSyncMode;
+
private SQLiteGlobal() {
}
@@ -103,6 +110,11 @@
* Gets the default database synchronization mode when WAL is not in use.
*/
public static String getDefaultSyncMode() {
+ // Use the FULL synchronous mode for system processes by default.
+ String defaultMode = sDefaultSyncMode;
+ if (defaultMode != null) {
+ return defaultMode;
+ }
return SystemProperties.get("debug.sqlite.syncmode",
Resources.getSystem().getString(
com.android.internal.R.string.db_default_sync_mode));
@@ -112,6 +124,11 @@
* Gets the database synchronization mode when in WAL mode.
*/
public static String getWALSyncMode() {
+ // Use the FULL synchronous mode for system processes by default.
+ String defaultMode = sDefaultSyncMode;
+ if (defaultMode != null) {
+ return defaultMode;
+ }
return SystemProperties.get("debug.sqlite.wal.syncmode",
Resources.getSystem().getString(
com.android.internal.R.string.db_wal_sync_mode));
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 52a2354..081d8d1 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -372,7 +372,7 @@
if (score < 0) {
throw new IllegalArgumentException("Score must be >= 0");
}
- queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
+ queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score, 0);
}
/**
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 5752b6f..591370f 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -241,6 +241,9 @@
} else {
try {
key = bp.getInterfaceDescriptor();
+ if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) {
+ key = "<proxy to dead node>";
+ }
} catch (Throwable t) {
key = "<exception during getDescriptor>";
}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 9c3a409..68572dd 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -469,6 +469,12 @@
* The height of the image/video in pixels.
*/
public static final String HEIGHT = "height";
+
+ /**
+ * Package that contributed this media.
+ * @hide
+ */
+ public static final String OWNER_PACKAGE_NAME = "owner_package_name";
}
/**
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 131fe13..092702c 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -421,8 +421,8 @@
boolean isWindowTraceEnabled();
/**
- * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
- * on the next user activity.
+ * Requests that the WindowManager sends
+ * WindowManagerPolicyConstants#ACTION_USER_ACTIVITY_NOTIFICATION on the next user activity.
*/
void requestUserActivityNotification();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e2e2b00..65ab3ac 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9008,8 +9008,6 @@
* composition. For more details see {@link AccessibilityDelegate}.
*
* @return The delegate, or null if none set.
- *
- * @hide
*/
public AccessibilityDelegate getAccessibilityDelegate() {
return mAccessibilityDelegate;
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 17ab956..e64d2af 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -96,7 +96,7 @@
return toJavaStringArray(env, cStrings);
}
-static jint verify(JNIEnv* env, jobjectArray packageInfo, android::vintf::DisabledChecks checks) {
+static jint verify(JNIEnv* env, jobjectArray packageInfo, android::vintf::CheckFlags::Type checks) {
std::vector<std::string> cPackageInfo;
if (packageInfo) {
size_t count = env->GetArrayLength(packageInfo);
@@ -116,11 +116,11 @@
}
static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
- return verify(env, packageInfo, ::android::vintf::ENABLE_ALL_CHECKS);
+ return verify(env, packageInfo, ::android::vintf::CheckFlags::ENABLE_ALL_CHECKS);
}
static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) {
- return verify(env, nullptr, ::android::vintf::DISABLE_AVB_CHECK);
+ return verify(env, nullptr, ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
}
static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, jclass) {
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 48113df..3db7f9d 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -265,11 +265,10 @@
optional int32 stack_id = 4;
optional .android.view.WindowLayoutParamsProto attributes = 5;
optional .android.graphics.RectProto given_content_insets = 6;
- reserved 7 to 10;
-// optional .android.graphics.RectProto frame = 7;
-// optional .android.graphics.RectProto containing_frame = 8;
-// optional .android.graphics.RectProto parent_frame = 9;
-// optional .android.graphics.RectProto content_frame = 10;
+ optional .android.graphics.RectProto frame = 7 [deprecated=true];
+ optional .android.graphics.RectProto containing_frame = 8 [deprecated=true];
+ optional .android.graphics.RectProto parent_frame = 9 [deprecated=true];
+ optional .android.graphics.RectProto content_frame = 10 [deprecated=true];
optional .android.graphics.RectProto content_insets = 11;
optional .android.graphics.RectProto surface_insets = 12;
optional WindowStateAnimatorProto animator = 13;
@@ -282,18 +281,16 @@
optional int32 system_ui_visibility = 21;
optional bool has_surface = 22;
optional bool is_ready_for_display = 23;
- reserved 24 to 28;
-// optional .android.graphics.RectProto display_frame = 24;
-// optional .android.graphics.RectProto overscan_frame = 25;
-// optional .android.graphics.RectProto visible_frame = 26;
-// optional .android.graphics.RectProto decor_frame = 27;
-// optional .android.graphics.RectProto outset_frame = 28;
+ optional .android.graphics.RectProto display_frame = 24 [deprecated=true];
+ optional .android.graphics.RectProto overscan_frame = 25 [deprecated=true];
+ optional .android.graphics.RectProto visible_frame = 26 [deprecated=true];
+ optional .android.graphics.RectProto decor_frame = 27 [deprecated=true];
+ optional .android.graphics.RectProto outset_frame = 28 [deprecated=true];
optional .android.graphics.RectProto overscan_insets = 29;
optional .android.graphics.RectProto visible_insets = 30;
optional .android.graphics.RectProto stable_insets = 31;
optional .android.graphics.RectProto outsets = 32;
- reserved 33;
-// optional .android.view.DisplayCutoutProto cutout = 33;
+ optional .android.view.DisplayCutoutProto cutout = 33 [deprecated=true];
optional bool remove_on_exit = 34;
optional bool destroying = 35;
optional bool removed = 36;
diff --git a/core/res/res/anim/keyguard_occlude_open_enter.xml b/core/res/res/anim/keyguard_occlude_open_enter.xml
deleted file mode 100644
index e742616..0000000
--- a/core/res/res/anim/keyguard_occlude_open_enter.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
- <translate
- android:fromYDelta="90%"
- android:toYDelta="0%"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="400"/>
- <alpha
- android:fromAlpha="0.0"
- android:toAlpha="1.0"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="300"/>
-</set>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 140bb7d8..2f45cce 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2156,7 +2156,6 @@
<java-symbol type="anim" name="push_down_out" />
<java-symbol type="anim" name="push_up_in" />
<java-symbol type="anim" name="push_up_out" />
- <java-symbol type="anim" name="keyguard_occlude_open_enter" />
<java-symbol type="anim" name="lock_screen_behind_enter" />
<java-symbol type="anim" name="lock_screen_behind_enter_wallpaper" />
<java-symbol type="anim" name="lock_screen_behind_enter_fade_in" />
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 2a906ae..d704957 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1301,6 +1301,11 @@
android:process=":MemoryFileProvider">
</provider>
+ <provider android:name="android.content.RedactingProvider"
+ android:authorities="android.content.RedactingProvider"
+ android:process=":RedactingProvider">
+ </provider>
+
<!-- Application components used for os tests -->
<service android:name="android.os.MessengerService"
diff --git a/core/tests/coretests/src/android/content/RedactingProvider.java b/core/tests/coretests/src/android/content/RedactingProvider.java
new file mode 100644
index 0000000..e2ad448
--- /dev/null
+++ b/core/tests/coretests/src/android/content/RedactingProvider.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.RedactingCursor;
+import android.net.Uri;
+import android.util.ArrayMap;
+
+public class RedactingProvider extends ContentProvider {
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ switch (uri.getLastPathSegment()) {
+ case "missing": {
+ final MatrixCursor cursor = new MatrixCursor(
+ new String[] { "name", "size", "_data" });
+ cursor.addRow(new Object[] { "foo", 10, "/path/to/foo" });
+ cursor.addRow(new Object[] { "bar", 20, "/path/to/bar" });
+
+ final ArrayMap<String, Object> redactions = new ArrayMap<>();
+ redactions.put("missing", null);
+ return RedactingCursor.create(cursor, redactions);
+ }
+ case "single": {
+ final MatrixCursor cursor = new MatrixCursor(
+ new String[] { "name", "size", "_data" });
+ cursor.addRow(new Object[] { "foo", 10, "/path/to/foo" });
+ cursor.addRow(new Object[] { "bar", 20, "/path/to/bar" });
+
+ final ArrayMap<String, Object> redactions = new ArrayMap<>();
+ redactions.put("name", null);
+ redactions.put("_data", "/dev/null");
+ return RedactingCursor.create(cursor, redactions);
+ }
+ case "multiple": {
+ final MatrixCursor cursor = new MatrixCursor(
+ new String[] { "_data", "name", "_data" });
+ cursor.addRow(new Object[] { "/path", "foo", "/path" });
+
+ final ArrayMap<String, Object> redactions = new ArrayMap<>();
+ redactions.put("_data", null);
+ return RedactingCursor.create(cursor, redactions);
+ }
+ }
+
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/tests/coretests/src/android/database/RedactingCursorTest.java b/core/tests/coretests/src/android/database/RedactingCursorTest.java
new file mode 100644
index 0000000..93998f3
--- /dev/null
+++ b/core/tests/coretests/src/android/database/RedactingCursorTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.net.Uri;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RedactingCursorTest {
+ private Context getContext() {
+ return InstrumentationRegistry.getContext();
+ }
+
+ @Test
+ public void testMissing() throws Exception {
+ final Cursor redacting = getContext().getContentResolver().query(
+ Uri.parse("content://android.content.RedactingProvider/missing"), null, null, null);
+
+ redacting.moveToNext();
+ assertEquals("foo", redacting.getString(0));
+ assertEquals(10, redacting.getInt(1));
+ assertEquals("/path/to/foo", redacting.getString(2));
+ redacting.moveToNext();
+ assertEquals("bar", redacting.getString(0));
+ assertEquals(20, redacting.getInt(1));
+ assertEquals("/path/to/bar", redacting.getString(2));
+ }
+
+ @Test
+ public void testSingle() throws Exception {
+ final Cursor redacting = getContext().getContentResolver().query(
+ Uri.parse("content://android.content.RedactingProvider/single"), null, null, null);
+
+ redacting.moveToNext();
+ assertEquals(null, redacting.getString(0));
+ assertEquals(10, redacting.getInt(1));
+ assertEquals("/dev/null", redacting.getString(2));
+ assertEquals(Cursor.FIELD_TYPE_NULL, redacting.getType(0));
+ assertEquals(Cursor.FIELD_TYPE_INTEGER, redacting.getType(1));
+ assertEquals(Cursor.FIELD_TYPE_STRING, redacting.getType(2));
+ assertTrue(redacting.isNull(0));
+ assertFalse(redacting.isNull(1));
+ assertFalse(redacting.isNull(2));
+
+ redacting.moveToNext();
+ assertEquals(null, redacting.getString(0));
+ assertEquals(20, redacting.getInt(1));
+ assertEquals("/dev/null", redacting.getString(2));
+ }
+
+ @Test
+ public void testMultiple() throws Exception {
+ final Cursor redacting = getContext().getContentResolver().query(
+ Uri.parse("content://android.content.RedactingProvider/multiple"),
+ null, null, null);
+
+ redacting.moveToNext();
+ assertEquals(null, redacting.getString(0));
+ assertEquals("foo", redacting.getString(1));
+ assertEquals(null, redacting.getString(2));
+ }
+}
diff --git a/location/java/android/location/Country.java b/location/java/android/location/Country.java
index 7c1485d..6f82b78 100644
--- a/location/java/android/location/Country.java
+++ b/location/java/android/location/Country.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -78,6 +79,7 @@
* <li>{@link #COUNTRY_SOURCE_LOCALE}</li>
* </ul>
*/
+ @UnsupportedAppUsage
public Country(final String countryIso, final int source) {
if (countryIso == null || source < COUNTRY_SOURCE_NETWORK
|| source > COUNTRY_SOURCE_LOCALE) {
@@ -107,6 +109,7 @@
/**
* @return the ISO 3166-1 two letters country code
*/
+ @UnsupportedAppUsage
public final String getCountryIso() {
return mCountryIso;
}
@@ -121,6 +124,7 @@
* <li>{@link #COUNTRY_SOURCE_LOCALE}</li>
* </ul>
*/
+ @UnsupportedAppUsage
public final int getSource() {
return mSource;
}
diff --git a/location/java/android/location/CountryDetector.java b/location/java/android/location/CountryDetector.java
index ec6dfb7..119d1e0 100644
--- a/location/java/android/location/CountryDetector.java
+++ b/location/java/android/location/CountryDetector.java
@@ -19,6 +19,7 @@
import java.util.HashMap;
import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
@@ -87,6 +88,7 @@
* create an instance of this class is using the factory
* Context.getSystemService.
*/
+ @UnsupportedAppUsage
public CountryDetector(ICountryDetector service) {
mService = service;
mListeners = new HashMap<CountryListener, ListenerTransport>();
@@ -98,6 +100,7 @@
* @return the country if it is available immediately, otherwise null will
* be returned.
*/
+ @UnsupportedAppUsage
public Country detectCountry() {
try {
return mService.detectCountry();
@@ -116,6 +119,7 @@
* implement the callback mechanism. If looper is null then the
* callbacks will be called on the main thread.
*/
+ @UnsupportedAppUsage
public void addCountryListener(CountryListener listener, Looper looper) {
synchronized (mListeners) {
if (!mListeners.containsKey(listener)) {
@@ -133,6 +137,7 @@
/**
* Remove the listener
*/
+ @UnsupportedAppUsage
public void removeCountryListener(CountryListener listener) {
synchronized (mListeners) {
ListenerTransport transport = mListeners.get(listener);
diff --git a/location/java/android/location/CountryListener.java b/location/java/android/location/CountryListener.java
index e36db41..70a83c5 100644
--- a/location/java/android/location/CountryListener.java
+++ b/location/java/android/location/CountryListener.java
@@ -16,6 +16,8 @@
package android.location;
+import android.annotation.UnsupportedAppUsage;
+
/**
* The listener for receiving the notification when the country is detected or
* changed
@@ -26,5 +28,6 @@
/**
* @param country the changed or detected country.
*/
+ @UnsupportedAppUsage
void onCountryDetected(Country country);
}
diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java
index 174fe3e..d90e4b5 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/location/java/android/location/GeocoderParams.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
@@ -53,6 +54,7 @@
/**
* returns the Geocoder's locale
*/
+ @UnsupportedAppUsage
public Locale getLocale() {
return mLocale;
}
@@ -60,6 +62,7 @@
/**
* returns the package name of the Geocoder's client
*/
+ @UnsupportedAppUsage
public String getClientPackage() {
return mPackageName;
}
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index 5de779a..ed2aa64 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -98,6 +99,7 @@
}
}
+ @UnsupportedAppUsage
public static final Parcelable.Creator<Geofence> CREATOR = new Parcelable.Creator<Geofence>() {
@Override
public Geofence createFromParcel(Parcel in) {
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index b601cde..d90a597 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.UnsupportedAppUsage;
import android.util.SparseArray;
import java.util.Iterator;
@@ -206,6 +207,7 @@
status.mAzimuths);
}
+ @UnsupportedAppUsage
void setTimeToFirstFix(int ttff) {
mTimeToFirstFix = ttff;
}
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 684cafa..70a97e1 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -123,8 +124,10 @@
}
};
+ @UnsupportedAppUsage
private String mProvider;
private long mTime = 0;
+ @UnsupportedAppUsage
private long mElapsedRealtimeNanos = 0;
private double mLatitude = 0.0;
private double mLongitude = 0.0;
@@ -1156,6 +1159,7 @@
* @param value the Location to attach
* @hide
*/
+ @UnsupportedAppUsage
public void setExtraLocation(String key, Location value) {
if (mExtras == null) {
mExtras = new Bundle();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 30a07ef..b5d9431 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -29,6 +29,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -68,6 +69,7 @@
private static final String TAG = "LocationManager";
private final Context mContext;
+ @UnsupportedAppUsage
private final ILocationManager mService;
private final GnssMeasurementCallbackTransport mGnssMeasurementCallbackTransport;
private final GnssNavigationMessageCallbackTransport mGnssNavigationMessageCallbackTransport;
@@ -1004,6 +1006,7 @@
}
}
+ @UnsupportedAppUsage
private void requestLocationUpdates(LocationRequest request, LocationListener listener,
Looper looper, PendingIntent intent) {
@@ -2328,6 +2331,7 @@
*
* @hide
*/
+ @UnsupportedAppUsage
public boolean sendNiResponse(int notifId, int userResponse) {
try {
return mService.sendNiResponse(notifId, userResponse);
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 96a0817..2d7f7e3 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -17,6 +17,7 @@
package android.location;
import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -141,16 +142,26 @@
*/
private static final double FASTEST_INTERVAL_FACTOR = 6.0; // 6x
+ @UnsupportedAppUsage
private int mQuality = POWER_LOW;
+ @UnsupportedAppUsage
private long mInterval = 60 * 60 * 1000; // 60 minutes
+ @UnsupportedAppUsage
private long mFastestInterval = (long) (mInterval / FASTEST_INTERVAL_FACTOR); // 10 minutes
+ @UnsupportedAppUsage
private boolean mExplicitFastestInterval = false;
+ @UnsupportedAppUsage
private long mExpireAt = Long.MAX_VALUE; // no expiry
+ @UnsupportedAppUsage
private int mNumUpdates = Integer.MAX_VALUE; // no expiry
+ @UnsupportedAppUsage
private float mSmallestDisplacement = 0.0f; // meters
+ @UnsupportedAppUsage
private WorkSource mWorkSource = null;
+ @UnsupportedAppUsage
private boolean mHideFromAppOps = false; // True if this request shouldn't be counted by AppOps
+ @UnsupportedAppUsage
private String mProvider = LocationManager.FUSED_PROVIDER;
// for deprecated APIs that explicitly request a provider
@@ -592,12 +603,14 @@
return mHideFromAppOps;
}
+ @UnsupportedAppUsage
private static void checkInterval(long millis) {
if (millis < 0) {
throw new IllegalArgumentException("invalid interval: " + millis);
}
}
+ @UnsupportedAppUsage
private static void checkQuality(int quality) {
switch (quality) {
case ACCURACY_FINE:
@@ -612,12 +625,14 @@
}
}
+ @UnsupportedAppUsage
private static void checkDisplacement(float meters) {
if (meters < 0.0f) {
throw new IllegalArgumentException("invalid displacement: " + meters);
}
}
+ @UnsupportedAppUsage
private static void checkProvider(String name) {
if (name == null) {
throw new IllegalArgumentException("invalid provider: " + name);
diff --git a/media/java/android/mtp/MtpPropertyList.java b/media/java/android/mtp/MtpPropertyList.java
index ede90da..557f099 100644
--- a/media/java/android/mtp/MtpPropertyList.java
+++ b/media/java/android/mtp/MtpPropertyList.java
@@ -16,6 +16,7 @@
package android.mtp;
+import android.annotation.UnsupportedAppUsage;
import java.util.ArrayList;
import java.util.List;
@@ -49,6 +50,7 @@
mStringValues = new ArrayList<>();
}
+ @UnsupportedAppUsage
public void append(int handle, int property, int type, long value) {
mObjectHandles.add(handle);
mPropertyCodes.add(property);
@@ -57,6 +59,7 @@
mStringValues.add(null);
}
+ @UnsupportedAppUsage
public void append(int handle, int property, String value) {
mObjectHandles.add(handle);
mPropertyCodes.add(property);
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 2625e0c..c714b3c 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -16,6 +16,7 @@
package android.mtp;
+import android.annotation.UnsupportedAppUsage;
import android.os.storage.StorageVolume;
/**
@@ -46,6 +47,7 @@
*
* @return the storage ID
*/
+ @UnsupportedAppUsage
public final int getStorageId() {
return mStorageId;
}
@@ -55,6 +57,7 @@
*
* @return the storage file path
*/
+ @UnsupportedAppUsage
public final String getPath() {
return mPath;
}
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index 53ec6c8..728e6e1 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -18,6 +18,7 @@
package android.opengl;
+import android.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
import android.view.Surface;
import android.view.SurfaceView;
@@ -163,6 +164,7 @@
/**
* {@hide}
*/
+ @UnsupportedAppUsage
public static native EGLDisplay eglGetDisplay(
long display_id
);
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index 137f2f5..d66e7ac 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -19,6 +19,8 @@
package android.opengl;
+import android.annotation.UnsupportedAppUsage;
+
/** OpenGL ES 2.0
*/
public class GLES20 {
@@ -824,6 +826,7 @@
// C function void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
/** @hide Method is broken, but used to be public (b/6006380) */
+ @UnsupportedAppUsage
public static native void glGetActiveAttrib(
int program,
int index,
@@ -872,6 +875,7 @@
// C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
/** @hide Method is broken, but used to be public (b/6006380) */
+ @UnsupportedAppUsage
public static native void glGetActiveUniform(
int program,
int index,
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 0f0a7e9d..8a3e6a0 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -16,6 +16,7 @@
package android.opengl;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Trace;
import android.util.AttributeSet;
@@ -1235,6 +1236,7 @@
EGLDisplay mEglDisplay;
EGLSurface mEglSurface;
EGLConfig mEglConfig;
+ @UnsupportedAppUsage
EGLContext mEglContext;
}
@@ -1844,6 +1846,7 @@
// End of member variables protected by the sGLThreadManager monitor.
+ @UnsupportedAppUsage
private EglHelper mEglHelper;
/**
@@ -1919,7 +1922,9 @@
private final WeakReference<GLSurfaceView> mThisWeakRef =
new WeakReference<GLSurfaceView>(this);
+ @UnsupportedAppUsage
private GLThread mGLThread;
+ @UnsupportedAppUsage
private Renderer mRenderer;
private boolean mDetached;
private EGLConfigChooser mEGLConfigChooser;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index 01df0ec..dddfa7a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -102,17 +102,4 @@
private boolean isRectZero(Rect r) {
return r.left == 0 && r.top == 0 && r.right == 0 && r.bottom == 0;
}
-
- @Test
- public void testPlusPaint_isEqualToBoltPaint() {
- // Before setting color
- assertTrue(mBatteryDrawable.mPlusPaint.hasEqualAttributes(mBatteryDrawable.mBoltPaint));
-
- final int fakeFillColor = 123;
- final int fakeBackgrundColor = 456;
-
- // After
- mBatteryDrawable.setColors(fakeFillColor, fakeBackgrundColor);
- assertTrue(mBatteryDrawable.mPlusPaint.hasEqualAttributes(mBatteryDrawable.mBoltPaint));
- }
}
diff --git a/packages/SystemUI/docs/plugin_hooks.md b/packages/SystemUI/docs/plugin_hooks.md
index 5b08bfc..9fe2e18 100644
--- a/packages/SystemUI/docs/plugin_hooks.md
+++ b/packages/SystemUI/docs/plugin_hooks.md
@@ -51,6 +51,10 @@
Use: Control over swipes/input for notification views, can be used to control what happens when you swipe/long-press
+### Action: com.android.systemui.action.PLUGIN_CLOCK
+Expected interface: [ClockPlugin](/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java)
+
+Use: Allows replacement of the keyguard main clock.
# Global plugin dependencies
These classes can be accessed by any plugin using PluginDependency as long as they @Requires them.
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
new file mode 100644
index 0000000..b4fc820
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.systemui.plugins;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+import android.graphics.Paint.Style;
+import android.view.View;
+
+/**
+ * This plugin is used to replace main clock in keyguard.
+ */
+@ProvidesInterface(action = ClockPlugin.ACTION, version = ClockPlugin.VERSION)
+public interface ClockPlugin extends Plugin {
+
+ String ACTION = "com.android.systemui.action.PLUGIN_CLOCK";
+ int VERSION = 1;
+
+ /**
+ * Get clock view.
+ * @return clock view from plugin.
+ */
+ View getView();
+
+ /**
+ * Set clock paint style.
+ * @param style The new style to set in the paint.
+ */
+ void setStyle(Style style);
+
+ /**
+ * Set clock text color.
+ * @param color A color value.
+ */
+ void setTextColor(int color);
+}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
new file mode 100644
index 0000000..89b873e
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, 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.
+*/
+-->
+
+<!-- This is a view that shows clock information in Keyguard. -->
+<com.android.keyguard.KeyguardClockSwitch
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_alignParentTop="true">
+ <TextClock
+ android:id="@+id/default_clock_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:letterSpacing="0.03"
+ android:textColor="?attr/wallpaperTextColor"
+ android:singleLine="true"
+ style="@style/widget_big_thin"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format" />
+</com.android.keyguard.KeyguardClockSwitch>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
index 87983b9..a795442 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
@@ -38,19 +38,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top">
- <TextClock
- android:id="@+id/clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_centerHorizontal="true"
- android:layout_alignParentTop="true"
- android:letterSpacing="0.03"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big_thin"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format" />
+ <include layout="@layout/keyguard_clock_switch"
+ android:id="@+id/clock_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
<View
android:id="@+id/clock_separator"
android:layout_width="@dimen/widget_separator_width"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index ba05ccf..4ae2d41 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -55,19 +55,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top">
- <TextClock
- android:id="@+id/clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_centerHorizontal="true"
- android:layout_alignParentTop="true"
- android:letterSpacing="0.03"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big_thin"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format" />
+ <include layout="@layout/keyguard_clock_switch"
+ android:id="@+id/clock_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
<View
android:id="@+id/clock_separator"
android:layout_width="@dimen/widget_separator_width"
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index baaf699..d72021e 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -18,14 +18,16 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/rounded_corner_content_padding"
+ android:layout_marginEnd="@dimen/rounded_corner_content_padding"
+ android:paddingStart="@dimen/nav_content_padding"
+ android:paddingEnd="@dimen/nav_content_padding">
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingStart="@dimen/rounded_corner_content_padding"
- android:paddingEnd="@dimen/rounded_corner_content_padding"
android:clipChildren="false"
android:clipToPadding="false">
@@ -34,8 +36,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
- android:paddingStart="@dimen/nav_content_padding"
- android:paddingEnd="@dimen/nav_content_padding"
android:clipToPadding="false"
android:clipChildren="false" />
@@ -46,8 +46,6 @@
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
- android:paddingStart="@dimen/nav_content_padding"
- android:paddingEnd="@dimen/nav_content_padding"
android:clipToPadding="false"
android:clipChildren="false" />
diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
index 6d5b7788..24a0c71 100644
--- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
@@ -18,14 +18,16 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/rounded_corner_content_padding"
+ android:layout_marginBottom="@dimen/rounded_corner_content_padding"
+ android:paddingTop="@dimen/nav_content_padding"
+ android:paddingBottom="@dimen/nav_content_padding">
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="@dimen/rounded_corner_content_padding"
- android:paddingBottom="@dimen/rounded_corner_content_padding"
android:clipChildren="false"
android:clipToPadding="false">
@@ -34,10 +36,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:paddingTop="@dimen/nav_content_padding"
- android:paddingBottom="@dimen/nav_content_padding"
- android:clipChildren="false"
- android:clipToPadding="false" />
+ android:clipToPadding="false"
+ android:clipChildren="false" />
<com.android.systemui.statusbar.phone.ReverseLinearLayout
android:id="@+id/center_group"
@@ -45,10 +45,8 @@
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
- android:paddingTop="@dimen/nav_content_padding"
- android:paddingBottom="@dimen/nav_content_padding"
- android:clipChildren="false"
- android:clipToPadding="false" />
+ android:clipToPadding="false"
+ android:clipChildren="false" />
</com.android.systemui.statusbar.phone.NearestTouchFrame>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
new file mode 100644
index 0000000..5bbbc52
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -0,0 +1,155 @@
+package com.android.keyguard;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.TextClock;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+
+/**
+ * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
+ */
+public class KeyguardClockSwitch extends FrameLayout {
+ /**
+ * Optional/alternative clock injected via plugin.
+ */
+ private ClockPlugin mClockPlugin;
+ /**
+ * Default clock.
+ */
+ private TextClock mClockView;
+
+ private final PluginListener<ClockPlugin> mClockPluginListener =
+ new PluginListener<ClockPlugin>() {
+ @Override
+ public void onPluginConnected(ClockPlugin plugin, Context pluginContext) {
+ View view = plugin.getView();
+ if (view != null) {
+ mClockPlugin = plugin;
+ addView(view, -1,
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ initPluginParams();
+ mClockView.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onPluginDisconnected(ClockPlugin plugin) {
+ View view = plugin.getView();
+ if (view != null) {
+ mClockPlugin = null;
+ removeView(view);
+ mClockView.setVisibility(View.VISIBLE);
+ }
+ }
+ };
+
+ public KeyguardClockSwitch(Context context) {
+ this(context, null);
+ }
+
+ public KeyguardClockSwitch(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mClockView = findViewById(R.id.default_clock_view);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ Dependency.get(PluginManager.class).addPluginListener(mClockPluginListener,
+ ClockPlugin.class);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ Dependency.get(PluginManager.class).removePluginListener(mClockPluginListener);
+ }
+
+ /**
+ * It will also update plugin setStyle if plugin is connected.
+ */
+ public void setStyle(Style style) {
+ mClockView.getPaint().setStyle(style);
+ if (mClockPlugin != null) {
+ mClockPlugin.setStyle(style);
+ }
+ }
+
+ /**
+ * It will also update plugin setTextColor if plugin is connected.
+ */
+ public void setTextColor(int color) {
+ mClockView.setTextColor(color);
+ if (mClockPlugin != null) {
+ mClockPlugin.setTextColor(color);
+ }
+ }
+
+ public void setShowCurrentUserTime(boolean showCurrentUserTime) {
+ mClockView.setShowCurrentUserTime(showCurrentUserTime);
+ }
+
+ public void setElegantTextHeight(boolean elegant) {
+ mClockView.setElegantTextHeight(elegant);
+ }
+
+ public void setTextSize(int unit, float size) {
+ mClockView.setTextSize(unit, size);
+ }
+
+ public void setFormat12Hour(CharSequence format) {
+ mClockView.setFormat12Hour(format);
+ }
+
+ public void setFormat24Hour(CharSequence format) {
+ mClockView.setFormat24Hour(format);
+ }
+
+ public Paint getPaint() {
+ return mClockView.getPaint();
+ }
+
+ public int getCurrentTextColor() {
+ return mClockView.getCurrentTextColor();
+ }
+
+ public float getTextSize() {
+ return mClockView.getTextSize();
+ }
+
+ public void refresh() {
+ mClockView.refresh();
+ }
+
+ /**
+ * When plugin changes, set all kept parameters into newer plugin.
+ */
+ private void initPluginParams() {
+ if (mClockPlugin != null) {
+ mClockPlugin.setStyle(getPaint().getStyle());
+ mClockPlugin.setTextColor(getCurrentTextColor());
+ }
+ }
+
+ @VisibleForTesting (otherwise = VisibleForTesting.NONE)
+ PluginListener getClockPluginListener() {
+ return mClockPluginListener;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 6da143c..6d1313c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -39,7 +39,6 @@
import android.view.View;
import android.widget.GridLayout;
import android.widget.RelativeLayout;
-import android.widget.TextClock;
import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
@@ -64,7 +63,7 @@
private final float mSmallClockScale;
private TextView mLogoutView;
- private TextClock mClockView;
+ private KeyguardClockSwitch mClockView;
private View mClockSeparator;
private TextView mOwnerInfo;
private KeyguardSliceView mKeyguardSlice;
@@ -248,7 +247,7 @@
.scaleX(clockScale)
.scaleY(clockScale)
.withEndAction(() -> {
- mClockView.getPaint().setStyle(style);
+ mClockView.setStyle(style);
mClockView.invalidate();
})
.start();
@@ -256,7 +255,7 @@
mClockView.setY(top);
mClockView.setScaleX(clockScale);
mClockView.setScaleY(clockScale);
- mClockView.getPaint().setStyle(style);
+ mClockView.setStyle(style);
mClockView.invalidate();
}
} else if (view == mClockSeparator) {
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 3c44eb4..0864ff0 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -55,6 +55,7 @@
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
/**
@@ -69,6 +70,10 @@
private static final long BACKOFF_MILLIS = 1000;
private static final long DEFERRED_CALLBACK_MILLIS = 5000;
+ // Default interaction flags if swipe up is disabled before connecting to launcher
+ private static final int DEFAULT_DISABLE_SWIPE_UP_STATE = FLAG_DISABLE_SWIPE_UP
+ | FLAG_SHOW_OVERVIEW_BUTTON;
+
private final Context mContext;
private final Handler mHandler;
private final Runnable mConnectionRunnable = this::internalConnectToCurrentUser;
@@ -220,7 +225,7 @@
// When launcher service is disabled, reset interaction flags because it is inactive
if (!isEnabled()) {
- mInteractionFlags = 0;
+ mInteractionFlags = getDefaultInteractionFlags();
Prefs.remove(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS);
}
@@ -300,7 +305,8 @@
com.android.internal.R.string.config_recentsComponentName));
mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(mRecentsComponentName.getPackageName());
- mInteractionFlags = Prefs.getInt(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS, 0);
+ mInteractionFlags = Prefs.getInt(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS,
+ getDefaultInteractionFlags());
// Listen for the package update changes.
if (SystemServicesProxy.getInstance(context)
@@ -397,6 +403,15 @@
}
}
+ private int getDefaultInteractionFlags() {
+ // If there is no settings available use device default or get it from settings
+ final boolean defaultState = getSwipeUpDefaultValue();
+ final boolean swipeUpEnabled = getSwipeUpSettingAvailable()
+ ? getSwipeUpEnabledFromSettings(defaultState)
+ : defaultState;
+ return swipeUpEnabled ? 0 : DEFAULT_DISABLE_SWIPE_UP_STATE;
+ }
+
private void notifyBackButtonAlphaChanged(float alpha, boolean animate) {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
mConnectionCallbacks.get(i).onBackButtonAlphaChanged(alpha, animate);
@@ -427,6 +442,21 @@
ActivityManagerWrapper.getInstance().getCurrentUserId()) != null;
}
+ private boolean getSwipeUpDefaultValue() {
+ return mContext.getResources()
+ .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default);
+ }
+
+ private boolean getSwipeUpSettingAvailable() {
+ return mContext.getResources()
+ .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_setting_available);
+ }
+
+ private boolean getSwipeUpEnabledFromSettings(boolean defaultValue) {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultValue ? 1 : 0) == 1;
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(TAG_OPS + " state:");
@@ -440,12 +470,10 @@
pw.print(" quickStepIntent="); pw.println(mQuickStepIntent);
pw.print(" quickStepIntentResolved="); pw.println(isEnabled());
- final int swipeUpDefaultValue = mContext.getResources()
- .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default) ? 1 : 0;
- final int swipeUpEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, swipeUpDefaultValue);
- pw.print(" swipeUpSetting="); pw.println(swipeUpEnabled != 0);
- pw.print(" swipeUpSettingDefault="); pw.println(swipeUpDefaultValue != 0);
+ final boolean swipeUpDefaultValue = getSwipeUpDefaultValue();
+ final boolean swipeUpEnabled = getSwipeUpEnabledFromSettings(swipeUpDefaultValue);
+ pw.print(" swipeUpSetting="); pw.println(swipeUpEnabled);
+ pw.print(" swipeUpSettingDefault="); pw.println(swipeUpDefaultValue);
}
public interface OverviewProxyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index fe8ea34..c96aa73 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -45,6 +45,7 @@
import java.util.Locale;
import java.util.concurrent.TimeUnit;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
import androidx.slice.builders.ListBuilder;
@@ -127,8 +128,8 @@
@Override
public Slice onBindSlice(Uri sliceUri) {
- ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
- builder.addRow(new RowBuilder(builder, mDateUri).setTitle(mLastText));
+ ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);
+ builder.addRow(new RowBuilder(mDateUri).setTitle(mLastText));
addNextAlarm(builder);
addZenMode(builder);
addPrimaryAction(builder);
@@ -139,11 +140,13 @@
// Add simple action because API requires it; Keyguard handles presenting
// its own slices so this action + icon are actually never used.
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
- Icon icon = Icon.createWithResource(getContext(), R.drawable.ic_access_alarms_big);
- SliceAction action = new SliceAction(pi, icon, mLastText);
+ IconCompat icon = IconCompat.createWithResource(getContext(),
+ R.drawable.ic_access_alarms_big);
+ SliceAction action = SliceAction.createDeeplink(pi, icon,
+ ListBuilder.ICON_IMAGE, mLastText);
- RowBuilder primaryActionRow = new RowBuilder(builder, Uri.parse(KEYGUARD_ACTION_URI))
- .setPrimaryAction(action);
+ RowBuilder primaryActionRow = new RowBuilder(Uri.parse(KEYGUARD_ACTION_URI))
+ .setPrimaryAction(action);
builder.addRow(primaryActionRow);
}
@@ -152,10 +155,11 @@
return;
}
- Icon alarmIcon = Icon.createWithResource(getContext(), R.drawable.ic_access_alarms_big);
- RowBuilder alarmRowBuilder = new RowBuilder(builder, mAlarmUri)
+ IconCompat alarmIcon = IconCompat.createWithResource(getContext(),
+ R.drawable.ic_access_alarms_big);
+ RowBuilder alarmRowBuilder = new RowBuilder(mAlarmUri)
.setTitle(mNextAlarm)
- .addEndItem(alarmIcon);
+ .addEndItem(alarmIcon, ListBuilder.ICON_IMAGE);
builder.addRow(alarmRowBuilder);
}
@@ -167,10 +171,11 @@
if (!isDndSuppressingNotifications()) {
return;
}
- RowBuilder dndBuilder = new RowBuilder(builder, mDndUri)
+ RowBuilder dndBuilder = new RowBuilder(mDndUri)
.setContentDescription(getContext().getResources()
.getString(R.string.accessibility_quick_settings_dnd))
- .addEndItem(Icon.createWithResource(getContext(), R.drawable.stat_sys_dnd));
+ .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.stat_sys_dnd),
+ ListBuilder.ICON_IMAGE);
builder.addRow(dndBuilder);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index af0ed284..506d697 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -40,7 +40,6 @@
private final int mShortAnimDuration;
private final StatusBar mStatusBar;
private final UserManagerHelper mUserManagerHelper;
- private int mCurrentForegroundUserId;
private boolean mShowing;
public FullscreenUserSwitcher(StatusBar statusBar, ViewStub containerStub, Context context) {
@@ -55,7 +54,6 @@
mUserGridView.setUserSelectionListener(this::onUserSelected);
mUserManagerHelper = new UserManagerHelper(context);
- updateCurrentForegroundUser();
mShortAnimDuration = mContainer.getResources()
.getInteger(android.R.integer.config_shortAnimTime);
@@ -78,22 +76,8 @@
}
public void onUserSwitched(int newUserId) {
- // The logic for foreground user change is needed here to exclude the reboot case. On
- // reboot, system fires ACTION_USER_SWITCHED change from -1 to 0 user. This is not an actual
- // user switch. We only want to trigger keyguard dismissal when foreground user changes.
- if (foregroundUserChanged()) {
- toggleSwitchInProgress(false);
- updateCurrentForegroundUser();
- mParent.post(this::dismissKeyguard);
- }
- }
-
- private boolean foregroundUserChanged() {
- return mCurrentForegroundUserId != mUserManagerHelper.getForegroundUserId();
- }
-
- private void updateCurrentForegroundUser() {
- mCurrentForegroundUserId = mUserManagerHelper.getForegroundUserId();
+ toggleSwitchInProgress(false);
+ mParent.post(this::dismissKeyguard);
}
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 8f552e3..92a9efe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -40,6 +40,8 @@
public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
public static final boolean FORCE_NO_BLANKING =
SystemProperties.getBoolean("debug.force_no_blanking", false);
+ public static final boolean FORCE_BLANKING =
+ SystemProperties.getBoolean("debug.force_blanking", false);
private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
private static DozeParameters sInstance;
@@ -183,7 +185,7 @@
* @return {@code true} if screen needs to be completely black before a power transition.
*/
public boolean getDisplayNeedsBlanking() {
- return !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
+ return FORCE_BLANKING || !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
com.android.internal.R.bool.config_displayBlanksAfterDoze);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index b80cd30..042e4ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -103,9 +103,9 @@
private float mDarkAmount;
/**
- * If keyguard will just fade away or will require a password.
+ * If keyguard will require a password or just fade away.
*/
- private boolean mFadeAway;
+ private boolean mCurrentlySecure;
/**
* Dozing and receiving a notification (AOD notification.)
@@ -135,7 +135,7 @@
public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
float panelExpansion, int parentHeight,
- int keyguardStatusHeight, float dark, boolean fadeAway, boolean pulsing,
+ int keyguardStatusHeight, float dark, boolean secure, boolean pulsing,
int bouncerTop) {
mMinTopMargin = minTopMargin + mContainerTopPadding;
mMaxShadeBottom = maxShadeBottom;
@@ -144,7 +144,7 @@
mHeight = parentHeight;
mKeyguardStatusHeight = keyguardStatusHeight;
mDarkAmount = dark;
- mFadeAway = fadeAway;
+ mCurrentlySecure = secure;
mPulsing = pulsing;
mBouncerTop = bouncerTop;
}
@@ -198,7 +198,7 @@
float clockYRegular = getExpandedClockPosition();
boolean hasEnoughSpace = mMinTopMargin + mKeyguardStatusHeight < mBouncerTop;
- float clockYTarget = !mFadeAway && hasEnoughSpace ?
+ float clockYTarget = mCurrentlySecure && hasEnoughSpace ?
mMinTopMargin : -mKeyguardStatusHeight;
// Move clock up while collapsing the shade
@@ -218,11 +218,11 @@
*/
private float getClockAlpha(int y) {
float alphaKeyguard;
- if (mFadeAway) {
+ if (mCurrentlySecure) {
+ alphaKeyguard = 1;
+ } else {
alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedClockPosition()));
alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
- } else {
- alphaKeyguard = 1;
}
return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 7db5802..7476963 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -92,6 +92,21 @@
private static final boolean DEBUG = false;
+ /**
+ * Fling expanding QS.
+ */
+ public static final int FLING_EXPAND = 0;
+
+ /**
+ * Fling collapsing QS, potentially stopping when QS becomes QQS.
+ */
+ public static final int FLING_COLLAPSE = 1;
+
+ /**
+ * Fing until QS is completely hidden.
+ */
+ public static final int FLING_HIDE = 2;
+
// Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
// changed.
private static final int CAP_HEIGHT = 1456;
@@ -524,8 +539,7 @@
totalHeight,
mKeyguardStatusView.getHeight(),
mInterpolatedDarkAmount,
- !mStatusBar.isKeyguardCurrentlySecure()
- || mStatusBar.isKeyguardOccludeAnimationRunning(),
+ mStatusBar.isKeyguardCurrentlySecure(),
mPulsing,
mBouncerTop);
mClockPositionAlgorithm.run(mClockPositionResult);
@@ -624,7 +638,7 @@
}
@Override
- public void resetViews() {
+ public void resetViews(boolean animate) {
mIsLaunchTransitionFinished = false;
mBlockTouches = false;
mUnlockIconActive = false;
@@ -632,11 +646,15 @@
mAffordanceHelper.reset(false);
mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
}
- closeQs();
mStatusBar.getGutsManager().closeAndSaveGuts(true /* leavebehind */, true /* force */,
true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
- mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, false /* animate */,
- true /* cancelAnimators */);
+ if (animate) {
+ animateCloseQs(true /* animateAway */);
+ } else {
+ closeQs();
+ }
+ mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, animate,
+ !animate /* cancelAnimators */);
mNotificationStackScroller.resetScrollPosition();
}
@@ -658,7 +676,13 @@
setQsExpansion(mQsMinExpansionHeight);
}
- public void animateCloseQs() {
+ /**
+ * Animate QS closing by flinging it.
+ * If QS is expanded, it will collapse into QQS and stop.
+ *
+ * @param animateAway Do not stop when QS becomes QQS. Fling until QS isn't visible anymore.
+ */
+ public void animateCloseQs(boolean animateAway) {
if (mQsExpansionAnimator != null) {
if (!mQsAnimatorExpand) {
return;
@@ -667,14 +691,7 @@
mQsExpansionAnimator.cancel();
setQsExpansion(height);
}
- flingSettings(0 /* vel */, false);
- }
-
- public void openQs() {
- cancelQsAnimation();
- if (mQsExpansionEnabled) {
- setQsExpansion(mQsMaxExpansionHeight);
- }
+ flingSettings(0 /* vel */, animateAway ? FLING_HIDE : FLING_COLLAPSE);
}
public void expandWithQs() {
@@ -687,7 +704,7 @@
public void expandWithoutQs() {
if (isQsExpanded()) {
- flingSettings(0 /* velocity */, false /* expand */);
+ flingSettings(0 /* velocity */, FLING_COLLAPSE);
} else {
expand(true /* animate */);
}
@@ -831,7 +848,7 @@
if (expandsQs) {
logQsSwipeDown(y);
}
- flingSettings(vel, expandsQs && !isCancelMotionEvent);
+ flingSettings(vel, expandsQs && !isCancelMotionEvent ? FLING_EXPAND : FLING_COLLAPSE);
}
private void logQsSwipeDown(float y) {
@@ -1100,7 +1117,8 @@
mLastOverscroll = 0f;
mQsExpansionFromOverscroll = false;
setQsExpansion(mQsExpansionHeight);
- flingSettings(!mQsExpansionEnabled && open ? 0f : velocity, open && mQsExpansionEnabled,
+ flingSettings(!mQsExpansionEnabled && open ? 0f : velocity,
+ open && mQsExpansionEnabled ? FLING_EXPAND : FLING_COLLAPSE,
new Runnable() {
@Override
public void run() {
@@ -1467,13 +1485,35 @@
}
}
- public void flingSettings(float vel, boolean expand) {
- flingSettings(vel, expand, null, false /* isClick */);
+ /**
+ * @see #flingSettings(float, int, Runnable, boolean)
+ */
+ public void flingSettings(float vel, int type) {
+ flingSettings(vel, type, null, false /* isClick */);
}
- protected void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable,
+ /**
+ * Animates QS or QQS as if the user had swiped up or down.
+ *
+ * @param vel Finger velocity or 0 when not initiated by touch events.
+ * @param type Either {@link #FLING_EXPAND}, {@link #FLING_COLLAPSE} or {@link #FLING_HIDE}.
+ * @param onFinishRunnable Runnable to be executed at the end of animation.
+ * @param isClick If originated by click (different interpolator and duration.)
+ */
+ protected void flingSettings(float vel, int type, final Runnable onFinishRunnable,
boolean isClick) {
- float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
+ float target;
+ switch (type) {
+ case FLING_EXPAND:
+ target = mQsMaxExpansionHeight;
+ break;
+ case FLING_COLLAPSE:
+ target = mQsMinExpansionHeight;
+ break;
+ case FLING_HIDE:
+ default:
+ target = 0;
+ }
if (target == mQsExpansionHeight) {
if (onFinishRunnable != null) {
onFinishRunnable.run();
@@ -1483,7 +1523,8 @@
// If we move in the opposite direction, reset velocity and use a different duration.
boolean oppositeDirection = false;
- if (vel > 0 && !expand || vel < 0 && expand) {
+ boolean expanding = type == FLING_EXPAND;
+ if (vel > 0 && !expanding || vel < 0 && expanding) {
vel = 0;
oppositeDirection = true;
}
@@ -1497,11 +1538,8 @@
if (oppositeDirection) {
animator.setDuration(350);
}
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- setQsExpansion((Float) animation.getAnimatedValue());
- }
+ animator.addUpdateListener(animation -> {
+ setQsExpansion((Float) animation.getAnimatedValue());
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -1515,7 +1553,7 @@
});
animator.start();
mQsExpansionAnimator = animator;
- mQsAnimatorExpand = expand;
+ mQsAnimatorExpand = expanding;
}
/**
@@ -2001,10 +2039,12 @@
public void onClick(View v) {
onQsExpansionStarted();
if (mQsExpanded) {
- flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */);
+ flingSettings(0 /* vel */, FLING_COLLAPSE, null /* onFinishRunnable */,
+ true /* isClick */);
} else if (mQsExpansionEnabled) {
mLockscreenGestureLogger.write(MetricsEvent.ACTION_SHADE_QS_TAP, 0, 0);
- flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */);
+ flingSettings(0 /* vel */, FLING_EXPAND, null /* onFinishRunnable */,
+ true /* isClick */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 5d23494..deac669e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -194,7 +194,7 @@
pv.collapse(delayed, speedUpFactor);
waiting = true;
} else {
- pv.resetViews();
+ pv.resetViews(false /* animate */);
pv.setExpandedFraction(0); // just in case
pv.cancelPeek();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index e4eeec1..1f09835 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -1240,7 +1240,7 @@
));
}
- public abstract void resetViews();
+ public abstract void resetViews(boolean animate);
protected abstract float getPeekHeight();
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index dd4ea3d..3c351ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -322,8 +322,6 @@
public static final int FADE_KEYGUARD_START_DELAY = 100;
public static final int FADE_KEYGUARD_DURATION = 300;
public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
- public static final int FADE_BACKDROP_DURATION = 300;
- public static final int FADE_BACKDROP_DURATION_FAST = 240;
/** If true, the system is in the half-boot-to-decryption-screen state.
* Prudently disable QS and notifications. */
@@ -545,7 +543,6 @@
private boolean mIsOccluded;
private boolean mWereIconsJustHidden;
private boolean mBouncerWasShowingWhenHidden;
- private boolean mKeyguardOccludeAnimationRunning;
// Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
// this animation is tied to the scrim for historic reasons.
@@ -1644,7 +1641,7 @@
boolean wakeAndUnlock = mBiometricUnlockController != null
&& mBiometricUnlockController.isWakeAndUnlock();
- if (mLaunchTransitionFadingAway && !mIsOccluded || wakeAndUnlock) {
+ if (mLaunchTransitionFadingAway || wakeAndUnlock) {
mBackdrop.setVisibility(View.INVISIBLE);
Trace.endSection();
return;
@@ -1763,8 +1760,7 @@
boolean cannotAnimateDoze = mDozing && !ScrimState.AOD.getAnimateChange();
if (mBiometricUnlockController.getMode()
== BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
- || hideBecauseOccluded && !mKeyguardOccludeAnimationRunning
- || cannotAnimateDoze) {
+ || hideBecauseOccluded || cannotAnimateDoze) {
// We are unlocking directly - no animation!
mBackdrop.setVisibility(View.GONE);
@@ -1775,9 +1771,7 @@
mBackdrop.animate()
.alpha(SRC_MIN_ALPHA)
.setInterpolator(Interpolators.ACCELERATE_DECELERATE)
- .setDuration(
- mKeyguardOccludeAnimationRunning
- ? FADE_BACKDROP_DURATION_FAST : FADE_BACKDROP_DURATION)
+ .setDuration(300)
.setStartDelay(0)
.withEndAction(() -> {
mBackdrop.setVisibility(View.GONE);
@@ -2245,7 +2239,8 @@
mNotificationPanel.expand(true /* animate */);
mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1);
} else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){
- mNotificationPanel.flingSettings(0 /* velocity */, true /* expand */);
+ mNotificationPanel.flingSettings(0 /* velocity */,
+ NotificationPanelView.FLING_EXPAND);
mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
}
}
@@ -3674,27 +3669,6 @@
}
/**
- * Is keyguard being occluded by a newly launched activity.
- */
- public boolean isKeyguardOccludeAnimationRunning() {
- return mKeyguardOccludeAnimationRunning;
- }
-
- /**
- * Plays the animation when new activity is launched over keyguard.
- */
- public void animateKeyguardOccluding() {
- mKeyguardOccludeAnimationRunning = true;
- addPostCollapseAction(() -> {
- mStatusBarKeyguardViewManager.reset(true /* hideBouncerWhenShowing */);
- mKeyguardOccludeAnimationRunning = false;
- });
- mStatusBarKeyguardViewManager.animateCollapsePanels(1.0f /* speedfactor */);
- updateScrimController();
- updateMediaMetaData(false /* metaDataChanged */, true /* allowEnterAnimation */);
- }
-
- /**
* Plays the animation when an activity that was occluding Keyguard goes away.
*/
public void animateKeyguardUnoccluding() {
@@ -3716,7 +3690,7 @@
Log.w(TAG, "Launch transition: Timeout!");
mNotificationPanel.onAffordanceLaunchEnded();
releaseGestureWakeLock();
- mNotificationPanel.resetViews();
+ mNotificationPanel.resetViews(false /* animate */);
}
private void runLaunchTransitionEndRunnable() {
@@ -3869,7 +3843,9 @@
Trace.beginSection("StatusBar#updateKeyguardState");
if (mState == StatusBarState.KEYGUARD) {
mKeyguardIndicationController.setVisible(true);
- mNotificationPanel.resetViews();
+ boolean dozingAnimated = mDozingRequested
+ && DozeParameters.getInstance(mContext).shouldControlScreenOff();
+ mNotificationPanel.resetViews(dozingAnimated);
if (mKeyguardUserSwitcher != null) {
mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked);
}
@@ -4014,7 +3990,7 @@
if (mNotificationPanel.isQsDetailShowing()) {
mNotificationPanel.closeQsDetail();
} else {
- mNotificationPanel.animateCloseQs();
+ mNotificationPanel.animateCloseQs(false /* animateAway */);
}
return true;
}
@@ -4039,7 +4015,7 @@
private void showBouncerIfKeyguard() {
if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
- && !mKeyguardViewMediator.isHiding() && !mKeyguardOccludeAnimationRunning) {
+ && !mKeyguardViewMediator.isHiding()) {
showBouncer(true /* scrimmed */);
}
}
@@ -4539,11 +4515,6 @@
@Override
public void onStartedGoingToSleep() {
- // in case we start going to sleep while new animation is launching over keyguard, make
- // sure to finish it
- if (mKeyguardOccludeAnimationRunning) {
- runPostCollapseRunnables();
- }
notifyHeadsUpGoingToSleep();
dismissVolumeDialog();
}
@@ -4785,7 +4756,7 @@
? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
mScrimController.transitionTo(state);
} else if (isInLaunchTransition() || mLaunchCameraOnScreenTurningOn
- || launchingAffordanceWithPreview || mKeyguardOccludeAnimationRunning) {
+ || launchingAffordanceWithPreview) {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 97088bd..c4424d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -365,11 +365,6 @@
}
});
return;
- } else if (animate) {
- mOccluded = true;
- mStatusBar.animateKeyguardOccluding();
- mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
- return;
}
} else if (!occluded && mOccluded && mShowing) {
StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
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 f83fb43..a38328a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -144,8 +144,7 @@
state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
final boolean keyguardOrAod = state.keyguardShowing
|| (state.dozing && mDozeParameters.getAlwaysOn());
- if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper
- && !state.keyguardOccluded) {
+ if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
} else {
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 1bdb7ad..196d9bc 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -119,7 +119,9 @@
// 3 Removed because of a revert.
if (oldVersion < 4) {
// Delay this so that we can wait for everything to be registered first.
- new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(() -> clearAll(), 5000);
+ final int user = mCurrentUser;
+ new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(
+ () -> clearAllFromUser(user), 5000);
}
setValue(TUNER_VERSION, newVersion);
}
@@ -221,6 +223,10 @@
@Override
public void clearAll() {
+ clearAllFromUser(mCurrentUser);
+ }
+
+ public void clearAllFromUser(int user) {
// A couple special cases.
Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
Intent intent = new Intent(DemoMode.ACTION_DEMO);
@@ -231,7 +237,7 @@
if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
continue;
}
- Settings.Secure.putString(mContentResolver, key, null);
+ Settings.Secure.putStringForUser(mContentResolver, key, null, user);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
new file mode 100644
index 0000000..e6e4857
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Color;
+import android.graphics.Paint.Style;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.text.TextPaint;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.TextClock;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidTestingRunner.class)
+public class KeyguardClockSwitchTest extends SysuiTestCase {
+ private PluginManager mPluginManager;
+
+ @Mock
+ TextClock mClockView;
+ @InjectMocks
+ KeyguardClockSwitch mKeyguardClockSwitch;
+
+ @Before
+ public void setUp() {
+ mPluginManager = mDependency.injectMockDependency(PluginManager.class);
+ LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+ mKeyguardClockSwitch =
+ (KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void onAttachToWindow_addPluginListener() {
+ mKeyguardClockSwitch.onAttachedToWindow();
+
+ ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
+ verify(mPluginManager).addPluginListener(listener.capture(), eq(ClockPlugin.class));
+ }
+
+ @Test
+ public void onDetachToWindow_removePluginListener() {
+ mKeyguardClockSwitch.onDetachedFromWindow();
+
+ ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
+ verify(mPluginManager).removePluginListener(listener.capture());
+ }
+
+ @Test
+ public void onPluginConnected_showPluginClock() {
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getView()).thenReturn(pluginView);
+ TextPaint paint = mock(TextPaint.class);
+ doReturn(paint).when(mClockView).getPaint();
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+
+ listener.onPluginConnected(plugin, null);
+
+ verify(mClockView).setVisibility(GONE);
+ assertThat(plugin.getView().getParent()).isEqualTo(mKeyguardClockSwitch);
+ }
+
+ @Test
+ public void onPluginDisconnected_showDefaultClock() {
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getView()).thenReturn(pluginView);
+ mClockView.setVisibility(GONE);
+ mKeyguardClockSwitch.addView(plugin.getView(), -1,
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+
+ listener.onPluginDisconnected(plugin);
+
+ verify(mClockView).setVisibility(VISIBLE);
+ assertThat(plugin.getView().getParent()).isNull();
+ }
+
+ @Test
+ public void setTextColor_defaultClockSetTextColor() {
+ mKeyguardClockSwitch.setTextColor(Color.YELLOW);
+
+ verify(mClockView).setTextColor(Color.YELLOW);
+ }
+
+ @Test
+ public void setTextColor_pluginClockSetTextColor() {
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getView()).thenReturn(pluginView);
+ TextPaint paint = mock(TextPaint.class);
+ doReturn(paint).when(mClockView).getPaint();
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+ listener.onPluginConnected(plugin, null);
+
+ mKeyguardClockSwitch.setTextColor(Color.WHITE);
+
+ verify(plugin).setTextColor(Color.WHITE);
+ }
+
+ @Test
+ public void setStyle_defaultClockSetStyle() {
+ TextPaint paint = mock(TextPaint.class);
+ Style style = mock(Style.class);
+ doReturn(paint).when(mClockView).getPaint();
+
+ mKeyguardClockSwitch.setStyle(style);
+
+ verify(paint).setStyle(style);
+ }
+
+ @Test
+ public void setStyle_pluginClockSetStyle() {
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getView()).thenReturn(pluginView);
+ TextPaint paint = mock(TextPaint.class);
+ doReturn(paint).when(mClockView).getPaint();
+ Style style = mock(Style.class);
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+ listener.onPluginConnected(plugin, null);
+
+ mKeyguardClockSwitch.setStyle(style);
+
+ verify(plugin).setStyle(style);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index d2e8371..4ec30fd 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -55,7 +55,7 @@
@Test
public void showSlice_notifiesListener() {
- ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
+ ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);
AtomicBoolean notified = new AtomicBoolean();
mKeyguardSliceView.setContentChangeListener(()-> notified.set(true));
mKeyguardSliceView.onChanged(builder.build());
@@ -74,13 +74,11 @@
@Test
public void hasHeader_readsSliceData() {
- ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
+ ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);
mKeyguardSliceView.onChanged(builder.build());
Assert.assertFalse("View should not have a header", mKeyguardSliceView.hasHeader());
- builder.setHeader((ListBuilder.HeaderBuilder headerBuilder) -> {
- headerBuilder.setTitle("header title!");
- });
+ builder.setHeader(new ListBuilder.HeaderBuilder().setTitle("header title!"));
mKeyguardSliceView.onChanged(builder.build());
Assert.assertTrue("View should have a header", mKeyguardSliceView.hasHeader());
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
index 1d8de2f..9e96df2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
@@ -22,7 +22,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.LayoutInflater;
-import android.widget.TextClock;
import com.android.systemui.SysuiTestCase;
@@ -40,7 +39,7 @@
@Mock
KeyguardSliceView mKeyguardSlice;
@Mock
- TextClock mClockView;
+ KeyguardClockSwitch mClockView;
@InjectMocks
KeyguardStatusView mKeyguardStatusView;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 46e2bfb..a26b1b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -137,7 +137,8 @@
@Test
public void addZenMode_addedToSlice() {
- ListBuilder listBuilder = spy(new ListBuilder(getContext(), mProvider.getUri()));
+ ListBuilder listBuilder = spy(new ListBuilder(getContext(), mProvider.getUri(),
+ ListBuilder.INFINITY));
mProvider.addZenMode(listBuilder);
verify(listBuilder, never()).addRow(any(ListBuilder.RowBuilder.class));
diff --git a/packages/WAPPushManager/AndroidManifest.xml b/packages/WAPPushManager/AndroidManifest.xml
index 89e9d6a..14e6e91 100644
--- a/packages/WAPPushManager/AndroidManifest.xml
+++ b/packages/WAPPushManager/AndroidManifest.xml
@@ -24,7 +24,8 @@
android:protectionLevel="signatureOrSystem" />
<original-package android:name="com.android.smspush" />
- <application>
+ <application
+ android:allowClearUserData="false">
<service android:name=".WapPushManager"
android:permission="com.android.smspush.WAPPUSH_MANAGER_BIND"
android:exported="true">
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 6cc6221..f8b4d74 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -941,9 +941,10 @@
// OS: 6.0
NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
- // ACTION: App notification settings > Block Notifications
+ // ACTION: App notification settings > Block Notifications or long press on
+ // notification blocks.
// CATEGORY: SETTINGS
- // OS: 6.0
+ // OS: 9.0
ACTION_BAN_APP_NOTES = 147;
// ACTION: Notification shade > Dismiss all button
@@ -6425,6 +6426,10 @@
// OS: Q (will also ship in PQ1A)
FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH = 1553;
+ // OPEN: Settings > Add face
+ // OS: Q
+ FACE_ENROLL_PREVIEW = 1554;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index a40afc3..f7c1c10 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -136,7 +136,7 @@
CountDownLatch mLatch;
FullBackupJob mJob; // if a scheduled job needs to be finished afterwards
IBackupObserver mBackupObserver;
- IBackupManagerMonitor mMonitor;
+ @Nullable private IBackupManagerMonitor mMonitor;
boolean mUserInitiated;
SinglePackageBackupRunner mBackupRunner;
private final int mBackupRunnerOpToken;
@@ -154,7 +154,7 @@
IFullBackupRestoreObserver observer,
String[] whichPackages, boolean updateSchedule,
FullBackupJob runningJob, CountDownLatch latch, IBackupObserver backupObserver,
- IBackupManagerMonitor monitor, @Nullable OnTaskFinishedListener listener,
+ @Nullable IBackupManagerMonitor monitor, @Nullable OnTaskFinishedListener listener,
boolean userInitiated) {
super(observer);
this.backupManagerService = backupManagerService;
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
new file mode 100644
index 0000000..8c83e67
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.keyvalue;
+
+import android.annotation.Nullable;
+import android.app.backup.BackupManager;
+import android.app.backup.BackupManagerMonitor;
+import android.app.backup.BackupTransport;
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IBackupObserver;
+import android.content.pm.PackageInfo;
+import android.util.EventLog;
+import android.util.Slog;
+
+import com.android.server.EventLogTags;
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.DataChangedJournal;
+import com.android.server.backup.remote.RemoteResult;
+import com.android.server.backup.utils.BackupManagerMonitorUtils;
+import com.android.server.backup.utils.BackupObserverUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+/**
+ * Reports events that happen during a key-value backup task to:
+ *
+ * <ul>
+ * <li>Logcat (main and event buffers).
+ * <li>Backup observer (see {@link IBackupObserver}).
+ * <li>Backup manager monitor (see {@link IBackupManagerMonitor}).
+ * </ul>
+ */
+// TODO: In KeyValueBackupTaskTest, remove direct assertions on logcat, observer or monitor and
+// verify calls to this object. Add these and more assertions to the test of this class.
+class KeyValueBackupReporter {
+ private static final String TAG = "KeyValueBackupTask";
+ private static final boolean DEBUG = BackupManagerService.DEBUG;
+ private static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || true;
+
+ private final BackupManagerService mBackupManagerService;
+ private final IBackupObserver mObserver;
+ @Nullable private IBackupManagerMonitor mMonitor;
+
+ KeyValueBackupReporter(
+ BackupManagerService backupManagerService,
+ IBackupObserver observer,
+ IBackupManagerMonitor monitor) {
+ mBackupManagerService = backupManagerService;
+ mObserver = observer;
+ mMonitor = monitor;
+ }
+
+ /** Returns the monitor or {@code null} if we lost connection to it. */
+ @Nullable
+ IBackupManagerMonitor getMonitor() {
+ return mMonitor;
+ }
+
+ void onSkipBackup() {
+ if (DEBUG) {
+ Slog.d(TAG, "Skipping backup since one is already in progress");
+ }
+ }
+
+ void onEmptyQueueAtStart() {
+ Slog.w(TAG, "Backup begun with an empty queue, nothing to do");
+ }
+
+ void onPmFoundInQueue() {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "PM metadata in queue, removing");
+ }
+ }
+
+ void onQueueReady(List<BackupRequest> queue) {
+ if (DEBUG) {
+ Slog.v(TAG, "Beginning backup of " + queue.size() + " targets");
+ }
+ }
+
+ void onTransportReady(String transportName) {
+ EventLog.writeEvent(EventLogTags.BACKUP_START, transportName);
+ }
+
+ void onInitializeTransport(String transportName) {
+ Slog.i(TAG, "Initializing transport and resetting backup state");
+ }
+
+ void onTransportInitialized(int status) {
+ if (status == BackupTransport.TRANSPORT_OK) {
+ EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
+ } else {
+ EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
+ Slog.e(TAG, "Transport error in initializeDevice()");
+ }
+ }
+
+ void onInitializeTransportError(Exception e) {
+ Slog.e(TAG, "Error during initialization", e);
+ }
+
+ void onSkipPm() {
+ Slog.d(TAG, "Skipping backup of PM metadata");
+ }
+
+ void onInvokePmAgentError(Exception e) {
+ Slog.e(TAG, "Error during PM metadata backup", e);
+ }
+
+ void onEmptyQueue() {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "Queue now empty");
+ }
+ }
+
+ void onStartPackageBackup(String packageName) {
+ Slog.d(TAG, "Starting key-value backup of " + packageName);
+ }
+
+ void onPackageNotEligibleForBackup(String packageName) {
+ Slog.i(TAG, "Package " + packageName + " no longer supports backup, skipping");
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ }
+
+ void onPackageEligibleForFullBackup(String packageName) {
+ Slog.i(
+ TAG,
+ "Package " + packageName + " performs full-backup rather than key-value, skipping");
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ }
+
+ void onPackageStopped(String packageName) {
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ }
+
+ void onBindAgentError(SecurityException e) {
+ Slog.d(TAG, "Error in bind/backup", e);
+ }
+
+ void onAgentUnknown(String packageName) {
+ Slog.d(TAG, "Package does not exist, skipping");
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_PACKAGE_NOT_FOUND);
+ }
+
+ void onAgentError(String packageName) {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "Agent failure for " + packageName + ", re-staging");
+ }
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE);
+ }
+
+ void onInvokeAgent(String packageName) {
+ if (DEBUG) {
+ Slog.d(TAG, "Invoking agent on " + packageName);
+ }
+ }
+
+ void onAgentFilesReady(File backupDataFile) {
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "Data file: " + backupDataFile);
+ }
+ }
+
+ void onRestoreconFailed(File backupDataFile) {
+ Slog.e(TAG, "SELinux restorecon failed on " + backupDataFile);
+ }
+
+ void onCallAgentDoBackupError(String packageName, boolean callingAgent, Exception e) {
+ if (callingAgent) {
+ Slog.e(TAG, "Error invoking agent on " + packageName + ": " + e);
+ } else {
+ Slog.e(TAG, "Error before invoking agent on " + packageName + ": " + e);
+ }
+ EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, e.toString());
+ }
+
+ void onFailAgentError(String packageName) {
+ Slog.w(TAG, "Error conveying failure to " + packageName);
+ }
+
+ void onAgentIllegalKey(PackageInfo packageInfo, String key) {
+ String packageName = packageInfo.packageName;
+ EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, "bad key");
+ mMonitor =
+ BackupManagerMonitorUtils.monitorEvent(
+ mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
+ packageInfo,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ BackupManagerMonitorUtils.putMonitoringExtra(
+ null, BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY, key));
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE);
+ if (MORE_DEBUG) {
+ Slog.i(
+ TAG,
+ "Agent failure for " + packageName + " with illegal key " + key + ", dropped");
+ }
+ }
+
+ void onReadAgentDataError(String packageName, IOException e) {
+ Slog.w(TAG, "Unable read backup data for " + packageName + ": " + e);
+ }
+
+ void onWriteWidgetDataError(String packageName, IOException e) {
+ Slog.w(TAG, "Unable to save widget data for " + packageName + ": " + e);
+ }
+
+ void onDigestError(NoSuchAlgorithmException e) {
+ Slog.e(TAG, "Unable to use SHA-1!");
+ }
+
+ void onWriteWidgetData(boolean priorStateExists, @Nullable byte[] widgetState) {
+ if (MORE_DEBUG) {
+ Slog.i(
+ TAG,
+ "Checking widget update: state="
+ + (widgetState != null)
+ + " prior="
+ + priorStateExists);
+ }
+ }
+
+ void onTruncateDataError() {
+ Slog.w(TAG, "Unable to roll back");
+ }
+
+ void onSendDataToTransport(String packageName) {
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "Sending non-empty data to transport for " + packageName);
+ }
+ }
+
+ void onNonIncrementalAndNonIncrementalRequired() {
+ Slog.e(TAG, "Transport requested non-incremental but already the case");
+ }
+
+ void onEmptyData(PackageInfo packageInfo) {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "No backup data written, not calling transport");
+ }
+ mMonitor =
+ BackupManagerMonitorUtils.monitorEvent(
+ mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
+ packageInfo,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
+ }
+
+ void onPackageBackupComplete(String packageName, long size) {
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.SUCCESS);
+ EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, packageName, size);
+ mBackupManagerService.logBackupComplete(packageName);
+ }
+
+ void onPackageBackupRejected(String packageName) {
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
+ EventLogTags.writeBackupAgentFailure(packageName, "Transport rejected");
+ }
+
+ void onPackageBackupQuotaExceeded(String packageName) {
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "Package " + packageName + " hit quota limit on key-value backup");
+ }
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
+ EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, packageName);
+ }
+
+ void onAgentDoQuotaExceededError(Exception e) {
+ Slog.e(TAG, "Unable to notify about quota exceeded: " + e);
+ }
+
+ void onPackageBackupNonIncrementalRequired(PackageInfo packageInfo) {
+ Slog.i(TAG, "Transport lost data, retrying package");
+ BackupManagerMonitorUtils.monitorEvent(
+ mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED,
+ packageInfo,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
+ /* extras */ null);
+ }
+
+ void onPackageBackupTransportFailure(String packageName) {
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_TRANSPORT_ABORTED);
+ EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, packageName);
+ }
+
+ void onPackageBackupError(String packageName, Exception e) {
+ Slog.e(TAG, "Transport error backing up " + packageName, e);
+ BackupObserverUtils.sendBackupOnPackageResult(
+ mObserver, packageName, BackupManager.ERROR_TRANSPORT_ABORTED);
+ EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, packageName);
+ }
+
+ void onCloseFileDescriptorError(String logName) {
+ Slog.w(TAG, "Error closing " + logName + " file-descriptor");
+ }
+
+ void onCancel() {
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "Cancel received");
+ }
+ }
+
+ void onAgentTimedOut(@Nullable PackageInfo packageInfo) {
+ String packageName = getPackageName(packageInfo);
+ Slog.i(TAG, "Agent " + packageName + " timed out");
+ EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
+ // Time-out used to be implemented as cancel w/ cancelAll = false.
+ // TODO: Change monitoring event to reflect time-out as an event itself.
+ mMonitor =
+ BackupManagerMonitorUtils.monitorEvent(
+ mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+ packageInfo,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+ BackupManagerMonitorUtils.putMonitoringExtra(
+ null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, false));
+ }
+
+ void onAgentCancelled(@Nullable PackageInfo packageInfo) {
+ String packageName = getPackageName(packageInfo);
+ Slog.i(TAG, "Cancel backing up " + packageName);
+ EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
+ mMonitor =
+ BackupManagerMonitorUtils.monitorEvent(
+ mMonitor,
+ BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+ packageInfo,
+ BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+ BackupManagerMonitorUtils.putMonitoringExtra(
+ null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, true));
+ }
+
+ private String getPackageName(@Nullable PackageInfo packageInfo) {
+ return (packageInfo != null) ? packageInfo.packageName : "no_package_yet";
+ }
+
+ void onRevertBackup() {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "Reverting backup queue, re-staging everything");
+ }
+ }
+
+ void onTransportRequestBackupTimeError(Exception e) {
+ Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e);
+ }
+
+ void onRemoteCallReturned(RemoteResult result) {
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "Agent call returned " + result);
+ }
+ }
+
+ void onJournalDeleteFailed(DataChangedJournal journal) {
+ Slog.e(TAG, "Unable to remove backup journal file " + journal);
+ }
+
+ void onSetCurrentTokenError(Exception e) {
+ Slog.e(TAG, "Transport threw reporting restore set: " + e);
+ }
+
+ void onTransportNotInitialized() {
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "Transport requires initialization, rerunning");
+ }
+ }
+
+ void onPendingInitializeTransportError(Exception e) {
+ Slog.w(TAG, "Failed to query transport name for pending init: " + e);
+ }
+
+ void onBackupFinished(int status) {
+ BackupObserverUtils.sendBackupFinished(mObserver, status);
+ }
+
+ void onStartFullBackup(List<String> pendingFullBackups) {
+ Slog.d(TAG, "Starting full backups for: " + pendingFullBackups);
+ }
+
+ void onKeyValueBackupFinished() {
+ Slog.i(TAG, "K/V backup pass finished");
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 1cb9933..41013aa 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -16,7 +16,11 @@
package com.android.server.backup.keyvalue;
-import static com.android.server.backup.BackupManagerService.DEBUG_BACKUP_TRACE;
+import static android.os.ParcelFileDescriptor.MODE_CREATE;
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
+
import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
import static com.android.server.backup.BackupManagerService.OP_PENDING;
import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
@@ -29,7 +33,6 @@
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManager;
-import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupTransport;
import android.app.backup.IBackupCallback;
import android.app.backup.IBackupManager;
@@ -47,7 +50,6 @@
import android.os.WorkSource;
import android.system.ErrnoException;
import android.system.Os;
-import android.util.EventLog;
import android.util.Pair;
import android.util.Slog;
@@ -55,12 +57,12 @@
import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.Preconditions;
import com.android.server.AppWidgetBackupBridge;
-import com.android.server.EventLogTags;
import com.android.server.backup.BackupAgentTimeoutParameters;
import com.android.server.backup.BackupManagerService;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.KeyValueBackupJob;
+import com.android.server.backup.TransportManager;
import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.internal.Operation;
@@ -69,9 +71,8 @@
import com.android.server.backup.remote.RemoteResult;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.utils.AppBackupUtils;
-import com.android.server.backup.utils.BackupManagerMonitorUtils;
-import com.android.server.backup.utils.BackupObserverUtils;
+import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -172,7 +173,7 @@
// TODO: Distinguish between cancel and time-out where possible for logging/monitoring/observing
public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
private static final String TAG = "KeyValueBackupTask";
- private static final boolean DEBUG = BackupManagerService.DEBUG || true;
+ private static final boolean DEBUG = BackupManagerService.DEBUG;
private static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || false;
private static final int THREAD_PRIORITY = Process.THREAD_PRIORITY_BACKGROUND;
private static final AtomicInteger THREAD_COUNT = new AtomicInteger();
@@ -212,8 +213,8 @@
List<BackupRequest> queue,
@Nullable DataChangedJournal dataChangedJournal,
IBackupObserver observer,
- IBackupManagerMonitor monitor,
- @Nullable OnTaskFinishedListener listener,
+ @Nullable IBackupManagerMonitor monitor,
+ OnTaskFinishedListener listener,
List<String> pendingFullBackups,
boolean userInitiated,
boolean nonIncremental) {
@@ -239,10 +240,13 @@
}
private final BackupManagerService mBackupManagerService;
+ private final PackageManager mPackageManager;
+ private final TransportManager mTransportManager;
private final TransportClient mTransportClient;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
private final IBackupObserver mObserver;
- private final OnTaskFinishedListener mListener;
+ private final KeyValueBackupReporter mReporter;
+ private final OnTaskFinishedListener mTaskFinishedListener;
private final boolean mUserInitiated;
private final boolean mNonIncremental;
private final int mCurrentOpToken;
@@ -251,7 +255,6 @@
private final List<BackupRequest> mQueue;
private final List<String> mPendingFullBackups;
@Nullable private final DataChangedJournal mJournal;
- private IBackupManagerMonitor mMonitor;
@Nullable private PerformFullTransportBackupTask mFullBackupTask;
private IBackupAgent mAgentBinder;
@@ -294,20 +297,22 @@
List<BackupRequest> queue,
@Nullable DataChangedJournal journal,
IBackupObserver observer,
- IBackupManagerMonitor monitor,
- @Nullable OnTaskFinishedListener listener,
+ @Nullable IBackupManagerMonitor monitor,
+ OnTaskFinishedListener taskFinishedListener,
List<String> pendingFullBackups,
boolean userInitiated,
boolean nonIncremental) {
mBackupManagerService = backupManagerService;
+ mTransportManager = backupManagerService.getTransportManager();
+ mPackageManager = backupManagerService.getPackageManager();
mTransportClient = transportClient;
mOriginalQueue = queue;
// We need to retain the original queue contents in case of transport failure
- mQueue = new ArrayList<>(mOriginalQueue);
+ mQueue = new ArrayList<>(queue);
mJournal = journal;
mObserver = observer;
- mMonitor = monitor;
- mListener = (listener != null) ? listener : OnTaskFinishedListener.NOP;
+ mReporter = new KeyValueBackupReporter(backupManagerService, observer, monitor);
+ mTaskFinishedListener = taskFinishedListener;
mPendingFullBackups = pendingFullBackups;
mUserInitiated = userInitiated;
mNonIncremental = nonIncremental;
@@ -332,7 +337,7 @@
public void run() {
Process.setThreadPriority(THREAD_PRIORITY);
- BackupState state = beginBackup();
+ BackupState state = startBackup();
while (state == BackupState.RUNNING_QUEUE || state == BackupState.BACKUP_PM) {
if (mCancelled) {
state = BackupState.CANCELLED;
@@ -342,24 +347,24 @@
state = backupPm();
break;
case RUNNING_QUEUE:
- Pair<BackupState, RemoteResult> stateAndResult = invokeNextAgent();
+ Pair<BackupState, RemoteResult> stateAndResult = extractNextAgentData();
state = stateAndResult.first;
if (state == null) {
- state = processAgentInvocation(stateAndResult.second);
+ state = handleAgentResult(stateAndResult.second);
}
break;
}
}
if (state == BackupState.CANCELLED) {
- finalizeCancelledBackup();
+ finishCancelledBackup();
} else {
- finalizeBackup();
+ finishBackup();
}
}
- private BackupState processAgentInvocation(RemoteResult result) {
+ private BackupState handleAgentResult(RemoteResult result) {
if (result == RemoteResult.FAILED_THREAD_INTERRUPTED) {
- // Not an explicit cancel, we need to flag it
+ // Not an explicit cancel, we need to flag it.
mCancelled = true;
handleAgentCancelled();
return BackupState.CANCELLED;
@@ -373,7 +378,7 @@
return BackupState.RUNNING_QUEUE;
}
Preconditions.checkState(result.succeeded());
- return handleAgentResult(result.get());
+ return sendDataToTransport(result.get());
}
@Override
@@ -382,24 +387,10 @@
@Override
public void operationComplete(long unusedResult) {}
- private BackupState beginBackup() {
- if (DEBUG_BACKUP_TRACE) {
- mBackupManagerService.clearBackupTrace();
- StringBuilder b = new StringBuilder(256);
- b.append("beginBackup: [");
- for (BackupRequest req : mOriginalQueue) {
- b.append(' ');
- b.append(req.packageName);
- }
- b.append(" ]");
- mBackupManagerService.addBackupTrace(b.toString());
- }
+ private BackupState startBackup() {
synchronized (mBackupManagerService.getCurrentOpLock()) {
if (mBackupManagerService.isBackupOperationInProgress()) {
- if (DEBUG) {
- Slog.d(TAG, "Skipping backup since one is already in progress");
- }
- mBackupManagerService.addBackupTrace("Skipped. Backup already in progress.");
+ mReporter.onSkipBackup();
return BackupState.FINAL;
}
}
@@ -415,19 +406,17 @@
/* runningJob */ null,
new CountDownLatch(1),
mObserver,
- mMonitor,
- mListener,
+ mReporter.getMonitor(),
+ mTaskFinishedListener,
mUserInitiated);
registerTask();
- mBackupManagerService.addBackupTrace("STATE => INITIAL");
mAgentBinder = null;
mStatus = BackupTransport.TRANSPORT_OK;
// Sanity check: if the queue is empty we have no work to do.
if (mOriginalQueue.isEmpty() && mPendingFullBackups.isEmpty()) {
- Slog.w(TAG, "Backup begun with an empty queue, nothing to do.");
- mBackupManagerService.addBackupTrace("queue empty at begin");
+ mReporter.onEmptyQueueAtStart();
return BackupState.FINAL;
}
@@ -441,55 +430,39 @@
// we're committed to evaluating it for backup regardless.
for (int i = 0; i < mQueue.size(); i++) {
if (PACKAGE_MANAGER_SENTINEL.equals(mQueue.get(i).packageName)) {
- if (MORE_DEBUG) {
- Slog.i(TAG, "PM metadata in queue, removing");
- }
+ mReporter.onPmFoundInQueue();
mQueue.remove(i);
skipPm = false;
break;
}
}
+ mReporter.onQueueReady(mQueue);
- if (DEBUG) {
- Slog.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
- }
File pmState = new File(mStateDir, PACKAGE_MANAGER_SENTINEL);
try {
- IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.beginBackup()");
+ IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.startBackup()");
String transportName = transport.name();
- EventLog.writeEvent(EventLogTags.BACKUP_START, transportName);
+ mReporter.onTransportReady(transportName);
- // If we haven't stored package manager metadata yet, we must init the transport.
+ // If we haven't stored PM metadata yet, we must initialize the transport.
if (pmState.length() <= 0) {
- Slog.i(TAG, "Initializing transport and resetting backup state");
- mBackupManagerService.addBackupTrace("initializing transport " + transportName);
- mBackupManagerService.resetBackupState(mStateDir); // Just to make sure.
+ mReporter.onInitializeTransport(transportName);
+ mBackupManagerService.resetBackupState(mStateDir);
mStatus = transport.initializeDevice();
-
- mBackupManagerService.addBackupTrace("transport.initializeDevice() == " + mStatus);
- if (mStatus == BackupTransport.TRANSPORT_OK) {
- EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
- } else {
- EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
- Slog.e(TAG, "Transport error in initializeDevice()");
- }
+ mReporter.onTransportInitialized(mStatus);
}
} catch (Exception e) {
- Slog.e(TAG, "Error during initialization", e);
- mBackupManagerService.addBackupTrace("Exception in backup thread during init: " + e);
+ mReporter.onInitializeTransportError(e);
mStatus = BackupTransport.TRANSPORT_ERROR;
}
- mBackupManagerService.addBackupTrace("exiting prelim: " + mStatus);
if (mStatus != BackupTransport.TRANSPORT_OK) {
- // if things went wrong at this point, we need to
- // restage everything and try again later.
- mBackupManagerService.resetBackupState(mStateDir); // Just to make sure.
+ mBackupManagerService.resetBackupState(mStateDir);
return BackupState.FINAL;
}
if (skipPm) {
- Slog.d(TAG, "Skipping backup of PM metadata");
+ mReporter.onSkipPm();
return BackupState.RUNNING_QUEUE;
}
@@ -498,38 +471,27 @@
private BackupState backupPm() {
RemoteResult agentResult = null;
- BackupState nextState;
try {
- // The package manager doesn't have a proper <application> etc, but since it's running
- // here in the system process we can just set up its agent directly and use a synthetic
- // BackupRequest.
+ // Since PM is running in the system process we can set up its agent directly.
BackupAgent pmAgent = mBackupManagerService.makeMetadataAgent();
Pair<Integer, RemoteResult> statusAndResult =
- invokeAgentForBackup(
+ extractAgentData(
PACKAGE_MANAGER_SENTINEL,
IBackupAgent.Stub.asInterface(pmAgent.onBind()));
mStatus = statusAndResult.first;
agentResult = statusAndResult.second;
-
- mBackupManagerService.addBackupTrace("PM agent invoke: " + mStatus);
} catch (Exception e) {
- Slog.e(TAG, "Error during PM metadata backup", e);
- mBackupManagerService.addBackupTrace("Exception in backup thread during pm: " + e);
+ mReporter.onInvokePmAgentError(e);
mStatus = BackupTransport.TRANSPORT_ERROR;
}
- mBackupManagerService.addBackupTrace("exiting backupPm: " + mStatus);
- if (mStatus == BackupTransport.TRANSPORT_OK) {
- Preconditions.checkNotNull(agentResult);
- nextState = processAgentInvocation(agentResult);
- } else {
- // if things went wrong at this point, we need to
- // restage everything and try again later.
- mBackupManagerService.resetBackupState(mStateDir); // Just to make sure.
- nextState = BackupState.FINAL;
+ if (mStatus != BackupTransport.TRANSPORT_OK) {
+ mBackupManagerService.resetBackupState(mStateDir);
+ return BackupState.FINAL;
}
- return nextState;
+ Preconditions.checkNotNull(agentResult);
+ return handleAgentResult(agentResult);
}
/**
@@ -540,250 +502,183 @@
* <li>({@code null}, agent result): In case we successfully called the agent.
* </ul>
*/
- private Pair<BackupState, RemoteResult> invokeNextAgent() {
+ private Pair<BackupState, RemoteResult> extractNextAgentData() {
mStatus = BackupTransport.TRANSPORT_OK;
- mBackupManagerService.addBackupTrace("invoke q=" + mQueue.size());
- // Sanity check that we have work to do. If not, skip to the end where
- // we reestablish the wakelock invariants etc.
if (mQueue.isEmpty()) {
- if (MORE_DEBUG) {
- Slog.i(TAG, "Queue now empty");
- }
+ mReporter.onEmptyQueue();
return Pair.create(BackupState.FINAL, null);
}
- // pop the entry we're going to process on this step
BackupRequest request = mQueue.remove(0);
+ String packageName = request.packageName;
+ mReporter.onStartPackageBackup(packageName);
- Slog.d(TAG, "Starting key-value backup of " + request);
- mBackupManagerService.addBackupTrace("launch agent for " + request.packageName);
-
- // Verify that the requested app exists; it might be something that
- // requested a backup but was then uninstalled. The request was
- // journalled and rather than tamper with the journal it's safer
- // to sanity-check here. This also gives us the classname of the
- // package's backup agent.
+ // Verify that the requested app is eligible for key-value backup.
RemoteResult agentResult = null;
try {
- PackageManager pm = mBackupManagerService.getPackageManager();
- mCurrentPackage = pm.getPackageInfo(request.packageName,
- PackageManager.GET_SIGNING_CERTIFICATES);
- if (!AppBackupUtils.appIsEligibleForBackup(mCurrentPackage.applicationInfo, pm)) {
- // The manifest has changed but we had a stale backup request pending. This won't
- // happen again because the app won't be requesting further backups.
- Slog.i(TAG, "Package " + request.packageName
- + " no longer supports backup, skipping");
- mBackupManagerService.addBackupTrace("skipping - not eligible, completion is noop");
- // Shouldn't happen in case of requested backup, as pre-check was done in
- // #requestBackup(), except to app update done concurrently
- BackupObserverUtils.sendBackupOnPackageResult(mObserver,
- mCurrentPackage.packageName,
- BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ mCurrentPackage = mPackageManager.getPackageInfo(
+ request.packageName, PackageManager.GET_SIGNING_CERTIFICATES);
+ ApplicationInfo applicationInfo = mCurrentPackage.applicationInfo;
+ if (!AppBackupUtils.appIsEligibleForBackup(applicationInfo, mPackageManager)) {
+ // The manifest has changed. This won't happen again because the app won't be
+ // requesting further backups.
+ mReporter.onPackageNotEligibleForBackup(packageName);
return Pair.create(BackupState.RUNNING_QUEUE, null);
}
if (AppBackupUtils.appGetsFullBackup(mCurrentPackage)) {
- // It's possible that this app *formerly* was enqueued for key-value backup, but has
- // since been updated and now only supports the full-backup path. Don't proceed with
- // a key-value backup for it in this case.
- Slog.i(TAG, "Package " + request.packageName
- + " performs full-backup rather than key-value, skipping");
- mBackupManagerService.addBackupTrace(
- "skipping - fullBackupOnly, completion is noop");
- // Shouldn't happen in case of requested backup, as pre-check was done in
- // #requestBackup()
- BackupObserverUtils.sendBackupOnPackageResult(mObserver,
- mCurrentPackage.packageName,
- BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ // Initially enqueued for key-value backup, but only supports full-backup now.
+ mReporter.onPackageEligibleForFullBackup(packageName);
return Pair.create(BackupState.RUNNING_QUEUE, null);
}
- if (AppBackupUtils.appIsStopped(mCurrentPackage.applicationInfo)) {
- // The app has been force-stopped or cleared or just installed,
- // and not yet launched out of that state, so just as it won't
- // receive broadcasts, we won't run it for backup.
- mBackupManagerService.addBackupTrace("skipping - stopped");
- BackupObserverUtils.sendBackupOnPackageResult(mObserver,
- mCurrentPackage.packageName,
- BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ if (AppBackupUtils.appIsStopped(applicationInfo)) {
+ // Just as it won't receive broadcasts, we won't run it for backup.
+ mReporter.onPackageStopped(packageName);
return Pair.create(BackupState.RUNNING_QUEUE, null);
}
try {
- mBackupManagerService.setWorkSource(
- new WorkSource(mCurrentPackage.applicationInfo.uid));
+ mBackupManagerService.setWorkSource(new WorkSource(applicationInfo.uid));
IBackupAgent agent =
mBackupManagerService.bindToAgentSynchronous(
- mCurrentPackage.applicationInfo,
+ applicationInfo,
ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
- mBackupManagerService.addBackupTrace("agent bound; a? = " + (agent != null));
if (agent != null) {
mAgentBinder = agent;
Pair<Integer, RemoteResult> statusAndResult =
- invokeAgentForBackup(request.packageName, agent);
+ extractAgentData(request.packageName, agent);
mStatus = statusAndResult.first;
agentResult = statusAndResult.second;
} else {
- // Timeout waiting for the agent
+ // Timeout waiting for the agent to bind.
mStatus = BackupTransport.AGENT_ERROR;
}
- } catch (SecurityException se) {
- // Try for the next one.
- Slog.d(TAG, "Error in bind/backup", se);
+ } catch (SecurityException e) {
+ mReporter.onBindAgentError(e);
mStatus = BackupTransport.AGENT_ERROR;
- mBackupManagerService.addBackupTrace("agent SE");
}
} catch (PackageManager.NameNotFoundException e) {
- Slog.d(TAG, "Package does not exist, skipping");
- mBackupManagerService.addBackupTrace("no such package");
mStatus = BackupTransport.AGENT_UNKNOWN;
} finally {
mBackupManagerService.setWorkSource(null);
}
if (mStatus != BackupTransport.TRANSPORT_OK) {
- BackupState nextState = BackupState.RUNNING_QUEUE;
mAgentBinder = null;
- // An agent-level failure means we re-enqueue this one agent for
- // a later retry, but otherwise proceed normally.
if (mStatus == BackupTransport.AGENT_ERROR) {
- if (MORE_DEBUG) {
- Slog.i(TAG, "Agent failure for " + request.packageName + ", re-staging");
- }
+ mReporter.onAgentError(packageName);
mBackupManagerService.dataChangedImpl(request.packageName);
mStatus = BackupTransport.TRANSPORT_OK;
- BackupObserverUtils
- .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
- BackupManager.ERROR_AGENT_FAILURE);
- } else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
- // Failed lookup of the app, so we couldn't bring up an agent, but
- // we're otherwise fine. Just drop it and go on to the next as usual.
- mStatus = BackupTransport.TRANSPORT_OK;
- BackupObserverUtils
- .sendBackupOnPackageResult(mObserver, request.packageName,
- BackupManager.ERROR_PACKAGE_NOT_FOUND);
- } else {
- // Transport-level failure means we re-enqueue everything
- revertAndEndBackup();
- nextState = BackupState.FINAL;
+ return Pair.create(BackupState.RUNNING_QUEUE, null);
}
- return Pair.create(nextState, null);
+ if (mStatus == BackupTransport.AGENT_UNKNOWN) {
+ mReporter.onAgentUnknown(packageName);
+ mStatus = BackupTransport.TRANSPORT_OK;
+ return Pair.create(BackupState.RUNNING_QUEUE, null);
+ }
+
+ // Transport-level failure, re-enqueue everything.
+ revertBackup();
+ return Pair.create(BackupState.FINAL, null);
}
// Success: caller will figure out the state based on call result
- mBackupManagerService.addBackupTrace("call made; result = " + agentResult);
return Pair.create(null, agentResult);
}
- private void finalizeBackup() {
- mBackupManagerService.addBackupTrace("finishing");
-
- // Mark packages that we didn't backup (because backup was cancelled, etc.) as needing
- // backup.
- for (BackupRequest req : mQueue) {
- mBackupManagerService.dataChangedImpl(req.packageName);
+ private void finishBackup() {
+ // Mark packages that we couldn't backup as pending backup.
+ for (BackupRequest request : mQueue) {
+ mBackupManagerService.dataChangedImpl(request.packageName);
}
- // Either backup was successful, in which case we of course do not need
- // this pass's journal any more; or it failed, in which case we just
- // re-enqueued all of these packages in the current active journal.
- // Either way, we no longer need this pass's journal.
+ // If backup succeeded, we just invalidated this journal. If not, we've already re-enqueued
+ // the packages and also don't need the journal.
if (mJournal != null && !mJournal.delete()) {
- Slog.e(TAG, "Unable to remove backup journal file " + mJournal);
+ mReporter.onJournalDeleteFailed(mJournal);
}
- // If everything actually went through and this is the first time we've
- // done a backup, we can now record what the current backup dataset token
- // is.
- String callerLogString = "KVBT.finalizeBackup()";
- if ((mBackupManagerService.getCurrentToken() == 0) && (mStatus
- == BackupTransport.TRANSPORT_OK)) {
- mBackupManagerService.addBackupTrace("success; recording token");
+ String callerLogString = "KVBT.finishBackup()";
+
+ // If we succeeded and this is the first time we've done a backup, we can record the current
+ // backup dataset token.
+ long currentToken = mBackupManagerService.getCurrentToken();
+ if ((mStatus == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
try {
IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
mBackupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
mBackupManagerService.writeRestoreTokens();
} catch (Exception e) {
- // nothing for it at this point, unfortunately, but this will be
- // recorded the next time we fully succeed.
- Slog.e(TAG, "Transport threw reporting restore set: " + e);
- mBackupManagerService.addBackupTrace("transport threw returning token");
+ // This will be recorded the next time we succeed.
+ mReporter.onSetCurrentTokenError(e);
}
}
- // Set up the next backup pass - at this point we can set mBackupRunning
- // to false to allow another pass to fire
synchronized (mBackupManagerService.getQueueLock()) {
mBackupManagerService.setBackupRunning(false);
if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
- if (MORE_DEBUG) {
- Slog.d(TAG, "Transport requires initialization, rerunning");
- }
- mBackupManagerService.addBackupTrace("init required; rerunning");
+ mReporter.onTransportNotInitialized();
try {
- String name = mBackupManagerService.getTransportManager()
- .getTransportName(mTransportClient.getTransportComponent());
- mBackupManagerService.getPendingInits().add(name);
+ IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
+ mBackupManagerService.getPendingInits().add(transport.name());
+ clearPmMetadata();
+ mBackupManagerService.backupNow();
} catch (Exception e) {
- Slog.w(TAG, "Failed to query transport name for init: " + e);
- // swallow it and proceed; we don't rely on this
+ mReporter.onPendingInitializeTransportError(e);
}
- clearMetadata();
- mBackupManagerService.backupNow();
}
}
- mBackupManagerService.clearBackupTrace();
-
unregisterTask();
+ mReporter.onKeyValueBackupFinished();
- if (!mCancelled && mStatus == BackupTransport.TRANSPORT_OK &&
- mPendingFullBackups != null && !mPendingFullBackups.isEmpty()) {
- Slog.d(TAG, "Starting full backups for: " + mPendingFullBackups);
- // Acquiring wakelock for PerformFullTransportBackupTask before its start.
- mBackupManagerService.getWakelock().acquire();
- // The full-backup task is now responsible for calling onFinish() on mListener, which
- // was the listener we passed it.
+ if (!mCancelled
+ && mStatus == BackupTransport.TRANSPORT_OK
+ && mFullBackupTask != null
+ && !mPendingFullBackups.isEmpty()) {
+ mReporter.onStartFullBackup(mPendingFullBackups);
+ // The key-value backup has finished but not the overall backup. Full-backup task will:
+ // * Call mObserver.backupFinished() (which is called by mReporter below).
+ // * Call mTaskFinishedListener.onFinished().
+ // * Release the wakelock.
(new Thread(mFullBackupTask, "full-transport-requested")).start();
- } else if (mCancelled) {
- mListener.onFinished(callerLogString);
- if (mFullBackupTask != null) {
- mFullBackupTask.unregisterTask();
- }
- BackupObserverUtils.sendBackupFinished(mObserver, BackupManager.ERROR_BACKUP_CANCELLED);
- } else {
- mListener.onFinished(callerLogString);
- if (mFullBackupTask != null) {
- mFullBackupTask.unregisterTask();
- }
- switch (mStatus) {
- case BackupTransport.TRANSPORT_OK:
- case BackupTransport.TRANSPORT_QUOTA_EXCEEDED:
- case BackupTransport.TRANSPORT_PACKAGE_REJECTED:
- BackupObserverUtils.sendBackupFinished(mObserver, BackupManager.SUCCESS);
- break;
- case BackupTransport.TRANSPORT_NOT_INITIALIZED:
- BackupObserverUtils.sendBackupFinished(mObserver,
- BackupManager.ERROR_TRANSPORT_ABORTED);
- break;
- case BackupTransport.TRANSPORT_ERROR:
- default:
- BackupObserverUtils.sendBackupFinished(mObserver,
- BackupManager.ERROR_TRANSPORT_ABORTED);
- break;
- }
+ return;
}
- Slog.i(TAG, "K/V backup pass finished");
+
+ if (mFullBackupTask != null) {
+ mFullBackupTask.unregisterTask();
+ }
+ mTaskFinishedListener.onFinished(callerLogString);
+ mReporter.onBackupFinished(getBackupFinishedStatus(mCancelled, mStatus));
mBackupManagerService.getWakelock().release();
}
- // Remove the PM metadata state. This will generate an init on the next pass.
- private void clearMetadata() {
- final File pmState = new File(mStateDir, PACKAGE_MANAGER_SENTINEL);
- if (pmState.exists()) pmState.delete();
+ private int getBackupFinishedStatus(boolean cancelled, int transportStatus) {
+ if (cancelled) {
+ return BackupManager.ERROR_BACKUP_CANCELLED;
+ }
+ switch (transportStatus) {
+ case BackupTransport.TRANSPORT_OK:
+ case BackupTransport.TRANSPORT_QUOTA_EXCEEDED:
+ case BackupTransport.TRANSPORT_PACKAGE_REJECTED:
+ return BackupManager.SUCCESS;
+ case BackupTransport.TRANSPORT_NOT_INITIALIZED:
+ case BackupTransport.TRANSPORT_ERROR:
+ default:
+ return BackupManager.ERROR_TRANSPORT_ABORTED;
+ }
+ }
+
+ /** Removes PM state, triggering initialization in the next key-value task. */
+ private void clearPmMetadata() {
+ File pmState = new File(mStateDir, PACKAGE_MANAGER_SENTINEL);
+ if (pmState.exists()) {
+ pmState.delete();
+ }
}
/**
@@ -791,22 +686,16 @@
* {@link BackupTransport#TRANSPORT_OK}, the second of the pair contains the agent result,
* otherwise {@code null}.
*/
- private Pair<Integer, RemoteResult> invokeAgentForBackup(
- String packageName, IBackupAgent agent) {
- if (DEBUG) {
- Slog.d(TAG, "Invoking agent on " + packageName);
- }
- mBackupManagerService.addBackupTrace("invoking " + packageName);
+ private Pair<Integer, RemoteResult> extractAgentData(String packageName, IBackupAgent agent) {
+ mReporter.onInvokeAgent(packageName);
File blankStateFile = new File(mStateDir, BLANK_STATE_FILE_NAME);
mSavedStateFile = new File(mStateDir, packageName);
+ File savedStateFileForAgent = (mNonIncremental) ? blankStateFile : mSavedStateFile;
mBackupDataFile =
new File(mBackupManagerService.getDataDir(), packageName + STAGING_FILE_SUFFIX);
mNewStateFile = new File(mStateDir, packageName + NEW_STATE_FILE_SUFFIX);
- if (MORE_DEBUG) {
- Slog.d(TAG, "Data file: " + mBackupDataFile);
- }
-
+ mReporter.onAgentFilesReady(mBackupDataFile);
mSavedState = null;
mBackupData = null;
@@ -815,46 +704,31 @@
boolean callingAgent = false;
final RemoteResult agentResult;
try {
- // Look up the package info & signatures. This is first so that if it
- // throws an exception, there's no file setup yet that would need to
- // be unraveled.
+ // TODO: Move this to backupPm()
if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
- // The metadata 'package' is synthetic; construct one and make
- // sure our global state is pointed at it
mCurrentPackage = new PackageInfo();
mCurrentPackage.packageName = packageName;
}
+ // MODE_CREATE to make an empty file if necessary
mSavedState = ParcelFileDescriptor.open(
- (mNonIncremental) ? blankStateFile : mSavedStateFile,
- ParcelFileDescriptor.MODE_READ_ONLY |
- ParcelFileDescriptor.MODE_CREATE); // Make an empty file if necessary
-
- mBackupData = ParcelFileDescriptor.open(mBackupDataFile,
- ParcelFileDescriptor.MODE_READ_WRITE |
- ParcelFileDescriptor.MODE_CREATE |
- ParcelFileDescriptor.MODE_TRUNCATE);
+ savedStateFileForAgent, MODE_READ_ONLY | MODE_CREATE);
+ mBackupData = ParcelFileDescriptor.open(
+ mBackupDataFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
+ mNewState = ParcelFileDescriptor.open(
+ mNewStateFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
if (!SELinux.restorecon(mBackupDataFile)) {
- Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataFile);
+ mReporter.onRestoreconFailed(mBackupDataFile);
}
- mNewState = ParcelFileDescriptor.open(mNewStateFile,
- ParcelFileDescriptor.MODE_READ_WRITE |
- ParcelFileDescriptor.MODE_CREATE |
- ParcelFileDescriptor.MODE_TRUNCATE);
-
- IBackupTransport transport =
- mTransportClient.connectOrThrow("KVBT.invokeAgentForBackup()");
-
- final long quota = transport.getBackupQuota(packageName, false /* isFullBackup */);
- callingAgent = true;
-
- // Initiate the target's backup pass
+ IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.extractAgentData()");
+ long quota = transport.getBackupQuota(packageName, /* isFullBackup */ false);
+ int transportFlags = transport.getTransportFlags();
long kvBackupAgentTimeoutMillis =
mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
- mBackupManagerService.addBackupTrace("calling agent doBackup()");
+ callingAgent = true;
agentResult =
remoteCall(
callback ->
@@ -864,22 +738,19 @@
mNewState,
quota,
callback,
- transport.getTransportFlags()),
+ transportFlags),
kvBackupAgentTimeoutMillis);
} catch (Exception e) {
- Slog.e(TAG, "Error invoking agent on " + packageName + ": " + e);
- mBackupManagerService.addBackupTrace("exception: " + e);
- EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, e.toString());
+ mReporter.onCallAgentDoBackupError(packageName, callingAgent, e);
errorCleanup();
+ // TODO: Remove the check on callingAgent when RemoteCall supports local agent calls.
int status =
callingAgent ? BackupTransport.AGENT_ERROR : BackupTransport.TRANSPORT_ERROR;
return Pair.create(status, null);
- } finally {
- if (mNonIncremental) {
- blankStateFile.delete();
- }
}
-
+ if (mNonIncremental) {
+ blankStateFile.delete();
+ }
return Pair.create(BackupTransport.TRANSPORT_OK, agentResult);
}
@@ -887,7 +758,7 @@
try {
agent.fail(message);
} catch (Exception e) {
- Slog.w(TAG, "Error conveying failure to " + mCurrentPackage.packageName);
+ mReporter.onFailAgentError(mCurrentPackage.packageName);
}
}
@@ -898,36 +769,27 @@
MessageDigest md = MessageDigest.getInstance("SHA-1");
checksum = md.digest(input);
} catch (NoSuchAlgorithmException e) {
- Slog.e(TAG, "Unable to use SHA-1!");
+ mReporter.onDigestError(e);
return "00";
}
- StringBuffer sb = new StringBuffer(checksum.length * 2);
+ StringBuilder string = new StringBuilder(checksum.length * 2);
for (byte item : checksum) {
- sb.append(Integer.toHexString(item));
+ string.append(Integer.toHexString(item));
}
- return sb.toString();
+ return string.toString();
}
private void writeWidgetPayloadIfAppropriate(FileDescriptor fd, String pkgName)
throws IOException {
// TODO: http://b/22388012
byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName, UserHandle.USER_SYSTEM);
- // has the widget state changed since last time?
- final File widgetFile = new File(mStateDir, pkgName + "_widget");
- final boolean priorStateExists = widgetFile.exists();
-
- if (MORE_DEBUG) {
- if (priorStateExists || widgetState != null) {
- Slog.i(TAG, "Checking widget update: state=" + (widgetState != null)
- + " prior=" + priorStateExists);
- }
- }
-
+ File widgetFile = new File(mStateDir, pkgName + "_widget");
+ boolean priorStateExists = widgetFile.exists();
if (!priorStateExists && widgetState == null) {
- // no prior state, no new state => nothing to do
return;
}
+ mReporter.onWriteWidgetData(priorStateExists, widgetState);
// if the new state is not null, we might need to compare checksums to
// determine whether to update the widget blob in the archive. If the
@@ -969,93 +831,67 @@
}
}
- private BackupState handleAgentResult(long unusedResult) {
+ private BackupState sendDataToTransport(long agentResult) {
Preconditions.checkState(mBackupData != null);
- final String pkgName = mCurrentPackage.packageName;
- final long filepos = mBackupDataFile.length();
+ String packageName = mCurrentPackage.packageName;
+ ApplicationInfo applicationInfo = mCurrentPackage.applicationInfo;
+ long filePos = mBackupDataFile.length();
FileDescriptor fd = mBackupData.getFileDescriptor();
+ boolean writingWidgetData = false;
try {
- // If it's a 3rd party app, see whether they wrote any protected keys
- // and complain mightily if they are attempting shenanigans.
- if (mCurrentPackage.applicationInfo != null &&
- (mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
- == 0) {
- ParcelFileDescriptor readFd = ParcelFileDescriptor.open(mBackupDataFile,
- ParcelFileDescriptor.MODE_READ_ONLY);
+ // If it's a 3rd party app, crash them if they wrote any protected keys.
+ if (applicationInfo != null &&
+ (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ ParcelFileDescriptor readFd =
+ ParcelFileDescriptor.open(mBackupDataFile, MODE_READ_ONLY);
BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
try {
while (in.readNextHeader()) {
- final String key = in.getKey();
+ String key = in.getKey();
if (key != null && key.charAt(0) >= 0xff00) {
- // Not okay: crash them and bail.
+ mReporter.onAgentIllegalKey(mCurrentPackage, key);
failAgent(mAgentBinder, "Illegal backup key: " + key);
- mBackupManagerService
- .addBackupTrace("illegal key " + key + " from " + pkgName);
- EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
- "bad key");
- mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
- BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
- mCurrentPackage,
- BackupManagerMonitor
- .LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
- BackupManagerMonitorUtils.putMonitoringExtra(null,
- BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
- key));
- BackupObserverUtils
- .sendBackupOnPackageResult(mObserver, pkgName,
- BackupManager.ERROR_AGENT_FAILURE);
errorCleanup();
- if (MORE_DEBUG) {
- Slog.i(TAG, "Agent failure for " + pkgName
- + " with illegal key " + key + ", dropped");
- }
-
return BackupState.RUNNING_QUEUE;
}
in.skipEntityData();
}
} finally {
- if (readFd != null) {
- readFd.close();
- }
+ readFd.close();
}
}
- // Piggyback the widget state payload, if any
- writeWidgetPayloadIfAppropriate(fd, pkgName);
+ writingWidgetData = true;
+ writeWidgetPayloadIfAppropriate(fd, packageName);
} catch (IOException e) {
- // Hard disk error; recovery/failure policy TBD. For now roll back,
- // but we may want to consider this a transport-level failure (i.e.
- // we're in such a bad state that we can't contemplate doing backup
- // operations any more during this pass).
- Slog.w(TAG, "Unable read backup data or to save widget state for " + pkgName);
+ if (writingWidgetData) {
+ mReporter.onWriteWidgetDataError(packageName, e);
+ } else {
+ mReporter.onReadAgentDataError(packageName, e);
+ }
try {
- Os.ftruncate(fd, filepos);
+ Os.ftruncate(fd, filePos);
} catch (ErrnoException ee) {
- Slog.w(TAG, "Unable to roll back");
+ mReporter.onTruncateDataError();
}
}
clearAgentState();
- mBackupManagerService.addBackupTrace("operation complete");
ParcelFileDescriptor backupData = null;
mStatus = BackupTransport.TRANSPORT_OK;
long size = 0;
try {
- IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.handleAgentResult()");
+ IBackupTransport transport =
+ mTransportClient.connectOrThrow("KVBT.sendDataToTransport()");
size = mBackupDataFile.length();
if (size > 0) {
- if (MORE_DEBUG) {
- Slog.v(TAG, "Sending non-empty data to transport for " + pkgName);
- }
boolean isNonIncremental = mSavedStateFile.length() == 0;
- if (mStatus == BackupTransport.TRANSPORT_OK) {
- backupData = ParcelFileDescriptor.open(mBackupDataFile,
- ParcelFileDescriptor.MODE_READ_ONLY);
- mBackupManagerService.addBackupTrace("sending data to transport");
+ if (mStatus == BackupTransport.TRANSPORT_OK) {
+ mReporter.onSendDataToTransport(packageName);
+ backupData = ParcelFileDescriptor.open(mBackupDataFile, MODE_READ_ONLY);
int userInitiatedFlag =
mUserInitiated ? BackupTransport.FLAG_USER_INITIATED : 0;
int incrementalFlag =
@@ -1069,114 +905,58 @@
if (isNonIncremental
&& mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
- // TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED is only valid if the backup was
- // incremental, as if the backup is non-incremental there is no state to
- // clear. This avoids us ending up in a retry loop if the transport always
- // returns this code.
- Slog.e(TAG, "Transport requested non-incremental but already the case");
- mBackupManagerService.addBackupTrace(
- "Transport requested non-incremental but already the case, error");
+ mReporter.onNonIncrementalAndNonIncrementalRequired();
mStatus = BackupTransport.TRANSPORT_ERROR;
}
- mBackupManagerService.addBackupTrace("data delivered: " + mStatus);
if (mStatus == BackupTransport.TRANSPORT_OK) {
- mBackupManagerService.addBackupTrace("finishing op on transport");
mStatus = transport.finishBackup();
- mBackupManagerService.addBackupTrace("finished: " + mStatus);
- } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
- mBackupManagerService.addBackupTrace("transport rejected package");
}
} else {
- if (MORE_DEBUG) {
- Slog.i(TAG, "No backup data written, not calling transport");
- }
- mBackupManagerService.addBackupTrace("no data to send");
- mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
- BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
- mCurrentPackage,
- BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
- null);
+ mReporter.onEmptyData(mCurrentPackage);
}
if (mStatus == BackupTransport.TRANSPORT_OK) {
- // After successful transport, delete the now-stale data
- // and juggle the files so that next time we supply the agent
- // with the new state file it just created.
mBackupDataFile.delete();
mNewStateFile.renameTo(mSavedStateFile);
- BackupObserverUtils.sendBackupOnPackageResult(
- mObserver, pkgName, BackupManager.SUCCESS);
- EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
- mBackupManagerService.logBackupComplete(pkgName);
+ mReporter.onPackageBackupComplete(packageName, size);
} else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
- // The transport has rejected backup of this specific package. Roll it
- // back but proceed with running the rest of the queue.
mBackupDataFile.delete();
mNewStateFile.delete();
- BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
- BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
- EventLogTags.writeBackupAgentFailure(pkgName, "Transport rejected");
+ mReporter.onPackageBackupRejected(packageName);
} else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
- BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
- BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
- EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, pkgName);
-
+ // TODO: Should reset files like above?
+ mReporter.onPackageBackupQuotaExceeded(packageName);
} else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
- Slog.i(TAG, "Transport lost data, retrying package");
- mBackupManagerService.addBackupTrace(
- "Transport lost data, retrying package:" + pkgName);
- BackupManagerMonitorUtils.monitorEvent(
- mMonitor,
- BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED,
- mCurrentPackage,
- BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
- /*extras=*/ null);
-
+ mReporter.onPackageBackupNonIncrementalRequired(mCurrentPackage);
mBackupDataFile.delete();
mSavedStateFile.delete();
mNewStateFile.delete();
// Immediately retry the package by adding it back to the front of the queue.
// We cannot add @pm@ to the queue because we back it up separately at the start
- // of the backup pass in state BACKUP_PM. Instead we retry this state (see
- // below).
- if (!PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
- mQueue.add(0, new BackupRequest(pkgName));
+ // of the backup pass in state BACKUP_PM. See below.
+ if (!PACKAGE_MANAGER_SENTINEL.equals(packageName)) {
+ mQueue.add(0, new BackupRequest(packageName));
}
-
} else {
- // Actual transport-level failure to communicate the data to the backend
- BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
- BackupManager.ERROR_TRANSPORT_ABORTED);
- EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
+ mReporter.onPackageBackupTransportFailure(packageName);
}
} catch (Exception e) {
- BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
- BackupManager.ERROR_TRANSPORT_ABORTED);
- Slog.e(TAG, "Transport error backing up " + pkgName, e);
- EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
+ mReporter.onPackageBackupError(packageName, e);
mStatus = BackupTransport.TRANSPORT_ERROR;
} finally {
- try {
- if (backupData != null) {
- backupData.close();
- }
- } catch (IOException e) {
- Slog.w(TAG, "Error closing backup data file-descriptor");
- }
+ tryCloseFileDescriptor(backupData, "backup data");
}
final BackupState nextState;
if (mStatus == BackupTransport.TRANSPORT_OK
|| mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
- // Success or single-package rejection. Proceed with the next app if any,
- // otherwise we're done.
nextState = BackupState.RUNNING_QUEUE;
} else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
// We want to immediately retry the current package.
- if (PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
+ if (PACKAGE_MANAGER_SENTINEL.equals(packageName)) {
nextState = BackupState.BACKUP_PM;
} else {
// This is an ordinary package so we will have added it back into the queue
@@ -1185,25 +965,21 @@
}
} else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
- if (MORE_DEBUG) {
- Slog.d(TAG, "Package " + mCurrentPackage.packageName +
- " hit quota limit on key-value backup");
- }
if (mAgentBinder != null) {
try {
IBackupTransport transport =
- mTransportClient.connectOrThrow("KVBT.handleAgentResult()");
+ mTransportClient.connectOrThrow("KVBT.sendDataToTransport()");
long quota = transport.getBackupQuota(mCurrentPackage.packageName, false);
mAgentBinder.doQuotaExceeded(size, quota);
} catch (Exception e) {
- Slog.e(TAG, "Unable to notify about quota exceeded: " + e.getMessage());
+ mReporter.onAgentDoQuotaExceededError(e);
}
}
nextState = BackupState.RUNNING_QUEUE;
} else {
// Any other error here indicates a transport-level failure. That means
// we need to halt everything and reschedule everything for next time.
- revertAndEndBackup();
+ revertBackup();
nextState = BackupState.FINAL;
}
@@ -1223,10 +999,9 @@
*/
@Override
public void handleCancel(boolean cancelAll) {
+ // This is called in a thread different from the one that executes method run().
Preconditions.checkArgument(cancelAll, "Can't partially cancel a key-value backup task");
- if (MORE_DEBUG) {
- Slog.v(TAG, "Cancel received");
- }
+ mReporter.onCancel();
mCancelled = true;
RemoteCall pendingCall = mPendingCall;
if (pendingCall != null) {
@@ -1236,66 +1011,35 @@
}
private void handleAgentTimeout() {
- String packageName = getPackageNameForLog();
- Slog.i(TAG, "Agent " + packageName + " timed out");
- EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
- mBackupManagerService.addBackupTrace("timeout of " + packageName);
- mMonitor =
- BackupManagerMonitorUtils.monitorEvent(
- mMonitor,
- BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
- mCurrentPackage,
- BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
- BackupManagerMonitorUtils.putMonitoringExtra(
- null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, false));
+ mReporter.onAgentTimedOut(mCurrentPackage);
errorCleanup();
}
private void handleAgentCancelled() {
- String packageName = getPackageNameForLog();
- Slog.i(TAG, "Cancel backing up " + packageName);
- EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
- mBackupManagerService.addBackupTrace("cancel of " + packageName);
+ mReporter.onAgentCancelled(mCurrentPackage);
errorCleanup();
}
- private void finalizeCancelledBackup() {
- mMonitor =
- BackupManagerMonitorUtils.monitorEvent(
- mMonitor,
- BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
- mCurrentPackage,
- BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
- BackupManagerMonitorUtils.putMonitoringExtra(
- null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, true));
- finalizeBackup();
+ private void finishCancelledBackup() {
+ finishBackup();
// finalizeBackup() may call the transport, so we only acknowledge the cancellation here.
mCancelAcknowledged.open();
}
- private String getPackageNameForLog() {
- return (mCurrentPackage != null) ? mCurrentPackage.packageName : "no_package_yet";
- }
-
- private void revertAndEndBackup() {
- if (MORE_DEBUG) {
- Slog.i(TAG, "Reverting backup queue, re-staging everything");
- }
- mBackupManagerService.addBackupTrace("transport error; reverting");
-
- // We want to reset the backup schedule based on whatever the transport suggests
- // by way of retry/backoff time.
+ private void revertBackup() {
+ mReporter.onRevertBackup();
long delay;
try {
IBackupTransport transport =
- mTransportClient.connectOrThrow("KVBT.revertAndEndBackup()");
+ mTransportClient.connectOrThrow("KVBT.revertBackup()");
delay = transport.requestBackupTime();
} catch (Exception e) {
- Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e);
- delay = 0; // use the scheduler's default
+ mReporter.onTransportRequestBackupTimeError(e);
+ // Use the scheduler's default.
+ delay = 0;
}
- KeyValueBackupJob.schedule(mBackupManagerService.getContext(), delay,
- mBackupManagerService.getConstants());
+ KeyValueBackupJob.schedule(
+ mBackupManagerService.getContext(), delay, mBackupManagerService.getConstants());
for (BackupRequest request : mOriginalQueue) {
mBackupManagerService.dataChangedImpl(request.packageName);
@@ -1308,50 +1052,37 @@
clearAgentState();
}
- // Cleanup common to both success and failure cases
private void clearAgentState() {
- try {
- if (mSavedState != null) {
- mSavedState.close();
- }
- } catch (IOException e) {
- Slog.w(TAG, "Error closing old state file-descriptor");
- }
- try {
- if (mBackupData != null) {
- mBackupData.close();
- }
- } catch (IOException e) {
- Slog.w(TAG, "Error closing backup data file-descriptor");
- }
- try {
- if (mNewState != null) {
- mNewState.close();
- }
- } catch (IOException e) {
- Slog.w(TAG, "Error closing new state file-descriptor");
- }
+ // Cleanup common to both success and failure cases.
+ tryCloseFileDescriptor(mSavedState, "old state");
+ tryCloseFileDescriptor(mBackupData, "backup data");
+ tryCloseFileDescriptor(mNewState, "new state");
synchronized (mBackupManagerService.getCurrentOpLock()) {
- // Current-operation callback handling requires the validity of these various
- // bits of internal state as an invariant of the operation still being live.
- // This means we make sure to clear all of the state in unison inside the lock.
+ // TODO: Do we still need this?
mSavedState = mBackupData = mNewState = null;
}
- // If this was a pseudo-package there's no associated Activity Manager state
+ // For PM metadata (for which applicationInfo is null) there is no agent-bound state.
if (mCurrentPackage.applicationInfo != null) {
- mBackupManagerService.addBackupTrace("unbinding " + mCurrentPackage.packageName);
mBackupManagerService.unbindAgent(mCurrentPackage.applicationInfo);
}
}
+ private void tryCloseFileDescriptor(@Nullable Closeable closeable, String logName) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ mReporter.onCloseFileDescriptorError(logName);
+ }
+ }
+ }
+
private RemoteResult remoteCall(RemoteCallable<IBackupCallback> remoteCallable, long timeoutMs)
throws RemoteException {
mPendingCall = new RemoteCall(mCancelled, remoteCallable, timeoutMs);
RemoteResult result = mPendingCall.call();
- if (MORE_DEBUG) {
- Slog.v(TAG, "Agent call returned " + result);
- }
+ mReporter.onRemoteCallReturned(result);
mPendingCall = null;
return result;
}
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 28e9b77..9af952d 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -136,7 +136,14 @@
/**
* Checks if the app is in a stopped state. This is not part of the general "eligible for
* backup?" check because we *do* still need to restore data to apps in this state (e.g.
- * newly-installing ones)
+ * newly-installing ones).
+ *
+ * <p>Reasons for such state:
+ * <ul>
+ * <li>The app has been force-stopped.
+ * <li>The app has been cleared.
+ * <li>The app has just been installed.
+ * </ul>
*/
public static boolean appIsStopped(ApplicationInfo app) {
return ((app.flags & ApplicationInfo.FLAG_STOPPED) != 0);
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
index b23781d..6f08376 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
@@ -21,6 +21,7 @@
import static com.android.server.backup.BackupManagerService.DEBUG;
import static com.android.server.backup.BackupManagerService.TAG;
+import android.annotation.Nullable;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.IBackupManagerMonitor;
import android.content.pm.PackageInfo;
@@ -44,8 +45,13 @@
* @param extras - additional event data.
* @return <code>monitor</code> if call succeeded and <code>null</code> otherwise.
*/
- public static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
- PackageInfo pkg, int category, Bundle extras) {
+ @Nullable
+ public static IBackupManagerMonitor monitorEvent(
+ @Nullable IBackupManagerMonitor monitor,
+ int id,
+ PackageInfo pkg,
+ int category,
+ Bundle extras) {
if (monitor != null) {
try {
Bundle bundle = new Bundle();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6b3f8f8..914404b 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2194,8 +2194,7 @@
break;
}
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
- Integer score = (Integer) msg.obj;
- if (score != null) updateNetworkScore(nai, score.intValue());
+ updateNetworkScore(nai, msg.arg1);
break;
}
case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index d06e785..f4d20b3 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1014,12 +1014,7 @@
Bundle finalExtras = new Bundle(extras);
String packageName = syncAdapterInfo.componentName.getPackageName();
// If the app did not run and has no account access, done
- try {
- if (!mPackageManagerInternal.wasPackageEverLaunched(packageName, userId)) {
- continue;
- }
- } catch (IllegalArgumentException e) {
- // Package not found, race with an uninstall
+ if (!wasPackageEverLaunched(packageName, userId)) {
continue;
}
mAccountManagerInternal.requestAccountAccess(account.account,
@@ -3352,7 +3347,7 @@
String packageName = op.owningPackage;
final int userId = UserHandle.getUserId(op.owningUid);
// If the app did not run and has no account access, done
- if (!mPackageManagerInternal.wasPackageEverLaunched(packageName, userId)) {
+ if (!wasPackageEverLaunched(packageName, userId)) {
return;
}
mAccountManagerInternal.requestAccountAccess(op.target.account,
@@ -4059,4 +4054,12 @@
public void resetTodayStats() {
mSyncStorageEngine.resetTodayStats(/*force=*/ true);
}
+
+ private boolean wasPackageEverLaunched(String packageName, int userId) {
+ try {
+ return mPackageManagerInternal.wasPackageEverLaunched(packageName, userId);
+ } catch (IllegalArgumentException e) {
+ return false; // Package has been removed.
+ }
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3f57faf..f487200 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2144,6 +2144,10 @@
enforceSystemOrSystemUI("setNotificationsEnabledForPackage");
mPreferencesHelper.setEnabled(pkg, uid, enabled);
+ mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_BAN_APP_NOTES)
+ .setType(MetricsEvent.TYPE_ACTION)
+ .setPackageName(pkg)
+ .setSubtype(enabled ? 1 : 0));
// Now, cancel any outstanding notifications that are part of a just-disabled app
if (!enabled) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ed1dc58..5769207 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -917,6 +917,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
android.Manifest.permission.USER_ACTIVITY);
+ break;
case MSG_RINGER_TOGGLE_CHORD:
handleRingerChordGesture();
break;
@@ -2452,11 +2453,13 @@
attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
break;
case TYPE_STATUS_BAR:
+
// If the Keyguard is in a hidden state (occluded by another window), we force to
- // remove the keyguard flag so that any change in-flight after setting
- // the keyguard as occluded wouldn't set the flag again.
+ // remove the wallpaper and keyguard flag so that any change in-flight after setting
+ // the keyguard as occluded wouldn't set these flags again.
// See {@link #processKeyguardSetHiddenResultLw}.
if (mKeyguardOccluded) {
+ attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
break;
@@ -5517,13 +5520,17 @@
mKeyguardDelegate.setOccluded(false, true /* animate */);
if (mStatusBar != null) {
mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
+ if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
+ mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+ }
}
return true;
} else if (isOccluded && changed && showing) {
mKeyguardOccluded = true;
- mKeyguardDelegate.setOccluded(true, !mShowingDream /* animate */);
+ mKeyguardDelegate.setOccluded(true, false /* animate */);
if (mStatusBar != null) {
mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
+ mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
}
return true;
} else if (changed) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 3ae5ced..b55adeb 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1711,8 +1711,8 @@
}
/**
- * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
- * on the next user activity.
+ * Requests that the WindowManager sends
+ * WindowManagerPolicyConstants#ACTION_USER_ACTIVITY_NOTIFICATION on the next user activity.
*/
public void requestUserActivityNotification();
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 7ee35e7..d73606f 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1557,7 +1557,7 @@
if (isKeyguardGoingAwayTransit(transit) && enter) {
a = loadKeyguardExitAnimation(transit);
} else if (transit == TRANSIT_KEYGUARD_OCCLUDE) {
- a = loadAnimationRes(lp, com.android.internal.R.anim.keyguard_occlude_open_enter);
+ a = null;
} else if (transit == TRANSIT_KEYGUARD_UNOCCLUDE && !enter) {
a = loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit);
} else if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 44d0187..ae2256a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2128,6 +2128,8 @@
}
}
mService.mAnimator.removeDisplayLocked(mDisplayId);
+ mWindowingLayer.release();
+ mOverlayLayer.release();
} finally {
mRemovingDisplay = false;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index b5566a7..dea4076 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -361,6 +361,11 @@
new RemoteAnimationTarget[appAnimations.size()]);
mPendingStart = false;
+ // Perform layout if it was scheduled before to make sure that we get correct content
+ // insets for the target app window after a rotation
+ final DisplayContent displayContent = mService.mRoot.getDisplayContent(mDisplayId);
+ displayContent.performLayout(false /* initial */, false /* updateInputWindows */);
+
final Rect minimizedHomeBounds = mTargetAppToken != null
&& mTargetAppToken.inSplitScreenSecondaryWindowingMode()
? mMinimizedHomeBounds
@@ -369,8 +374,7 @@
&& mTargetAppToken.findMainWindow() != null
? mTargetAppToken.findMainWindow().mContentInsets
: null;
- mRunner.onAnimationStart(mController, appTargets, contentInsets,
- minimizedHomeBounds);
+ mRunner.onAnimationStart(mController, appTargets, contentInsets, minimizedHomeBounds);
if (DEBUG_RECENTS_ANIMATIONS) {
Slog.d(TAG, "startAnimation(): Notify animation start:");
for (int i = 0; i < mPendingAnimations.size(); i++) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b6f3d3b..c82c242 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -28,6 +28,7 @@
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteCompatibilityWalFlags;
+import android.database.sqlite.SQLiteGlobal;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
@@ -355,6 +356,10 @@
Binder.setWarnOnBlocking(true);
// The system server should always load safe labels
PackageItemInfo.setForceSafeLabels(true);
+
+ // Default to FULL within the system server.
+ SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;
+
// Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
SQLiteCompatibilityWalFlags.init(null);
diff --git a/services/robotests/README b/services/robotests/README
new file mode 100644
index 0000000..3c68292
--- /dev/null
+++ b/services/robotests/README
@@ -0,0 +1,23 @@
+This folder is for Robolectric tests inside the platform.
+
+To add a test class annotate it as follows:
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderClasses({ClassUnderTest.class, DependencyClasses.class})
+@SystemLoaderPackages({"com.android.server.yourmodule"})
+
+Robolectric loads some classes that it decides from versioned jars of the framework. Since we are
+part of the framework some of our classes get loaded from these jars. This is NOT what we want, we
+want to test against what we wrote in the tree. Because of this we use a custom test runner,
+FrameworkRobolectricTestRunner, that bypasses these jars and loads certain classes from the system
+class loader.
+
+To specify which classes to load use either @SystemLoaderClasses or @SystemLoaderPackages. In
+practice:
+* You MUST put the class under test here.
+* If you encounter any exceptions that might be caused by a different version of the class being
+loaded, such as NoSuchMethodException, put the class involved in the exception in this annotation
+and try again.
+
+Check Android.mk file for more info.
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index de22201..e316d5b 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -1382,6 +1382,7 @@
verify(agentMock.agent).onQuotaExceeded(anyLong(), eq(1234L));
assertEventLogged(EventLogTags.BACKUP_QUOTA_EXCEEDED, PACKAGE_1.packageName);
assertBackupNotPendingFor(PACKAGE_1);
+ // TODO: Assert about state/staging files (possible bug)
}
@Test
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 25851e3..b7ccee5 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -16,16 +16,16 @@
package android.telephony;
-import android.os.Parcel;
-import android.os.Parcelable;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSDPA;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_HSUPA;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSUPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+import android.os.Parcel;
+import android.os.Parcelable;
/**
@@ -100,6 +100,39 @@
mCid = cid;
}
+ /** @hide */
+ public NeighboringCellInfo(final CellInfoGsm info) {
+ mNetworkType = TelephonyManager.NETWORK_TYPE_GPRS;
+
+ mRssi = info.getCellSignalStrength().getAsuLevel();
+ if (mRssi == Integer.MAX_VALUE) mRssi = UNKNOWN_RSSI;
+
+ mLac = info.getCellIdentity().getLac();
+ if (mLac == Integer.MAX_VALUE) mLac = UNKNOWN_CID;
+
+ mCid = info.getCellIdentity().getCid();
+ if (mCid == Integer.MAX_VALUE) mCid = UNKNOWN_CID;
+
+ mPsc = UNKNOWN_CID;
+ }
+
+ /** @hide */
+ public NeighboringCellInfo(final CellInfoWcdma info) {
+ mNetworkType = TelephonyManager.NETWORK_TYPE_UMTS;
+
+ mRssi = info.getCellSignalStrength().getAsuLevel();
+ if (mRssi == Integer.MAX_VALUE) mRssi = UNKNOWN_RSSI;
+
+ mLac = info.getCellIdentity().getLac();
+ if (mLac == Integer.MAX_VALUE) mLac = UNKNOWN_CID;
+
+ mCid = info.getCellIdentity().getCid();
+ if (mCid == Integer.MAX_VALUE) mCid = UNKNOWN_CID;
+
+ mPsc = info.getCellIdentity().getPsc();
+ if (mPsc == Integer.MAX_VALUE) mPsc = UNKNOWN_CID;
+ }
+
/**
* Initialize the object from rssi, location string, and radioType
* radioType is one of following
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b2eb5e0..8782a41 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1544,7 +1544,7 @@
* @return List of NeighboringCellInfo or null if info unavailable.
*
* @deprecated Use {@link #getAllCellInfo} which returns a superset of the information
- * from NeighboringCellInfo.
+ * from NeighboringCellInfo, including LTE cell information.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index c6f8622..e924a25 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -16,10 +16,14 @@
package android.telephony.ims;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Provides the result to the update operation for the supplementary service configuration.
*
@@ -34,6 +38,30 @@
public static final int DISABLED = 0;
public static final int ENABLED = 1;
+ /**
+ * Provision status of service
+ */
+ /** @hide */
+ @IntDef({
+ SERVICE_PROVISIONING_UNKNOWN,
+ SERVICE_NOT_PROVISIONED,
+ SERVICE_PROVISIONED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ServiceProvisionStatus {}
+ /**
+ * Unknown provision status for the service.
+ */
+ public static final int SERVICE_PROVISIONING_UNKNOWN = (-1);
+ /**
+ * Service is not provisioned.
+ */
+ public static final int SERVICE_NOT_PROVISIONED = 0;
+ /**
+ * Service is provisioned.
+ */
+ public static final int SERVICE_PROVISIONED = 1;
+
// 0: disabled, 1: enabled
/** @hide */
// TODO: Make private, do not modify this field directly, use getter!
@@ -41,6 +69,8 @@
/** @hide */
// TODO: Make private, do not modify this field directly, use getter!
public String mIcbNum;
+ /** @hide */
+ public int mProvisionStatus = SERVICE_PROVISIONING_UNKNOWN;
/**@hide*/
// TODO: Remove! Do not use this constructor, instead use public version.
@@ -74,16 +104,30 @@
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mStatus);
out.writeString(mIcbNum);
+ out.writeInt(mProvisionStatus);
}
@Override
public String toString() {
- return super.toString() + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled");
+ return super.toString() + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled")
+ + ", ProvisionStatus: " + provisionStatusToString(mProvisionStatus);
+ }
+
+ private static String provisionStatusToString(int pStatus) {
+ switch (pStatus) {
+ case SERVICE_NOT_PROVISIONED:
+ return "Service not provisioned";
+ case SERVICE_PROVISIONED:
+ return "Service provisioned";
+ default:
+ return "Service provisioning unknown";
+ }
}
private void readFromParcel(Parcel in) {
mStatus = in.readInt();
mIcbNum = in.readString();
+ mProvisionStatus = in.readInt();
}
public static final Creator<ImsSsInfo> CREATOR =
@@ -112,4 +156,15 @@
public String getIcbNum() {
return mIcbNum;
}
+
+ /**
+ * @return Supplementary Service Provision status. Valid Values are:
+ * {@link #SERVICE_PROVISIONING_UNKNOWN},
+ * {@link #SERVICE_NOT_PROVISIONED},
+ * {@link #SERVICE_PROVISIONED}
+ */
+ @ServiceProvisionStatus
+ public int getProvisionStatus() {
+ return mProvisionStatus;
+ }
}