Merge "Introduce a Lifecycle for system services"

This commit is contained in:
Adam Lesinski
2013-12-13 18:33:01 +00:00
committed by Android (Google) Code Review
31 changed files with 2300 additions and 1622 deletions

View File

@@ -1,18 +1,18 @@
LOCAL_PATH:= $(call my-dir)
# the library
# Build services.jar
# ============================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(call all-subdir-java-files) \
com/android/server/EventLogTags.logtags \
com/android/server/am/EventLogTags.logtags
LOCAL_MODULE:= services
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_SRC_FILES := \
$(call all-subdir-java-files) \
com/android/server/EventLogTags.logtags \
com/android/server/am/EventLogTags.logtags
LOCAL_JAVA_LIBRARIES := android.policy conscrypt telephony-common
include $(BUILD_JAVA_LIBRARY)
include $(BUILD_DROIDDOC)

View File

@@ -31,6 +31,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -64,54 +65,51 @@ import static android.app.AlarmManager.ELAPSED_REALTIME;
import com.android.internal.util.LocalLog;
class AlarmManagerService extends IAlarmManager.Stub {
class AlarmManagerService extends SystemService {
// The threshold for how long an alarm can be late before we print a
// warning message. The time duration is in milliseconds.
private static final long LATE_ALARM_THRESHOLD = 10 * 1000;
private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
private static final int RTC_MASK = 1 << RTC;
private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
private static final int TIME_CHANGED_MASK = 1 << 16;
private static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
static final int TIME_CHANGED_MASK = 1 << 16;
static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
// Mask for testing whether a given alarm type is wakeup vs non-wakeup
private static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
private static final String TAG = "AlarmManager";
private static final String ClockReceiver_TAG = "ClockReceiver";
private static final boolean localLOGV = false;
private static final boolean DEBUG_BATCH = localLOGV || false;
private static final boolean DEBUG_VALIDATE = localLOGV || false;
private static final int ALARM_EVENT = 1;
private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
static final String TAG = "AlarmManager";
static final String ClockReceiver_TAG = "ClockReceiver";
static final boolean localLOGV = false;
static final boolean DEBUG_BATCH = localLOGV || false;
static final boolean DEBUG_VALIDATE = localLOGV || false;
static final int ALARM_EVENT = 1;
static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
private static final Intent mBackgroundIntent
static final Intent mBackgroundIntent
= new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
private static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
private static final boolean WAKEUP_STATS = false;
static final boolean WAKEUP_STATS = false;
private final Context mContext;
final LocalLog mLog = new LocalLog(TAG);
private final LocalLog mLog = new LocalLog(TAG);
final Object mLock = new Object();
private Object mLock = new Object();
private int mDescriptor;
int mDescriptor;
private long mNextWakeup;
private long mNextNonWakeup;
private int mBroadcastRefCount = 0;
private PowerManager.WakeLock mWakeLock;
private ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
private final AlarmThread mWaitThread = new AlarmThread();
private final AlarmHandler mHandler = new AlarmHandler();
private ClockReceiver mClockReceiver;
int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
final AlarmHandler mHandler = new AlarmHandler();
ClockReceiver mClockReceiver;
private UninstallReceiver mUninstallReceiver;
private final ResultReceiver mResultReceiver = new ResultReceiver();
private final PendingIntent mTimeTickSender;
private final PendingIntent mDateChangeSender;
final ResultReceiver mResultReceiver = new ResultReceiver();
PendingIntent mTimeTickSender;
PendingIntent mDateChangeSender;
class WakeupEvent {
public long when;
@@ -125,8 +123,8 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
private final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
private final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
static final class Batch {
long start; // These endpoints are always in ELAPSED
@@ -317,9 +315,9 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
// minimum recurrence period or alarm futurity for us to be able to fuzz it
private static final long MIN_FUZZABLE_INTERVAL = 10000;
private static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
private final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>();
static final long MIN_FUZZABLE_INTERVAL = 10000;
static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>();
static long convertToElapsed(long when, int type) {
final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
@@ -403,7 +401,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
private static final class InFlight extends Intent {
static final class InFlight extends Intent {
final PendingIntent mPendingIntent;
final WorkSource mWorkSource;
final Pair<String, ComponentName> mTarget;
@@ -427,7 +425,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
private static final class FilterStats {
static final class FilterStats {
final BroadcastStats mBroadcastStats;
final Pair<String, ComponentName> mTarget;
@@ -443,7 +441,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
private static final class BroadcastStats {
static final class BroadcastStats {
final String mPackageName;
long aggregateTime;
@@ -459,47 +457,48 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
private final HashMap<String, BroadcastStats> mBroadcastStats
final HashMap<String, BroadcastStats> mBroadcastStats
= new HashMap<String, BroadcastStats>();
public AlarmManagerService(Context context) {
mContext = context;
@Override
public void onStart() {
mDescriptor = init();
mNextWakeup = mNextNonWakeup = 0;
// We have to set current TimeZone info to kernel
// because kernel doesn't keep this after reboot
String tz = SystemProperties.get(TIMEZONE_PROPERTY);
if (tz != null) {
setTimeZone(tz);
}
setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mTimeTickSender = PendingIntent.getBroadcastAsUser(context, 0,
mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
new Intent(Intent.ACTION_TIME_TICK).addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND), 0,
UserHandle.ALL);
Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
mDateChangeSender = PendingIntent.getBroadcastAsUser(context, 0, intent,
mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
// now that we have initied the driver schedule the alarm
mClockReceiver= new ClockReceiver();
mClockReceiver = new ClockReceiver();
mClockReceiver.scheduleTimeTickEvent();
mClockReceiver.scheduleDateChangedEvent();
mUninstallReceiver = new UninstallReceiver();
if (mDescriptor != -1) {
mWaitThread.start();
AlarmThread waitThread = new AlarmThread();
waitThread.start();
} else {
Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
}
publishBinderService(Context.ALARM_SERVICE, mService);
}
@Override
protected void finalize() throws Throwable {
try {
close(mDescriptor);
@@ -508,19 +507,51 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
@Override
public void set(int type, long triggerAtTime, long windowLength, long interval,
PendingIntent operation, WorkSource workSource) {
if (workSource != null) {
mContext.enforceCallingPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS,
"AlarmManager.set");
void setTimeZoneImpl(String tz) {
if (TextUtils.isEmpty(tz)) {
return;
}
set(type, triggerAtTime, windowLength, interval, operation, false, workSource);
TimeZone zone = TimeZone.getTimeZone(tz);
// Prevent reentrant calls from stepping on each other when writing
// the time zone property
boolean timeZoneWasChanged = false;
synchronized (this) {
String current = SystemProperties.get(TIMEZONE_PROPERTY);
if (current == null || !current.equals(zone.getID())) {
if (localLOGV) {
Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
}
timeZoneWasChanged = true;
SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
}
// Update the kernel timezone information
// Kernel tracks time offsets as 'minutes west of GMT'
int gmtOffset = zone.getOffset(System.currentTimeMillis());
setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
}
TimeZone.setDefault(null);
if (timeZoneWasChanged) {
Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time-zone", zone.getID());
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
}
}
public void set(int type, long triggerAtTime, long windowLength, long interval,
void removeImpl(PendingIntent operation) {
if (operation == null) {
return;
}
synchronized (mLock) {
removeLocked(operation);
}
}
void setImpl(int type, long triggerAtTime, long windowLength, long interval,
PendingIntent operation, boolean isStandalone, WorkSource workSource) {
if (operation == null) {
Slog.w(TAG, "set/setRepeating ignored because there is no intent");
@@ -606,231 +637,64 @@ class AlarmManagerService extends IAlarmManager.Stub {
rescheduleKernelAlarmsLocked();
}
private void logBatchesLocked() {
ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
PrintWriter pw = new PrintWriter(bs);
final long nowRTC = System.currentTimeMillis();
final long nowELAPSED = SystemClock.elapsedRealtime();
final int NZ = mAlarmBatches.size();
for (int iz = 0; iz < NZ; iz++) {
Batch bz = mAlarmBatches.get(iz);
pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC);
pw.flush();
Slog.v(TAG, bs.toString());
bs.reset();
}
}
private boolean validateConsistencyLocked() {
if (DEBUG_VALIDATE) {
long lastTime = Long.MIN_VALUE;
final int N = mAlarmBatches.size();
for (int i = 0; i < N; i++) {
Batch b = mAlarmBatches.get(i);
if (b.start >= lastTime) {
// duplicate start times are okay because of standalone batches
lastTime = b.start;
} else {
Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
logBatchesLocked();
return false;
}
}
}
return true;
}
private Batch findFirstWakeupBatchLocked() {
final int N = mAlarmBatches.size();
for (int i = 0; i < N; i++) {
Batch b = mAlarmBatches.get(i);
if (b.hasWakeups()) {
return b;
}
}
return null;
}
private void rescheduleKernelAlarmsLocked() {
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
// prior to that which contains no wakeups, we schedule that as well.
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
final Batch firstBatch = mAlarmBatches.get(0);
if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
mNextWakeup = firstWakeup.start;
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
}
if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
mNextNonWakeup = firstBatch.start;
setLocked(ELAPSED_REALTIME, firstBatch.start);
}
}
}
public void setTime(long millis) {
mContext.enforceCallingOrSelfPermission(
"android.permission.SET_TIME",
"setTime");
SystemClock.setCurrentTimeMillis(millis);
}
public void setTimeZone(String tz) {
mContext.enforceCallingOrSelfPermission(
"android.permission.SET_TIME_ZONE",
"setTimeZone");
long oldId = Binder.clearCallingIdentity();
try {
if (TextUtils.isEmpty(tz)) return;
TimeZone zone = TimeZone.getTimeZone(tz);
// Prevent reentrant calls from stepping on each other when writing
// the time zone property
boolean timeZoneWasChanged = false;
synchronized (this) {
String current = SystemProperties.get(TIMEZONE_PROPERTY);
if (current == null || !current.equals(zone.getID())) {
if (localLOGV) {
Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
}
timeZoneWasChanged = true;
SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
}
// Update the kernel timezone information
// Kernel tracks time offsets as 'minutes west of GMT'
int gmtOffset = zone.getOffset(System.currentTimeMillis());
setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
private final IBinder mService = new IAlarmManager.Stub() {
@Override
public void set(int type, long triggerAtTime, long windowLength, long interval,
PendingIntent operation, WorkSource workSource) {
if (workSource != null) {
getContext().enforceCallingPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS,
"AlarmManager.set");
}
TimeZone.setDefault(null);
setImpl(type, triggerAtTime, windowLength, interval, operation,
false, workSource);
}
if (timeZoneWasChanged) {
Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time-zone", zone.getID());
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
} finally {
Binder.restoreCallingIdentity(oldId);
@Override
public void setTime(long millis) {
getContext().enforceCallingOrSelfPermission(
"android.permission.SET_TIME",
"setTime");
SystemClock.setCurrentTimeMillis(millis);
}
}
public void remove(PendingIntent operation) {
if (operation == null) {
return;
}
synchronized (mLock) {
removeLocked(operation);
}
}
public void removeLocked(PendingIntent operation) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
didRemove |= b.remove(operation);
if (b.size() == 0) {
mAlarmBatches.remove(i);
@Override
public void setTimeZone(String tz) {
getContext().enforceCallingOrSelfPermission(
"android.permission.SET_TIME_ZONE",
"setTimeZone");
final long oldId = Binder.clearCallingIdentity();
try {
setTimeZoneImpl(tz);
} finally {
Binder.restoreCallingIdentity(oldId);
}
}
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(operation) changed bounds; rebatching");
}
rebatchAllAlarmsLocked(true);
rescheduleKernelAlarmsLocked();
}
}
@Override
public void remove(PendingIntent operation) {
removeImpl(operation);
public void removeLocked(String packageName) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
didRemove |= b.remove(packageName);
if (b.size() == 0) {
mAlarmBatches.remove(i);
}
}
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(package) changed bounds; rebatching");
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump AlarmManager from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
rebatchAllAlarmsLocked(true);
rescheduleKernelAlarmsLocked();
}
}
public void removeUserLocked(int userHandle) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
didRemove |= b.remove(userHandle);
if (b.size() == 0) {
mAlarmBatches.remove(i);
}
dumpImpl(pw);
}
};
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(user) changed bounds; rebatching");
}
rebatchAllAlarmsLocked(true);
rescheduleKernelAlarmsLocked();
}
}
public boolean lookForPackageLocked(String packageName) {
for (int i = 0; i < mAlarmBatches.size(); i++) {
Batch b = mAlarmBatches.get(i);
if (b.hasPackage(packageName)) {
return true;
}
}
return false;
}
private void setLocked(int type, long when)
{
if (mDescriptor != -1)
{
// The kernel never triggers alarms with negative wakeup times
// so we ensure they are positive.
long alarmSeconds, alarmNanoseconds;
if (when < 0) {
alarmSeconds = 0;
alarmNanoseconds = 0;
} else {
alarmSeconds = when / 1000;
alarmNanoseconds = (when % 1000) * 1000 * 1000;
}
set(mDescriptor, type, alarmSeconds, alarmNanoseconds);
}
else
{
Message msg = Message.obtain();
msg.what = ALARM_EVENT;
mHandler.removeMessages(ALARM_EVENT);
mHandler.sendMessageAtTime(msg, when);
}
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump AlarmManager from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
void dumpImpl(PrintWriter pw) {
synchronized (mLock) {
pw.println("Current Alarm Manager state:");
final long nowRTC = System.currentTimeMillis();
@@ -980,6 +844,159 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
private void logBatchesLocked() {
ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
PrintWriter pw = new PrintWriter(bs);
final long nowRTC = System.currentTimeMillis();
final long nowELAPSED = SystemClock.elapsedRealtime();
final int NZ = mAlarmBatches.size();
for (int iz = 0; iz < NZ; iz++) {
Batch bz = mAlarmBatches.get(iz);
pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC);
pw.flush();
Slog.v(TAG, bs.toString());
bs.reset();
}
}
private boolean validateConsistencyLocked() {
if (DEBUG_VALIDATE) {
long lastTime = Long.MIN_VALUE;
final int N = mAlarmBatches.size();
for (int i = 0; i < N; i++) {
Batch b = mAlarmBatches.get(i);
if (b.start >= lastTime) {
// duplicate start times are okay because of standalone batches
lastTime = b.start;
} else {
Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
logBatchesLocked();
return false;
}
}
}
return true;
}
private Batch findFirstWakeupBatchLocked() {
final int N = mAlarmBatches.size();
for (int i = 0; i < N; i++) {
Batch b = mAlarmBatches.get(i);
if (b.hasWakeups()) {
return b;
}
}
return null;
}
void rescheduleKernelAlarmsLocked() {
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
// prior to that which contains no wakeups, we schedule that as well.
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
final Batch firstBatch = mAlarmBatches.get(0);
if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
mNextWakeup = firstWakeup.start;
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
}
if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
mNextNonWakeup = firstBatch.start;
setLocked(ELAPSED_REALTIME, firstBatch.start);
}
}
}
private void removeLocked(PendingIntent operation) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
didRemove |= b.remove(operation);
if (b.size() == 0) {
mAlarmBatches.remove(i);
}
}
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(operation) changed bounds; rebatching");
}
rebatchAllAlarmsLocked(true);
rescheduleKernelAlarmsLocked();
}
}
void removeLocked(String packageName) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
didRemove |= b.remove(packageName);
if (b.size() == 0) {
mAlarmBatches.remove(i);
}
}
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(package) changed bounds; rebatching");
}
rebatchAllAlarmsLocked(true);
rescheduleKernelAlarmsLocked();
}
}
void removeUserLocked(int userHandle) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
didRemove |= b.remove(userHandle);
if (b.size() == 0) {
mAlarmBatches.remove(i);
}
}
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(user) changed bounds; rebatching");
}
rebatchAllAlarmsLocked(true);
rescheduleKernelAlarmsLocked();
}
}
boolean lookForPackageLocked(String packageName) {
for (int i = 0; i < mAlarmBatches.size(); i++) {
Batch b = mAlarmBatches.get(i);
if (b.hasPackage(packageName)) {
return true;
}
}
return false;
}
private void setLocked(int type, long when) {
if (mDescriptor != -1) {
// The kernel never triggers alarms with negative wakeup times
// so we ensure they are positive.
long alarmSeconds, alarmNanoseconds;
if (when < 0) {
alarmSeconds = 0;
alarmNanoseconds = 0;
} else {
alarmSeconds = when / 1000;
alarmNanoseconds = (when % 1000) * 1000 * 1000;
}
set(mDescriptor, type, alarmSeconds, alarmNanoseconds);
} else {
Message msg = Message.obtain();
msg.what = ALARM_EVENT;
mHandler.removeMessages(ALARM_EVENT);
mHandler.sendMessageAtTime(msg, when);
}
}
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
String prefix, String label, long now) {
for (int i=list.size()-1; i>=0; i--) {
@@ -1020,7 +1037,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
private native int waitForAlarm(int fd);
private native int setKernelTimezone(int fd, int minuteswest);
private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
// batches are temporally sorted, so we need only pull from the
// start of the list until we either empty it or hit a batch
// that is not yet deliverable
@@ -1166,13 +1183,13 @@ class AlarmManagerService extends IAlarmManager.Stub {
if (DEBUG_BATCH) {
Slog.v(TAG, "Time changed notification from kernel; rebatching");
}
remove(mTimeTickSender);
removeImpl(mTimeTickSender);
rebatchAllAlarms();
mClockReceiver.scheduleTimeTickEvent();
Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
}
synchronized (mLock) {
@@ -1206,7 +1223,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
Alarm alarm = triggerList.get(i);
try {
if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
alarm.operation.send(mContext, 0,
alarm.operation.send(getContext(), 0,
mBackgroundIntent.putExtra(
Intent.EXTRA_ALARM_COUNT, alarm.count),
mResultReceiver, mHandler);
@@ -1248,7 +1265,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
// is a repeating alarm, so toss the hoser.
remove(alarm.operation);
removeImpl(alarm.operation);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Failure sending alarm.", e);
@@ -1310,7 +1327,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
// is a repeating alarm, so toss the hoser.
remove(alarm.operation);
removeImpl(alarm.operation);
}
}
}
@@ -1323,7 +1340,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_DATE_CHANGED);
mContext.registerReceiver(this, filter);
getContext().registerReceiver(this, filter);
}
@Override
@@ -1354,7 +1371,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
final long tickEventDelay = nextTime - currentTime;
final WorkSource workSource = null; // Let system take blame for time tick events.
set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
0, mTimeTickSender, true, workSource);
}
@@ -1368,7 +1385,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
calendar.add(Calendar.DAY_OF_MONTH, 1);
final WorkSource workSource = null; // Let system take blame for date change events.
set(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource);
setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource);
}
}
@@ -1379,12 +1396,12 @@ class AlarmManagerService extends IAlarmManager.Stub {
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
getContext().registerReceiver(this, filter);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
sdFilter.addAction(Intent.ACTION_USER_STOPPED);
mContext.registerReceiver(this, sdFilter);
getContext().registerReceiver(this, sdFilter);
}
@Override

