Merge "Add set-time and set-timezone shell cmds to alarm service" into pi-dev
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 8e76dd3..b4de3a3 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -322,6 +322,8 @@
         <permission name="android.permission.SET_ANIMATION_SCALE"/>
         <permission name="android.permission.SET_DEBUG_APP"/>
         <permission name="android.permission.SET_PROCESS_LIMIT"/>
+        <permission name="android.permission.SET_TIME"/>
+        <permission name="android.permission.SET_TIME_ZONE"/>
         <permission name="android.permission.SIGNAL_PERSISTENT_PROCESSES"/>
         <permission name="android.permission.STOP_APP_SWITCHES"/>
         <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d284bf9..26cd0e4 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -125,6 +125,8 @@
     <uses-permission android:name="android.permission.MANAGE_AUTO_FILL" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.SET_TIME" />
+    <uses-permission android:name="android.permission.SET_TIME_ZONE" />
     <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
     <!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) -->
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index d17ca7f..d066056 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -57,6 +57,9 @@
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
@@ -1369,6 +1372,17 @@
         }
     }
 
+    boolean setTimeImpl(long millis) {
+        if (mNativeData == 0) {
+            Slog.w(TAG, "Not setting time since no alarm driver is available.");
+            return false;
+        }
+
+        synchronized (mLock) {
+            return setKernelTime(mNativeData, millis) == 0;
+        }
+    }
+
     void setTimeZoneImpl(String tz) {
         if (TextUtils.isEmpty(tz)) {
             return;
@@ -1766,14 +1780,7 @@
                     "android.permission.SET_TIME",
                     "setTime");
 
-            if (mNativeData == 0) {
-                Slog.w(TAG, "Not setting time since no alarm driver is available.");
-                return false;
-            }
-
-            synchronized (mLock) {
-                return setKernelTime(mNativeData, millis) == 0;
-            }
+            return setTimeImpl(millis);
         }
 
         @Override
@@ -1836,6 +1843,13 @@
                 dumpImpl(pw);
             }
         }
+
+        @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out,
+                FileDescriptor err, String[] args, ShellCallback callback,
+                ResultReceiver resultReceiver) {
+            (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
+        }
     };
 
     void dumpImpl(PrintWriter pw) {
@@ -4244,4 +4258,49 @@
             }
         }
     }
+
+    private class ShellCmd extends ShellCommand {
+
+        IAlarmManager getBinderService() {
+            return IAlarmManager.Stub.asInterface(mService);
+        }
+
+        @Override
+        public int onCommand(String cmd) {
+            if (cmd == null) {
+                return handleDefaultCommands(cmd);
+            }
+
+            final PrintWriter pw = getOutPrintWriter();
+            try {
+                switch (cmd) {
+                    case "set-time":
+                        final long millis = Long.parseLong(getNextArgRequired());
+                        return (getBinderService().setTime(millis)) ? 0 : -1;
+                    case "set-timezone":
+                        final String tz = getNextArgRequired();
+                        getBinderService().setTimeZone(tz);
+                        return 0;
+                    default:
+                        return handleDefaultCommands(cmd);
+                }
+            } catch (Exception e) {
+                pw.println(e);
+            }
+            return -1;
+        }
+
+        @Override
+        public void onHelp() {
+            PrintWriter pw = getOutPrintWriter();
+            pw.println("Alarm manager service (alarm) commands:");
+            pw.println("  help");
+            pw.println("    Print this help text.");
+            pw.println("  set-time TIME");
+            pw.println("    Set the system clock time to TIME where TIME is milliseconds");
+            pw.println("    since the Epoch.");
+            pw.println("  set-timezone TZ");
+            pw.println("    Set the system timezone to TZ where TZ is an Olson id.");
+        }
+    }
 }