summaryrefslogtreecommitdiff
path: root/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'cmds')
-rw-r--r--cmds/am/src/com/android/commands/am/Instrument.java13
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java114
-rw-r--r--cmds/bootanimation/Android.mk29
-rw-r--r--cmds/bootanimation/BootAnimation.cpp17
-rw-r--r--cmds/bootanimation/BootAnimation.h40
-rw-r--r--cmds/bootanimation/BootAnimationUtil.cpp61
-rw-r--r--cmds/bootanimation/BootAnimationUtil.h25
-rw-r--r--cmds/bootanimation/bootanimation_main.cpp116
-rw-r--r--cmds/bootanimation/iot/BootAction.cpp175
-rw-r--r--cmds/bootanimation/iot/BootAction.h63
-rw-r--r--cmds/bootanimation/iot/iotbootanimation_main.cpp93
-rw-r--r--cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java8
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java4
-rw-r--r--cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java120
14 files changed, 725 insertions, 153 deletions
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 4966b4380d9b..c6d83f51a40a 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -25,7 +25,6 @@ import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.os.Build;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.AndroidException;
@@ -34,6 +33,8 @@ import android.view.IWindowManager;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
@@ -95,6 +96,12 @@ public class Instrument {
public void onError(String errorText, boolean commandError);
}
+ private static Collection<String> sorted(Collection<String> list) {
+ final ArrayList<String> copy = new ArrayList<>(list);
+ Collections.sort(copy);
+ return copy;
+ }
+
/**
* Printer for the 'classic' text based status reporting.
*/
@@ -124,7 +131,7 @@ public class Instrument {
System.out.print(pretty);
} else {
if (results != null) {
- for (String key : results.keySet()) {
+ for (String key : sorted(results.keySet())) {
System.out.println(
"INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
}
@@ -214,7 +221,7 @@ public class Instrument {
private void writeBundle(ProtoOutputStream proto, long fieldId, Bundle bundle) {
final long bundleToken = proto.startObject(fieldId);
- for (final String key: bundle.keySet()) {
+ for (final String key: sorted(bundle.keySet())) {
final long entryToken = proto.startRepeatedObject(
InstrumentationData.ResultsBundle.ENTRIES);
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 1bcfb22fe2f2..b61cdecbfb7b 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -17,8 +17,8 @@
package com.android.commands.bmgr;
import android.app.backup.BackupManager;
-import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupProgress;
+import android.app.backup.BackupTransport;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupObserver;
import android.app.backup.IRestoreObserver;
@@ -30,8 +30,11 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.UserHandle;
-import android.util.Log;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.HashSet;
@@ -97,6 +100,11 @@ public final class Bmgr {
return;
}
+ if ("init".equals(op)) {
+ doInit();
+ return;
+ }
+
if ("list".equals(op)) {
doList();
return;
@@ -204,7 +212,7 @@ public final class Bmgr {
System.out.println("Performing full transport backup");
String pkg;
- ArrayList<String> allPkgs = new ArrayList<String>();
+ ArraySet<String> allPkgs = new ArraySet<String>();
while ((pkg = nextArg()) != null) {
allPkgs.add(pkg);
}
@@ -218,45 +226,77 @@ public final class Bmgr {
}
}
- class BackupObserver extends IBackupObserver.Stub {
- boolean done = false;
+ // IBackupObserver generically usable for any backup/init operation
+ abstract class Observer extends IBackupObserver.Stub {
+ private final Object trigger = new Object();
+
+ @GuardedBy("trigger")
+ private volatile boolean done = false;
@Override
public void onUpdate(String currentPackage, BackupProgress backupProgress) {
- System.out.println(
- "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred
- + "/" + backupProgress.bytesExpected);
}
@Override
public void onResult(String currentPackage, int status) {
- System.out.println("Package " + currentPackage + " with result: "
- + convertBackupStatusToString(status));
}
@Override
public void backupFinished(int status) {
- System.out.println("Backup finished with result: "
- + convertBackupStatusToString(status));
- synchronized (this) {
+ synchronized (trigger) {
done = true;
- this.notify();
+ trigger.notify();
}
}
+ public boolean done() {
+ return this.done;
+ }
+
+ // Wait forever
public void waitForCompletion() {
+ waitForCompletion(0);
+ }
+
+ // Wait for a given time and then give up
+ public void waitForCompletion(long timeout) {
// The backupFinished() callback will throw the 'done' flag; we
// just sit and wait on that notification.
- synchronized (this) {
- while (!this.done) {
+ final long targetTime = SystemClock.elapsedRealtime() + timeout;
+ synchronized (trigger) {
+ // Wait until either we're done, or we've reached a stated positive timeout
+ while (!done && (timeout <= 0 || SystemClock.elapsedRealtime() < targetTime)) {
try {
- this.wait();
+ trigger.wait(1000L);
} catch (InterruptedException ex) {
}
}
}
}
+ }
+
+ class BackupObserver extends Observer {
+ @Override
+ public void onUpdate(String currentPackage, BackupProgress backupProgress) {
+ super.onUpdate(currentPackage, backupProgress);
+ System.out.println(
+ "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred
+ + "/" + backupProgress.bytesExpected);
+ }
+ @Override
+ public void onResult(String currentPackage, int status) {
+ super.onResult(currentPackage, status);
+ System.out.println("Package " + currentPackage + " with result: "
+ + convertBackupStatusToString(status));
+ }
+
+ @Override
+ public void backupFinished(int status) {
+ super.backupFinished(status);
+ System.out.println("Backup finished with result: "
+ + convertBackupStatusToString(status));
+ }
}
private static String convertBackupStatusToString(int errorCode) {
@@ -270,7 +310,8 @@ public final class Bmgr {
case BackupManager.ERROR_TRANSPORT_ABORTED:
return "Transport error";
case BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED:
- return "Transport rejected package";
+ return "Transport rejected package because it wasn't able to process it"
+ + " at the time";
case BackupManager.ERROR_AGENT_FAILURE:
return "Agent error";
case BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED:
@@ -348,7 +389,9 @@ public final class Bmgr {
} else if (pkg.equals("--incremental")) {
nonIncrementalBackup = false;
} else {
- allPkgs.add(pkg);
+ if (!allPkgs.contains(pkg)) {
+ allPkgs.add(pkg);
+ }
}
}
if (backupAll) {
@@ -469,6 +512,39 @@ public final class Bmgr {
}
}
+ class InitObserver extends Observer {
+ public int result = BackupTransport.TRANSPORT_ERROR;
+
+ @Override
+ public void backupFinished(int status) {
+ super.backupFinished(status);
+ result = status;
+ }
+ }
+
+ private void doInit() {
+ ArraySet<String> transports = new ArraySet<>();
+ String transport;
+ while ((transport = nextArg()) != null) {
+ transports.add(transport);
+ }
+ if (transports.size() == 0) {
+ showUsage();
+ return;
+ }
+
+ InitObserver observer = new InitObserver();
+ try {
+ System.out.println("Initializing transports: " + transports);
+ mBmgr.initializeTransports(transports.toArray(new String[transports.size()]), observer);
+ observer.waitForCompletion(30*1000L);
+ System.out.println("Initialization result: " + observer.result);
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(BMGR_NOT_RUNNING_ERR);
+ }
+ }
+
private void doList() {
String arg = nextArg(); // sets, transports, packages set#
if ("transports".equals(arg)) {
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 7ab402a2cd46..73ec63f396b4 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -8,10 +8,6 @@ bootanimation_CommonCFlags += -Wall -Werror -Wunused -Wunreachable-code
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- bootanimation_main.cpp \
- audioplay.cpp \
-
LOCAL_CFLAGS += ${bootanimation_CommonCFlags}
LOCAL_SHARED_LIBRARIES := \
@@ -24,6 +20,29 @@ LOCAL_SHARED_LIBRARIES := \
liblog \
libutils \
+LOCAL_SRC_FILES:= \
+ BootAnimationUtil.cpp \
+
+ifeq ($(PRODUCT_IOT),true)
+LOCAL_SRC_FILES += \
+ iot/iotbootanimation_main.cpp \
+ iot/BootAction.cpp
+
+LOCAL_SHARED_LIBRARIES += \
+ libandroidthings \
+ libbase \
+ libbinder
+
+LOCAL_STATIC_LIBRARIES += cpufeatures
+
+else
+
+LOCAL_SRC_FILES += \
+ bootanimation_main.cpp \
+ audioplay.cpp \
+
+endif # PRODUCT_IOT
+
LOCAL_MODULE:= bootanimation
LOCAL_INIT_RC := bootanim.rc
@@ -45,6 +64,8 @@ LOCAL_CFLAGS += ${bootanimation_CommonCFlags}
LOCAL_SRC_FILES:= \
BootAnimation.cpp
+LOCAL_CFLAGS += ${bootanimation_CommonCFlags}
+
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
frameworks/wilhelm/include
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6b2de4b7f1ff..6526123aba13 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -96,11 +96,9 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16;
// ---------------------------------------------------------------------------
-BootAnimation::BootAnimation(InitCallback initCallback,
- PlayPartCallback partCallback)
+BootAnimation::BootAnimation(sp<Callbacks> callbacks)
: Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
- mTimeFormat12Hour(false), mTimeCheckThread(NULL),
- mInitCallback(initCallback), mPlayPartCallback(partCallback) {
+ mTimeFormat12Hour(false), mTimeCheckThread(NULL), mCallbacks(callbacks) {
mSession = new SurfaceComposerClient();
std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
@@ -357,6 +355,8 @@ bool BootAnimation::android()
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
+ mCallbacks->init({});
+
// clear screen
glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
@@ -424,6 +424,7 @@ void BootAnimation::checkExit() {
int exitnow = atoi(value);
if (exitnow) {
requestExit();
+ mCallbacks->shutdown();
}
}
@@ -777,9 +778,7 @@ bool BootAnimation::preloadZip(Animation& animation)
}
}
- if (mInitCallback != nullptr) {
- mInitCallback(animation.parts);
- }
+ mCallbacks->init(animation.parts);
zip->endIteration(cookie);
@@ -887,9 +886,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
if(exitPending() && !part.playUntilComplete)
break;
- if (mPlayPartCallback != nullptr) {
- mPlayPartCallback(i, part, r);
- }
+ mCallbacks->playPart(i, part, r);
glClearColor(
part.backgroundColor[0],
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 3ebe7d6e4dff..56e131523bcb 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -93,22 +93,27 @@ public:
Font clockFont;
};
- // Callback will be called during initialization after we have loaded
- // the animation and be provided with all parts in animation.
- typedef std::function<void(const Vector<Animation::Part>& parts)> InitCallback;
-
- // Callback will be called while animation is playing before each part is
- // played. It will be provided with the part and play count for it.
- // It will be provided with the partNumber for the part about to be played,
- // as well as a reference to the part itself. It will also be provided with
- // which play of that part is about to start, some parts are repeated
- // multiple times.
- typedef std::function<void(int partNumber, const Animation::Part& part, int playNumber)>
- PlayPartCallback;
-
- // Callbacks may be null and will be called from this class's internal
- // thread.
- BootAnimation(InitCallback initCallback, PlayPartCallback partCallback);
+ // All callbacks will be called from this class's internal thread.
+ class Callbacks : public RefBase {
+ public:
+ // Will be called during initialization after we have loaded
+ // the animation and be provided with all parts in animation.
+ virtual void init(const Vector<Animation::Part>& /*parts*/) {}
+
+ // Will be called while animation is playing before each part is
+ // played. It will be provided with the part and play count for it.
+ // It will be provided with the partNumber for the part about to be played,
+ // as well as a reference to the part itself. It will also be provided with
+ // which play of that part is about to start, some parts are repeated
+ // multiple times.
+ virtual void playPart(int /*partNumber*/, const Animation::Part& /*part*/,
+ int /*playNumber*/) {}
+
+ // Will be called when animation is done and thread is shutting down.
+ virtual void shutdown() {}
+ };
+
+ BootAnimation(sp<Callbacks> callbacks);
sp<SurfaceComposerClient> session() const;
@@ -170,8 +175,7 @@ private:
String8 mZipFileName;
SortedVector<String8> mLoadedFiles;
sp<TimeCheckThread> mTimeCheckThread = nullptr;
- InitCallback mInitCallback = nullptr;
- PlayPartCallback mPlayPartCallback = nullptr;
+ sp<Callbacks> mCallbacks;
};
// ---------------------------------------------------------------------------
diff --git a/cmds/bootanimation/BootAnimationUtil.cpp b/cmds/bootanimation/BootAnimationUtil.cpp
new file mode 100644
index 000000000000..7718daf61d81
--- /dev/null
+++ b/cmds/bootanimation/BootAnimationUtil.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BootAnimationUtil.h"
+
+#include <inttypes.h>
+
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+
+bool bootAnimationDisabled() {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.sf.nobootanimation", value, "0");
+ if (atoi(value) > 0) {
+ return true;
+ }
+
+ property_get("ro.boot.quiescent", value, "0");
+ return atoi(value) > 0;
+}
+
+void waitForSurfaceFlinger() {
+ // TODO: replace this with better waiting logic in future, b/35253872
+ int64_t waitStartTime = elapsedRealtime();
+ sp<IServiceManager> sm = defaultServiceManager();
+ const String16 name("SurfaceFlinger");
+ const int SERVICE_WAIT_SLEEP_MS = 100;
+ const int LOG_PER_RETRIES = 10;
+ int retry = 0;
+ while (sm->checkService(name) == nullptr) {
+ retry++;
+ if ((retry % LOG_PER_RETRIES) == 0) {
+ ALOGW("Waiting for SurfaceFlinger, waited for %" PRId64 " ms",
+ elapsedRealtime() - waitStartTime);
+ }
+ usleep(SERVICE_WAIT_SLEEP_MS * 1000);
+ };
+ int64_t totalWaited = elapsedRealtime() - waitStartTime;
+ if (totalWaited > SERVICE_WAIT_SLEEP_MS) {
+ ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited);
+ }
+}
+
+} // namespace android
diff --git a/cmds/bootanimation/BootAnimationUtil.h b/cmds/bootanimation/BootAnimationUtil.h
new file mode 100644
index 000000000000..60987cd1ccd1
--- /dev/null
+++ b/cmds/bootanimation/BootAnimationUtil.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace android {
+
+// Returns true if boot animation is disabled.
+bool bootAnimationDisabled();
+
+// Waits until the surface flinger is up.
+void waitForSurfaceFlinger();
+
+} // namespace android
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index c11d90522ffd..8501982d071c 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -30,6 +30,7 @@
#include <android-base/properties.h>
#include "BootAnimation.h"
+#include "BootAnimationUtil.h"
#include "audioplay.h"
using namespace android;
@@ -95,6 +96,49 @@ bool playSoundsAllowed() {
return true;
}
+class AudioAnimationCallbacks : public android::BootAnimation::Callbacks {
+public:
+ void init(const Vector<Animation::Part>& parts) override {
+ const Animation::Part* partWithAudio = nullptr;
+ for (const Animation::Part& part : parts) {
+ if (part.audioData != nullptr) {
+ partWithAudio = &part;
+ }
+ }
+
+ if (partWithAudio == nullptr) {
+ return;
+ }
+
+ ALOGD("found audio.wav, creating playback engine");
+ initAudioThread = new InitAudioThread(partWithAudio->audioData,
+ partWithAudio->audioLength);
+ initAudioThread->run("BootAnimation::InitAudioThread", PRIORITY_NORMAL);
+ };
+
+ void playPart(int partNumber, const Animation::Part& part, int playNumber) override {
+ // only play audio file the first time we animate the part
+ if (playNumber == 0 && part.audioData && playSoundsAllowed()) {
+ ALOGD("playing clip for part%d, size=%d",
+ partNumber, part.audioLength);
+ // Block until the audio engine is finished initializing.
+ if (initAudioThread != nullptr) {
+ initAudioThread->join();
+ }
+ audioplay::playClip(part.audioData, part.audioLength);
+ }
+ };
+
+ void shutdown() override {
+ // we've finally played everything we're going to play
+ audioplay::setPlaying(false);
+ audioplay::destroy();
+ };
+
+private:
+ sp<InitAudioThread> initAudioThread = nullptr;
+};
+
} // namespace
@@ -102,83 +146,21 @@ int main()
{
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.sf.nobootanimation", value, "0");
- int noBootAnimation = atoi(value);
- if (!noBootAnimation) {
- property_get("ro.boot.quiescent", value, "0");
- noBootAnimation = atoi(value);
- }
+ bool noBootAnimation = bootAnimationDisabled();
ALOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
- // TODO: replace this with better waiting logic in future, b/35253872
- int64_t waitStartTime = elapsedRealtime();
- sp<IServiceManager> sm = defaultServiceManager();
- const String16 name("SurfaceFlinger");
- const int SERVICE_WAIT_SLEEP_MS = 100;
- const int LOG_PER_RETRIES = 10;
- int retry = 0;
- while (sm->checkService(name) == nullptr) {
- retry++;
- if ((retry % LOG_PER_RETRIES) == 0) {
- ALOGW("Waiting for SurfaceFlinger, waited for %" PRId64 " ms",
- elapsedRealtime() - waitStartTime);
- }
- usleep(SERVICE_WAIT_SLEEP_MS * 1000);
- };
- int64_t totalWaited = elapsedRealtime() - waitStartTime;
- if (totalWaited > SERVICE_WAIT_SLEEP_MS) {
- ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited);
- }
-
- // TODO: Move audio code to a new class that just exports the callbacks.
- sp<InitAudioThread> initAudioThread = nullptr;
-
- auto initCallback = [&](const Vector<Animation::Part>& parts) {
- const Animation::Part* partWithAudio = nullptr;
- for (const Animation::Part& part : parts) {
- if (part.audioData != nullptr) {
- partWithAudio = &part;
- }
- }
-
- if (partWithAudio == nullptr) {
- return;
- }
-
- ALOGD("found audio.wav, creating playback engine");
- initAudioThread = new InitAudioThread(partWithAudio->audioData,
- partWithAudio->audioLength);
- initAudioThread->run("BootAnimation::InitAudioThread", PRIORITY_NORMAL);
-
- };
-
- auto partCallback = [&](int partNumber, const Animation::Part& part,
- int playNumber) {
- // only play audio file the first time we animate the part
- if (playNumber == 0 && part.audioData && playSoundsAllowed()) {
- ALOGD("playing clip for part%d, size=%d",
- partNumber, part.audioLength);
- // Block until the audio engine is finished initializing.
- if (initAudioThread != nullptr) {
- initAudioThread->join();
- }
- audioplay::playClip(part.audioData, part.audioLength);
- }
- };
+ waitForSurfaceFlinger();
// create the boot animation object
- sp<BootAnimation> boot = new BootAnimation(initCallback, partCallback);
+ sp<BootAnimation> boot = new BootAnimation(new AudioAnimationCallbacks());
+ ALOGV("Boot animation set up. Joining pool.");
IPCThreadState::self()->joinThreadPool();
-
- // we've finally played everything we're going to play
- audioplay::setPlaying(false);
- audioplay::destroy();
}
+ ALOGV("Boot animation exit");
return 0;
}
diff --git a/cmds/bootanimation/iot/BootAction.cpp b/cmds/bootanimation/iot/BootAction.cpp
new file mode 100644
index 000000000000..8fda87e99099
--- /dev/null
+++ b/cmds/bootanimation/iot/BootAction.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BootAction.h"
+
+#define LOG_TAG "BootAction"
+
+#include <android-base/strings.h>
+#include <cpu-features.h>
+#include <dlfcn.h>
+#include <pio/peripheral_manager_client.h>
+#include <utils/Log.h>
+
+using android::base::Split;
+using android::base::Join;
+using android::base::StartsWith;
+using android::base::EndsWith;
+
+namespace android {
+
+BootAction::~BootAction() {
+ if (mLibHandle != nullptr) {
+ dlclose(mLibHandle);
+ }
+}
+
+bool BootAction::init(const std::string& libraryPath, const std::string& config) {
+ APeripheralManagerClient* client = nullptr;
+ ALOGD("Connecting to peripheralmanager");
+ // Wait for peripheral manager to come up.
+ while (client == nullptr) {
+ client = APeripheralManagerClient_new();
+ if (client == nullptr) {
+ ALOGV("peripheralmanager is not up, sleeping before we check again.");
+ usleep(250000);
+ }
+ }
+ ALOGD("Peripheralmanager is up.");
+ APeripheralManagerClient_delete(client);
+
+ std::string path_to_lib = libraryPath;
+ if (!parseConfig(config, &path_to_lib)) {
+ return false;
+ }
+
+ ALOGI("Loading boot action %s", path_to_lib.c_str());
+ mLibHandle = dlopen(path_to_lib.c_str(), RTLD_NOW);
+ if (mLibHandle == nullptr) {
+ ALOGE("Unable to load library at %s :: %s",
+ path_to_lib.c_str(), dlerror());
+ return false;
+ }
+
+ void* loaded = nullptr;
+ if (!loadSymbol("boot_action_init", &loaded) || loaded == nullptr) {
+ return false;
+ }
+ mLibInit = reinterpret_cast<libInit>(loaded);
+
+ loaded = nullptr;
+ if (!loadSymbol("boot_action_shutdown", &loaded) || loaded == nullptr) {
+ return false;
+ }
+ mLibShutdown = reinterpret_cast<libShutdown>(loaded);
+
+ // StartPart is considered optional, if it isn't exported by the library
+ // we will still call init and shutdown.
+ loaded = nullptr;
+ if (!loadSymbol("boot_action_start_part", &loaded) || loaded == nullptr) {
+ ALOGI("No boot_action_start_part found, action will not be told when "
+ "Animation parts change.");
+ } else {
+ mLibStartPart = reinterpret_cast<libStartPart>(loaded);
+ }
+
+ ALOGD("Entering boot_action_init");
+ bool result = mLibInit();
+ ALOGD("Returned from boot_action_init");
+ return result;
+}
+
+void BootAction::startPart(int partNumber, int playNumber) {
+ if (mLibStartPart == nullptr) return;
+
+ ALOGD("Entering boot_action_start_part");
+ mLibStartPart(partNumber, playNumber);
+ ALOGD("Returned from boot_action_start_part");
+}
+
+void BootAction::shutdown() {
+ ALOGD("Entering boot_action_shutdown");
+ mLibShutdown();
+ ALOGD("Returned from boot_action_shutdown");
+}
+
+bool BootAction::loadSymbol(const char* symbol, void** loaded) {
+ *loaded = dlsym(mLibHandle, symbol);
+ if (loaded == nullptr) {
+ ALOGE("Unable to load symbol : %s :: %s", symbol, dlerror());
+ return false;
+ }
+ return true;
+}
+
+
+bool BootAction::parseConfig(const std::string& config, std::string* path) {
+ auto lines = Split(config, "\n");
+
+ if (lines.size() < 1) {
+ ALOGE("Config format invalid, expected one line, found %d",
+ lines.size());
+ return false;
+ }
+
+ size_t lineNumber = 0;
+ auto& line1 = lines.at(lineNumber);
+ while (StartsWith(line1, "#")) {
+ if (lines.size() < ++lineNumber) {
+ ALOGE("Config file contains no non-comment lines.");
+ return false;
+ }
+ line1 = lines.at(lineNumber);
+ }
+
+ const std::string libraryNameToken("LIBRARY_NAME=");
+ if (!StartsWith(line1, libraryNameToken.c_str())) {
+ ALOGE("Invalid config format, expected second line to start with %s "
+ "Instead found: %s", libraryNameToken.c_str(), line1.c_str());
+ return false;
+ }
+
+ std::string libraryName = line1.substr(libraryNameToken.length());
+
+ *path += "/";
+ *path += architectureDirectory();
+ *path += "/";
+ *path += libraryName;
+
+ return true;
+}
+
+const char* BootAction::architectureDirectory() {
+ switch(android_getCpuFamily()) {
+ case ANDROID_CPU_FAMILY_ARM:
+ return "arm";
+ case ANDROID_CPU_FAMILY_X86:
+ return "x86";
+ case ANDROID_CPU_FAMILY_MIPS:
+ return "mips";
+ case ANDROID_CPU_FAMILY_ARM64:
+ return "arm64";
+ case ANDROID_CPU_FAMILY_X86_64:
+ return "x86_64";
+ case ANDROID_CPU_FAMILY_MIPS64:
+ return "mips64";
+ default:
+ ALOGE("Unsupported cpu family: %d", android_getCpuFamily());
+ return "";
+ }
+}
+
+} // namespace android
diff --git a/cmds/bootanimation/iot/BootAction.h b/cmds/bootanimation/iot/BootAction.h
new file mode 100644
index 000000000000..31d0d1f65b95
--- /dev/null
+++ b/cmds/bootanimation/iot/BootAction.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BOOTANIMATION_BOOTACTION_H
+#define _BOOTANIMATION_BOOTACTION_H
+
+#include <string>
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+class BootAction : public RefBase {
+public:
+ ~BootAction();
+ // Parse the contents of the config file. We expect one line:
+ // LIBRARY_NAME=
+ //
+ // LIBRARY_NAME is the name of the shared library that contains the boot action.
+ bool init(const std::string& libraryPath, const std::string& config);
+
+ // The animation is going to start playing partNumber for the playCount'th
+ // time, update the action as needed.
+ // This is run in the same thread as the boot animation,
+ // you must not block here.
+ void startPart(int partNumber, int playCount);
+
+ // Shutdown the boot action, this will be called shortly before the
+ // process is shut down to allow time for cleanup.
+ void shutdown();
+
+private:
+ typedef bool (*libInit)();
+ typedef void (*libStartPart)(int partNumber, int playNumber);
+ typedef void (*libShutdown)();
+
+ bool parseConfig(const std::string& config, std::string* path);
+ bool loadSymbol(const char* symbol, void** loaded);
+ const char* architectureDirectory();
+
+ void* mLibHandle = nullptr;
+ libInit mLibInit = nullptr;
+ libStartPart mLibStartPart = nullptr;
+ libShutdown mLibShutdown = nullptr;
+};
+
+} // namespace android
+
+
+#endif // _BOOTANIMATION_BOOTACTION_H
diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp
new file mode 100644
index 000000000000..d1ae786e83af
--- /dev/null
+++ b/cmds/bootanimation/iot/iotbootanimation_main.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IotBootAnimation"
+
+#include <android-base/file.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+#include <sys/resource.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <BootAnimation.h>
+
+#include "BootAction.h"
+#include "BootAnimationUtil.h"
+
+using namespace android;
+using android::base::ReadFileToString;
+
+// Create a typedef for readability.
+typedef android::BootAnimation::Animation Animation;
+
+namespace {
+
+class BootActionAnimationCallbacks : public android::BootAnimation::Callbacks {public:
+ void init(const Vector<Animation::Part>&) override {
+ // Create and initialize BootActions if we have a boot_action.conf.
+ std::string bootActionConf;
+ if (ReadFileToString("/oem/app/etc/boot_action.conf", &bootActionConf)) {
+ mBootAction = new BootAction();
+ if (!mBootAction->init("/oem/app/lib", bootActionConf)) {
+ mBootAction = NULL;
+ }
+ } else {
+ ALOGI("No boot actions specified");
+ }
+
+ };
+
+ void playPart(int partNumber, const Animation::Part&, int playNumber) override {
+ if (mBootAction != nullptr) {
+ mBootAction->startPart(partNumber, playNumber);
+ }
+ };
+
+ void shutdown() override {
+ if (mBootAction != nullptr) {
+ mBootAction->shutdown();
+ // Give it two seconds to shut down.
+ sleep(2);
+ mBootAction = nullptr;
+ }
+ };
+
+private:
+ sp<BootAction> mBootAction = nullptr;
+};
+
+} // namespace
+
+int main() {
+ setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
+
+ if (bootAnimationDisabled()) {
+ ALOGI("boot animation disabled");
+ return 0;
+ }
+
+ waitForSurfaceFlinger();
+
+ sp<ProcessState> proc(ProcessState::self());
+ ProcessState::self()->startThreadPool();
+
+ sp<BootAnimation> boot = new BootAnimation(new BootActionAnimationCallbacks());
+
+ IPCThreadState::self()->joinThreadPool();
+ return 0;
+}
diff --git a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
index 1e426d62e4e0..b9fedd365925 100644
--- a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
+++ b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
@@ -33,6 +33,10 @@ public final class LockSettingsCmd extends BaseCommand {
" locksettings set-pin [--old OLD_CREDENTIAL] NEW_PIN\n" +
" locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n" +
" locksettings clear [--old OLD_CREDENTIAL]\n" +
+ " locksettings verify [--old OLD_CREDENTIAL]\n" +
+ "\n" +
+ "flags: \n" +
+ " --user USER_ID: specify the user, default value is current user\n" +
"\n" +
"locksettings set-pattern: sets a pattern\n" +
" A pattern is specified by a non-separated list of numbers that index the cell\n" +
@@ -44,7 +48,9 @@ public final class LockSettingsCmd extends BaseCommand {
"\n" +
"locksettings set-password: sets a password\n" +
"\n" +
- "locksettings clear: clears the unlock credential\n";
+ "locksettings clear: clears the unlock credential\n" +
+ "\n" +
+ "locksettings verify: verifies the credential and unlocks the user\n";
public static void main(String[] args) {
(new LockSettingsCmd()).run(args);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index c4193f647c32..f0189c240a85 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -414,7 +414,7 @@ public final class Pm {
try {
ApkLite baseApk = PackageParser.parseApkLite(file, 0);
PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
- null, null);
+ null, null, null);
params.sessionParams.setSize(
PackageHelper.calculateInstalledSize(pkgLite, false,
params.sessionParams.abiOverride));
@@ -1033,7 +1033,7 @@ public final class Pm {
if (info != null) {
System.out.println("Success: created user id " + info.id);
- return 1;
+ return 0;
} else {
System.err.println("Error: couldn't create User.");
return 1;
diff --git a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
index 50ee56455b48..360b2308b1c7 100644
--- a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
+++ b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
@@ -29,10 +29,41 @@ public class RequestSync {
private int mNextArg;
private String mCurArgData;
+ enum Operation {
+ REQUEST_SYNC {
+ @Override
+ void invoke(RequestSync caller) {
+ ContentResolver.requestSync(caller.mAccount, caller.mAuthority, caller.mExtras);
+ }
+ },
+ ADD_PERIODIC_SYNC {
+ @Override
+ void invoke(RequestSync caller) {
+ ContentResolver.addPeriodicSync(caller.mAccount, caller.mAuthority, caller.mExtras,
+ caller.mPeriodicIntervalSeconds);
+ }
+ },
+ REMOVE_PERIODIC_SYNC {
+ @Override
+ void invoke(RequestSync caller) {
+ ContentResolver.removePeriodicSync(
+ caller.mAccount, caller.mAuthority, caller.mExtras);
+ }
+ };
+
+ abstract void invoke(RequestSync caller);
+ }
+
+ private Operation mOperation;
+
// account & authority
- private String mAccountName = null;
- private String mAccountType = null;
- private String mAuthority = null;
+ private String mAccountName;
+ private String mAccountType;
+ private String mAuthority;
+
+ private Account mAccount;
+
+ private int mPeriodicIntervalSeconds;
// extras
private Bundle mExtras = new Bundle();
@@ -80,11 +111,28 @@ public class RequestSync {
}
}
- ContentResolver.requestSync(account, mAuthority, mExtras);
+ mAccount = account;
+
+ mOperation.invoke(this);
}
}
private boolean parseArgs() throws URISyntaxException {
+ mOperation = Operation.REQUEST_SYNC;
+ if (mArgs.length > 0) {
+ switch (mArgs[0]) {
+ case "add-periodic":
+ mNextArg++;
+ mOperation = Operation.ADD_PERIODIC_SYNC;
+ mPeriodicIntervalSeconds = Integer.parseInt(nextArgRequired());
+ break;
+ case "remove-periodic":
+ mNextArg++;
+ mOperation = Operation.REMOVE_PERIODIC_SYNC;
+ break;
+ }
+ }
+
String opt;
while ((opt=nextOption()) != null) {
if (opt.equals("-h") || opt.equals("--help")) {
@@ -114,6 +162,8 @@ public class RequestSync {
mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS, true);
} else if (opt.equals("-u") || opt.equals("--upload-only")) {
mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
+ } else if (opt.equals("--rc") || opt.equals("--require-charging")) {
+ mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING, true);
} else if (opt.equals("-e") || opt.equals("--es") || opt.equals("--extra-string")) {
final String key = nextArgRequired();
final String value = nextArgRequired();
@@ -207,31 +257,43 @@ public class RequestSync {
private static void showUsage() {
System.err.println(
- "usage: requestsync [options]\n" +
- "With no options, a sync will be requested for all account and all sync\n" +
- "authorities with no extras. Options can be:\n" +
- " -h|--help: Display this message\n" +
- " -n|--account-name <ACCOUNT-NAME>\n" +
- " -t|--account-type <ACCOUNT-TYPE>\n" +
- " -a|--authority <AUTHORITY>\n" +
- " Add ContentResolver extras:\n" +
- " --is|--ignore-settings: Add SYNC_EXTRAS_IGNORE_SETTINGS\n" +
- " --ib|--ignore-backoff: Add SYNC_EXTRAS_IGNORE_BACKOFF\n" +
- " --dd|--discard-deletions: Add SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS\n" +
- " --nr|--no-retry: Add SYNC_EXTRAS_DO_NOT_RETRY\n" +
- " --ex|--expedited: Add SYNC_EXTRAS_EXPEDITED\n" +
- " --i|--initialize: Add SYNC_EXTRAS_INITIALIZE\n" +
- " --m|--manual: Add SYNC_EXTRAS_MANUAL\n" +
- " --od|--override-deletions: Add SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS\n" +
- " --u|--upload-only: Add SYNC_EXTRAS_UPLOAD\n" +
- " Add custom extras:\n" +
- " -e|--es|--extra-string <KEY> <VALUE>\n" +
- " --esn|--extra-string-null <KEY>\n" +
- " --ei|--extra-int <KEY> <VALUE>\n" +
- " --el|--extra-long <KEY> <VALUE>\n" +
- " --ef|--extra-float <KEY> <VALUE>\n" +
- " --ed|--extra-double <KEY> <VALUE>\n" +
- " --ez|--extra-bool <KEY> <VALUE>\n"
+ "Usage:\n" +
+ "\n" +
+ " requestsync [options]\n" +
+ " With no options, a sync will be requested for all account and all sync\n" +
+ " authorities with no extras.\n" +
+ " Basic options:\n" +
+ " -h|--help: Display this message\n" +
+ " -n|--account-name <ACCOUNT-NAME>\n" +
+ " -t|--account-type <ACCOUNT-TYPE>\n" +
+ " -a|--authority <AUTHORITY>\n" +
+ " ContentResolver extra options:\n" +
+ " --is|--ignore-settings: Add SYNC_EXTRAS_IGNORE_SETTINGS\n" +
+ " --ib|--ignore-backoff: Add SYNC_EXTRAS_IGNORE_BACKOFF\n" +
+ " --dd|--discard-deletions: Add SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS\n" +
+ " --nr|--no-retry: Add SYNC_EXTRAS_DO_NOT_RETRY\n" +
+ " --ex|--expedited: Add SYNC_EXTRAS_EXPEDITED\n" +
+ " -i|--initialize: Add SYNC_EXTRAS_INITIALIZE\n" +
+ " --m|--manual: Add SYNC_EXTRAS_MANUAL\n" +
+ " --od|--override-deletions: Add SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS\n" +
+ " -u|--upload-only: Add SYNC_EXTRAS_UPLOAD\n" +
+ " --rc|--require-charging: Add SYNC_EXTRAS_REQUIRE_CHARGING\n" +
+ " Custom extra options:\n" +
+ " -e|--es|--extra-string <KEY> <VALUE>\n" +
+ " --esn|--extra-string-null <KEY>\n" +
+ " --ei|--extra-int <KEY> <VALUE>\n" +
+ " --el|--extra-long <KEY> <VALUE>\n" +
+ " --ef|--extra-float <KEY> <VALUE>\n" +
+ " --ed|--extra-double <KEY> <VALUE>\n" +
+ " --ez|--extra-bool <KEY> <VALUE>\n" +
+ "\n" +
+ " requestsync add-periodic INTERVAL-SECOND [options]\n" +
+ " requestsync remove-periodic [options]\n" +
+ " Mandatory options:\n" +
+ " -n|--account-name <ACCOUNT-NAME>\n" +
+ " -t|--account-type <ACCOUNT-TYPE>\n" +
+ " -a|--authority <AUTHORITY>\n" +
+ " Also takes the above extra options.\n"
);
}
}