View File

@@ -19,6 +19,8 @@ package com.android.server;
import android.os.BatteryStats;
import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import android.app.ActivityManagerNative;
import android.content.ContentResolver;
@@ -134,13 +136,10 @@ public final class BatteryService extends Binder {
private boolean mSentLowBatteryBroadcast = false;
private BatteryListener mBatteryPropertiesListener;
private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
public BatteryService(Context context, LightsService lights) {
public BatteryService(Context context, LightsManager lightsManager) {
mContext = context;
mHandler = new Handler(true /*async*/);
mLed = new Led(context, lights);
mLed = new Led(context, lightsManager);
mBatteryStats = BatteryStatsService.getService();
mCriticalBatteryLevel = mContext.getResources().getInteger(
@@ -158,13 +157,11 @@ public final class BatteryService extends Binder {
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
mBatteryPropertiesListener = new BatteryListener();
IBinder b = ServiceManager.getService("batteryproperties");
mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
@@ -677,7 +674,7 @@ public final class BatteryService extends Binder {
};
private final class Led {
private final LightsService.Light mBatteryLight;
private final Light mBatteryLight;
private final int mBatteryLowARGB;
private final int mBatteryMediumARGB;
@@ -685,8 +682,8 @@ public final class BatteryService extends Binder {
private final int mBatteryLedOn;
private final int mBatteryLedOff;
public Led(Context context, LightsService lights) {
mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
public Led(Context context, LightsManager lights) {
mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);
mBatteryLowARGB = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLowARGB);
@@ -712,7 +709,7 @@ public final class BatteryService extends Binder {
mBatteryLight.setColor(mBatteryLowARGB);
} else {
// Flash red when battery is low and not charging
mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED,
mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
mBatteryLedOn, mBatteryLedOff);
}
} else if (status == BatteryManager.BATTERY_STATUS_CHARGING
@@ -732,8 +729,14 @@ public final class BatteryService extends Binder {
}
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
@Override
public void batteryPropertiesChanged(BatteryProperties props) {
BatteryService.this.update(props);
final long identity = Binder.clearCallingIdentity();
try {
BatteryService.this.update(props);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
}

View File

@@ -30,7 +30,7 @@ import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
import com.android.server.EventLogTags;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.wm.WindowManagerService;
import org.xmlpull.v1.XmlPullParser;

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2013 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 android.util.ArrayMap;
/**
* This class is used in a similar way as ServiceManager, except the services registered here
* are not Binder objects and are only available in the same process.
*
* Once all services are converted to the SystemService interface, this class can be absorbed
* into SystemServiceManager.
*/
public final class LocalServices {
private LocalServices() {}
private static final ArrayMap<Class<?>, Object> sLocalServiceObjects =
new ArrayMap<Class<?>, Object>();
/**
* Returns a local service instance that implements the specified interface.
*
* @param type The type of service.
* @return The service object.
*/
@SuppressWarnings("unchecked")
public static <T> T getService(Class<T> type) {
synchronized (sLocalServiceObjects) {
return (T) sLocalServiceObjects.get(type);
}
}
/**
* Adds a service instance of the specified interface to the global registry of local services.
*/
public static <T> void addService(Class<T> type, T service) {
synchronized (sLocalServiceObjects) {
if (sLocalServiceObjects.containsKey(type)) {
throw new IllegalStateException("Overriding service registration");
}
sLocalServiceObjects.put(type, service);
}
}
}

View File

@@ -17,6 +17,8 @@
package com.android.server;
import android.app.ActivityManagerNative;
import android.app.IAlarmManager;
import android.app.INotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -58,9 +60,12 @@ import com.android.server.devicepolicy.DevicePolicyManagerService;
import com.android.server.display.DisplayManagerService;
import com.android.server.dreams.DreamManagerService;
import com.android.server.input.InputManagerService;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LightsService;
import com.android.server.media.MediaRouterService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
import com.android.server.notification.NotificationManagerService;
import com.android.server.os.SchedulingPolicyService;
import com.android.server.pm.Installer;
import com.android.server.pm.PackageManagerService;
@@ -69,6 +74,10 @@ import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.print.PrintManagerService;
import com.android.server.search.SearchManagerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightService;
import com.android.server.usb.UsbService;
import com.android.server.wallpaper.WallpaperManagerService;
import com.android.server.wifi.WifiService;
@@ -131,12 +140,12 @@ class ServerThread {
Installer installer = null;
AccountManagerService accountManager = null;
ContentService contentService = null;
LightsService lights = null;
LightsManager lights = null;
PowerManagerService power = null;
DisplayManagerService display = null;
BatteryService battery = null;
VibratorService vibrator = null;
AlarmManagerService alarm = null;
IAlarmManager alarm = null;
MountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
@@ -152,8 +161,7 @@ class ServerThread {
DockObserver dock = null;
UsbService usb = null;
SerialService serial = null;
TwilightService twilight = null;
UiModeManagerService uiMode = null;
TwilightManager twilight = null;
RecognitionManagerService recognition = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
@@ -203,6 +211,8 @@ class ServerThread {
Slog.e("System", "************ Failure starting bootstrap service", e);
}
final SystemServiceManager systemServiceManager = new SystemServiceManager(context);
boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
boolean disableMedia = SystemProperties.getBoolean("config.disable_media", false);
boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
@@ -278,8 +288,8 @@ class ServerThread {
Slog.i(TAG, "System Content Providers");
ActivityManagerService.installSystemProviders();
Slog.i(TAG, "Lights Service");
lights = new LightsService(context);
systemServiceManager.startService(LightsService.class);
lights = LocalServices.getService(LightsManager.class);
Slog.i(TAG, "Battery Service");
battery = new BatteryService(context, lights);
@@ -295,17 +305,16 @@ class ServerThread {
// only initialize the power service after we have started the
// lights service, content providers and the battery service.
power.init(context, lights, ActivityManagerService.self(), battery,
power.init(context, lights, battery,
BatteryStatsService.getService(),
ActivityManagerService.self().getAppOpsService(), display);
Slog.i(TAG, "Alarm Manager");
alarm = new AlarmManagerService(context);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);
systemServiceManager.startService(AlarmManagerService.class);
alarm = IAlarmManager.Stub.asInterface(
ServiceManager.getService(Context.ALARM_SERVICE));
Slog.i(TAG, "Init Watchdog");
Watchdog.getInstance().init(context, battery, power, alarm,
ActivityManagerService.self());
Watchdog.getInstance().init(context, ActivityManagerService.self());
Watchdog.getInstance().addThread(wmHandler, "WindowManager thread");
Slog.i(TAG, "Input Manager");
@@ -350,9 +359,9 @@ class ServerThread {
DevicePolicyManagerService devicePolicy = null;
StatusBarManagerService statusBar = null;
INotificationManager notification = null;
InputMethodManagerService imm = null;
AppWidgetService appWidget = null;
NotificationManagerService notification = null;
WallpaperManagerService wallpaper = null;
LocationManagerService location = null;
CountryDetectorService countryDetector = null;
@@ -401,7 +410,7 @@ class ServerThread {
ActivityManagerNative.getDefault().showBootMessage(
context.getResources().getText(
com.android.internal.R.string.android_upgrading_starting_apps),
false);
false);
} catch (RemoteException e) {
}
@@ -571,22 +580,12 @@ class ServerThread {
reportWtf("making Content Service ready", e);
}
try {
Slog.i(TAG, "Notification Manager");
notification = new NotificationManagerService(context, statusBar, lights);
ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);
networkPolicy.bindNotificationManager(notification);
} catch (Throwable e) {
reportWtf("starting Notification Manager", e);
}
systemServiceManager.startService(NotificationManagerService.class);
notification = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
networkPolicy.bindNotificationManager(notification);
try {
Slog.i(TAG, "Device Storage Monitor");
ServiceManager.addService(DeviceStorageMonitorService.SERVICE,
new DeviceStorageMonitorService(context));
} catch (Throwable e) {
reportWtf("starting DeviceStorageMonitor service", e);
}
systemServiceManager.startService(DeviceStorageMonitorService.class);
if (!disableLocation) {
try {
@@ -685,20 +684,10 @@ class ServerThread {
}
}
try {
Slog.i(TAG, "Twilight Service");
twilight = new TwilightService(context);
} catch (Throwable e) {
reportWtf("starting TwilightService", e);
}
systemServiceManager.startService(TwilightService.class);
twilight = LocalServices.getService(TwilightManager.class);
try {
Slog.i(TAG, "UI Mode Manager Service");
// Listen for UI mode changes
uiMode = new UiModeManagerService(context, twilight);
} catch (Throwable e) {
reportWtf("starting UiModeManagerService", e);
}
systemServiceManager.startService(UiModeManagerService.class);
if (!disableNonCoreServices) {
try {
@@ -858,13 +847,7 @@ class ServerThread {
}
}
if (notification != null) {
try {
notification.systemReady();
} catch (Throwable e) {
reportWtf("making Notification Service ready", e);
}
}
systemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
try {
wm.systemReady();
@@ -913,8 +896,6 @@ class ServerThread {
final ConnectivityService connectivityF = connectivity;
final DockObserver dockF = dock;
final UsbService usbF = usb;
final TwilightService twilightF = twilight;
final UiModeManagerService uiModeF = uiMode;
final AppWidgetService appWidgetF = appWidget;
final WallpaperManagerService wallpaperF = wallpaper;
final InputMethodManagerService immF = imm;
@@ -991,16 +972,6 @@ class ServerThread {
} catch (Throwable e) {
reportWtf("making USB Service ready", e);
}
try {
if (twilightF != null) twilightF.systemReady();
} catch (Throwable e) {
reportWtf("makin Twilight Service ready", e);
}
try {
if (uiModeF != null) uiModeF.systemReady();
} catch (Throwable e) {
reportWtf("making UI Mode Service ready", e);
}
try {
if (recognitionF != null) recognitionF.systemReady();
} catch (Throwable e) {
@@ -1010,6 +981,7 @@ class ServerThread {
// It is now okay to let the various system services start their
// third party code...
systemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
try {
if (appWidgetF != null) appWidgetF.systemRunning(safeMode);
@@ -1086,6 +1058,8 @@ class ServerThread {
} catch (Throwable e) {
reportWtf("Notifying MediaRouterService running", e);
}
systemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
}
});

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2013 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 android.content.Context;
import android.os.IBinder;
import android.os.ServiceManager;
/**
* System services respond to lifecycle events that help the services know what
*/
public abstract class SystemService {
/*
* Boot Phases
*/
public static final int PHASE_SYSTEM_SERVICES_READY = 500;
public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
public static final int PHASE_BOOT_COMPLETE = 1000;
private SystemServiceManager mManager;
private Context mContext;
final void init(Context context, SystemServiceManager manager) {
mContext = context;
mManager = manager;
onCreate(context);
}
/**
* Services are not yet available. This is a good place to do setup work that does
* not require other services.
*
* @param context The system context.
*/
public void onCreate(Context context) {}
/**
* Called when the dependencies listed in the @Service class-annotation are available
* and after the chosen start phase.
* When this method returns, the service should be published.
*/
public abstract void onStart();
/**
* Called on each phase of the boot process. Phases before the service's start phase
* (as defined in the @Service annotation) are never received.
*
* @param phase The current boot phase.
*/
public void onBootPhase(int phase) {}
/**
* Publish the service so it is accessible to other services and apps.
*/
protected final void publishBinderService(String name, IBinder service) {
ServiceManager.addService(name, service);
}
/**
* Get a binder service by its name.
*/
protected final IBinder getBinderService(String name) {
return ServiceManager.getService(name);
}
/**
* Publish the service so it is only accessible to the system process.
*/
protected final <T> void publishLocalService(Class<T> type, T service) {
LocalServices.addService(type, service);
}
/**
* Get a local service by interface.
*/
protected final <T> T getLocalService(Class<T> type) {
return LocalServices.getService(type);
}
public final Context getContext() {
return mContext;
}
// /**
// * Called when a new user has been created. If your service deals with multiple users, this
// * method should be overridden.
// *
// * @param userHandle The user that was created.
// */
// public void onUserCreated(int userHandle) {
// }
//
// /**
// * Called when an existing user has started a new session. If your service deals with multiple
// * users, this method should be overridden.
// *
// * @param userHandle The user who started a new session.
// */
// public void onUserStarted(int userHandle) {
// }
//
// /**
// * Called when a background user session has entered the foreground. If your service deals with
// * multiple users, this method should be overridden.
// *
// * @param userHandle The user who's session entered the foreground.
// */
// public void onUserForeground(int userHandle) {
// }
//
// /**
// * Called when a foreground user session has entered the background. If your service deals with
// * multiple users, this method should be overridden;
// *
// * @param userHandle The user who's session entered the background.
// */
// public void onUserBackground(int userHandle) {
// }
//
// /**
// * Called when a user's active session has stopped. If your service deals with multiple users,
// * this method should be overridden.
// *
// * @param userHandle The user who's session has stopped.
// */
// public void onUserStopped(int userHandle) {
// }
//
// /**
// * Called when a user has been removed from the system. If your service deals with multiple
// * users, this method should be overridden.
// *
// * @param userHandle The user who has been removed.
// */
// public void onUserRemoved(int userHandle) {
// }
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2013 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 android.content.Context;
import android.util.Log;
import android.util.Slog;
import java.util.ArrayList;
/**
* Manages creating, starting, and other lifecycle events of system services.
*/
public class SystemServiceManager {
private static final String TAG = "SystemServiceManager";
private final Context mContext;
// Services that should receive lifecycle events.
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
private int mCurrentPhase = -1;
public SystemServiceManager(Context context) {
mContext = context;
}
/**
* Creates and starts a system service. The class must be a subclass of
* {@link com.android.server.SystemService}.
*
* @param serviceClass A Java class that implements the SystemService interface.
* @throws RuntimeException if the service fails to start.
*/
public void startService(Class<?> serviceClass) {
final SystemService serviceInstance = createInstance(serviceClass);
try {
Slog.i(TAG, "Creating " + serviceClass.getSimpleName());
serviceInstance.init(mContext, this);
} catch (Throwable e) {
throw new RuntimeException("Failed to create service " + serviceClass.getName(), e);
}
mServices.add(serviceInstance);
try {
Slog.i(TAG, "Starting " + serviceClass.getSimpleName());
serviceInstance.onStart();
} catch (Throwable e) {
throw new RuntimeException("Failed to start service " + serviceClass.getName(), e);
}
}
/**
* Starts the specified boot phase for all system services that have been started up to
* this point.
*
* @param phase The boot phase to start.
*/
public void startBootPhase(final int phase) {
if (phase <= mCurrentPhase) {
throw new IllegalArgumentException("Next phase must be larger than previous");
}
mCurrentPhase = phase;
Slog.i(TAG, "Starting phase " + mCurrentPhase);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
try {
service.onBootPhase(mCurrentPhase);
} catch (Throwable e) {
reportWtf("Service " + service.getClass().getName() +
" threw an Exception processing boot phase " + mCurrentPhase, e);
}
}
}
/**
* Outputs the state of this manager to the System log.
*/
public void dump() {
StringBuilder builder = new StringBuilder();
builder.append("Current phase: ").append(mCurrentPhase).append("\n");
builder.append("Services:\n");
final int startedLen = mServices.size();
for (int i = 0; i < startedLen; i++) {
final SystemService service = mServices.get(i);
builder.append("\t")
.append(service.getClass().getSimpleName())
.append("\n");
}
Slog.e(TAG, builder.toString());
}
private SystemService createInstance(Class<?> clazz) {
// Make sure it's a type we expect
if (!SystemService.class.isAssignableFrom(clazz)) {
reportWtf("Class " + clazz.getName() + " does not extend " +
SystemService.class.getName());
}
try {
return (SystemService) clazz.newInstance();
} catch (InstantiationException e) {
reportWtf("Class " + clazz.getName() + " is abstract", e);
} catch (IllegalAccessException e) {
reportWtf("Class " + clazz.getName() +
" must have a public no-arg constructor", e);
}
return null;
}
private static void reportWtf(String message) {
reportWtf(message, null);
}
private static void reportWtf(String message, Throwable e) {
Slog.i(TAG, "******************************");
Log.wtf(TAG, message, e);
// Make sure we die
throw new RuntimeException(message, e);
}
}

View File

@@ -34,9 +34,9 @@ import android.content.res.Configuration;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.Sandman;
@@ -47,9 +47,11 @@ import java.io.PrintWriter;
import com.android.internal.R;
import com.android.internal.app.DisableCarModeActivity;
import com.android.server.TwilightService.TwilightState;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
final class UiModeManagerService extends IUiModeManager.Stub {
final class UiModeManagerService extends SystemService {
private static final String TAG = UiModeManager.class.getSimpleName();
private static final boolean LOG = false;
@@ -57,40 +59,36 @@ final class UiModeManagerService extends IUiModeManager.Stub {
private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
private final Context mContext;
private final TwilightService mTwilightService;
private final Handler mHandler = new Handler();
final Object mLock = new Object();
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mNightMode = UiModeManager.MODE_NIGHT_NO;
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
int mNightMode = UiModeManager.MODE_NIGHT_NO;
private boolean mCarModeEnabled = false;
private boolean mCharging = false;
private final int mDefaultUiModeType;
private final boolean mCarModeKeepsScreenOn;
private final boolean mDeskModeKeepsScreenOn;
private final boolean mTelevision;
private int mDefaultUiModeType;
private boolean mCarModeKeepsScreenOn;
private boolean mDeskModeKeepsScreenOn;
private boolean mTelevision;
private boolean mComputedNightMode;
private int mCurUiMode = 0;
int mCurUiMode = 0;
private int mSetUiMode = 0;
private boolean mHoldingConfiguration = false;
private Configuration mConfiguration = new Configuration();
boolean mSystemReady;
private boolean mSystemReady;
private final Handler mHandler = new Handler();
private TwilightManager mTwilightManager;
private NotificationManager mNotificationManager;
private StatusBarManager mStatusBarManager;
private final PowerManager mPowerManager;
private final PowerManager.WakeLock mWakeLock;
private PowerManager.WakeLock mWakeLock;
static Intent buildHomeIntent(String category) {
private static Intent buildHomeIntent(String category) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(category);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -142,28 +140,26 @@ final class UiModeManagerService extends IUiModeManager.Stub {
}
};
private final TwilightService.TwilightListener mTwilightListener =
new TwilightService.TwilightListener() {
private final TwilightListener mTwilightListener = new TwilightListener() {
@Override
public void onTwilightStateChanged() {
updateTwilight();
}
};
public UiModeManagerService(Context context, TwilightService twilight) {
mContext = context;
mTwilightService = twilight;
@Override
public void onStart() {
final Context context = getContext();
mTwilightManager = getLocalService(TwilightManager.class);
final PowerManager powerManager =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
ServiceManager.addService(Context.UI_MODE_SERVICE, this);
mContext.registerReceiver(mDockModeReceiver,
context.registerReceiver(mDockModeReceiver,
new IntentFilter(Intent.ACTION_DOCK_EVENT));
mContext.registerReceiver(mBatteryReceiver,
context.registerReceiver(mBatteryReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
mConfiguration.setToDefaults();
mDefaultUiModeType = context.getResources().getInteger(
@@ -175,101 +171,139 @@ final class UiModeManagerService extends IUiModeManager.Stub {
mTelevision = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEVISION);
mNightMode = Settings.Secure.getInt(mContext.getContentResolver(),
mNightMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
mTwilightService.registerListener(mTwilightListener, mHandler);
mTwilightManager.registerListener(mTwilightListener, mHandler);
publishBinderService(Context.UI_MODE_SERVICE, mService);
}
@Override // Binder call
public void disableCarMode(int flags) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
setCarModeLocked(false);
if (mSystemReady) {
updateLocked(0, flags);
private final IBinder mService = new IUiModeManager.Stub() {
@Override
public void enableCarMode(int flags) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
setCarModeLocked(true);
if (mSystemReady) {
updateLocked(flags, 0);
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void enableCarMode(int flags) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
setCarModeLocked(true);
if (mSystemReady) {
updateLocked(flags, 0);
@Override
public void disableCarMode(int flags) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
setCarModeLocked(false);
if (mSystemReady) {
updateLocked(0, flags);
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public int getCurrentModeType() {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void setNightMode(int mode) {
switch (mode) {
case UiModeManager.MODE_NIGHT_NO:
case UiModeManager.MODE_NIGHT_YES:
case UiModeManager.MODE_NIGHT_AUTO:
break;
default:
throw new IllegalArgumentException("Unknown mode: " + mode);
}
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
if (isDoingNightModeLocked() && mNightMode != mode) {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.UI_NIGHT_MODE, mode);
mNightMode = mode;
updateLocked(0, 0);
@Override
public int getCurrentModeType() {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public int getNightMode() {
@Override
public void setNightMode(int mode) {
switch (mode) {
case UiModeManager.MODE_NIGHT_NO:
case UiModeManager.MODE_NIGHT_YES:
case UiModeManager.MODE_NIGHT_AUTO:
break;
default:
throw new IllegalArgumentException("Unknown mode: " + mode);
}
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
if (isDoingNightModeLocked() && mNightMode != mode) {
Settings.Secure.putInt(getContext().getContentResolver(),
Settings.Secure.UI_NIGHT_MODE, mode);
mNightMode = mode;
updateLocked(0, 0);
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override
public int getNightMode() {
synchronized (mLock) {
return mNightMode;
}
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump uimode service from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
dumpImpl(pw);
}
};
void dumpImpl(PrintWriter pw) {
synchronized (mLock) {
return mNightMode;
pw.println("Current UI Mode Service state:");
pw.print(" mDockState="); pw.print(mDockState);
pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
pw.print(" mNightMode="); pw.print(mNightMode);
pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
pw.print(" mSystemReady="); pw.println(mSystemReady);
pw.print(" mTwilightService.getCurrentState()=");
pw.println(mTwilightManager.getCurrentState());
}
}
void systemReady() {
synchronized (mLock) {
mSystemReady = true;
mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
updateComputedNightModeLocked();
updateLocked(0, 0);
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
synchronized (mLock) {
mSystemReady = true;
mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
updateComputedNightModeLocked();
updateLocked(0, 0);
}
}
}
private boolean isDoingNightModeLocked() {
boolean isDoingNightModeLocked() {
return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
}
private void setCarModeLocked(boolean enabled) {
void setCarModeLocked(boolean enabled) {
if (mCarModeEnabled != enabled) {
mCarModeEnabled = enabled;
}
@@ -344,7 +378,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
}
}
private void updateLocked(int enableFlags, int disableFlags) {
void updateLocked(int enableFlags, int disableFlags) {
String action = null;
String oldAction = null;
if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
@@ -359,7 +393,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
adjustStatusBarCarModeLocked();
if (oldAction != null) {
mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
}
mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
action = UiModeManager.ACTION_ENTER_CAR_MODE;
@@ -367,7 +401,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
} else if (isDeskDockState(mDockState)) {
if (!isDeskDockState(mLastBroadcastState)) {
if (oldAction != null) {
mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
}
mLastBroadcastState = mDockState;
action = UiModeManager.ACTION_ENTER_DESK_MODE;
@@ -393,7 +427,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
Intent intent = new Intent(action);
intent.putExtra("enableFlags", enableFlags);
intent.putExtra("disableFlags", disableFlags);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
getContext().sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
mResultReceiver, null, Activity.RESULT_OK, null, null);
// Attempting to make this transition a little more clean, we are going
@@ -491,7 +525,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
// activity manager take care of both the start and config
// change.
Intent homeIntent = buildHomeIntent(category);
if (Sandman.shouldStartDockApp(mContext, homeIntent)) {
if (Sandman.shouldStartDockApp(getContext(), homeIntent)) {
try {
int result = ActivityManagerNative.getDefault().startActivityWithConfig(
null, null, homeIntent, null, null, null, 0, 0,
@@ -513,14 +547,15 @@ final class UiModeManagerService extends IUiModeManager.Stub {
// If we did not start a dock app, then start dreaming if supported.
if (category != null && !dockAppStarted) {
Sandman.startDreamWhenDockedIfAppropriate(mContext);
Sandman.startDreamWhenDockedIfAppropriate(getContext());
}
}
private void adjustStatusBarCarModeLocked() {
final Context context = getContext();
if (mStatusBarManager == null) {
mStatusBarManager = (StatusBarManager)
mContext.getSystemService(Context.STATUS_BAR_SERVICE);
context.getSystemService(Context.STATUS_BAR_SERVICE);
}
// Fear not: StatusBarManagerService manages a list of requests to disable
@@ -536,12 +571,12 @@ final class UiModeManagerService extends IUiModeManager.Stub {
if (mNotificationManager == null) {
mNotificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
context.getSystemService(Context.NOTIFICATION_SERVICE);
}
if (mNotificationManager != null) {
if (mCarModeEnabled) {
Intent carModeOffIntent = new Intent(mContext, DisableCarModeActivity.class);
Intent carModeOffIntent = new Intent(context, DisableCarModeActivity.class);
Notification n = new Notification();
n.icon = R.drawable.stat_notify_car_mode;
@@ -549,10 +584,10 @@ final class UiModeManagerService extends IUiModeManager.Stub {
n.flags = Notification.FLAG_ONGOING_EVENT;
n.when = 0;
n.setLatestEventInfo(
mContext,
mContext.getString(R.string.car_mode_disable_notification_title),
mContext.getString(R.string.car_mode_disable_notification_message),
PendingIntent.getActivityAsUser(mContext, 0, carModeOffIntent, 0,
context,
context.getString(R.string.car_mode_disable_notification_title),
context.getString(R.string.car_mode_disable_notification_message),
PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0,
null, UserHandle.CURRENT));
mNotificationManager.notifyAsUser(null,
R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
@@ -563,7 +598,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
}
}
private void updateTwilight() {
void updateTwilight() {
synchronized (mLock) {
if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
updateComputedNightModeLocked();
@@ -573,36 +608,11 @@ final class UiModeManagerService extends IUiModeManager.Stub {
}
private void updateComputedNightModeLocked() {
TwilightState state = mTwilightService.getCurrentState();
TwilightState state = mTwilightManager.getCurrentState();
if (state != null) {
mComputedNightMode = state.isNight();
}
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump uimode service from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
synchronized (mLock) {
pw.println("Current UI Mode Service state:");
pw.print(" mDockState="); pw.print(mDockState);
pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
pw.print(" mNightMode="); pw.print(mNightMode);
pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
pw.print(" mSystemReady="); pw.println(mSystemReady);
pw.print(" mTwilightService.getCurrentState()=");
pw.println(mTwilightService.getCurrentState());
}
}
}

View File

@@ -76,9 +76,6 @@ public class Watchdog extends Thread {
final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<HandlerChecker>();
final HandlerChecker mMonitorChecker;
ContentResolver mResolver;
BatteryService mBattery;
PowerManagerService mPower;
AlarmManagerService mAlarm;
ActivityManagerService mActivity;
int mPhonePid;
@@ -230,13 +227,8 @@ public class Watchdog extends Thread {
"i/o thread", DEFAULT_TIMEOUT));
}
public void init(Context context, BatteryService battery,
PowerManagerService power, AlarmManagerService alarm,
ActivityManagerService activity) {
public void init(Context context, ActivityManagerService activity) {
mResolver = context.getContentResolver();
mBattery = battery;
mPower = power;
mAlarm = alarm;
mActivity = activity;
context.registerReceiver(new RebootRequestReceiver(),

View File

@@ -18,7 +18,8 @@ package com.android.server.am;
import com.android.internal.app.ProcessStats;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.NotificationManagerService;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
import android.app.INotificationManager;
import android.app.Notification;
@@ -427,8 +428,8 @@ final class ServiceRecord extends Binder {
final Notification localForegroundNoti = foregroundNoti;
ams.mHandler.post(new Runnable() {
public void run() {
NotificationManagerService nm =
(NotificationManagerService) NotificationManager.getService();
NotificationManagerInternal nm = LocalServices.getService(
NotificationManagerInternal.class);
if (nm == null) {
return;
}
@@ -479,7 +480,7 @@ final class ServiceRecord extends Binder {
throw new RuntimeException("icon must be non-zero");
}
int[] outId = new int[1];
nm.enqueueNotificationInternal(localPackageName, localPackageName,
nm.enqueueNotification(localPackageName, localPackageName,
appUid, appPid, null, localForegroundId, localForegroundNoti,
outId, userId);
} catch (RuntimeException e) {

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2013 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.lights;
public abstract class Light {
public static final int LIGHT_FLASH_NONE = 0;
public static final int LIGHT_FLASH_TIMED = 1;
public static final int LIGHT_FLASH_HARDWARE = 2;
/**
* Light brightness is managed by a user setting.
*/
public static final int BRIGHTNESS_MODE_USER = 0;
/**
* Light brightness is managed by a light sensor.
*/
public static final int BRIGHTNESS_MODE_SENSOR = 1;
public abstract void setBrightness(int brightness);
public abstract void setBrightness(int brightness, int brightnessMode);
public abstract void setColor(int color);
public abstract void setFlashing(int color, int mode, int onMS, int offMS);
public abstract void pulse();
public abstract void pulse(int color, int onMS);
public abstract void turnOff();
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2013 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.lights;
public abstract class LightsManager {
public static final int LIGHT_ID_BACKLIGHT = 0;
public static final int LIGHT_ID_KEYBOARD = 1;
public static final int LIGHT_ID_BUTTONS = 2;
public static final int LIGHT_ID_BATTERY = 3;
public static final int LIGHT_ID_NOTIFICATIONS = 4;
public static final int LIGHT_ID_ATTENTION = 5;
public static final int LIGHT_ID_BLUETOOTH = 6;
public static final int LIGHT_ID_WIFI = 7;
public static final int LIGHT_ID_COUNT = 8;
public abstract Light getLight(int id);
}

View File

@@ -14,59 +14,38 @@
* limitations under the License.
*/
package com.android.server;
package com.android.server.lights;
import com.android.server.SystemService;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.IHardwareService;
import android.os.ServiceManager;
import android.os.Message;
import android.util.Slog;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class LightsService {
private static final String TAG = "LightsService";
private static final boolean DEBUG = false;
public class LightsService extends SystemService {
static final String TAG = "LightsService";
static final boolean DEBUG = false;
public static final int LIGHT_ID_BACKLIGHT = 0;
public static final int LIGHT_ID_KEYBOARD = 1;
public static final int LIGHT_ID_BUTTONS = 2;
public static final int LIGHT_ID_BATTERY = 3;
public static final int LIGHT_ID_NOTIFICATIONS = 4;
public static final int LIGHT_ID_ATTENTION = 5;
public static final int LIGHT_ID_BLUETOOTH = 6;
public static final int LIGHT_ID_WIFI = 7;
public static final int LIGHT_ID_COUNT = 8;
final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
public static final int LIGHT_FLASH_NONE = 0;
public static final int LIGHT_FLASH_TIMED = 1;
public static final int LIGHT_FLASH_HARDWARE = 2;
private final class LightImpl extends Light {
/**
* Light brightness is managed by a user setting.
*/
public static final int BRIGHTNESS_MODE_USER = 0;
/**
* Light brightness is managed by a light sensor.
*/
public static final int BRIGHTNESS_MODE_SENSOR = 1;
private final Light mLights[] = new Light[LIGHT_ID_COUNT];
public final class Light {
private Light(int id) {
private LightImpl(int id) {
mId = id;
}
@Override
public void setBrightness(int brightness) {
setBrightness(brightness, BRIGHTNESS_MODE_USER);
}
@Override
public void setBrightness(int brightness, int brightnessMode) {
synchronized (this) {
int color = brightness & 0x000000ff;
@@ -75,23 +54,26 @@ public class LightsService {
}
}
@Override
public void setColor(int color) {
synchronized (this) {
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
}
}
@Override
public void setFlashing(int color, int mode, int onMS, int offMS) {
synchronized (this) {
setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
}
}
@Override
public void pulse() {
pulse(0x00ffffff, 7);
}
@Override
public void pulse(int color, int onMS) {
synchronized (this) {
if (mColor == 0 && !mFlashing) {
@@ -101,6 +83,7 @@ public class LightsService {
}
}
@Override
public void turnOff() {
synchronized (this) {
setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
@@ -153,9 +136,10 @@ public class LightsService {
}
public void setFlashlightEnabled(boolean on) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT)
final Context context = getContext();
if (context.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT)
!= PackageManager.PERMISSION_GRANTED &&
mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
context.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires FLASHLIGHT or HARDWARE_TEST permission");
}
@@ -172,31 +156,41 @@ public class LightsService {
}
};
LightsService(Context context) {
@Override
public void onCreate(Context context) {
mNativePointer = init_native();
mContext = context;
ServiceManager.addService("hardware", mLegacyFlashlightHack);
for (int i = 0; i < LIGHT_ID_COUNT; i++) {
mLights[i] = new Light(i);
for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
mLights[i] = new LightImpl(i);
}
}
@Override
public void onStart() {
publishBinderService("hardware", mLegacyFlashlightHack);
publishLocalService(LightsManager.class, mService);
}
private final LightsManager mService = new LightsManager() {
@Override
public com.android.server.lights.Light getLight(int id) {
if (id < LIGHT_ID_COUNT) {
return mLights[id];
} else {
return null;
}
}
};
protected void finalize() throws Throwable {
finalize_native(mNativePointer);
super.finalize();
}
public Light getLight(int id) {
return mLights[id];
}
private Handler mH = new Handler() {
@Override
public void handleMessage(Message msg) {
Light light = (Light)msg.obj;
LightImpl light = (LightImpl)msg.obj;
light.stopFlashing();
}
};
@@ -204,10 +198,8 @@ public class LightsService {
private static native int init_native();
private static native void finalize_native(int ptr);
private static native void setLight_native(int ptr, int light, int color, int mode,
static native void setLight_native(int ptr, int light, int color, int mode,
int onMS, int offMS, int brightnessMode);
private final Context mContext;
private int mNativePointer;
int mNativePointer;
}

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2013, 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.notification;
public interface NotificationDelegate {
void onSetDisabled(int status);
void onClearAll();
void onNotificationClick(String pkg, String tag, int id);
void onNotificationClear(String pkg, String tag, int id);
void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message);
void onPanelRevealed();
}

View File

@@ -0,0 +1,8 @@
package com.android.server.notification;
import android.app.Notification;
public interface NotificationManagerInternal {
void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid,
String tag, int id, Notification notification, int[] idReceived, int userId);
}

View File

@@ -38,10 +38,10 @@ import com.android.internal.content.PackageHelper;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.DeviceStorageMonitorService;
import com.android.server.EventLogTags;
import com.android.server.IntentResolver;
import com.android.server.LocalServices;
import com.android.server.Watchdog;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -92,6 +92,7 @@ import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
import android.content.res.Resources;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -127,7 +128,6 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
import android.view.Display;
import android.view.WindowManager;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -162,6 +162,7 @@ import libcore.io.Libcore;
import libcore.io.StructStat;
import com.android.internal.R;
import com.android.server.storage.DeviceStorageMonitorInternal;
/**
* Keep track of all those .apks everywhere.
@@ -1067,6 +1068,12 @@ public class PackageManagerService extends IPackageManager.Stub {
return res;
}
private static void getDefaultDisplayMetrics(Context context, DisplayMetrics metrics) {
DisplayManager displayManager = (DisplayManager) context.getSystemService(
Context.DISPLAY_SERVICE);
displayManager.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics);
}
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
@@ -1114,9 +1121,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mInstaller = installer;
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
d.getMetrics(mMetrics);
getDefaultDisplayMetrics(context, mMetrics);
synchronized (mInstallLock) {
// writer
@@ -7339,6 +7344,15 @@ public class PackageManagerService extends IPackageManager.Stub {
return pkgLite.recommendedInstallLocation;
}
private long getMemoryLowThreshold() {
final DeviceStorageMonitorInternal
dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
if (dsm == null) {
return 0L;
}
return dsm.getMemoryLowThreshold();
}
/*
* Invoke remote method to get package information and install
* location values. Override install location based on default
@@ -7356,15 +7370,9 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
final long lowThreshold;
final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
.getService(DeviceStorageMonitorService.SERVICE);
if (dsm == null) {
final long lowThreshold = getMemoryLowThreshold();
if (lowThreshold == 0L) {
Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
lowThreshold = 0L;
} else {
lowThreshold = dsm.getMemoryLowThreshold();
}
try {
@@ -7922,8 +7930,8 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
final long lowThreshold;
final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
.getService(DeviceStorageMonitorService.SERVICE);
final DeviceStorageMonitorInternal
dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
if (dsm == null) {
Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
lowThreshold = 0L;
@@ -9738,10 +9746,10 @@ public class PackageManagerService extends IPackageManager.Stub {
clearExternalStorageDataSync(packageName, userId, true);
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
DeviceStorageMonitorInternal
dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
if (dsm != null) {
dsm.updateMemory();
dsm.checkMemory();
}
}
if(observer != null) {
@@ -11566,12 +11574,17 @@ public class PackageManagerService extends IPackageManager.Stub {
return true;
}
@Override
public boolean isStorageLow() {
final long token = Binder.clearCallingIdentity();
try {
final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
.getService(DeviceStorageMonitorService.SERVICE);
return dsm.isMemoryLow();
final DeviceStorageMonitorInternal
dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
if (dsm != null) {
return dsm.isMemoryLow();
} else {
return false;
}
} finally {
Binder.restoreCallingIdentity(token);
}

View File

@@ -16,10 +16,11 @@
package com.android.server.power;
import com.android.server.LightsService;
import com.android.server.TwilightService;
import com.android.server.TwilightService.TwilightState;
import com.android.server.lights.LightsManager;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.display.DisplayManagerService;
import com.android.server.twilight.TwilightState;
import android.animation.Animator;
import android.animation.ObjectAnimator;
@@ -179,10 +180,10 @@ final class DisplayPowerController {
private Handler mCallbackHandler;
// The lights service.
private final LightsService mLights;
private final LightsManager mLights;
// The twilight service.
private final TwilightService mTwilight;
private final TwilightManager mTwilight;
// The display manager.
private final DisplayManagerService mDisplayManager;
@@ -351,7 +352,7 @@ final class DisplayPowerController {
* Creates the display power controller.
*/
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
LightsService lights, TwilightService twilight, SensorManager sensorManager,
LightsManager lights, TwilightManager twilight, SensorManager sensorManager,
DisplayManagerService displayManager,
SuspendBlocker displaySuspendBlocker, DisplayBlanker displayBlanker,
Callbacks callbacks, Handler callbackHandler) {
@@ -528,7 +529,7 @@ final class DisplayPowerController {
private void initialize() {
mPowerState = new DisplayPowerState(
new ElectronBeam(mDisplayManager), mDisplayBlanker,
mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT));
mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));
mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
@@ -1368,8 +1369,7 @@ final class DisplayPowerController {
}
};
private final TwilightService.TwilightListener mTwilightListener =
new TwilightService.TwilightListener() {
private final TwilightListener mTwilightListener = new TwilightListener() {
@Override
public void onTwilightStateChanged() {
mTwilightChanged = true;

View File

@@ -16,7 +16,7 @@
package com.android.server.power;
import com.android.server.LightsService;
import com.android.server.lights.Light;
import android.os.AsyncTask;
import android.os.Handler;
@@ -56,7 +56,7 @@ final class DisplayPowerState {
private final Choreographer mChoreographer;
private final ElectronBeam mElectronBeam;
private final DisplayBlanker mDisplayBlanker;
private final LightsService.Light mBacklight;
private final Light mBacklight;
private final PhotonicModulator mPhotonicModulator;
private boolean mScreenOn;
@@ -72,7 +72,7 @@ final class DisplayPowerState {
private Runnable mCleanListener;
public DisplayPowerState(ElectronBeam electronBean,
DisplayBlanker displayBlanker, LightsService.Light backlight) {
DisplayBlanker displayBlanker, Light backlight) {
mHandler = new Handler(true /*async*/);
mChoreographer = Choreographer.getInstance();
mElectronBeam = electronBean;

View File

@@ -20,10 +20,11 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.server.BatteryService;
import com.android.server.EventLogTags;
import com.android.server.LightsService;
import com.android.server.TwilightService;
import com.android.server.lights.LightsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import com.android.server.twilight.TwilightManager;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService;
import com.android.server.display.DisplayManagerService;
import com.android.server.dreams.DreamManagerService;
@@ -168,7 +169,7 @@ public final class PowerManagerService extends IPowerManager.Stub
private static final int DREAM_BATTERY_LEVEL_DRAIN_CUTOFF = 5;
private Context mContext;
private LightsService mLightsService;
private LightsManager mLightsManager;
private BatteryService mBatteryService;
private DisplayManagerService mDisplayManagerService;
private IBatteryStats mBatteryStats;
@@ -181,7 +182,7 @@ public final class PowerManagerService extends IPowerManager.Stub
private WirelessChargerDetector mWirelessChargerDetector;
private SettingsObserver mSettingsObserver;
private DreamManagerService mDreamManager;
private LightsService.Light mAttentionLight;
private Light mAttentionLight;
private final Object mLock = new Object();
@@ -396,11 +397,11 @@ public final class PowerManagerService extends IPowerManager.Stub
* Initialize the power manager.
* Must be called before any other functions within the power manager are called.
*/
public void init(Context context, LightsService ls,
ActivityManagerService am, BatteryService bs, IBatteryStats bss,
public void init(Context context, LightsManager ls,
BatteryService bs, IBatteryStats bss,
IAppOpsService appOps, DisplayManagerService dm) {
mContext = context;
mLightsService = ls;
mLightsManager = ls;
mBatteryService = bs;
mBatteryStats = bss;
mAppOps = appOps;
@@ -427,12 +428,12 @@ public final class PowerManagerService extends IPowerManager.Stub
}
}
public void systemReady(TwilightService twilight, DreamManagerService dreamManager) {
public void systemReady(TwilightManager twilight, DreamManagerService dreamManager) {
synchronized (mLock) {
mSystemReady = true;
mDreamManager = dreamManager;
PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
@@ -448,7 +449,7 @@ public final class PowerManagerService extends IPowerManager.Stub
// The display power controller runs on the power manager service's
// own handler thread to ensure timely operation.
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
mContext, mNotifier, mLightsService, twilight, sensorManager,
mContext, mNotifier, mLightsManager, twilight, sensorManager,
mDisplayManagerService, mDisplaySuspendBlocker, mDisplayBlanker,
mDisplayPowerControllerCallbacks, mHandler);
@@ -456,7 +457,7 @@ public final class PowerManagerService extends IPowerManager.Stub
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
@@ -2061,7 +2062,7 @@ public final class PowerManagerService extends IPowerManager.Stub
}
private void setAttentionLightInternal(boolean on, int color) {
LightsService.Light light;
Light light;
synchronized (mLock) {
if (!mSystemReady) {
return;
@@ -2070,7 +2071,7 @@ public final class PowerManagerService extends IPowerManager.Stub
}
// Control light outside of lock.
light.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
light.setFlashing(color, Light.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
}
/**

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2013, 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.statusbar;
import com.android.server.notification.NotificationDelegate;
import android.os.IBinder;
import android.service.notification.StatusBarNotification;
public interface StatusBarManagerInternal {
void setNotificationDelegate(NotificationDelegate delegate);
IBinder addNotification(StatusBarNotification notification);
void updateNotification(IBinder key, StatusBarNotification notification);
void removeNotification(IBinder key);
}

View File

@@ -14,26 +14,28 @@
* limitations under the License.
*/
package com.android.server;
package com.android.server.statusbar;
import android.app.StatusBarManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationDelegate;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -51,31 +53,31 @@ import java.util.Map;
public class StatusBarManagerService extends IStatusBarService.Stub
implements WindowManagerService.OnHardKeyboardStatusChangeListener
{
static final String TAG = "StatusBarManagerService";
static final boolean SPEW = false;
private static final String TAG = "StatusBarManagerService";
private static final boolean SPEW = false;
final Context mContext;
final WindowManagerService mWindowManager;
Handler mHandler = new Handler();
NotificationCallbacks mNotificationCallbacks;
volatile IStatusBar mBar;
StatusBarIconList mIcons = new StatusBarIconList();
HashMap<IBinder,StatusBarNotification> mNotifications
private final Context mContext;
private final WindowManagerService mWindowManager;
private Handler mHandler = new Handler();
private NotificationDelegate mNotificationDelegate;
private volatile IStatusBar mBar;
private StatusBarIconList mIcons = new StatusBarIconList();
private HashMap<IBinder,StatusBarNotification> mNotifications
= new HashMap<IBinder,StatusBarNotification>();
// for disabling the status bar
final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
IBinder mSysUiVisToken = new Binder();
int mDisabled = 0;
private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
private IBinder mSysUiVisToken = new Binder();
private int mDisabled = 0;
Object mLock = new Object();
private Object mLock = new Object();
// encompasses lights-out mode and other flags defined on View
int mSystemUiVisibility = 0;
boolean mMenuVisible = false;
int mImeWindowVis = 0;
int mImeBackDisposition;
IBinder mImeToken = null;
int mCurrentUserId;
private int mSystemUiVisibility = 0;
private boolean mMenuVisible = false;
private int mImeWindowVis = 0;
private int mImeBackDisposition;
private IBinder mImeToken = null;
private int mCurrentUserId;
private class DisableRecord implements IBinder.DeathRecipient {
int userId;
@@ -90,16 +92,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
public interface NotificationCallbacks {
void onSetDisabled(int status);
void onClearAll();
void onNotificationClick(String pkg, String tag, int id);
void onNotificationClear(String pkg, String tag, int id);
void onPanelRevealed();
void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message);
}
/**
* Construct the service, add the status bar view to the window manager
*/
@@ -110,15 +102,74 @@ public class StatusBarManagerService extends IStatusBarService.Stub
final Resources res = context.getResources();
mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons));
LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
}
public void setNotificationCallbacks(NotificationCallbacks listener) {
mNotificationCallbacks = listener;
}
/**
* Private API used by NotificationManagerService.
*/
private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() {
@Override
public void setNotificationDelegate(NotificationDelegate delegate) {
synchronized (mNotifications) {
mNotificationDelegate = delegate;
}
}
@Override
public IBinder addNotification(StatusBarNotification notification) {
synchronized (mNotifications) {
IBinder key = new Binder();
mNotifications.put(key, notification);
if (mBar != null) {
try {
mBar.addNotification(key, notification);
} catch (RemoteException ex) {
}
}
return key;
}
}
@Override
public void updateNotification(IBinder key, StatusBarNotification notification) {
synchronized (mNotifications) {
if (!mNotifications.containsKey(key)) {
throw new IllegalArgumentException("updateNotification key not found: " + key);
}
mNotifications.put(key, notification);
if (mBar != null) {
try {
mBar.updateNotification(key, notification);
} catch (RemoteException ex) {
}
}
}
}
@Override
public void removeNotification(IBinder key) {
synchronized (mNotifications) {
final StatusBarNotification n = mNotifications.remove(key);
if (n == null) {
Slog.e(TAG, "removeNotification key not found: " + key);
return;
}
if (mBar != null) {
try {
mBar.removeNotification(key);
} catch (RemoteException ex) {
}
}
}
}
};
// ================================================================================
// From IStatusBarService
// ================================================================================
@Override
public void expandNotificationsPanel() {
enforceExpandStatusBar();
@@ -130,6 +181,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void collapsePanels() {
enforceExpandStatusBar();
@@ -141,6 +193,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void expandSettingsPanel() {
enforceExpandStatusBar();
@@ -152,6 +205,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void disable(int what, IBinder token, String pkg) {
disableInternal(mCurrentUserId, what, token, pkg);
}
@@ -177,7 +231,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
mDisabled = net;
mHandler.post(new Runnable() {
public void run() {
mNotificationCallbacks.onSetDisabled(net);
mNotificationDelegate.onSetDisabled(net);
}
});
if (mBar != null) {
@@ -189,6 +243,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
String contentDescription) {
enforceStatusBar();
@@ -214,6 +269,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void setIconVisibility(String slot, boolean visible) {
enforceStatusBar();
@@ -241,6 +297,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void removeIcon(String slot) {
enforceStatusBar();
@@ -265,6 +322,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
* Hide or show the on-screen Menu key. Only call this from the window manager, typically in
* response to a window with FLAG_NEEDS_MENU_KEY set.
*/
@Override
public void topAppWindowChanged(final boolean menuVisible) {
enforceStatusBar();
@@ -285,6 +343,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition) {
enforceStatusBar();
@@ -312,6 +371,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void setSystemUiVisibility(int vis, int mask) {
// also allows calls from window manager which is in this process.
enforceStatusBarService();
@@ -344,6 +404,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void setHardKeyboardEnabled(final boolean enabled) {
mHandler.post(new Runnable() {
public void run() {
@@ -426,6 +487,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
// ================================================================================
// Callbacks from the status bar service.
// ================================================================================
@Override
public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
int switches[], List<IBinder> binders) {
@@ -458,86 +520,64 @@ public class StatusBarManagerService extends IStatusBarService.Stub
* The status bar service should call this each time the user brings the panel from
* invisible to visible in order to clear the notification light.
*/
@Override
public void onPanelRevealed() {
enforceStatusBarService();
// tell the notification manager to turn off the lights.
mNotificationCallbacks.onPanelRevealed();
long identity = Binder.clearCallingIdentity();
try {
// tell the notification manager to turn off the lights.
mNotificationDelegate.onPanelRevealed();
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void onNotificationClick(String pkg, String tag, int id) {
enforceStatusBarService();
mNotificationCallbacks.onNotificationClick(pkg, tag, id);
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.onNotificationClick(pkg, tag, id);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message) {
enforceStatusBarService();
// WARNING: this will call back into us to do the remove. Don't hold any locks.
mNotificationCallbacks.onNotificationError(pkg, tag, id, uid, initialPid, message);
long identity = Binder.clearCallingIdentity();
try {
// WARNING: this will call back into us to do the remove. Don't hold any locks.
mNotificationDelegate.onNotificationError(pkg, tag, id, uid, initialPid, message);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void onNotificationClear(String pkg, String tag, int id) {
enforceStatusBarService();
mNotificationCallbacks.onNotificationClear(pkg, tag, id);
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.onNotificationClear(pkg, tag, id);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void onClearAllNotifications() {
enforceStatusBarService();
mNotificationCallbacks.onClearAll();
}
// ================================================================================
// Callbacks for NotificationManagerService.
// ================================================================================
public IBinder addNotification(StatusBarNotification notification) {
synchronized (mNotifications) {
IBinder key = new Binder();
mNotifications.put(key, notification);
if (mBar != null) {
try {
mBar.addNotification(key, notification);
} catch (RemoteException ex) {
}
}
return key;
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.onClearAll();
} finally {
Binder.restoreCallingIdentity(identity);
}
}
public void updateNotification(IBinder key, StatusBarNotification notification) {
synchronized (mNotifications) {
if (!mNotifications.containsKey(key)) {
throw new IllegalArgumentException("updateNotification key not found: " + key);
}
mNotifications.put(key, notification);
if (mBar != null) {
try {
mBar.updateNotification(key, notification);
} catch (RemoteException ex) {
}
}
}
}
public void removeNotification(IBinder key) {
synchronized (mNotifications) {
final StatusBarNotification n = mNotifications.remove(key);
if (n == null) {
Slog.e(TAG, "removeNotification key not found: " + key);
return;
}
if (mBar != null) {
try {
mBar.removeNotification(key);
} catch (RemoteException ex) {
}
}
}
}
// ================================================================================
// Can be called from any thread

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2013, 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.storage;
public interface DeviceStorageMonitorInternal {
boolean isMemoryLow();
long getMemoryLowThreshold();
void checkMemory();
}

View File

@@ -14,7 +14,10 @@
* limitations under the License.
*/
package com.android.server;
package com.android.server.storage;
import com.android.server.EventLogTags;
import com.android.server.SystemService;
import android.app.Notification;
import android.app.NotificationManager;
@@ -29,8 +32,8 @@ import android.os.Binder;
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
@@ -66,13 +69,13 @@ import java.io.PrintWriter;
* settings parameter with a default value of 2MB), the free memory is
* logged to the event log.
*/
public class DeviceStorageMonitorService extends Binder {
private static final String TAG = "DeviceStorageMonitorService";
public class DeviceStorageMonitorService extends SystemService {
static final String TAG = "DeviceStorageMonitorService";
private static final boolean DEBUG = false;
private static final boolean localLOGV = false;
static final boolean DEBUG = false;
static final boolean localLOGV = false;
private static final int DEVICE_MEMORY_WHAT = 1;
static final int DEVICE_MEMORY_WHAT = 1;
private static final int MONITOR_INTERVAL = 1; //in minutes
private static final int LOW_MEMORY_NOTIFICATION_ID = 1;
@@ -84,9 +87,8 @@ public class DeviceStorageMonitorService extends Binder {
private long mFreeMemAfterLastCacheClear; // on /data
private long mLastReportedFreeMem;
private long mLastReportedFreeMemTime;
private boolean mLowMemFlag=false;
boolean mLowMemFlag=false;
private boolean mMemFullFlag=false;
private Context mContext;
private ContentResolver mResolver;
private long mTotalMemory; // on /data
private StatFs mDataFileStats;
@@ -98,19 +100,19 @@ public class DeviceStorageMonitorService extends Binder {
private static final File CACHE_PATH = Environment.getDownloadCacheDirectory();
private long mThreadStartTime = -1;
private boolean mClearSucceeded = false;
private boolean mClearingCache;
boolean mClearSucceeded = false;
boolean mClearingCache;
private Intent mStorageLowIntent;
private Intent mStorageOkIntent;
private Intent mStorageFullIntent;
private Intent mStorageNotFullIntent;
private CachePackageDataObserver mClearCacheObserver;
private final CacheFileDeletedObserver mCacheFileDeletedObserver;
private CacheFileDeletedObserver mCacheFileDeletedObserver;
private static final int _TRUE = 1;
private static final int _FALSE = 0;
// This is the raw threshold that has been set at which we consider
// storage to be low.
private long mMemLowThreshold;
long mMemLowThreshold;
// This is the threshold at which we start trying to flush caches
// to get below the low threshold limit. It is less than the low
// threshold; we will allow storage to get a bit beyond the limit
@@ -126,13 +128,13 @@ public class DeviceStorageMonitorService extends Binder {
/**
* This string is used for ServiceManager access to this class.
*/
public static final String SERVICE = "devicestoragemonitor";
static final String SERVICE = "devicestoragemonitor";
/**
* Handler that checks the amount of disk space on the device and sends a
* notification if the device runs low on disk space
*/
Handler mHandler = new Handler() {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//don't handle an invalid message
@@ -144,7 +146,7 @@ public class DeviceStorageMonitorService extends Binder {
}
};
class CachePackageDataObserver extends IPackageDataObserver.Stub {
private class CachePackageDataObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(String packageName, boolean succeeded) {
mClearSucceeded = succeeded;
mClearingCache = false;
@@ -154,7 +156,7 @@ public class DeviceStorageMonitorService extends Binder {
}
}
private final void restatDataDir() {
private void restatDataDir() {
try {
mDataFileStats.restat(DATA_PATH.getAbsolutePath());
mFreeMem = (long) mDataFileStats.getAvailableBlocks() *
@@ -206,7 +208,7 @@ public class DeviceStorageMonitorService extends Binder {
}
}
private final void clearCache() {
private void clearCache() {
if (mClearCacheObserver == null) {
// Lazy instantiation
mClearCacheObserver = new CachePackageDataObserver();
@@ -223,7 +225,7 @@ public class DeviceStorageMonitorService extends Binder {
}
}
private final void checkMemory(boolean checkCache) {
void checkMemory(boolean checkCache) {
//if the thread that was started to clear cache is still running do nothing till its
//finished clearing cache. Ideally this flag could be modified by clearCache
// and should be accessed via a lock but even if it does this test will fail now and
@@ -300,7 +302,7 @@ public class DeviceStorageMonitorService extends Binder {
postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);
}
private void postCheckMemoryMsg(boolean clearCache, long delay) {
void postCheckMemoryMsg(boolean clearCache, long delay) {
// Remove queued messages
mHandler.removeMessages(DEVICE_MEMORY_WHAT);
mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT,
@@ -312,10 +314,10 @@ public class DeviceStorageMonitorService extends Binder {
* Constructor to run service. initializes the disk space threshold value
* and posts an empty message to kickstart the process.
*/
public DeviceStorageMonitorService(Context context) {
@Override
public void onCreate(Context context) {
mLastReportedFreeMemTime = 0;
mContext = context;
mResolver = mContext.getContentResolver();
mResolver = context.getContentResolver();
//create StatFs object
mDataFileStats = new StatFs(DATA_PATH.getAbsolutePath());
mSystemFileStats = new StatFs(SYSTEM_PATH.getAbsolutePath());
@@ -331,9 +333,12 @@ public class DeviceStorageMonitorService extends Binder {
mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
}
@Override
public void onStart() {
// cache storage thresholds
final StorageManager sm = StorageManager.from(context);
final StorageManager sm = StorageManager.from(getContext());
mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH);
mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH);
@@ -345,6 +350,78 @@ public class DeviceStorageMonitorService extends Binder {
mCacheFileDeletedObserver = new CacheFileDeletedObserver();
mCacheFileDeletedObserver.startWatching();
publishBinderService(SERVICE, mRemoteService);
publishLocalService(DeviceStorageMonitorInternal.class, mLocalService);
}
private final DeviceStorageMonitorInternal mLocalService = new DeviceStorageMonitorInternal() {
@Override
public void checkMemory() {
// force an early check
postCheckMemoryMsg(true, 0);
}
@Override
public boolean isMemoryLow() {
return mLowMemFlag;
}
@Override
public long getMemoryLowThreshold() {
return mMemLowThreshold;
}
};
private final IBinder mRemoteService = new Binder() {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
dumpImpl(pw);
}
};
void dumpImpl(PrintWriter pw) {
final Context context = getContext();
pw.println("Current DeviceStorageMonitor state:");
pw.print(" mFreeMem="); pw.print(Formatter.formatFileSize(context, mFreeMem));
pw.print(" mTotalMemory=");
pw.println(Formatter.formatFileSize(context, mTotalMemory));
pw.print(" mFreeMemAfterLastCacheClear=");
pw.println(Formatter.formatFileSize(context, mFreeMemAfterLastCacheClear));
pw.print(" mLastReportedFreeMem=");
pw.print(Formatter.formatFileSize(context, mLastReportedFreeMem));
pw.print(" mLastReportedFreeMemTime=");
TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw);
pw.println();
pw.print(" mLowMemFlag="); pw.print(mLowMemFlag);
pw.print(" mMemFullFlag="); pw.println(mMemFullFlag);
pw.print(" mClearSucceeded="); pw.print(mClearSucceeded);
pw.print(" mClearingCache="); pw.println(mClearingCache);
pw.print(" mMemLowThreshold=");
pw.print(Formatter.formatFileSize(context, mMemLowThreshold));
pw.print(" mMemFullThreshold=");
pw.println(Formatter.formatFileSize(context, mMemFullThreshold));
pw.print(" mMemCacheStartTrimThreshold=");
pw.print(Formatter.formatFileSize(context, mMemCacheStartTrimThreshold));
pw.print(" mMemCacheTrimToThreshold=");
pw.println(Formatter.formatFileSize(context, mMemCacheTrimToThreshold));
}
/**
@@ -352,7 +429,8 @@ public class DeviceStorageMonitorService extends Binder {
* an error dialog indicating low disk space and launch the Installer
* application
*/
private final void sendNotification() {
private void sendNotification() {
final Context context = getContext();
if(localLOGV) Slog.i(TAG, "Sending low memory notification");
//log the event to event log with the amount of free storage(in bytes) left on the device
EventLog.writeEvent(EventLogTags.LOW_STORAGE, mFreeMem);
@@ -363,86 +441,58 @@ public class DeviceStorageMonitorService extends Binder {
lowMemIntent.putExtra("memory", mFreeMem);
lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationManager mNotificationMgr =
(NotificationManager)mContext.getSystemService(
(NotificationManager)context.getSystemService(
Context.NOTIFICATION_SERVICE);
CharSequence title = mContext.getText(
CharSequence title = context.getText(
com.android.internal.R.string.low_internal_storage_view_title);
CharSequence details = mContext.getText(
CharSequence details = context.getText(
com.android.internal.R.string.low_internal_storage_view_text);
PendingIntent intent = PendingIntent.getActivityAsUser(mContext, 0, lowMemIntent, 0,
PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0,
null, UserHandle.CURRENT);
Notification notification = new Notification();
notification.icon = com.android.internal.R.drawable.stat_notify_disk_full;
notification.tickerText = title;
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.setLatestEventInfo(mContext, title, details, intent);
notification.setLatestEventInfo(context, title, details, intent);
mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
UserHandle.ALL);
mContext.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
context.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
}
/**
* Cancels low storage notification and sends OK intent.
*/
private final void cancelNotification() {
private void cancelNotification() {
final Context context = getContext();
if(localLOGV) Slog.i(TAG, "Canceling low memory notification");
NotificationManager mNotificationMgr =
(NotificationManager)mContext.getSystemService(
(NotificationManager)context.getSystemService(
Context.NOTIFICATION_SERVICE);
//cancel notification since memory has been freed
mNotificationMgr.cancelAsUser(null, LOW_MEMORY_NOTIFICATION_ID, UserHandle.ALL);
mContext.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
mContext.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL);
context.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
context.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL);
}
/**
* Send a notification when storage is full.
*/
private final void sendFullNotification() {
private void sendFullNotification() {
if(localLOGV) Slog.i(TAG, "Sending memory full notification");
mContext.sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
getContext().sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
}
/**
* Cancels memory full notification and sends "not full" intent.
*/
private final void cancelFullNotification() {
private void cancelFullNotification() {
if(localLOGV) Slog.i(TAG, "Canceling memory full notification");
mContext.removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
mContext.sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL);
getContext().removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
getContext().sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL);
}
public void updateMemory() {
int callingUid = getCallingUid();
if(callingUid != Process.SYSTEM_UID) {
return;
}
// force an early check
postCheckMemoryMsg(true, 0);
}
/**
* Callable from other things in the system service to obtain the low memory
* threshold.
*
* @return low memory threshold in bytes
*/
public long getMemoryLowThreshold() {
return mMemLowThreshold;
}
/**
* Callable from other things in the system process to check whether memory
* is low.
*
* @return true is memory is low
*/
public boolean isMemoryLow() {
return mLowMemFlag;
}
public static class CacheFileDeletedObserver extends FileObserver {
private static class CacheFileDeletedObserver extends FileObserver {
public CacheFileDeletedObserver() {
super(Environment.getDownloadCacheDirectory().getAbsolutePath(), FileObserver.DELETE);
}
@@ -452,40 +502,4 @@ public class DeviceStorageMonitorService extends Binder {
EventLogTags.writeCacheFileDeleted(path);
}
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
pw.println("Current DeviceStorageMonitor state:");
pw.print(" mFreeMem="); pw.print(Formatter.formatFileSize(mContext, mFreeMem));
pw.print(" mTotalMemory=");
pw.println(Formatter.formatFileSize(mContext, mTotalMemory));
pw.print(" mFreeMemAfterLastCacheClear=");
pw.println(Formatter.formatFileSize(mContext, mFreeMemAfterLastCacheClear));
pw.print(" mLastReportedFreeMem=");
pw.print(Formatter.formatFileSize(mContext, mLastReportedFreeMem));
pw.print(" mLastReportedFreeMemTime=");
TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw);
pw.println();
pw.print(" mLowMemFlag="); pw.print(mLowMemFlag);
pw.print(" mMemFullFlag="); pw.println(mMemFullFlag);
pw.print(" mClearSucceeded="); pw.print(mClearSucceeded);
pw.print(" mClearingCache="); pw.println(mClearingCache);
pw.print(" mMemLowThreshold=");
pw.print(Formatter.formatFileSize(mContext, mMemLowThreshold));
pw.print(" mMemFullThreshold=");
pw.println(Formatter.formatFileSize(mContext, mMemFullThreshold));
pw.print(" mMemCacheStartTrimThreshold=");
pw.print(Formatter.formatFileSize(mContext, mMemCacheStartTrimThreshold));
pw.print(" mMemCacheTrimToThreshold=");
pw.println(Formatter.formatFileSize(mContext, mMemCacheTrimToThreshold));
}
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2013 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.twilight;
public interface TwilightListener {
void onTwilightStateChanged();
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2013 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.twilight;
import android.os.Handler;
public interface TwilightManager {
void registerListener(TwilightListener listener, Handler handler);
TwilightState getCurrentState();
}

View File

@@ -14,7 +14,10 @@
* limitations under the License.
*/
package com.android.server;
package com.android.server.twilight;
import com.android.server.SystemService;
import com.android.server.TwilightCalculator;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -34,9 +37,7 @@ import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Slog;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import libcore.util.Objects;
@@ -47,78 +48,88 @@ import libcore.util.Objects;
* Used by the UI mode manager and other components to adjust night mode
* effects based on sunrise and sunset.
*/
public final class TwilightService {
private static final String TAG = "TwilightService";
private static final boolean DEBUG = false;
private static final String ACTION_UPDATE_TWILIGHT_STATE =
public final class TwilightService extends SystemService {
static final String TAG = "TwilightService";
static final boolean DEBUG = false;
static final String ACTION_UPDATE_TWILIGHT_STATE =
"com.android.server.action.UPDATE_TWILIGHT_STATE";
private final Context mContext;
private final AlarmManager mAlarmManager;
private final LocationManager mLocationManager;
private final LocationHandler mLocationHandler;
final Object mLock = new Object();
private final Object mLock = new Object();
AlarmManager mAlarmManager;
LocationManager mLocationManager;
LocationHandler mLocationHandler;
private final ArrayList<TwilightListenerRecord> mListeners =
final ArrayList<TwilightListenerRecord> mListeners =
new ArrayList<TwilightListenerRecord>();
private boolean mSystemReady;
TwilightState mTwilightState;
private TwilightState mTwilightState;
public TwilightService(Context context) {
mContext = context;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
mLocationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
@Override
public void onStart() {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mLocationManager = (LocationManager) getContext().getSystemService(
Context.LOCATION_SERVICE);
mLocationHandler = new LocationHandler();
IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(ACTION_UPDATE_TWILIGHT_STATE);
getContext().registerReceiver(mUpdateLocationReceiver, filter);
publishLocalService(TwilightManager.class, mService);
}
void systemReady() {
synchronized (mLock) {
mSystemReady = true;
private static class TwilightListenerRecord implements Runnable {
private final TwilightListener mListener;
private final Handler mHandler;
IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(ACTION_UPDATE_TWILIGHT_STATE);
mContext.registerReceiver(mUpdateLocationReceiver, filter);
public TwilightListenerRecord(TwilightListener listener, Handler handler) {
mListener = listener;
mHandler = handler;
}
if (!mListeners.isEmpty()) {
mLocationHandler.enableLocationUpdates();
public void postUpdate() {
mHandler.post(this);
}
@Override
public void run() {
mListener.onTwilightStateChanged();
}
}
private final TwilightManager mService = new TwilightManager() {
/**
* Gets the current twilight state.
*
* @return The current twilight state, or null if no information is available.
*/
@Override
public TwilightState getCurrentState() {
synchronized (mLock) {
return mTwilightState;
}
}
}
/**
* Gets the current twilight state.
*
* @return The current twilight state, or null if no information is available.
*/
public TwilightState getCurrentState() {
synchronized (mLock) {
return mTwilightState;
}
}
/**
* Listens for twilight time.
*
* @param listener The listener.
*/
@Override
public void registerListener(TwilightListener listener, Handler handler) {
synchronized (mLock) {
mListeners.add(new TwilightListenerRecord(listener, handler));
/**
* Listens for twilight time.
*
* @param listener The listener.
* @param handler The handler on which to post calls into the listener.
*/
public void registerListener(TwilightListener listener, Handler handler) {
synchronized (mLock) {
mListeners.add(new TwilightListenerRecord(listener, handler));
if (mSystemReady && mListeners.size() == 1) {
mLocationHandler.enableLocationUpdates();
if (mListeners.size() == 1) {
mLocationHandler.enableLocationUpdates();
}
}
}
}
};
private void setTwilightState(TwilightState state) {
synchronized (mLock) {
@@ -128,9 +139,10 @@ public final class TwilightService {
}
mTwilightState = state;
int count = mListeners.size();
for (int i = 0; i < count; i++) {
mListeners.get(i).post();
final int listenerLen = mListeners.size();
for (int i = 0; i < listenerLen; i++) {
mListeners.get(i).postUpdate();
}
}
}
@@ -162,124 +174,6 @@ public final class TwilightService {
return distance >= totalAccuracy;
}
/**
* Describes whether it is day or night.
* This object is immutable.
*/
public static final class TwilightState {
private final boolean mIsNight;
private final long mYesterdaySunset;
private final long mTodaySunrise;
private final long mTodaySunset;
private final long mTomorrowSunrise;
TwilightState(boolean isNight,
long yesterdaySunset,
long todaySunrise, long todaySunset,
long tomorrowSunrise) {
mIsNight = isNight;
mYesterdaySunset = yesterdaySunset;
mTodaySunrise = todaySunrise;
mTodaySunset = todaySunset;
mTomorrowSunrise = tomorrowSunrise;
}
/**
* Returns true if it is currently night time.
*/
public boolean isNight() {
return mIsNight;
}
/**
* Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase,
* or -1 if the sun never sets.
*/
public long getYesterdaySunset() {
return mYesterdaySunset;
}
/**
* Returns the time of today's sunrise in the System.currentTimeMillis() timebase,
* or -1 if the sun never rises.
*/
public long getTodaySunrise() {
return mTodaySunrise;
}
/**
* Returns the time of today's sunset in the System.currentTimeMillis() timebase,
* or -1 if the sun never sets.
*/
public long getTodaySunset() {
return mTodaySunset;
}
/**
* Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase,
* or -1 if the sun never rises.
*/
public long getTomorrowSunrise() {
return mTomorrowSunrise;
}
@Override
public boolean equals(Object o) {
return o instanceof TwilightState && equals((TwilightState)o);
}
public boolean equals(TwilightState other) {
return other != null
&& mIsNight == other.mIsNight
&& mYesterdaySunset == other.mYesterdaySunset
&& mTodaySunrise == other.mTodaySunrise
&& mTodaySunset == other.mTodaySunset
&& mTomorrowSunrise == other.mTomorrowSunrise;
}
@Override
public int hashCode() {
return 0; // don't care
}
@Override
public String toString() {
DateFormat f = DateFormat.getDateTimeInstance();
return "{TwilightState: isNight=" + mIsNight
+ ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset))
+ ", mTodaySunrise=" + f.format(new Date(mTodaySunrise))
+ ", mTodaySunset=" + f.format(new Date(mTodaySunset))
+ ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise))
+ "}";
}
}
/**
* Listener for changes in twilight state.
*/
public interface TwilightListener {
public void onTwilightStateChanged();
}
private static final class TwilightListenerRecord implements Runnable {
private final TwilightListener mListener;
private final Handler mHandler;
public TwilightListenerRecord(TwilightListener listener, Handler handler) {
mListener = listener;
mHandler = handler;
}
public void post() {
mHandler.post(this);
}
@Override
public void run() {
mListener.onTwilightStateChanged();
}
}
private final class LocationHandler extends Handler {
private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
@@ -518,11 +412,12 @@ public final class TwilightService {
}
Intent updateIntent = new Intent(ACTION_UPDATE_TWILIGHT_STATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, updateIntent, 0);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getContext(), 0, updateIntent, 0);
mAlarmManager.cancel(pendingIntent);
mAlarmManager.setExact(AlarmManager.RTC, nextUpdate, pendingIntent);
}
};
}
private final BroadcastReceiver mUpdateLocationReceiver = new BroadcastReceiver() {
@Override

View File

@@ -0,0 +1,112 @@
/*
* Copyright (C) 2013 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.twilight;
import java.text.DateFormat;
import java.util.Date;
/**
* Describes whether it is day or night.
* This object is immutable.
*/
public class TwilightState {
private final boolean mIsNight;
private final long mYesterdaySunset;
private final long mTodaySunrise;
private final long mTodaySunset;
private final long mTomorrowSunrise;
TwilightState(boolean isNight,
long yesterdaySunset,
long todaySunrise, long todaySunset,
long tomorrowSunrise) {
mIsNight = isNight;
mYesterdaySunset = yesterdaySunset;
mTodaySunrise = todaySunrise;
mTodaySunset = todaySunset;
mTomorrowSunrise = tomorrowSunrise;
}
/**
* Returns true if it is currently night time.
*/
public boolean isNight() {
return mIsNight;
}
/**
* Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase,
* or -1 if the sun never sets.
*/
public long getYesterdaySunset() {
return mYesterdaySunset;
}
/**
* Returns the time of today's sunrise in the System.currentTimeMillis() timebase,
* or -1 if the sun never rises.
*/
public long getTodaySunrise() {
return mTodaySunrise;
}
/**
* Returns the time of today's sunset in the System.currentTimeMillis() timebase,
* or -1 if the sun never sets.
*/
public long getTodaySunset() {
return mTodaySunset;
}
/**
* Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase,
* or -1 if the sun never rises.
*/
public long getTomorrowSunrise() {
return mTomorrowSunrise;
}
@Override
public boolean equals(Object o) {
return o instanceof TwilightState && equals((TwilightState)o);
}
public boolean equals(TwilightState other) {
return other != null
&& mIsNight == other.mIsNight
&& mYesterdaySunset == other.mYesterdaySunset
&& mTodaySunrise == other.mTodaySunrise
&& mTodaySunset == other.mTodaySunset
&& mTomorrowSunrise == other.mTomorrowSunrise;
}
@Override
public int hashCode() {
return 0; // don't care
}
@Override
public String toString() {
DateFormat f = DateFormat.getDateTimeInstance();
return "{TwilightState: isNight=" + mIsNight
+ ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset))
+ ", mTodaySunrise=" + f.format(new Date(mTodaySunrise))
+ ", mTodaySunset=" + f.format(new Date(mTodaySunset))
+ ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise))
+ "}";
}
}

View File

@@ -8,7 +8,7 @@ LOCAL_SRC_FILES:= \
com_android_server_input_InputApplicationHandle.cpp \
com_android_server_input_InputManagerService.cpp \
com_android_server_input_InputWindowHandle.cpp \
com_android_server_LightsService.cpp \
com_android_server_lights_LightsService.cpp \
com_android_server_power_PowerManagerService.cpp \
com_android_server_SerialService.cpp \
com_android_server_SystemServer.cpp \

View File

@@ -134,7 +134,7 @@ static JNINativeMethod method_table[] = {
int register_android_server_LightsService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/LightsService",
return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
method_table, NELEM(method_table));
}