summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--api/system-current.txt18
-rw-r--r--core/java/android/app/SystemServiceRegistry.java13
-rw-r--r--core/java/android/content/Context.java14
-rw-r--r--core/java/android/os/ISystemUpdateManager.aidl27
-rw-r--r--core/java/android/os/SystemUpdateManager.java152
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--services/core/java/com/android/server/SystemUpdateManagerService.java255
-rw-r--r--services/java/com/android/server/SystemServer.java9
9 files changed, 493 insertions, 1 deletions
diff --git a/Android.bp b/Android.bp
index 641ce5fdff3c..d1332bb4fe87 100644
--- a/Android.bp
+++ b/Android.bp
@@ -230,6 +230,7 @@ java_library {
"core/java/android/os/ISchedulingPolicyService.aidl",
"core/java/android/os/IStatsCompanionService.aidl",
"core/java/android/os/IStatsManager.aidl",
+ "core/java/android/os/ISystemUpdateManager.aidl",
"core/java/android/os/IThermalEventListener.aidl",
"core/java/android/os/IThermalService.aidl",
"core/java/android/os/IUpdateLock.aidl",
diff --git a/api/system-current.txt b/api/system-current.txt
index dcea0044272f..a1ec2c44cd49 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -131,6 +131,7 @@ package android {
field public static final java.lang.String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
field public static final java.lang.String READ_RUNTIME_PROFILES = "android.permission.READ_RUNTIME_PROFILES";
field public static final java.lang.String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
+ field public static final java.lang.String READ_SYSTEM_UPDATE_INFO = "android.permission.READ_SYSTEM_UPDATE_INFO";
field public static final java.lang.String READ_WALLPAPER_INTERNAL = "android.permission.READ_WALLPAPER_INTERNAL";
field public static final java.lang.String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL";
field public static final java.lang.String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS";
@@ -761,6 +762,7 @@ package android.content {
field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
field public static final java.lang.String STATS_MANAGER = "stats";
+ field public static final java.lang.String SYSTEM_UPDATE_SERVICE = "system_update";
field public static final java.lang.String VR_SERVICE = "vrmanager";
field public static final java.lang.String WIFI_RTT_SERVICE = "rttmanager";
field public static final java.lang.String WIFI_SCANNING_SERVICE = "wifiscanner";
@@ -3503,6 +3505,22 @@ package android.os {
method public abstract void onResult(android.os.Bundle);
}
+ public class SystemUpdateManager {
+ method public android.os.Bundle retrieveSystemUpdateInfo();
+ method public void updateSystemUpdateInfo(android.os.PersistableBundle);
+ field public static final java.lang.String KEY_IS_SECURITY_UPDATE = "is_security_update";
+ field public static final java.lang.String KEY_STATUS = "status";
+ field public static final java.lang.String KEY_TARGET_BUILD_FINGERPRINT = "target_build_fingerprint";
+ field public static final java.lang.String KEY_TARGET_SECURITY_PATCH_LEVEL = "target_security_patch_level";
+ field public static final java.lang.String KEY_TITLE = "title";
+ field public static final int STATUS_IDLE = 1; // 0x1
+ field public static final int STATUS_IN_PROGRESS = 3; // 0x3
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int STATUS_WAITING_DOWNLOAD = 2; // 0x2
+ field public static final int STATUS_WAITING_INSTALL = 4; // 0x4
+ field public static final int STATUS_WAITING_REBOOT = 5; // 0x5
+ }
+
public class UpdateEngine {
ctor public UpdateEngine();
method public void applyPayload(java.lang.String, long, long, java.lang.String[]);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 33277eae0520..fb8d1017e205 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -112,6 +112,7 @@ import android.os.IBinder;
import android.os.IHardwarePropertiesManager;
import android.os.IPowerManager;
import android.os.IRecoverySystem;
+import android.os.ISystemUpdateManager;
import android.os.IUserManager;
import android.os.IncidentManager;
import android.os.PowerManager;
@@ -119,6 +120,7 @@ import android.os.Process;
import android.os.RecoverySystem;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.SystemUpdateManager;
import android.os.SystemVibrator;
import android.os.UserHandle;
import android.os.UserManager;
@@ -485,6 +487,17 @@ final class SystemServiceRegistry {
return new StorageStatsManager(ctx, service);
}});
+ registerService(Context.SYSTEM_UPDATE_SERVICE, SystemUpdateManager.class,
+ new CachedServiceFetcher<SystemUpdateManager>() {
+ @Override
+ public SystemUpdateManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.SYSTEM_UPDATE_SERVICE);
+ ISystemUpdateManager service = ISystemUpdateManager.Stub.asInterface(b);
+ return new SystemUpdateManager(service);
+ }});
+
registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
new CachedServiceFetcher<TelephonyManager>() {
@Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 265f7c7425db..f69aab01d821 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3024,7 +3024,8 @@ public abstract class Context {
//@hide: INCIDENT_SERVICE,
//@hide: STATS_COMPANION_SERVICE,
COMPANION_DEVICE_SERVICE,
- CROSS_PROFILE_APPS_SERVICE
+ CROSS_PROFILE_APPS_SERVICE,
+ //@hide: SYSTEM_UPDATE_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -3242,6 +3243,17 @@ public abstract class Context {
/**
* Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.os.SystemUpdateManager} for accessing the system update
+ * manager service.
+ *
+ * @see #getSystemService(String)
+ * @hide
+ */
+ @SystemApi
+ public static final String SYSTEM_UPDATE_SERVICE = "system_update";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.WindowManager} for accessing the system's window
* manager.
*
diff --git a/core/java/android/os/ISystemUpdateManager.aidl b/core/java/android/os/ISystemUpdateManager.aidl
new file mode 100644
index 000000000000..f7f50791f528
--- /dev/null
+++ b/core/java/android/os/ISystemUpdateManager.aidl
@@ -0,0 +1,27 @@
+/* //device/java/android/android/os/ISystemUpdateInfo.aidl
+**
+** 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.
+*/
+
+package android.os;
+
+import android.os.Bundle;
+import android.os.PersistableBundle;
+
+/** @hide */
+interface ISystemUpdateManager {
+ Bundle retrieveSystemUpdateInfo();
+ void updateSystemUpdateInfo(in PersistableBundle data);
+}
diff --git a/core/java/android/os/SystemUpdateManager.java b/core/java/android/os/SystemUpdateManager.java
new file mode 100644
index 000000000000..ce3e225975f0
--- /dev/null
+++ b/core/java/android/os/SystemUpdateManager.java
@@ -0,0 +1,152 @@
+/*
+ * 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.os;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * Allows querying and posting system update information.
+ *
+ * {@hide}
+ */
+@SystemApi
+@SystemService(Context.SYSTEM_UPDATE_SERVICE)
+public class SystemUpdateManager {
+ private static final String TAG = "SystemUpdateManager";
+
+ /** The status key of the system update info, expecting an int value. */
+ @SystemApi
+ public static final String KEY_STATUS = "status";
+
+ /** The title of the current update, expecting a String value. */
+ @SystemApi
+ public static final String KEY_TITLE = "title";
+
+ /** Whether it is a security update, expecting a boolean value. */
+ @SystemApi
+ public static final String KEY_IS_SECURITY_UPDATE = "is_security_update";
+
+ /** The build fingerprint after installing the current update, expecting a String value. */
+ @SystemApi
+ public static final String KEY_TARGET_BUILD_FINGERPRINT = "target_build_fingerprint";
+
+ /** The security patch level after installing the current update, expecting a String value. */
+ @SystemApi
+ public static final String KEY_TARGET_SECURITY_PATCH_LEVEL = "target_security_patch_level";
+
+ /**
+ * The KEY_STATUS value that indicates there's no update status info available.
+ */
+ @SystemApi
+ public static final int STATUS_UNKNOWN = 0;
+
+ /**
+ * The KEY_STATUS value that indicates there's no pending update.
+ */
+ @SystemApi
+ public static final int STATUS_IDLE = 1;
+
+ /**
+ * The KEY_STATUS value that indicates an update is available for download, but pending user
+ * approval to start.
+ */
+ @SystemApi
+ public static final int STATUS_WAITING_DOWNLOAD = 2;
+
+ /**
+ * The KEY_STATUS value that indicates an update is in progress (i.e. downloading or installing
+ * has started).
+ */
+ @SystemApi
+ public static final int STATUS_IN_PROGRESS = 3;
+
+ /**
+ * The KEY_STATUS value that indicates an update is available for install.
+ */
+ @SystemApi
+ public static final int STATUS_WAITING_INSTALL = 4;
+
+ /**
+ * The KEY_STATUS value that indicates an update will be installed after a reboot. This applies
+ * to both of A/B and non-A/B OTAs.
+ */
+ @SystemApi
+ public static final int STATUS_WAITING_REBOOT = 5;
+
+ private final ISystemUpdateManager mService;
+
+ /** @hide */
+ public SystemUpdateManager(ISystemUpdateManager service) {
+ mService = checkNotNull(service, "missing ISystemUpdateManager");
+ }
+
+ /**
+ * Queries the current pending system update info.
+ *
+ * <p>Requires the {@link android.Manifest.permission#READ_SYSTEM_UPDATE_INFO} or
+ * {@link android.Manifest.permission#RECOVERY} permission.
+ *
+ * @return A {@code Bundle} that contains the pending system update information in key-value
+ * pairs.
+ *
+ * @throws SecurityException if the caller is not allowed to read the info.
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_SYSTEM_UPDATE_INFO,
+ android.Manifest.permission.RECOVERY,
+ })
+ public Bundle retrieveSystemUpdateInfo() {
+ try {
+ return mService.retrieveSystemUpdateInfo();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Allows a system updater to publish the pending update info.
+ *
+ * <p>The reported info will not persist across reboots. Because only the reporting updater
+ * understands the criteria to determine a successful/failed update.
+ *
+ * <p>Requires the {@link android.Manifest.permission#RECOVERY} permission.
+ *
+ * @param infoBundle The {@code PersistableBundle} that contains the system update information,
+ * such as the current update status. {@link #KEY_STATUS} is required in the bundle.
+ *
+ * @throws IllegalArgumentException if @link #KEY_STATUS} does not exist.
+ * @throws SecurityException if the caller is not allowed to update the info.
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.RECOVERY)
+ public void updateSystemUpdateInfo(PersistableBundle infoBundle) {
+ if (infoBundle == null || !infoBundle.containsKey(KEY_STATUS)) {
+ throw new IllegalArgumentException("Missing status in the bundle");
+ }
+ try {
+ mService.updateSystemUpdateInfo(infoBundle);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ba30981e6377..bf9d79bc75dd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2313,6 +2313,11 @@
<permission android:name="android.permission.RECOVERY"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows an application to read system update info.
+ @hide -->
+ <permission android:name="android.permission.READ_SYSTEM_UPDATE_INFO"
+ android:protectionLevel="signature" />
+
<!-- Allows the system to bind to an application's task services
@hide -->
<permission android:name="android.permission.BIND_JOB_SERVICE"
diff --git a/services/core/java/com/android/server/SystemUpdateManagerService.java b/services/core/java/com/android/server/SystemUpdateManagerService.java
new file mode 100644
index 000000000000..6c1ffdd32d18
--- /dev/null
+++ b/services/core/java/com/android/server/SystemUpdateManagerService.java
@@ -0,0 +1,255 @@
+/*
+ * 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;
+
+import static android.os.SystemUpdateManager.KEY_STATUS;
+import static android.os.SystemUpdateManager.STATUS_IDLE;
+import static android.os.SystemUpdateManager.STATUS_UNKNOWN;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
+import android.Manifest;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.ISystemUpdateManager;
+import android.os.PersistableBundle;
+import android.os.SystemUpdateManager;
+import android.provider.Settings;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+public class SystemUpdateManagerService extends ISystemUpdateManager.Stub {
+
+ private static final String TAG = "SystemUpdateManagerService";
+
+ private static final int UID_UNKNOWN = -1;
+
+ private static final String INFO_FILE = "system-update-info.xml";
+ private static final int INFO_FILE_VERSION = 0;
+ private static final String TAG_INFO = "info";
+ private static final String KEY_VERSION = "version";
+ private static final String KEY_UID = "uid";
+ private static final String KEY_BOOT_COUNT = "boot-count";
+ private static final String KEY_INFO_BUNDLE = "info-bundle";
+
+ private final Context mContext;
+ private final AtomicFile mFile;
+ private final Object mLock = new Object();
+ private int mLastUid = UID_UNKNOWN;
+ private int mLastStatus = STATUS_UNKNOWN;
+
+ public SystemUpdateManagerService(Context context) {
+ mContext = context;
+ mFile = new AtomicFile(new File(Environment.getDataSystemDirectory(), INFO_FILE));
+
+ // Populate mLastUid and mLastStatus.
+ synchronized (mLock) {
+ loadSystemUpdateInfoLocked();
+ }
+ }
+
+ @Override
+ public void updateSystemUpdateInfo(PersistableBundle infoBundle) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.RECOVERY, TAG);
+
+ int status = infoBundle.getInt(KEY_STATUS, STATUS_UNKNOWN);
+ if (status == STATUS_UNKNOWN) {
+ Slog.w(TAG, "Invalid status info. Ignored");
+ return;
+ }
+
+ // There could be multiple updater apps running on a device. But only one at most should
+ // be active (i.e. with a pending update), with the rest reporting idle status. We will
+ // only accept the reported status if any of the following conditions holds:
+ // a) none has been reported before;
+ // b) the current on-file status was last reported by the same caller;
+ // c) an active update is being reported.
+ int uid = Binder.getCallingUid();
+ if (mLastUid == UID_UNKNOWN || mLastUid == uid || status != STATUS_IDLE) {
+ synchronized (mLock) {
+ saveSystemUpdateInfoLocked(infoBundle, uid);
+ }
+ } else {
+ Slog.i(TAG, "Inactive updater reporting IDLE status. Ignored");
+ }
+ }
+
+ @Override
+ public Bundle retrieveSystemUpdateInfo() {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.READ_SYSTEM_UPDATE_INFO)
+ == PackageManager.PERMISSION_DENIED
+ && mContext.checkCallingOrSelfPermission(Manifest.permission.RECOVERY)
+ == PackageManager.PERMISSION_DENIED) {
+ throw new SecurityException("Can't read system update info. Requiring "
+ + "READ_SYSTEM_UPDATE_INFO or RECOVERY permission.");
+ }
+
+ synchronized (mLock) {
+ return loadSystemUpdateInfoLocked();
+ }
+ }
+
+ // Reads and validates the info file. Returns the loaded info bundle on success; or a default
+ // info bundle with UNKNOWN status.
+ private Bundle loadSystemUpdateInfoLocked() {
+ PersistableBundle loadedBundle = null;
+ try (FileInputStream fis = mFile.openRead()) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(fis, StandardCharsets.UTF_8.name());
+ loadedBundle = readInfoFileLocked(parser);
+ } catch (FileNotFoundException e) {
+ Slog.i(TAG, "No existing info file " + mFile.getBaseFile());
+ } catch (XmlPullParserException e) {
+ Slog.e(TAG, "Failed to parse the info file:", e);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to read the info file:", e);
+ }
+
+ // Validate the loaded bundle.
+ if (loadedBundle == null) {
+ return removeInfoFileAndGetDefaultInfoBundleLocked();
+ }
+
+ int version = loadedBundle.getInt(KEY_VERSION, -1);
+ if (version == -1) {
+ Slog.w(TAG, "Invalid info file (invalid version). Ignored");
+ return removeInfoFileAndGetDefaultInfoBundleLocked();
+ }
+
+ int lastUid = loadedBundle.getInt(KEY_UID, -1);
+ if (lastUid == -1) {
+ Slog.w(TAG, "Invalid info file (invalid UID). Ignored");
+ return removeInfoFileAndGetDefaultInfoBundleLocked();
+ }
+
+ int lastBootCount = loadedBundle.getInt(KEY_BOOT_COUNT, -1);
+ if (lastBootCount == -1 || lastBootCount != getBootCount()) {
+ Slog.w(TAG, "Outdated info file. Ignored");
+ return removeInfoFileAndGetDefaultInfoBundleLocked();
+ }
+
+ PersistableBundle infoBundle = loadedBundle.getPersistableBundle(KEY_INFO_BUNDLE);
+ if (infoBundle == null) {
+ Slog.w(TAG, "Invalid info file (missing info). Ignored");
+ return removeInfoFileAndGetDefaultInfoBundleLocked();
+ }
+
+ int lastStatus = infoBundle.getInt(KEY_STATUS, STATUS_UNKNOWN);
+ if (lastStatus == STATUS_UNKNOWN) {
+ Slog.w(TAG, "Invalid info file (invalid status). Ignored");
+ return removeInfoFileAndGetDefaultInfoBundleLocked();
+ }
+
+ // Everything looks good upon reaching this point.
+ mLastStatus = lastStatus;
+ mLastUid = lastUid;
+ return new Bundle(infoBundle);
+ }
+
+ private void saveSystemUpdateInfoLocked(PersistableBundle infoBundle, int uid) {
+ // Wrap the incoming bundle with extra info (e.g. version, uid, boot count). We use nested
+ // PersistableBundle to avoid manually parsing XML attributes when loading the info back.
+ PersistableBundle outBundle = new PersistableBundle();
+ outBundle.putPersistableBundle(KEY_INFO_BUNDLE, infoBundle);
+ outBundle.putInt(KEY_VERSION, INFO_FILE_VERSION);
+ outBundle.putInt(KEY_UID, uid);
+ outBundle.putInt(KEY_BOOT_COUNT, getBootCount());
+
+ // Only update the info on success.
+ if (writeInfoFileLocked(outBundle)) {
+ mLastUid = uid;
+ mLastStatus = infoBundle.getInt(KEY_STATUS);
+ }
+ }
+
+ // Performs I/O work only, without validating the loaded info.
+ @Nullable
+ private PersistableBundle readInfoFileLocked(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != END_DOCUMENT) {
+ if (type == START_TAG && TAG_INFO.equals(parser.getName())) {
+ return PersistableBundle.restoreFromXml(parser);
+ }
+ }
+ return null;
+ }
+
+ private boolean writeInfoFileLocked(PersistableBundle outBundle) {
+ FileOutputStream fos = null;
+ try {
+ fos = mFile.startWrite();
+
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(fos, StandardCharsets.UTF_8.name());
+ out.startDocument(null, true);
+
+ out.startTag(null, TAG_INFO);
+ outBundle.saveToXml(out);
+ out.endTag(null, TAG_INFO);
+
+ out.endDocument();
+ mFile.finishWrite(fos);
+ return true;
+ } catch (IOException | XmlPullParserException e) {
+ Slog.e(TAG, "Failed to save the info file:", e);
+ if (fos != null) {
+ mFile.failWrite(fos);
+ }
+ }
+ return false;
+ }
+
+ private Bundle removeInfoFileAndGetDefaultInfoBundleLocked() {
+ if (mFile.exists()) {
+ Slog.i(TAG, "Removing info file");
+ mFile.delete();
+ }
+
+ mLastStatus = STATUS_UNKNOWN;
+ mLastUid = UID_UNKNOWN;
+ Bundle infoBundle = new Bundle();
+ infoBundle.putInt(KEY_STATUS, STATUS_UNKNOWN);
+ return infoBundle;
+ }
+
+ private int getBootCount() {
+ return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
+ }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e660c50fcbc1..94a356e65878 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1172,6 +1172,15 @@ public final class SystemServer {
}
traceEnd();
+ traceBeginAndSlog("StartSystemUpdateManagerService");
+ try {
+ ServiceManager.addService(Context.SYSTEM_UPDATE_SERVICE,
+ new SystemUpdateManagerService(context));
+ } catch (Throwable e) {
+ reportWtf("starting SystemUpdateManagerService", e);
+ }
+ traceEnd();
+
traceBeginAndSlog("StartUpdateLockService");
try {
ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,