Merge "Introduce a Lifecycle for system services"
This commit is contained in:
committed by
Android (Google) Code Review
commit
eb3a0fadfe
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
58
services/java/com/android/server/LocalServices.java
Normal file
58
services/java/com/android/server/LocalServices.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
151
services/java/com/android/server/SystemService.java
Normal file
151
services/java/com/android/server/SystemService.java
Normal 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) {
|
||||
// }
|
||||
}
|
||||
141
services/java/com/android/server/SystemServiceManager.java
Normal file
141
services/java/com/android/server/SystemServiceManager.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
41
services/java/com/android/server/lights/Light.java
Normal file
41
services/java/com/android/server/lights/Light.java
Normal 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();
|
||||
}
|
||||
31
services/java/com/android/server/lights/LightsManager.java
Normal file
31
services/java/com/android/server/lights/LightsManager.java
Normal 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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
112
services/java/com/android/server/twilight/TwilightState.java
Normal file
112
services/java/com/android/server/twilight/TwilightState.java
Normal 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))
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
@@ -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 \
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user